From d8da7dc9f2ca67cd874f85fd9efd71c3825aa1d9 Mon Sep 17 00:00:00 2001 From: "brking@charter.net" Date: Wed, 5 Jul 2006 17:00:01 -0500 Subject: [PATCH] --- yaml --- r: 34976 b: refs/heads/master c: f4c8aa1107969c26b1984eb2996a58f816dea71f h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/.gitignore | 8 - trunk/CREDITS | 9 +- trunk/Documentation/00-INDEX | 2 - trunk/Documentation/DocBook/kernel-api.tmpl | 9 +- trunk/Documentation/SubmittingPatches | 12 +- .../accounting/delay-accounting.txt | 10 +- trunk/Documentation/cciss.txt | 1 - trunk/Documentation/connector/ucon.c | 206 - trunk/Documentation/cpu-freq/user-guide.txt | 5 +- trunk/Documentation/cpu-hotplug.txt | 12 +- trunk/Documentation/cpusets.txt | 6 - trunk/Documentation/crypto/api-intro.txt | 36 +- trunk/Documentation/devices.txt | 8 +- trunk/Documentation/fb/imacfb.txt | 31 - .../feature-removal-schedule.txt | 20 - trunk/Documentation/filesystems/00-INDEX | 4 +- trunk/Documentation/filesystems/relay.txt | 479 -- trunk/Documentation/filesystems/relayfs.txt | 442 ++ trunk/Documentation/i386/boot.txt | 1 - trunk/Documentation/i386/zero-page.txt | 4 - trunk/Documentation/infiniband/ipoib.txt | 2 + trunk/Documentation/initrd.txt | 16 - trunk/Documentation/input/joystick.txt | 1 + trunk/Documentation/kbuild/makefiles.txt | 14 - trunk/Documentation/kernel-parameters.txt | 10 +- trunk/Documentation/kobject.txt | 2 +- trunk/Documentation/netlabel/00-INDEX | 10 - trunk/Documentation/netlabel/cipso_ipv4.txt | 48 - .../draft-ietf-cipso-ipsecurity-01.txt | 791 --- trunk/Documentation/netlabel/introduction.txt | 46 - .../Documentation/netlabel/lsm_interface.txt | 47 - trunk/Documentation/networking/ip-sysctl.txt | 56 +- trunk/Documentation/networking/secid.txt | 14 - .../powerpc/booting-without-of.txt | 16 +- trunk/Documentation/scsi/ChangeLog.megaraid | 123 - .../sound/alsa/ALSA-Configuration.txt | 44 +- .../alsa/DocBook/writing-an-alsa-driver.tmpl | 5 +- trunk/Documentation/sysctl/fs.txt | 20 - trunk/Documentation/sysctl/kernel.txt | 25 +- trunk/Documentation/usb/proc_usb_info.txt | 2 +- trunk/Documentation/usb/usb-help.txt | 3 +- trunk/Documentation/x86_64/boot-options.txt | 7 - trunk/MAINTAINERS | 88 +- trunk/Makefile | 44 +- trunk/arch/alpha/kernel/err_ev7.c | 8 +- trunk/arch/alpha/kernel/osf_sys.c | 4 +- trunk/arch/alpha/kernel/setup.c | 50 +- trunk/arch/alpha/kernel/sys_ruffian.c | 8 +- trunk/arch/alpha/kernel/time.c | 2 +- trunk/arch/arm/Makefile | 3 +- trunk/arch/arm/common/dmabounce.c | 8 +- trunk/arch/arm/common/gic.c | 3 +- trunk/arch/arm/common/locomo.c | 15 +- trunk/arch/arm/common/rtctime.c | 1 - trunk/arch/arm/common/sa1111.c | 12 +- trunk/arch/arm/common/vic.c | 3 +- trunk/arch/arm/configs/csb337_defconfig | 37 +- trunk/arch/arm/configs/ep93xx_defconfig | 15 +- trunk/arch/arm/configs/pnx4008_defconfig | 715 ++- trunk/arch/arm/kernel/Makefile | 3 +- trunk/arch/arm/kernel/ecard.c | 3 +- trunk/arch/arm/kernel/entry-armv.S | 21 +- trunk/arch/arm/kernel/head.S | 8 +- trunk/arch/arm/kernel/irq.c | 1 - trunk/arch/arm/kernel/isa.c | 63 +- trunk/arch/arm/kernel/traps.c | 5 +- trunk/arch/arm/mach-at91rm9200/gpio.c | 3 +- trunk/arch/arm/mach-at91rm9200/irq.c | 3 +- trunk/arch/arm/mach-footbridge/cats-hw.c | 2 +- trunk/arch/arm/mach-footbridge/dc21285.c | 1 + trunk/arch/arm/mach-imx/irq.c | 6 +- .../arch/arm/mach-integrator/integrator_ap.c | 3 +- .../arch/arm/mach-integrator/integrator_cp.c | 9 +- trunk/arch/arm/mach-integrator/pci_v3.c | 2 - trunk/arch/arm/mach-iop3xx/iop321-irq.c | 3 +- trunk/arch/arm/mach-iop3xx/iop331-irq.c | 6 +- trunk/arch/arm/mach-ixp4xx/common-pci.c | 2 + trunk/arch/arm/mach-ixp4xx/gtwx5715-setup.c | 7 +- trunk/arch/arm/mach-ixp4xx/nslu2-pci.c | 1 - trunk/arch/arm/mach-ixp4xx/nslu2-power.c | 1 - trunk/arch/arm/mach-lh7a40x/arch-kev7a400.c | 3 +- trunk/arch/arm/mach-lh7a40x/arch-lpd7a40x.c | 3 +- trunk/arch/arm/mach-lh7a40x/irq-kev7a400.c | 3 +- trunk/arch/arm/mach-lh7a40x/irq-lh7a400.c | 6 +- trunk/arch/arm/mach-lh7a40x/irq-lh7a404.c | 12 +- trunk/arch/arm/mach-lh7a40x/irq-lpd7a40x.c | 3 +- trunk/arch/arm/mach-omap1/fpga.c | 6 +- trunk/arch/arm/mach-omap1/irq.c | 3 +- trunk/arch/arm/mach-omap2/irq.c | 3 +- trunk/arch/arm/mach-pxa/corgi_ssp.c | 20 +- trunk/arch/arm/mach-pxa/irq.c | 12 +- trunk/arch/arm/mach-pxa/lpd270.c | 3 +- trunk/arch/arm/mach-pxa/lubbock.c | 3 +- trunk/arch/arm/mach-pxa/mainstone.c | 3 +- trunk/arch/arm/mach-pxa/ssp.c | 35 +- trunk/arch/arm/mach-s3c2410/Kconfig | 8 - trunk/arch/arm/mach-s3c2410/Makefile | 37 +- trunk/arch/arm/mach-s3c2410/cpu.h | 10 + trunk/arch/arm/mach-s3c2410/devs.c | 12 +- trunk/arch/arm/mach-s3c2410/dma.c | 243 +- trunk/arch/arm/mach-s3c2410/irq.c | 4 +- trunk/arch/arm/mach-s3c2410/irq.h | 10 - trunk/arch/arm/mach-s3c2410/mach-anubis.c | 49 +- trunk/arch/arm/mach-s3c2410/mach-bast.c | 25 + trunk/arch/arm/mach-s3c2410/mach-h1940.c | 17 + trunk/arch/arm/mach-s3c2410/mach-osiris.c | 20 +- trunk/arch/arm/mach-s3c2410/mach-rx3715.c | 9 + trunk/arch/arm/mach-s3c2410/mach-smdk2410.c | 4 + trunk/arch/arm/mach-s3c2410/mach-smdk2413.c | 15 +- trunk/arch/arm/mach-s3c2410/mach-vr1000.c | 19 + trunk/arch/arm/mach-s3c2410/s3c2400-gpio.c | 5 +- trunk/arch/arm/mach-s3c2410/s3c2410.h | 8 + trunk/arch/arm/mach-s3c2410/s3c2412-irq.c | 130 - trunk/arch/arm/mach-s3c2410/s3c2412.c | 29 - trunk/arch/arm/mach-s3c2410/s3c2440-irq.c | 3 + trunk/arch/arm/mach-s3c2410/s3c244x-irq.c | 12 +- trunk/arch/arm/mach-sa1100/irq.c | 9 +- trunk/arch/arm/mach-sa1100/ssp.c | 46 +- trunk/arch/arm/mach-shark/irq.c | 3 +- trunk/arch/arm/mach-versatile/core.c | 5 +- trunk/arch/arm/mm/Kconfig | 13 +- trunk/arch/arm/mm/flush.c | 26 - trunk/arch/arm/mm/ioremap.c | 2 - trunk/arch/arm/mm/proc-arm926.S | 2 +- trunk/arch/arm/mm/proc-syms.c | 8 - trunk/arch/arm/mm/proc-xscale.S | 30 +- trunk/arch/arm/plat-omap/gpio.c | 8 +- trunk/arch/arm/vfp/vfp.h | 18 +- trunk/arch/arm/vfp/vfpdouble.c | 50 +- trunk/arch/arm/vfp/vfphw.S | 10 +- trunk/arch/arm/vfp/vfpmodule.c | 4 +- trunk/arch/arm/vfp/vfpsingle.c | 55 +- trunk/arch/frv/Kconfig | 4 - trunk/arch/frv/Makefile | 5 +- trunk/arch/frv/boot/Makefile | 3 +- trunk/arch/frv/kernel/time.c | 81 + trunk/arch/i386/Kconfig | 6 +- trunk/arch/i386/crypto/Makefile | 3 - trunk/arch/i386/crypto/aes.c | 3 +- trunk/arch/i386/crypto/twofish-i586-asm.S | 335 -- trunk/arch/i386/crypto/twofish.c | 97 - trunk/arch/i386/kernel/Makefile | 4 +- trunk/arch/i386/kernel/acpi/boot.c | 2 +- trunk/arch/i386/kernel/acpi/wakeup.S | 5 +- trunk/arch/i386/kernel/audit.c | 23 + trunk/arch/i386/kernel/cpu/cpufreq/Kconfig | 3 +- .../i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 49 +- trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c | 361 +- trunk/arch/i386/kernel/cpu/cpufreq/longhaul.h | 48 +- .../kernel/cpu/cpufreq/speedstep-centrino.c | 42 +- trunk/arch/i386/kernel/cpu/intel_cacheinfo.c | 2 +- trunk/arch/i386/kernel/cpu/mcheck/mce.h | 2 +- trunk/arch/i386/kernel/entry.S | 6 +- trunk/arch/i386/kernel/head.S | 14 +- trunk/arch/i386/kernel/hpet.c | 2 +- trunk/arch/i386/kernel/irq.c | 5 + trunk/arch/i386/kernel/kprobes.c | 9 +- trunk/arch/i386/kernel/machine_kexec.c | 13 +- trunk/arch/i386/kernel/nmi.c | 1 - trunk/arch/i386/kernel/process.c | 4 +- trunk/arch/i386/kernel/smpboot.c | 62 +- trunk/arch/i386/kernel/time.c | 2 +- trunk/arch/i386/kernel/traps.c | 32 +- trunk/arch/i386/kernel/vsyscall.lds.S | 1 - trunk/arch/i386/oprofile/nmi_int.c | 2 - trunk/arch/i386/pci/init.c | 8 +- trunk/arch/i386/pci/mmconfig.c | 2 +- trunk/arch/ia64/Kconfig | 8 +- trunk/arch/ia64/configs/sn2_defconfig | 2 +- trunk/arch/ia64/defconfig | 2 +- trunk/arch/ia64/hp/sim/simscsi.c | 5 +- trunk/arch/ia64/ia32/audit.c | 26 - trunk/arch/ia64/kernel/Makefile | 3 +- trunk/arch/ia64/kernel/acpi.c | 2 +- trunk/arch/ia64/kernel/audit.c | 35 - trunk/arch/ia64/kernel/efi.c | 6 +- trunk/arch/ia64/kernel/entry.S | 4 +- trunk/arch/ia64/kernel/gate.lds.S | 1 - trunk/arch/ia64/kernel/head.S | 7 +- trunk/arch/ia64/kernel/ia64_ksyms.c | 2 +- trunk/arch/ia64/kernel/kprobes.c | 9 - trunk/arch/ia64/kernel/pal.S | 18 +- trunk/arch/ia64/kernel/palinfo.c | 47 +- trunk/arch/ia64/kernel/perfmon.c | 4 +- trunk/arch/ia64/kernel/sys_ia64.c | 28 +- trunk/arch/ia64/kernel/topology.c | 8 +- trunk/arch/ia64/kernel/traps.c | 5 +- trunk/arch/ia64/kernel/uncached.c | 86 +- trunk/arch/ia64/lib/Makefile | 2 +- trunk/arch/ia64/mm/contig.c | 16 +- trunk/arch/ia64/mm/discontig.c | 68 +- trunk/arch/ia64/mm/init.c | 55 - trunk/arch/ia64/mm/ioremap.c | 6 +- trunk/arch/ia64/sn/kernel/setup.c | 2 +- trunk/arch/ia64/sn/kernel/xpc_channel.c | 4 +- trunk/arch/ia64/sn/kernel/xpc_main.c | 30 +- trunk/arch/ia64/sn/kernel/xpc_partition.c | 24 +- trunk/arch/ia64/sn/pci/tioce_provider.c | 6 +- trunk/arch/parisc/kernel/vmlinux.lds.S | 1 - trunk/arch/powerpc/Kconfig | 47 +- trunk/arch/powerpc/Kconfig.debug | 16 - trunk/arch/powerpc/boot/Makefile | 7 +- trunk/arch/powerpc/boot/dts/mpc7448hpc2.dts | 190 - trunk/arch/powerpc/boot/dts/mpc8349emds.dts | 328 -- trunk/arch/powerpc/boot/dts/mpc8540ads.dts | 257 - trunk/arch/powerpc/boot/dts/mpc8541cds.dts | 244 - trunk/arch/powerpc/boot/dts/mpc8548cds.dts | 287 -- trunk/arch/powerpc/boot/dts/mpc8555cds.dts | 244 - trunk/arch/powerpc/boot/dts/mpc8641_hpcn.dts | 339 -- trunk/arch/powerpc/boot/flatdevtree.h | 46 - trunk/arch/powerpc/boot/main.c | 250 +- trunk/arch/powerpc/boot/ops.h | 100 - trunk/arch/powerpc/boot/{of.c => prom.c} | 144 +- trunk/arch/powerpc/boot/prom.h | 41 + trunk/arch/powerpc/boot/stdio.c | 4 +- trunk/arch/powerpc/boot/stdio.h | 8 - trunk/arch/powerpc/boot/types.h | 23 - trunk/arch/powerpc/configs/cell_defconfig | 58 +- trunk/arch/powerpc/configs/chrp32_defconfig | 31 +- trunk/arch/powerpc/configs/g5_defconfig | 125 +- trunk/arch/powerpc/configs/iseries_defconfig | 79 +- trunk/arch/powerpc/configs/maple_defconfig | 131 +- .../powerpc/configs/mpc7448_hpc2_defconfig | 64 +- .../powerpc/configs/mpc834x_itx_defconfig | 20 +- ...4x_mds_defconfig => mpc834x_sys_defconfig} | 104 +- .../powerpc/configs/mpc8540_ads_defconfig | 84 +- .../powerpc/configs/mpc85xx_cds_defconfig | 75 +- .../powerpc/configs/mpc8641_hpcn_defconfig | 62 +- trunk/arch/powerpc/configs/pmac32_defconfig | 122 +- trunk/arch/powerpc/configs/ppc64_defconfig | 198 +- trunk/arch/powerpc/configs/pseries_defconfig | 80 +- trunk/arch/powerpc/kernel/Makefile | 10 +- trunk/arch/powerpc/kernel/asm-offsets.c | 17 +- trunk/arch/powerpc/kernel/audit.c | 66 - trunk/arch/powerpc/kernel/btext.c | 24 +- trunk/arch/powerpc/kernel/compat_audit.c | 38 - ...{cpu_setup_ppc970.S => cpu_setup_power4.S} | 101 +- trunk/arch/powerpc/kernel/cputable.c | 21 - trunk/arch/powerpc/kernel/crash.c | 13 +- trunk/arch/powerpc/kernel/crash_dump.c | 2 +- trunk/arch/powerpc/kernel/dma_64.c | 65 +- trunk/arch/powerpc/kernel/entry_64.S | 8 - trunk/arch/powerpc/kernel/fpu.S | 5 - trunk/arch/powerpc/kernel/head_64.S | 89 +- trunk/arch/powerpc/kernel/ibmebus.c | 6 +- trunk/arch/powerpc/kernel/io.c | 131 - trunk/arch/powerpc/kernel/irq.c | 91 +- trunk/arch/powerpc/kernel/kprobes.c | 2 - trunk/arch/powerpc/kernel/legacy_serial.c | 56 +- trunk/arch/powerpc/kernel/lparcfg.c | 30 +- trunk/arch/powerpc/kernel/machine_kexec.c | 56 - trunk/arch/powerpc/kernel/machine_kexec_64.c | 67 +- trunk/arch/powerpc/kernel/misc.S | 158 + trunk/arch/powerpc/kernel/misc_64.S | 2 +- trunk/arch/powerpc/kernel/of_device.c | 24 + trunk/arch/powerpc/kernel/paca.c | 15 +- trunk/arch/powerpc/kernel/pci_32.c | 39 +- trunk/arch/powerpc/kernel/pci_64.c | 78 +- trunk/arch/powerpc/kernel/pci_dn.c | 13 +- trunk/arch/powerpc/kernel/ppc_ksyms.c | 23 +- trunk/arch/powerpc/kernel/prom.c | 44 +- trunk/arch/powerpc/kernel/prom_init.c | 52 +- trunk/arch/powerpc/kernel/prom_parse.c | 116 +- trunk/arch/powerpc/kernel/rtas-proc.c | 25 +- trunk/arch/powerpc/kernel/rtas.c | 68 +- trunk/arch/powerpc/kernel/rtas_pci.c | 28 +- trunk/arch/powerpc/kernel/setup-common.c | 32 +- trunk/arch/powerpc/kernel/setup_64.c | 23 +- trunk/arch/powerpc/kernel/smp-tbsync.c | 5 +- trunk/arch/powerpc/kernel/smp.c | 24 +- trunk/arch/powerpc/kernel/sysfs.c | 13 +- trunk/arch/powerpc/kernel/time.c | 56 +- trunk/arch/powerpc/kernel/traps.c | 57 +- trunk/arch/powerpc/kernel/udbg_16550.c | 6 +- trunk/arch/powerpc/kernel/vdso32/Makefile | 3 +- trunk/arch/powerpc/kernel/vdso32/vdso32.lds.S | 1 - trunk/arch/powerpc/kernel/vdso64/Makefile | 3 +- trunk/arch/powerpc/kernel/vdso64/vdso64.lds.S | 1 - trunk/arch/powerpc/kernel/vio.c | 16 +- trunk/arch/powerpc/lib/Makefile | 1 + trunk/arch/powerpc/lib/e2a.c | 116 + trunk/arch/powerpc/lib/locks.c | 27 +- trunk/arch/powerpc/lib/memcpy_64.S | 11 +- trunk/arch/powerpc/mm/44x_mmu.c | 4 +- trunk/arch/powerpc/mm/hugetlbpage.c | 2 +- trunk/arch/powerpc/mm/lmb.c | 3 +- trunk/arch/powerpc/mm/numa.c | 31 +- trunk/arch/powerpc/mm/slb.c | 37 +- trunk/arch/powerpc/mm/tlb_64.c | 1 - .../arch/powerpc/platforms/83xx/mpc834x_itx.c | 53 +- .../arch/powerpc/platforms/83xx/mpc834x_sys.c | 60 +- trunk/arch/powerpc/platforms/83xx/mpc83xx.h | 1 - trunk/arch/powerpc/platforms/83xx/pci.c | 13 +- trunk/arch/powerpc/platforms/85xx/Kconfig | 1 + .../arch/powerpc/platforms/85xx/mpc85xx_ads.c | 166 +- .../arch/powerpc/platforms/85xx/mpc85xx_cds.c | 214 +- trunk/arch/powerpc/platforms/85xx/pci.c | 4 +- .../powerpc/platforms/86xx/mpc8641_hpcn.h | 32 + .../powerpc/platforms/86xx/mpc86xx_hpcn.c | 338 +- trunk/arch/powerpc/platforms/86xx/pci.c | 7 +- trunk/arch/powerpc/platforms/Makefile | 1 - trunk/arch/powerpc/platforms/cell/cbe_regs.c | 8 +- trunk/arch/powerpc/platforms/cell/interrupt.c | 25 +- trunk/arch/powerpc/platforms/cell/iommu.c | 22 +- trunk/arch/powerpc/platforms/cell/setup.c | 4 + trunk/arch/powerpc/platforms/cell/smp.c | 4 +- .../arch/powerpc/platforms/cell/spider-pic.c | 10 +- trunk/arch/powerpc/platforms/cell/spu_base.c | 18 +- trunk/arch/powerpc/platforms/chrp/nvram.c | 5 +- trunk/arch/powerpc/platforms/chrp/pci.c | 53 +- trunk/arch/powerpc/platforms/chrp/setup.c | 60 +- .../powerpc/platforms/embedded6xx/Kconfig | 1 - .../platforms/embedded6xx/mpc7448_hpc2.c | 83 +- trunk/arch/powerpc/platforms/iseries/Kconfig | 8 +- trunk/arch/powerpc/platforms/iseries/dt.c | 45 +- .../powerpc/platforms/iseries/hvlpconfig.c | 13 - trunk/arch/powerpc/platforms/iseries/iommu.c | 19 +- .../arch/powerpc/platforms/iseries/lpardata.c | 6 +- .../arch/powerpc/platforms/iseries/lpevents.c | 2 +- .../powerpc/platforms/iseries/main_store.h | 126 +- trunk/arch/powerpc/platforms/iseries/pci.c | 289 +- trunk/arch/powerpc/platforms/iseries/setup.c | 1 - .../arch/powerpc/platforms/iseries/viopath.c | 28 +- .../arch/powerpc/platforms/iseries/vpdinfo.c | 22 +- trunk/arch/powerpc/platforms/maple/pci.c | 70 +- trunk/arch/powerpc/platforms/maple/setup.c | 44 +- trunk/arch/powerpc/platforms/pasemi/Makefile | 1 - trunk/arch/powerpc/platforms/pasemi/pasemi.h | 8 - trunk/arch/powerpc/platforms/pasemi/pci.c | 198 - trunk/arch/powerpc/platforms/pasemi/setup.c | 188 - trunk/arch/powerpc/platforms/pasemi/time.c | 29 - .../powerpc/platforms/powermac/backlight.c | 61 +- .../powerpc/platforms/powermac/bootx_init.c | 50 +- .../powerpc/platforms/powermac/cpufreq_32.c | 23 +- .../powerpc/platforms/powermac/cpufreq_64.c | 103 +- .../arch/powerpc/platforms/powermac/feature.c | 30 +- .../arch/powerpc/platforms/powermac/low_i2c.c | 24 +- trunk/arch/powerpc/platforms/powermac/pci.c | 37 +- .../powerpc/platforms/powermac/pfunc_base.c | 4 +- .../powerpc/platforms/powermac/pfunc_core.c | 5 +- trunk/arch/powerpc/platforms/powermac/pic.c | 6 +- trunk/arch/powerpc/platforms/powermac/setup.c | 18 +- trunk/arch/powerpc/platforms/powermac/smp.c | 9 +- .../powerpc/platforms/powermac/udbg_scc.c | 10 +- trunk/arch/powerpc/platforms/pseries/Makefile | 1 - trunk/arch/powerpc/platforms/pseries/eeh.c | 96 +- .../powerpc/platforms/pseries/eeh_cache.c | 17 +- .../powerpc/platforms/pseries/eeh_driver.c | 112 +- .../powerpc/platforms/pseries/eeh_event.c | 4 +- .../arch/powerpc/platforms/pseries/firmware.c | 2 +- trunk/arch/powerpc/platforms/pseries/hvCall.S | 273 +- .../powerpc/platforms/pseries/hvCall_inst.c | 129 - .../powerpc/platforms/pseries/hvconsole.c | 5 +- trunk/arch/powerpc/platforms/pseries/iommu.c | 13 +- trunk/arch/powerpc/platforms/pseries/lpar.c | 46 +- trunk/arch/powerpc/platforms/pseries/nvram.c | 5 +- trunk/arch/powerpc/platforms/pseries/pci.c | 2 +- .../platforms/pseries/plpar_wrappers.h | 107 +- trunk/arch/powerpc/platforms/pseries/ras.c | 4 +- trunk/arch/powerpc/platforms/pseries/rtasd.c | 4 +- trunk/arch/powerpc/platforms/pseries/setup.c | 50 +- trunk/arch/powerpc/platforms/pseries/smp.c | 12 +- trunk/arch/powerpc/platforms/pseries/xics.c | 50 +- trunk/arch/powerpc/sysdev/Makefile | 4 +- trunk/arch/powerpc/sysdev/dart_iommu.c | 7 +- trunk/arch/powerpc/sysdev/fsl_soc.c | 68 +- trunk/arch/powerpc/sysdev/fsl_soc.h | 2 - trunk/arch/powerpc/sysdev/i8259.c | 2 +- trunk/arch/powerpc/sysdev/ipic.c | 345 +- trunk/arch/powerpc/sysdev/ipic.h | 23 +- trunk/arch/powerpc/sysdev/mmio_nvram.c | 4 +- trunk/arch/powerpc/sysdev/mpic.c | 223 +- trunk/arch/powerpc/sysdev/tsi108_dev.c | 10 +- trunk/arch/powerpc/sysdev/tsi108_pci.c | 25 +- trunk/arch/powerpc/xmon/xmon.c | 10 - trunk/arch/ppc/Kconfig | 6 +- trunk/arch/ppc/configs/prep_defconfig | 585 +-- trunk/arch/ppc/kernel/misc.S | 88 + trunk/arch/ppc/kernel/ppc_ksyms.c | 9 + trunk/arch/ppc/kernel/setup.c | 17 +- trunk/arch/ppc/kernel/smp-tbsync.c | 7 +- trunk/arch/ppc/kernel/vmlinux.lds.S | 1 - trunk/arch/ppc/platforms/85xx/mpc8560_ads.c | 89 - .../ppc/platforms/85xx/mpc85xx_ads_common.h | 19 - trunk/arch/ppc/platforms/85xx/sbc8560.h | 1 - trunk/arch/ppc/platforms/85xx/sbc85xx.h | 18 - trunk/arch/ppc/platforms/mpc8272ads_setup.c | 154 +- trunk/arch/ppc/platforms/mpc866ads_setup.c | 192 +- trunk/arch/ppc/platforms/mpc885ads_setup.c | 175 +- trunk/arch/ppc/platforms/pq2ads_pd.h | 82 + trunk/arch/ppc/syslib/Makefile | 2 +- trunk/arch/ppc/syslib/ipic.c | 646 --- trunk/arch/ppc/syslib/ipic.h | 47 - trunk/arch/ppc/syslib/m8260_pci_erratum9.c | 16 + trunk/arch/ppc/syslib/mpc85xx_devices.c | 89 +- trunk/arch/ppc/syslib/mpc8xx_devices.c | 8 - trunk/arch/ppc/syslib/mpc8xx_sys.c | 6 +- trunk/arch/ppc/syslib/pq2_devices.c | 5 - trunk/arch/ppc/syslib/pq2_sys.c | 3 +- trunk/arch/ppc/xmon/start.c | 28 +- trunk/arch/ppc/xmon/xmon.c | 28 +- trunk/arch/s390/Kconfig | 21 +- trunk/arch/s390/appldata/appldata.h | 16 + trunk/arch/s390/appldata/appldata_base.c | 89 +- trunk/arch/s390/appldata/appldata_os.c | 1 - trunk/arch/s390/crypto/aes_s390.c | 285 +- trunk/arch/s390/crypto/crypt_s390.h | 3 - trunk/arch/s390/crypto/des_s390.c | 559 +-- trunk/arch/s390/crypto/sha1_s390.c | 2 - trunk/arch/s390/crypto/sha256_s390.c | 2 - trunk/arch/s390/defconfig | 45 +- trunk/arch/s390/hypfs/hypfs.h | 2 +- trunk/arch/s390/hypfs/hypfs_diag.c | 16 +- trunk/arch/s390/hypfs/hypfs_diag.h | 2 +- trunk/arch/s390/hypfs/inode.c | 12 +- trunk/arch/s390/kernel/Makefile | 7 +- trunk/arch/s390/kernel/audit.c | 66 - trunk/arch/s390/kernel/compat_audit.c | 38 - trunk/arch/s390/kernel/entry.S | 12 - trunk/arch/s390/kernel/entry64.S | 16 +- trunk/arch/s390/kernel/head.S | 69 +- trunk/arch/s390/kernel/head31.S | 48 +- trunk/arch/s390/kernel/head64.S | 59 +- trunk/arch/s390/kernel/ipl.c | 942 ---- trunk/arch/s390/kernel/kprobes.c | 657 --- trunk/arch/s390/kernel/reipl.S | 33 +- trunk/arch/s390/kernel/reipl64.S | 34 +- trunk/arch/s390/kernel/reipl_diag.c | 39 + trunk/arch/s390/kernel/s390_ksyms.c | 6 + trunk/arch/s390/kernel/setup.c | 272 +- trunk/arch/s390/kernel/signal.c | 40 +- trunk/arch/s390/kernel/smp.c | 10 +- trunk/arch/s390/kernel/traps.c | 31 +- trunk/arch/s390/kernel/vmlinux.lds.S | 3 +- trunk/arch/s390/lib/Makefile | 4 +- trunk/arch/s390/lib/uaccess.S | 210 + trunk/arch/s390/lib/uaccess64.S | 206 + trunk/arch/s390/lib/uaccess_mvcos.c | 156 - trunk/arch/s390/lib/uaccess_std.c | 340 -- trunk/arch/s390/mm/cmm.c | 30 +- trunk/arch/s390/mm/fault.c | 40 +- trunk/arch/s390/mm/init.c | 42 +- trunk/arch/sh/kernel/cpu/sh4/sq.c | 10 +- trunk/arch/sh64/Makefile | 1 + trunk/arch/sh64/kernel/process.c | 3 - trunk/arch/sh64/mach-cayman/setup.c | 6 +- trunk/arch/sh64/mm/ioremap.c | 4 +- trunk/arch/sparc/kernel/ebus.c | 7 +- trunk/arch/sparc/kernel/ioport.c | 2 - trunk/arch/sparc/kernel/setup.c | 4 +- trunk/arch/sparc/kernel/smp.c | 1 + trunk/arch/sparc/kernel/sun4d_smp.c | 2 +- trunk/arch/sparc/kernel/sun4m_smp.c | 2 + trunk/arch/sparc/kernel/sys_sparc.c | 37 +- trunk/arch/sparc/kernel/time.c | 74 +- trunk/arch/sparc64/Kconfig | 4 - trunk/arch/sparc64/defconfig | 25 +- trunk/arch/sparc64/kernel/Makefile | 3 - trunk/arch/sparc64/kernel/audit.c | 66 - trunk/arch/sparc64/kernel/compat_audit.c | 37 - trunk/arch/sparc64/kernel/sys_sparc.c | 46 +- trunk/arch/sparc64/kernel/time.c | 2 +- trunk/arch/sparc64/mm/generic.c | 2 - trunk/arch/um/kernel/dyn.lds.S | 1 - trunk/arch/v850/kernel/setup.c | 6 +- trunk/arch/v850/kernel/v850_ksyms.c | 16 + trunk/arch/x86_64/Kconfig | 4 - trunk/arch/x86_64/crypto/Makefile | 3 - trunk/arch/x86_64/crypto/aes.c | 5 +- trunk/arch/x86_64/crypto/twofish-x86_64-asm.S | 324 -- trunk/arch/x86_64/crypto/twofish.c | 97 - trunk/arch/x86_64/defconfig | 71 +- trunk/arch/x86_64/ia32/Makefile | 1 - trunk/arch/x86_64/ia32/audit.c | 26 - trunk/arch/x86_64/ia32/ia32_binfmt.c | 57 +- trunk/arch/x86_64/ia32/ia32entry.S | 2 +- trunk/arch/x86_64/ia32/vsyscall.lds | 1 - trunk/arch/x86_64/kernel/audit.c | 35 - trunk/arch/x86_64/kernel/e820.c | 6 +- trunk/arch/x86_64/kernel/entry.S | 21 +- trunk/arch/x86_64/kernel/head.S | 1 - trunk/arch/x86_64/kernel/init_task.c | 5 - trunk/arch/x86_64/kernel/machine_kexec.c | 13 +- trunk/arch/x86_64/kernel/mce.c | 12 +- trunk/arch/x86_64/kernel/mce_amd.c | 19 +- trunk/arch/x86_64/kernel/pci-calgary.c | 77 +- trunk/arch/x86_64/kernel/pci-nommu.c | 2 - trunk/arch/x86_64/kernel/pci-swiotlb.c | 5 +- trunk/arch/x86_64/kernel/setup.c | 6 +- trunk/arch/x86_64/kernel/setup64.c | 3 +- trunk/arch/x86_64/kernel/smp.c | 2 +- trunk/arch/x86_64/kernel/tce.c | 4 +- trunk/arch/x86_64/kernel/time.c | 18 +- trunk/arch/x86_64/kernel/traps.c | 32 +- trunk/arch/x86_64/pci/k8-bus.c | 10 +- trunk/arch/xtensa/kernel/ptrace.c | 2 +- trunk/arch/xtensa/kernel/traps.c | 6 +- trunk/block/cfq-iosched.c | 2 +- trunk/block/elevator.c | 3 +- trunk/block/ll_rw_blk.c | 14 - trunk/crypto/Kconfig | 154 +- trunk/crypto/Makefile | 16 +- trunk/crypto/aes.c | 5 +- trunk/crypto/algapi.c | 486 -- trunk/crypto/anubis.c | 3 +- trunk/crypto/api.c | 428 +- trunk/crypto/arc4.c | 2 +- trunk/crypto/blkcipher.c | 405 -- trunk/crypto/blowfish.c | 3 +- trunk/crypto/cast5.c | 8 +- trunk/crypto/cast6.c | 5 +- trunk/crypto/cbc.c | 344 -- trunk/crypto/cipher.c | 117 +- trunk/crypto/crc32c.c | 30 +- trunk/crypto/crypto_null.c | 2 +- trunk/crypto/cryptomgr.c | 156 - trunk/crypto/des.c | 6 +- trunk/crypto/digest.c | 155 +- trunk/crypto/ecb.c | 181 - trunk/crypto/hash.c | 61 - trunk/crypto/hmac.c | 290 +- trunk/crypto/internal.h | 106 +- trunk/crypto/khazad.c | 8 +- trunk/crypto/michael_mic.c | 5 +- trunk/crypto/proc.c | 13 +- trunk/crypto/scatterwalk.c | 89 +- trunk/crypto/scatterwalk.h | 52 +- trunk/crypto/serpent.c | 19 +- trunk/crypto/sha1.c | 3 - trunk/crypto/sha256.c | 3 - trunk/crypto/tcrypt.c | 901 ++-- trunk/crypto/tcrypt.h | 202 +- trunk/crypto/tea.c | 16 +- trunk/crypto/twofish.c | 700 ++- trunk/crypto/twofish_common.c | 744 --- trunk/drivers/acpi/ac.c | 2 - trunk/drivers/acpi/acpi_memhotplug.c | 21 +- trunk/drivers/acpi/battery.c | 3 - trunk/drivers/acpi/bus.c | 11 +- trunk/drivers/acpi/dock.c | 13 +- trunk/drivers/acpi/hotkey.c | 281 +- trunk/drivers/acpi/i2c_ec.c | 2 +- trunk/drivers/acpi/osl.c | 10 - trunk/drivers/acpi/sbs.c | 3 - trunk/drivers/acpi/scan.c | 12 +- trunk/drivers/acpi/utils.c | 2 +- trunk/drivers/atm/he.c | 13 +- trunk/drivers/base/hypervisor.c | 3 +- trunk/drivers/base/node.c | 2 +- trunk/drivers/base/topology.c | 2 +- trunk/drivers/block/cciss.c | 10 +- trunk/drivers/block/cryptoloop.c | 160 +- trunk/drivers/block/floppy.c | 12 +- trunk/drivers/block/nbd.c | 19 +- trunk/drivers/block/pktcdvd.c | 6 +- trunk/drivers/cdrom/gscd.c | 2 +- trunk/drivers/char/Kconfig | 22 - trunk/drivers/char/Makefile | 2 - trunk/drivers/char/agp/agp.h | 2 +- trunk/drivers/char/agp/backend.c | 2 +- trunk/drivers/char/agp/efficeon-agp.c | 16 +- trunk/drivers/char/agp/frontend.c | 27 +- trunk/drivers/char/agp/generic.c | 39 +- trunk/drivers/char/agp/intel-agp.c | 173 +- trunk/drivers/char/agp/uninorth-agp.c | 4 +- trunk/drivers/char/agp/via-agp.c | 4 +- trunk/drivers/char/briq_panel.c | 271 -- trunk/drivers/char/drm/radeon_state.c | 9 +- trunk/drivers/char/hvc_console.c | 19 +- trunk/drivers/char/hvc_console.h | 2 +- trunk/drivers/char/hvc_iseries.c | 594 --- trunk/drivers/char/hvc_rtas.c | 2 +- trunk/drivers/char/hvc_vio.c | 7 +- trunk/drivers/char/hvsi.c | 15 +- trunk/drivers/char/hw_random/geode-rng.c | 6 +- trunk/drivers/char/hw_random/intel-rng.c | 2 +- trunk/drivers/char/hw_random/omap-rng.c | 51 +- trunk/drivers/char/ipmi/ipmi_msghandler.c | 1 - trunk/drivers/char/ipmi/ipmi_si_intf.c | 9 +- trunk/drivers/char/istallion.c | 2 +- trunk/drivers/char/keyboard.c | 139 +- trunk/drivers/char/moxa.c | 8 +- trunk/drivers/char/pc8736x_gpio.c | 1 + trunk/drivers/char/snsc.c | 7 +- trunk/drivers/char/synclink_gt.c | 14 +- trunk/drivers/char/tpm/tpm_atmel.h | 4 +- trunk/drivers/char/tty_io.c | 808 +--- trunk/drivers/char/tty_ioctl.c | 59 +- trunk/drivers/char/viocons.c | 31 +- trunk/drivers/char/viotape.c | 6 +- trunk/drivers/char/vt_ioctl.c | 2 - trunk/drivers/char/watchdog/Kconfig | 8 +- trunk/drivers/char/watchdog/sbc8360.c | 4 +- trunk/drivers/connector/cn_proc.c | 20 +- trunk/drivers/cpufreq/cpufreq.c | 77 +- trunk/drivers/cpufreq/cpufreq_ondemand.c | 173 +- trunk/drivers/cpufreq/cpufreq_stats.c | 2 + trunk/drivers/crypto/Kconfig | 45 +- trunk/drivers/crypto/Makefile | 8 +- trunk/drivers/crypto/padlock-aes.c | 258 +- trunk/drivers/crypto/padlock-generic.c | 63 + trunk/drivers/crypto/padlock-sha.c | 318 -- trunk/drivers/crypto/padlock.c | 58 - trunk/drivers/crypto/padlock.h | 17 +- trunk/drivers/edac/edac_mc.h | 1 - trunk/drivers/hwmon/abituguru.c | 99 +- trunk/drivers/i2c/busses/i2c-powermac.c | 3 +- trunk/drivers/i2c/busses/scx200_acb.c | 7 +- trunk/drivers/i2c/chips/tps65010.c | 12 +- trunk/drivers/ide/Kconfig | 15 +- trunk/drivers/ide/ide-disk.c | 2 +- trunk/drivers/ide/ide-dma.c | 2 +- trunk/drivers/ide/ide-iops.c | 2 - trunk/drivers/ide/ide-proc.c | 2 - trunk/drivers/ide/ide.c | 5 +- trunk/drivers/ide/pci/aec62xx.c | 12 +- trunk/drivers/ide/pci/alim15x3.c | 2 +- trunk/drivers/ide/pci/generic.c | 30 - trunk/drivers/ide/pci/it821x.c | 11 +- trunk/drivers/ide/pci/serverworks.c | 10 +- trunk/drivers/ide/pci/sgiioc4.c | 60 +- trunk/drivers/ide/pci/siimage.c | 6 +- trunk/drivers/ide/pci/sis5513.c | 2 - trunk/drivers/ide/pci/via82cxxx.c | 3 +- trunk/drivers/ide/ppc/pmac.c | 8 +- trunk/drivers/ieee1394/ohci1394.c | 4 +- trunk/drivers/ieee1394/sbp2.c | 3 - trunk/drivers/infiniband/Kconfig | 4 +- trunk/drivers/infiniband/Makefile | 4 +- trunk/drivers/infiniband/core/Makefile | 4 +- trunk/drivers/infiniband/core/addr.c | 48 +- trunk/drivers/infiniband/core/cache.c | 8 +- trunk/drivers/infiniband/core/cm.c | 70 +- trunk/drivers/infiniband/core/cma.c | 405 +- trunk/drivers/infiniband/core/device.c | 6 +- trunk/drivers/infiniband/core/iwcm.c | 1019 ---- trunk/drivers/infiniband/core/iwcm.h | 62 - trunk/drivers/infiniband/core/mad.c | 19 +- trunk/drivers/infiniband/core/mad_priv.h | 2 +- trunk/drivers/infiniband/core/mad_rmpp.c | 94 +- trunk/drivers/infiniband/core/sa_query.c | 70 +- trunk/drivers/infiniband/core/smi.c | 16 +- trunk/drivers/infiniband/core/sysfs.c | 13 +- trunk/drivers/infiniband/core/ucm.c | 9 +- trunk/drivers/infiniband/core/user_mad.c | 7 +- trunk/drivers/infiniband/core/uverbs.h | 2 - trunk/drivers/infiniband/core/uverbs_cmd.c | 64 +- trunk/drivers/infiniband/core/uverbs_main.c | 8 +- trunk/drivers/infiniband/core/verbs.c | 21 +- trunk/drivers/infiniband/hw/amso1100/Kbuild | 8 - trunk/drivers/infiniband/hw/amso1100/Kconfig | 15 - trunk/drivers/infiniband/hw/amso1100/c2.c | 1255 ----- trunk/drivers/infiniband/hw/amso1100/c2.h | 551 --- trunk/drivers/infiniband/hw/amso1100/c2_ae.c | 321 -- trunk/drivers/infiniband/hw/amso1100/c2_ae.h | 108 - .../drivers/infiniband/hw/amso1100/c2_alloc.c | 144 - trunk/drivers/infiniband/hw/amso1100/c2_cm.c | 452 -- trunk/drivers/infiniband/hw/amso1100/c2_cq.c | 433 -- .../drivers/infiniband/hw/amso1100/c2_intr.c | 209 - trunk/drivers/infiniband/hw/amso1100/c2_mm.c | 375 -- trunk/drivers/infiniband/hw/amso1100/c2_mq.c | 174 - trunk/drivers/infiniband/hw/amso1100/c2_mq.h | 106 - trunk/drivers/infiniband/hw/amso1100/c2_pd.c | 89 - .../infiniband/hw/amso1100/c2_provider.c | 870 ---- .../infiniband/hw/amso1100/c2_provider.h | 181 - trunk/drivers/infiniband/hw/amso1100/c2_qp.c | 975 ---- .../drivers/infiniband/hw/amso1100/c2_rnic.c | 664 --- .../infiniband/hw/amso1100/c2_status.h | 158 - .../drivers/infiniband/hw/amso1100/c2_user.h | 82 - trunk/drivers/infiniband/hw/amso1100/c2_vq.c | 260 - trunk/drivers/infiniband/hw/amso1100/c2_vq.h | 63 - trunk/drivers/infiniband/hw/amso1100/c2_wr.h | 1520 ------ trunk/drivers/infiniband/hw/ehca/Kconfig | 16 - trunk/drivers/infiniband/hw/ehca/Makefile | 16 - trunk/drivers/infiniband/hw/ehca/ehca_av.c | 271 -- .../drivers/infiniband/hw/ehca/ehca_classes.h | 346 -- .../infiniband/hw/ehca/ehca_classes_pSeries.h | 236 - trunk/drivers/infiniband/hw/ehca/ehca_cq.c | 427 -- trunk/drivers/infiniband/hw/ehca/ehca_eq.c | 185 - trunk/drivers/infiniband/hw/ehca/ehca_hca.c | 241 - trunk/drivers/infiniband/hw/ehca/ehca_irq.c | 762 --- trunk/drivers/infiniband/hw/ehca/ehca_irq.h | 77 - .../drivers/infiniband/hw/ehca/ehca_iverbs.h | 182 - trunk/drivers/infiniband/hw/ehca/ehca_main.c | 818 ---- trunk/drivers/infiniband/hw/ehca/ehca_mcast.c | 131 - trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c | 2261 --------- trunk/drivers/infiniband/hw/ehca/ehca_mrmw.h | 140 - trunk/drivers/infiniband/hw/ehca/ehca_pd.c | 114 - trunk/drivers/infiniband/hw/ehca/ehca_qes.h | 259 - trunk/drivers/infiniband/hw/ehca/ehca_qp.c | 1507 ------ trunk/drivers/infiniband/hw/ehca/ehca_reqs.c | 653 --- trunk/drivers/infiniband/hw/ehca/ehca_sqp.c | 111 - trunk/drivers/infiniband/hw/ehca/ehca_tools.h | 172 - .../drivers/infiniband/hw/ehca/ehca_uverbs.c | 392 -- trunk/drivers/infiniband/hw/ehca/hcp_if.c | 874 ---- trunk/drivers/infiniband/hw/ehca/hcp_if.h | 261 - trunk/drivers/infiniband/hw/ehca/hcp_phyp.c | 80 - trunk/drivers/infiniband/hw/ehca/hcp_phyp.h | 90 - trunk/drivers/infiniband/hw/ehca/hipz_fns.h | 68 - .../infiniband/hw/ehca/hipz_fns_core.h | 100 - trunk/drivers/infiniband/hw/ehca/hipz_hw.h | 388 -- trunk/drivers/infiniband/hw/ehca/ipz_pt_fn.c | 149 - trunk/drivers/infiniband/hw/ehca/ipz_pt_fn.h | 247 - trunk/drivers/infiniband/hw/ipath/Kconfig | 21 +- trunk/drivers/infiniband/hw/ipath/Makefile | 29 +- .../infiniband/hw/ipath/ipath_common.h | 19 +- trunk/drivers/infiniband/hw/ipath/ipath_cq.c | 183 +- .../drivers/infiniband/hw/ipath/ipath_debug.h | 2 + .../drivers/infiniband/hw/ipath/ipath_diag.c | 155 +- .../infiniband/hw/ipath/ipath_driver.c | 349 +- .../infiniband/hw/ipath/ipath_file_ops.c | 35 +- trunk/drivers/infiniband/hw/ipath/ipath_fs.c | 4 +- .../ipath/{ipath_iba6110.c => ipath_ht400.c} | 53 +- .../infiniband/hw/ipath/ipath_init_chip.c | 21 +- .../drivers/infiniband/hw/ipath/ipath_intr.c | 24 +- .../infiniband/hw/ipath/ipath_kernel.h | 57 +- .../drivers/infiniband/hw/ipath/ipath_keys.c | 3 +- .../drivers/infiniband/hw/ipath/ipath_layer.c | 1179 ++++- .../drivers/infiniband/hw/ipath/ipath_layer.h | 115 + trunk/drivers/infiniband/hw/ipath/ipath_mad.c | 339 +- .../drivers/infiniband/hw/ipath/ipath_mmap.c | 122 - trunk/drivers/infiniband/hw/ipath/ipath_mr.c | 12 - .../ipath/{ipath_iba6120.c => ipath_pe800.c} | 82 +- trunk/drivers/infiniband/hw/ipath/ipath_qp.c | 242 +- trunk/drivers/infiniband/hw/ipath/ipath_rc.c | 9 +- .../infiniband/hw/ipath/ipath_registers.h | 7 +- trunk/drivers/infiniband/hw/ipath/ipath_ruc.c | 160 +- trunk/drivers/infiniband/hw/ipath/ipath_srq.c | 244 +- .../drivers/infiniband/hw/ipath/ipath_stats.c | 27 + .../drivers/infiniband/hw/ipath/ipath_sysfs.c | 41 +- trunk/drivers/infiniband/hw/ipath/ipath_uc.c | 5 +- trunk/drivers/infiniband/hw/ipath/ipath_ud.c | 182 +- .../drivers/infiniband/hw/ipath/ipath_verbs.c | 687 +-- .../drivers/infiniband/hw/ipath/ipath_verbs.h | 252 +- .../infiniband/hw/ipath/ipath_verbs_mcast.c | 7 - .../infiniband/hw/ipath/ipath_wc_ppc64.c | 52 - .../drivers/infiniband/hw/ipath/verbs_debug.h | 108 + .../infiniband/hw/mthca/mthca_allocator.c | 30 +- trunk/drivers/infiniband/hw/mthca/mthca_av.c | 2 +- .../drivers/infiniband/hw/mthca/mthca_catas.c | 62 - trunk/drivers/infiniband/hw/mthca/mthca_cmd.c | 2 +- trunk/drivers/infiniband/hw/mthca/mthca_cq.c | 10 +- trunk/drivers/infiniband/hw/mthca/mthca_dev.h | 12 +- trunk/drivers/infiniband/hw/mthca/mthca_mad.c | 2 +- .../drivers/infiniband/hw/mthca/mthca_main.c | 94 +- .../infiniband/hw/mthca/mthca_provider.c | 13 +- .../infiniband/hw/mthca/mthca_provider.h | 4 +- trunk/drivers/infiniband/hw/mthca/mthca_qp.c | 74 +- trunk/drivers/infiniband/hw/mthca/mthca_srq.c | 2 +- trunk/drivers/infiniband/hw/mthca/mthca_uar.c | 2 +- trunk/drivers/infiniband/ulp/ipoib/Kconfig | 3 +- trunk/drivers/infiniband/ulp/ipoib/ipoib.h | 2 - trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c | 194 +- .../drivers/infiniband/ulp/ipoib/ipoib_main.c | 37 +- .../infiniband/ulp/ipoib/ipoib_multicast.c | 35 +- trunk/drivers/infiniband/ulp/iser/Kconfig | 2 +- .../drivers/infiniband/ulp/iser/iscsi_iser.c | 23 +- .../drivers/infiniband/ulp/iser/iscsi_iser.h | 7 +- .../drivers/infiniband/ulp/iser/iser_memory.c | 80 +- .../drivers/infiniband/ulp/iser/iser_verbs.c | 10 +- trunk/drivers/infiniband/ulp/srp/ib_srp.c | 76 +- trunk/drivers/input/evdev.c | 10 +- trunk/drivers/input/gameport/fm801-gp.c | 4 +- trunk/drivers/input/gameport/gameport.c | 66 +- trunk/drivers/input/input.c | 57 +- .../input/joystick/iforce/iforce-main.c | 19 +- trunk/drivers/input/joystick/spaceball.c | 2 +- trunk/drivers/input/keyboard/atkbd.c | 103 +- trunk/drivers/input/misc/wistron_btns.c | 4 +- trunk/drivers/input/mouse/logips2pp.c | 3 +- trunk/drivers/input/mouse/psmouse-base.c | 7 + trunk/drivers/input/mouse/trackpoint.c | 52 +- trunk/drivers/input/serio/libps2.c | 5 - trunk/drivers/input/serio/serio.c | 65 +- trunk/drivers/isdn/hardware/eicon/divasync.h | 1 + trunk/drivers/macintosh/Kconfig | 13 +- trunk/drivers/macintosh/adbhid.c | 14 +- trunk/drivers/macintosh/macio_asic.c | 10 +- trunk/drivers/macintosh/macio_sysfs.c | 8 +- trunk/drivers/macintosh/smu.c | 19 +- trunk/drivers/macintosh/therm_adt746x.c | 8 +- trunk/drivers/macintosh/therm_pm72.c | 232 +- trunk/drivers/macintosh/therm_pm72.h | 33 +- trunk/drivers/macintosh/therm_windtunnel.c | 4 +- trunk/drivers/macintosh/via-cuda.c | 4 +- trunk/drivers/macintosh/via-pmu-backlight.c | 121 +- trunk/drivers/macintosh/via-pmu-led.c | 4 +- trunk/drivers/macintosh/via-pmu.c | 61 +- trunk/drivers/macintosh/windfarm_pm81.c | 4 +- trunk/drivers/macintosh/windfarm_pm91.c | 2 +- .../drivers/macintosh/windfarm_smu_controls.c | 13 +- trunk/drivers/macintosh/windfarm_smu_sat.c | 8 +- .../drivers/macintosh/windfarm_smu_sensors.c | 12 +- trunk/drivers/md/dm-crypt.c | 146 +- trunk/drivers/md/dm-mpath.c | 3 +- trunk/drivers/md/dm-raid1.c | 4 +- trunk/drivers/md/linear.c | 6 +- trunk/drivers/md/md.c | 13 - trunk/drivers/md/raid1.c | 64 +- trunk/drivers/media/Kconfig | 2 +- trunk/drivers/media/common/saa7146_video.c | 2 - trunk/drivers/media/dvb/b2c2/Kconfig | 1 - trunk/drivers/media/dvb/bt8xx/Kconfig | 1 - trunk/drivers/media/dvb/bt8xx/dst.c | 58 +- trunk/drivers/media/dvb/dvb-core/Makefile | 6 +- .../drivers/media/dvb/dvb-core/dvb_frontend.c | 15 +- trunk/drivers/media/dvb/dvb-usb/Kconfig | 1 - trunk/drivers/media/dvb/frontends/Kconfig | 60 +- trunk/drivers/media/dvb/frontends/Makefile | 2 +- trunk/drivers/media/dvb/frontends/dvb-pll.c | 24 +- trunk/drivers/media/dvb/pluto2/Kconfig | 1 - trunk/drivers/media/dvb/ttpci/Kconfig | 5 - trunk/drivers/media/dvb/ttpci/av7110.c | 4 +- trunk/drivers/media/dvb/ttpci/av7110_v4l.c | 12 +- trunk/drivers/media/dvb/ttpci/budget-av.c | 3 - trunk/drivers/media/dvb/ttpci/budget-ci.c | 2 - trunk/drivers/media/dvb/ttpci/budget-core.c | 57 +- trunk/drivers/media/dvb/ttpci/budget-patch.c | 2 - trunk/drivers/media/dvb/ttpci/budget.c | 5 +- trunk/drivers/media/dvb/ttpci/budget.h | 7 +- trunk/drivers/media/dvb/ttusb-budget/Kconfig | 3 +- trunk/drivers/media/radio/Kconfig | 12 +- trunk/drivers/media/radio/Makefile | 1 - trunk/drivers/media/video/Kconfig | 24 +- trunk/drivers/media/video/Makefile | 2 +- trunk/drivers/media/video/bt8xx/Kconfig | 2 +- trunk/drivers/media/video/bt8xx/bttv-driver.c | 15 +- trunk/drivers/media/video/bt8xx/bttv-input.c | 1 - trunk/drivers/media/video/bt8xx/bttv-vbi.c | 15 +- trunk/drivers/media/video/compat_ioctl32.c | 54 +- trunk/drivers/media/video/cpia2/Kconfig | 2 +- .../media/video/cx25840/cx25840-core.c | 4 +- trunk/drivers/media/video/cx88/Kconfig | 1 - trunk/drivers/media/video/cx88/cx88-input.c | 2 +- trunk/drivers/media/video/cx88/cx88-video.c | 5 +- .../drivers/media/{radio => video}/dsbr100.c | 0 trunk/drivers/media/video/msp3400-driver.c | 10 +- trunk/drivers/media/video/msp3400-kthreads.c | 4 +- .../drivers/media/video/pvrusb2/pvrusb2-hdw.c | 8 +- .../drivers/media/video/pvrusb2/pvrusb2-io.c | 9 +- .../drivers/media/video/pvrusb2/pvrusb2-io.h | 2 - .../media/video/pvrusb2/pvrusb2-ioread.c | 5 +- .../media/video/pvrusb2/pvrusb2-sysfs.c | 85 +- trunk/drivers/media/video/pwc/Kconfig | 2 +- trunk/drivers/media/video/pwc/pwc-if.c | 1 - trunk/drivers/media/video/saa7134/Kconfig | 1 - .../media/video/saa7134/saa7134-alsa.c | 10 +- .../media/video/saa7134/saa7134-core.c | 16 +- .../drivers/media/video/saa7134/saa7134-oss.c | 10 +- .../media/video/saa7134/saa7134-video.c | 6 +- trunk/drivers/media/video/saa7134/saa7134.h | 4 +- trunk/drivers/media/video/stradis.c | 1 + trunk/drivers/media/video/tuner-core.c | 31 +- trunk/drivers/media/video/tuner-simple.c | 19 +- trunk/drivers/media/video/tuner-types.c | 24 +- trunk/drivers/media/video/usbvideo/Kconfig | 8 +- trunk/drivers/media/video/v4l1-compat.c | 4 - trunk/drivers/media/video/v4l2-common.c | 24 +- trunk/drivers/media/video/videodev.c | 29 +- trunk/drivers/media/video/vivi.c | 4 +- trunk/drivers/media/video/zoran.h | 2 +- trunk/drivers/media/video/zoran_driver.c | 22 +- trunk/drivers/message/fusion/mptbase.h | 1 + trunk/drivers/message/fusion/mptfc.c | 92 +- trunk/drivers/mmc/imxmmc.c | 69 +- trunk/drivers/mmc/mmc.c | 55 +- trunk/drivers/mmc/mmc_block.c | 60 +- trunk/drivers/mmc/mmc_queue.c | 3 +- trunk/drivers/mmc/wbsd.c | 9 +- trunk/drivers/mtd/Kconfig | 10 +- trunk/drivers/mtd/Makefile | 1 - trunk/drivers/mtd/chips/cfi_cmdset_0001.c | 87 +- trunk/drivers/mtd/chips/cfi_cmdset_0002.c | 112 - trunk/drivers/mtd/chips/jedec_probe.c | 14 - trunk/drivers/mtd/devices/block2mtd.c | 93 +- trunk/drivers/mtd/devices/m25p80.c | 12 +- trunk/drivers/mtd/devices/pmc551.c | 1158 +++-- trunk/drivers/mtd/maps/Kconfig | 20 +- trunk/drivers/mtd/maps/Makefile | 1 + trunk/drivers/mtd/maps/amd76xrom.c | 5 +- trunk/drivers/mtd/maps/arctic-mtd.c | 14 +- trunk/drivers/mtd/maps/beech-mtd.c | 14 +- trunk/drivers/mtd/maps/cstm_mips_ixx.c | 18 +- trunk/drivers/mtd/maps/ebony.c | 4 - trunk/drivers/mtd/maps/fortunet.c | 3 - trunk/drivers/mtd/maps/ichxrom.c | 3 +- trunk/drivers/mtd/maps/iq80310.c | 118 + trunk/drivers/mtd/maps/ixp4xx.c | 2 +- trunk/drivers/mtd/maps/l440gx.c | 12 +- trunk/drivers/mtd/maps/lasat.c | 2 - trunk/drivers/mtd/maps/nettel.c | 34 +- trunk/drivers/mtd/maps/ocotea.c | 4 - trunk/drivers/mtd/maps/pcmciamtd.c | 4 - trunk/drivers/mtd/maps/physmap.c | 33 - trunk/drivers/mtd/maps/redwood.c | 11 +- trunk/drivers/mtd/maps/sbc8240.c | 11 +- trunk/drivers/mtd/maps/scx200_docflash.c | 9 +- trunk/drivers/mtd/maps/walnut.c | 4 - trunk/drivers/mtd/mtdchar.c | 9 +- trunk/drivers/mtd/mtdcore.c | 10 - trunk/drivers/mtd/nand/Kconfig | 2 +- trunk/drivers/mtd/nand/ams-delta.c | 10 +- trunk/drivers/mtd/nand/au1550nd.c | 11 + trunk/drivers/mtd/nand/edb7312.c | 3 - trunk/drivers/mtd/nand/nand_base.c | 12 +- trunk/drivers/mtd/nand/ndfc.c | 2 +- trunk/drivers/mtd/nand/ppchameleonevb.c | 7 - trunk/drivers/mtd/nand/sharpsl.c | 7 +- trunk/drivers/mtd/ssfdc.c | 474 -- trunk/drivers/net/3c515.c | 3 +- trunk/drivers/net/3c59x.c | 2 +- trunk/drivers/net/8139cp.c | 6 +- trunk/drivers/net/82596.c | 9 +- trunk/drivers/net/Kconfig | 43 +- trunk/drivers/net/Makefile | 3 - trunk/drivers/net/ac3200.c | 3 +- trunk/drivers/net/acenic.c | 8 +- trunk/drivers/net/appletalk/Kconfig | 2 +- trunk/drivers/net/appletalk/cops.c | 2 +- trunk/drivers/net/arcnet/com20020-pci.c | 1 - trunk/drivers/net/at1700.c | 2 +- trunk/drivers/net/bmac.c | 13 +- trunk/drivers/net/bnx2.c | 51 +- trunk/drivers/net/bnx2.h | 12 +- trunk/drivers/net/cassini.c | 4 +- trunk/drivers/net/chelsio/sge.c | 10 +- trunk/drivers/net/cs89x0.c | 3 +- trunk/drivers/net/dl2k.c | 2 +- trunk/drivers/net/dm9000.c | 18 +- trunk/drivers/net/e100.c | 6 +- trunk/drivers/net/e1000/e1000_hw.c | 89 +- trunk/drivers/net/e1000/e1000_hw.h | 32 + trunk/drivers/net/e1000/e1000_main.c | 29 +- trunk/drivers/net/e2100.c | 4 +- trunk/drivers/net/eepro.c | 3 +- trunk/drivers/net/eexpress.c | 2 +- trunk/drivers/net/es3210.c | 3 +- trunk/drivers/net/eth16i.c | 2 +- trunk/drivers/net/fealnx.c | 2 +- trunk/drivers/net/forcedeth.c | 3 +- trunk/drivers/net/fs_enet/Makefile | 6 +- trunk/drivers/net/fs_enet/fec.h | 42 - trunk/drivers/net/fs_enet/fs_enet-main.c | 207 +- trunk/drivers/net/fs_enet/fs_enet-mii.c | 505 ++ trunk/drivers/net/fs_enet/fs_enet.h | 40 +- trunk/drivers/net/fs_enet/mac-fcc.c | 32 +- trunk/drivers/net/fs_enet/mac-fec.c | 142 +- trunk/drivers/net/fs_enet/mac-scc.c | 4 +- trunk/drivers/net/fs_enet/mii-bitbang.c | 448 +- trunk/drivers/net/fs_enet/mii-fec.c | 243 - trunk/drivers/net/fs_enet/mii-fixed.c | 91 + trunk/drivers/net/gianfar.c | 2 +- trunk/drivers/net/hamachi.c | 2 +- trunk/drivers/net/ibm_emac/ibm_emac_core.c | 2 +- trunk/drivers/net/ibmveth.c | 3 +- trunk/drivers/net/ibmveth.h | 27 +- trunk/drivers/net/ioc3-eth.c | 2 +- trunk/drivers/net/irda/ali-ircc.c | 8 +- trunk/drivers/net/irda/irport.c | 4 +- trunk/drivers/net/irda/via-ircc.c | 5 +- trunk/drivers/net/irda/w83977af_ir.c | 4 +- trunk/drivers/net/ixgb/ixgb_main.c | 2 +- trunk/drivers/net/lance.c | 2 +- trunk/drivers/net/lne390.c | 2 +- trunk/drivers/net/lp486e.c | 6 +- trunk/drivers/net/mace.c | 2 +- trunk/drivers/net/mv643xx_eth.c | 4 +- trunk/drivers/net/myri10ge/myri10ge.c | 36 +- trunk/drivers/net/ni52.c | 2 +- trunk/drivers/net/ni65.c | 2 +- trunk/drivers/net/ns83820.c | 2 +- trunk/drivers/net/pcmcia/xirc2ps_cs.c | 18 +- trunk/drivers/net/pcnet32.c | 25 +- trunk/drivers/net/phy/Kconfig | 17 - trunk/drivers/net/phy/Makefile | 1 - trunk/drivers/net/phy/fixed.c | 358 -- trunk/drivers/net/phy/mdio_bus.c | 1 - trunk/drivers/net/phy/phy.c | 8 +- trunk/drivers/net/phy/phy_device.c | 51 +- trunk/drivers/net/ppp_generic.c | 30 +- trunk/drivers/net/ppp_mppe.c | 68 +- trunk/drivers/net/r8169.c | 2 +- trunk/drivers/net/s2io.c | 389 +- trunk/drivers/net/s2io.h | 10 - trunk/drivers/net/seeq8005.c | 2 +- trunk/drivers/net/sk98lin/skge.c | 6 +- trunk/drivers/net/skge.c | 11 +- trunk/drivers/net/sky2.c | 11 +- trunk/drivers/net/smc911x.c | 1 - trunk/drivers/net/smc91x.c | 8 +- trunk/drivers/net/smc91x.h | 29 +- trunk/drivers/net/spider_net.c | 24 +- trunk/drivers/net/spider_net.h | 3 - trunk/drivers/net/spider_net_ethtool.c | 13 - trunk/drivers/net/starfire.c | 6 +- trunk/drivers/net/sundance.c | 2 +- trunk/drivers/net/sungem.c | 6 +- trunk/drivers/net/sunhme.c | 6 +- trunk/drivers/net/sunlance.c | 35 +- trunk/drivers/net/tg3.c | 256 +- trunk/drivers/net/tg3.h | 8 +- trunk/drivers/net/tokenring/ibmtr.c | 4 +- trunk/drivers/net/tokenring/smctr.c | 5 +- trunk/drivers/net/tulip/winbond-840.c | 2 +- trunk/drivers/net/tulip/xircom_cb.c | 3 +- trunk/drivers/net/typhoon.c | 2 +- trunk/drivers/net/ucc_geth.c | 4278 ----------------- trunk/drivers/net/ucc_geth.h | 1339 ------ trunk/drivers/net/ucc_geth_phy.c | 801 --- trunk/drivers/net/ucc_geth_phy.h | 217 - trunk/drivers/net/via-rhine.c | 92 +- trunk/drivers/net/via-velocity.c | 19 +- trunk/drivers/net/wan/c101.c | 9 +- trunk/drivers/net/wd.c | 4 +- trunk/drivers/net/wireless/Kconfig | 1 - trunk/drivers/net/wireless/airo.c | 22 +- .../net/wireless/bcm43xx/bcm43xx_main.c | 2 +- trunk/drivers/net/wireless/hostap/hostap_hw.c | 3 - trunk/drivers/net/wireless/orinoco.c | 4 +- trunk/drivers/net/wireless/spectrum_cs.c | 2 +- trunk/drivers/net/wireless/strip.c | 6 +- trunk/drivers/net/wireless/zd1201.c | 2 - trunk/drivers/net/wireless/zd1211rw/zd_chip.c | 65 +- trunk/drivers/net/wireless/zd1211rw/zd_chip.h | 10 +- trunk/drivers/net/wireless/zd1211rw/zd_mac.c | 59 +- trunk/drivers/net/wireless/zd1211rw/zd_mac.h | 11 +- trunk/drivers/net/wireless/zd1211rw/zd_usb.c | 7 +- trunk/drivers/pci/hotplug/Kconfig | 9 +- trunk/drivers/pci/hotplug/acpiphp_core.c | 3 +- trunk/drivers/pci/hotplug/acpiphp_glue.c | 2 +- trunk/drivers/pci/hotplug/cpci_hotplug_pci.c | 54 +- trunk/drivers/pci/hotplug/pciehp.h | 5 - trunk/drivers/pci/hotplug/pciehp_hpc.c | 4 + trunk/drivers/pci/hotplug/rpaphp_core.c | 32 +- trunk/drivers/pci/pci-driver.c | 3 +- trunk/drivers/pci/pcie/portdrv_pci.c | 38 +- trunk/drivers/pci/quirks.c | 67 +- trunk/drivers/pci/search.c | 48 +- trunk/drivers/pcmcia/pcmcia_ioctl.c | 16 +- trunk/drivers/pcmcia/pcmcia_resource.c | 15 +- trunk/drivers/pnp/interface.c | 12 +- trunk/drivers/pnp/pnpacpi/rsparser.c | 8 - trunk/drivers/pnp/pnpbios/core.c | 2 +- trunk/drivers/rtc/rtc-s3c.c | 124 +- trunk/drivers/s390/Kconfig | 30 +- trunk/drivers/s390/block/dasd.c | 202 +- trunk/drivers/s390/block/dasd_devmap.c | 168 +- trunk/drivers/s390/block/dasd_eckd.c | 22 +- trunk/drivers/s390/block/dasd_eer.c | 2 +- trunk/drivers/s390/block/dasd_genhd.c | 10 +- trunk/drivers/s390/block/dasd_int.h | 1 - trunk/drivers/s390/block/xpram.c | 27 +- trunk/drivers/s390/char/Makefile | 1 - trunk/drivers/s390/char/monwriter.c | 292 -- trunk/drivers/s390/char/tape_class.c | 2 +- trunk/drivers/s390/char/vmcp.c | 2 +- trunk/drivers/s390/char/vmcp.h | 2 +- trunk/drivers/s390/cio/ccwgroup.c | 24 +- trunk/drivers/s390/cio/chsc.c | 13 +- trunk/drivers/s390/cio/cio.c | 95 +- trunk/drivers/s390/cio/css.c | 203 +- trunk/drivers/s390/cio/device.c | 128 +- trunk/drivers/s390/cio/device_fsm.c | 64 +- trunk/drivers/s390/cio/device_ops.c | 20 +- trunk/drivers/s390/cio/device_pgid.c | 108 +- trunk/drivers/s390/cio/qdio.c | 4 +- trunk/drivers/s390/cio/qdio.h | 16 +- trunk/drivers/s390/crypto/Makefile | 15 +- trunk/drivers/s390/crypto/ap_bus.c | 1221 ----- trunk/drivers/s390/crypto/ap_bus.h | 158 - trunk/drivers/s390/crypto/z90common.h | 166 + trunk/drivers/s390/crypto/z90crypt.h | 71 + trunk/drivers/s390/crypto/z90hardware.c | 2531 ++++++++++ trunk/drivers/s390/crypto/z90main.c | 3379 +++++++++++++ trunk/drivers/s390/crypto/zcrypt_api.c | 1091 ----- trunk/drivers/s390/crypto/zcrypt_api.h | 141 - trunk/drivers/s390/crypto/zcrypt_cca_key.h | 350 -- trunk/drivers/s390/crypto/zcrypt_cex2a.c | 435 -- trunk/drivers/s390/crypto/zcrypt_cex2a.h | 126 - trunk/drivers/s390/crypto/zcrypt_error.h | 133 - trunk/drivers/s390/crypto/zcrypt_mono.c | 100 - trunk/drivers/s390/crypto/zcrypt_pcica.c | 418 -- trunk/drivers/s390/crypto/zcrypt_pcica.h | 117 - trunk/drivers/s390/crypto/zcrypt_pcicc.c | 630 --- trunk/drivers/s390/crypto/zcrypt_pcicc.h | 176 - trunk/drivers/s390/crypto/zcrypt_pcixcc.c | 951 ---- trunk/drivers/s390/crypto/zcrypt_pcixcc.h | 79 - trunk/drivers/s390/net/Kconfig | 9 + trunk/drivers/s390/net/Makefile | 1 + trunk/drivers/s390/net/ctcmain.c | 3 - trunk/drivers/s390/net/iucv.c | 4 +- trunk/drivers/s390/net/lcs.c | 13 +- trunk/drivers/s390/net/netiucv.c | 80 +- trunk/drivers/s390/net/qeth.h | 73 +- trunk/drivers/s390/net/qeth_eddp.c | 5 +- trunk/drivers/s390/net/qeth_main.c | 525 +- trunk/drivers/s390/net/qeth_proc.c | 23 +- trunk/drivers/s390/net/qeth_sys.c | 64 +- trunk/drivers/s390/net/qeth_tso.h | 2 +- trunk/drivers/s390/s390mach.c | 17 +- trunk/drivers/s390/scsi/zfcp_aux.c | 120 +- trunk/drivers/s390/scsi/zfcp_ccw.c | 5 - trunk/drivers/s390/scsi/zfcp_def.h | 23 +- trunk/drivers/s390/scsi/zfcp_erp.c | 212 +- trunk/drivers/s390/scsi/zfcp_ext.h | 9 +- trunk/drivers/s390/scsi/zfcp_fsf.c | 122 +- trunk/drivers/s390/scsi/zfcp_qdio.c | 79 +- trunk/drivers/s390/scsi/zfcp_scsi.c | 73 +- trunk/drivers/s390/sysinfo.c | 455 +- trunk/drivers/sbus/char/openprom.c | 13 +- trunk/drivers/scsi/ahci.c | 10 +- trunk/drivers/scsi/aic7xxx/aicasm/Makefile | 2 - trunk/drivers/scsi/arm/Kconfig | 3 - trunk/drivers/scsi/arm/scsi.h | 2 +- trunk/drivers/scsi/ata_piix.c | 117 +- trunk/drivers/scsi/esp.c | 3 +- trunk/drivers/scsi/hptiop.c | 568 ++- trunk/drivers/scsi/ibmvscsi/rpa_vscsi.c | 11 +- trunk/drivers/scsi/ide-scsi.c | 2 +- trunk/drivers/scsi/iscsi_tcp.c | 343 +- trunk/drivers/scsi/iscsi_tcp.h | 11 +- trunk/drivers/scsi/libata-core.c | 49 +- trunk/drivers/scsi/libata-eh.c | 69 +- trunk/drivers/scsi/libata-scsi.c | 13 - trunk/drivers/scsi/libiscsi.c | 214 +- trunk/drivers/scsi/lpfc/lpfc_attr.c | 101 +- trunk/drivers/scsi/lpfc/lpfc_crtn.h | 1 - trunk/drivers/scsi/lpfc/lpfc_ct.c | 13 +- trunk/drivers/scsi/lpfc/lpfc_els.c | 21 +- trunk/drivers/scsi/lpfc/lpfc_hbadisc.c | 15 +- trunk/drivers/scsi/lpfc/lpfc_init.c | 13 +- trunk/drivers/scsi/lpfc/lpfc_mbox.c | 16 - trunk/drivers/scsi/lpfc/lpfc_nportdisc.c | 24 +- trunk/drivers/scsi/lpfc/lpfc_scsi.c | 21 +- trunk/drivers/scsi/lpfc/lpfc_sli.c | 57 +- trunk/drivers/scsi/lpfc/lpfc_sli.h | 20 - trunk/drivers/scsi/lpfc/lpfc_version.h | 2 +- trunk/drivers/scsi/mac53c94.c | 2 +- trunk/drivers/scsi/megaraid/mega_common.h | 6 - trunk/drivers/scsi/megaraid/megaraid_ioctl.h | 4 - trunk/drivers/scsi/megaraid/megaraid_mbox.c | 58 +- trunk/drivers/scsi/megaraid/megaraid_mbox.h | 4 +- trunk/drivers/scsi/megaraid/megaraid_mm.c | 2 +- trunk/drivers/scsi/megaraid/megaraid_mm.h | 4 +- trunk/drivers/scsi/mesh.c | 5 +- trunk/drivers/scsi/pdc_adma.c | 3 +- trunk/drivers/scsi/qla2xxx/qla_def.h | 1 - trunk/drivers/scsi/qla2xxx/qla_init.c | 11 - trunk/drivers/scsi/qla2xxx/qla_iocb.c | 1 - trunk/drivers/scsi/qla2xxx/qla_isr.c | 5 - trunk/drivers/scsi/qla2xxx/qla_os.c | 15 +- trunk/drivers/scsi/qla2xxx/qla_version.h | 4 +- trunk/drivers/scsi/sata_mv.c | 3 +- trunk/drivers/scsi/sata_promise.c | 7 - trunk/drivers/scsi/sata_sil24.c | 1 + trunk/drivers/scsi/sata_svw.c | 2 +- trunk/drivers/scsi/sata_via.c | 118 +- trunk/drivers/scsi/scsi_error.c | 20 +- trunk/drivers/scsi/scsi_ioctl.c | 5 +- trunk/drivers/scsi/scsi_transport_iscsi.c | 15 +- trunk/drivers/scsi/sg.c | 8 +- trunk/drivers/scsi/sym53c8xx_2/sym_glue.c | 2 +- trunk/drivers/serial/8250_pci.c | 31 +- trunk/drivers/serial/pmac_zilog.c | 9 +- trunk/drivers/serial/s3c2410.c | 2 +- trunk/drivers/serial/serial_core.c | 3 - trunk/drivers/serial/sh-sci.c | 4 +- trunk/drivers/serial/sunsab.c | 9 - trunk/drivers/serial/sunzilog.c | 3 - trunk/drivers/usb/Kconfig | 2 +- trunk/drivers/usb/core/devio.c | 20 +- trunk/drivers/usb/core/file.c | 13 +- trunk/drivers/usb/gadget/Kconfig | 2 +- trunk/drivers/usb/gadget/at91_udc.c | 176 +- trunk/drivers/usb/gadget/at91_udc.h | 1 - trunk/drivers/usb/gadget/dummy_hcd.c | 6 +- trunk/drivers/usb/gadget/ether.c | 45 +- trunk/drivers/usb/host/ehci-hcd.c | 2 +- trunk/drivers/usb/host/ohci-at91.c | 88 +- trunk/drivers/usb/host/ohci-au1xxx.c | 1 + trunk/drivers/usb/host/ohci-hcd.c | 3 +- trunk/drivers/usb/host/uhci-q.c | 8 +- trunk/drivers/usb/input/appletouch.c | 2 +- trunk/drivers/usb/input/ati_remote.c | 174 +- trunk/drivers/usb/input/hid-core.c | 149 +- trunk/drivers/usb/input/hid-input.c | 3 +- trunk/drivers/usb/input/hiddev.c | 72 +- trunk/drivers/usb/input/usbtouchscreen.c | 2 +- trunk/drivers/usb/input/yealink.c | 12 +- trunk/drivers/usb/misc/cypress_cy7c63.c | 11 +- trunk/drivers/usb/misc/sisusbvga/sisusb.c | 2 - trunk/drivers/usb/misc/usbtest.c | 5 +- trunk/drivers/usb/net/pegasus.h | 3 - trunk/drivers/usb/net/rtl8150.c | 84 +- trunk/drivers/usb/serial/Kconfig | 24 +- trunk/drivers/usb/serial/Makefile | 1 + trunk/drivers/usb/serial/anydata.c | 123 + trunk/drivers/usb/serial/ftdi_sio.c | 4 - trunk/drivers/usb/serial/ftdi_sio.h | 15 - trunk/drivers/usb/serial/ipaq.c | 3 - trunk/drivers/usb/serial/option.c | 76 +- trunk/drivers/usb/serial/pl2303.c | 2 +- trunk/drivers/usb/serial/pl2303.h | 8 +- trunk/drivers/usb/serial/usb-serial.c | 4 +- trunk/drivers/usb/storage/unusual_devs.h | 65 +- trunk/drivers/usb/storage/usb.c | 13 +- trunk/drivers/video/Kconfig | 40 +- trunk/drivers/video/Makefile | 1 - trunk/drivers/video/S3triofb.c | 12 +- trunk/drivers/video/aty/aty128fb.c | 31 +- trunk/drivers/video/aty/atyfb_base.c | 22 +- trunk/drivers/video/aty/radeon_backlight.c | 4 +- trunk/drivers/video/aty/radeon_base.c | 26 +- trunk/drivers/video/aty/radeon_monitor.c | 12 +- trunk/drivers/video/aty/radeon_pm.c | 150 +- trunk/drivers/video/aty/radeonfb.h | 6 +- trunk/drivers/video/au1100fb.c | 18 +- trunk/drivers/video/backlight/Kconfig | 4 +- trunk/drivers/video/console/fbcon.c | 4 +- trunk/drivers/video/console/mdacon.c | 4 +- trunk/drivers/video/fb_notify.c | 46 - trunk/drivers/video/fbmem.c | 54 +- trunk/drivers/video/imacfb.c | 49 +- trunk/drivers/video/matrox/g450_pll.c | 8 - trunk/drivers/video/nvidia/nv_backlight.c | 18 +- trunk/drivers/video/nvidia/nv_of.c | 12 +- trunk/drivers/video/nvidia/nvidia.c | 9 +- trunk/drivers/video/offb.c | 307 +- trunk/drivers/video/riva/fbdev.c | 34 +- trunk/fs/9p/conv.c | 6 +- trunk/fs/9p/vfs_inode.c | 6 +- trunk/fs/Kconfig | 8 +- trunk/fs/adfs/super.c | 2 +- trunk/fs/befs/linuxvfs.c | 11 +- trunk/fs/block_dev.c | 114 +- trunk/fs/buffer.c | 7 +- trunk/fs/cifs/CHANGES | 15 - trunk/fs/cifs/README | 2 +- trunk/fs/cifs/cifs_fs_sb.h | 2 - trunk/fs/cifs/cifsencrypt.c | 3 +- trunk/fs/cifs/cifsfs.c | 8 +- trunk/fs/cifs/cifsfs.h | 2 +- trunk/fs/cifs/cifsglob.h | 18 +- trunk/fs/cifs/cifspdu.h | 2 - trunk/fs/cifs/cifsproto.h | 4 - trunk/fs/cifs/cifssmb.c | 28 +- trunk/fs/cifs/connect.c | 79 +- trunk/fs/cifs/dir.c | 27 +- trunk/fs/cifs/file.c | 98 +- trunk/fs/cifs/netmisc.c | 1 - trunk/fs/cifs/readdir.c | 13 +- trunk/fs/cifs/sess.c | 2 +- trunk/fs/cifs/smberr.h | 1 - trunk/fs/cifs/transport.c | 618 +-- trunk/fs/cifs/xattr.c | 8 +- trunk/fs/coda/file.c | 4 +- trunk/fs/configfs/dir.c | 32 +- trunk/fs/dcache.c | 164 +- trunk/fs/efs/symlink.c | 3 +- trunk/fs/eventpoll.c | 4 +- trunk/fs/exec.c | 10 +- trunk/fs/ext2/balloc.c | 1 + trunk/fs/ext2/ialloc.c | 1 + trunk/fs/ext2/super.c | 43 +- trunk/fs/ext3/balloc.c | 6 +- trunk/fs/ext3/inode.c | 32 +- trunk/fs/ext3/namei.c | 15 +- trunk/fs/ext3/super.c | 42 - trunk/fs/freevxfs/vxfs_lookup.c | 2 - trunk/fs/fuse/control.c | 4 +- trunk/fs/fuse/dir.c | 47 +- trunk/fs/fuse/file.c | 10 +- trunk/fs/fuse/fuse_i.h | 2 +- trunk/fs/fuse/inode.c | 2 +- trunk/fs/inotify_user.c | 2 +- trunk/fs/ioprio.c | 30 +- trunk/fs/jbd/commit.c | 6 +- trunk/fs/jbd/journal.c | 92 +- trunk/fs/jbd/transaction.c | 11 +- trunk/fs/jffs2/jffs2_fs_i.h | 4 + trunk/fs/jffs2/nodelist.c | 6 +- trunk/fs/jffs2/nodelist.h | 1 + trunk/fs/jffs2/summary.c | 5 - trunk/fs/jffs2/xattr.c | 1 + trunk/fs/jfs/inode.c | 16 +- trunk/fs/jfs/jfs_inode.h | 1 - trunk/fs/jfs/super.c | 118 +- trunk/fs/lockd/clntproc.c | 10 +- trunk/fs/lockd/host.c | 51 +- trunk/fs/lockd/mon.c | 41 +- trunk/fs/lockd/svclock.c | 12 +- trunk/fs/lockd/svcsubs.c | 15 +- trunk/fs/locks.c | 6 +- trunk/fs/minix/inode.c | 13 +- trunk/fs/namei.c | 19 +- trunk/fs/nfs/Makefile | 6 +- trunk/fs/nfs/callback.c | 31 +- trunk/fs/nfs/callback.h | 7 +- trunk/fs/nfs/callback_proc.c | 13 +- trunk/fs/nfs/client.c | 1448 ------ trunk/fs/nfs/delegation.c | 35 +- trunk/fs/nfs/delegation.h | 10 +- trunk/fs/nfs/dir.c | 338 +- trunk/fs/nfs/direct.c | 50 +- trunk/fs/nfs/file.c | 12 +- trunk/fs/nfs/getroot.c | 311 -- trunk/fs/nfs/idmap.c | 49 +- trunk/fs/nfs/inode.c | 46 +- trunk/fs/nfs/internal.h | 105 +- trunk/fs/nfs/mount_clnt.c | 30 +- trunk/fs/nfs/namespace.c | 38 +- trunk/fs/nfs/nfs2xdr.c | 21 +- trunk/fs/nfs/nfs3proc.c | 42 +- trunk/fs/nfs/nfs3xdr.c | 7 +- trunk/fs/nfs/nfs4_fs.h | 78 +- trunk/fs/nfs/nfs4namespace.c | 118 +- trunk/fs/nfs/nfs4proc.c | 253 +- trunk/fs/nfs/nfs4renewd.c | 20 +- trunk/fs/nfs/nfs4state.c | 174 +- trunk/fs/nfs/nfs4xdr.c | 71 +- trunk/fs/nfs/proc.c | 41 +- trunk/fs/nfs/read.c | 76 +- trunk/fs/nfs/super.c | 1411 ++++-- trunk/fs/nfs/write.c | 54 +- trunk/fs/nfsd/nfs4callback.c | 66 +- trunk/fs/nfsd/nfs4recover.c | 21 +- trunk/fs/nfsd/nfsfh.c | 20 +- trunk/fs/ocfs2/Makefile | 1 - trunk/fs/ocfs2/alloc.c | 28 +- trunk/fs/ocfs2/aops.c | 83 +- trunk/fs/ocfs2/buffer_head_io.c | 95 +- trunk/fs/ocfs2/buffer_head_io.h | 2 +- trunk/fs/ocfs2/cluster/heartbeat.c | 8 +- trunk/fs/ocfs2/dir.c | 28 +- trunk/fs/ocfs2/dlm/dlmast.c | 10 +- trunk/fs/ocfs2/dlm/dlmmaster.c | 1 + trunk/fs/ocfs2/dlm/dlmunlock.c | 43 +- trunk/fs/ocfs2/dlmglue.c | 9 +- trunk/fs/ocfs2/dlmglue.h | 5 +- trunk/fs/ocfs2/file.c | 3 - trunk/fs/ocfs2/inode.c | 32 +- trunk/fs/ocfs2/inode.h | 3 - trunk/fs/ocfs2/ioctl.c | 136 - trunk/fs/ocfs2/ioctl.h | 16 - trunk/fs/ocfs2/localalloc.c | 8 - trunk/fs/ocfs2/namei.c | 32 +- trunk/fs/ocfs2/ocfs2.h | 2 +- trunk/fs/ocfs2/ocfs2_fs.h | 24 +- trunk/fs/ocfs2/suballoc.c | 261 +- trunk/fs/ocfs2/suballoc.h | 2 - trunk/fs/ocfs2/super.c | 8 +- trunk/fs/ocfs2/uptodate.c | 21 +- trunk/fs/ocfs2/uptodate.h | 2 - trunk/fs/partitions/Kconfig | 2 +- trunk/fs/partitions/sun.c | 2 +- trunk/fs/proc/proc_misc.c | 2 +- trunk/fs/reiserfs/file.c | 2 +- trunk/fs/reiserfs/inode.c | 26 +- trunk/fs/reiserfs/ioctl.c | 2 +- trunk/fs/reiserfs/xattr.c | 2 +- trunk/fs/super.c | 1 - trunk/fs/udf/ialloc.c | 11 +- trunk/fs/udf/super.c | 9 +- trunk/fs/udf/truncate.c | 64 +- trunk/fs/ufs/balloc.c | 2 +- trunk/fs/ufs/inode.c | 35 +- trunk/fs/ufs/namei.c | 3 +- trunk/fs/ufs/truncate.c | 77 +- trunk/fs/ufs/util.c | 17 +- trunk/fs/xfs/linux-2.6/xfs_aops.c | 18 +- trunk/fs/xfs/linux-2.6/xfs_buf.h | 4 +- trunk/fs/xfs/linux-2.6/xfs_lrw.c | 27 +- trunk/fs/xfs/linux-2.6/xfs_super.c | 7 - trunk/fs/xfs/quota/xfs_qm_bhv.c | 21 +- trunk/fs/xfs/xfs_alloc.c | 103 +- trunk/fs/xfs/xfs_alloc.h | 20 - trunk/fs/xfs/xfs_bmap.c | 2 +- trunk/fs/xfs/xfs_fsops.c | 16 +- trunk/fs/xfs/xfs_inode.c | 17 +- trunk/fs/xfs/xfs_log.c | 12 +- trunk/fs/xfs/xfs_mount.c | 32 +- trunk/fs/xfs/xfs_vfsops.c | 5 +- trunk/include/Kbuild | 11 +- trunk/include/asm-alpha/Kbuild | 10 +- trunk/include/asm-alpha/compiler.h | 3 - trunk/include/asm-alpha/page.h | 6 +- .../include/asm-arm/arch-iop3xx/iop331-irqs.h | 4 + trunk/include/asm-arm/arch-omap/clock.h | 2 + trunk/include/asm-arm/arch-pxa/ssp.h | 4 +- .../asm-arm/arch-s3c2410/anubis-cpld.h | 3 + .../include/asm-arm/arch-s3c2410/anubis-irq.h | 4 +- .../include/asm-arm/arch-s3c2410/anubis-map.h | 2 + trunk/include/asm-arm/arch-s3c2410/audio.h | 4 + .../include/asm-arm/arch-s3c2410/bast-cpld.h | 5 + trunk/include/asm-arm/arch-s3c2410/bast-irq.h | 6 +- trunk/include/asm-arm/arch-s3c2410/bast-map.h | 4 + trunk/include/asm-arm/arch-s3c2410/bast-pmu.h | 3 + .../asm-arm/arch-s3c2410/debug-macro.S | 3 + trunk/include/asm-arm/arch-s3c2410/dma.h | 151 +- trunk/include/asm-arm/arch-s3c2410/fb.h | 7 + trunk/include/asm-arm/arch-s3c2410/hardware.h | 10 + trunk/include/asm-arm/arch-s3c2410/idle.h | 4 + trunk/include/asm-arm/arch-s3c2410/iic.h | 4 + trunk/include/asm-arm/arch-s3c2410/io.h | 8 +- trunk/include/asm-arm/arch-s3c2410/irqs.h | 9 +- trunk/include/asm-arm/arch-s3c2410/map.h | 7 + trunk/include/asm-arm/arch-s3c2410/memory.h | 14 +- trunk/include/asm-arm/arch-s3c2410/nand.h | 3 + .../include/asm-arm/arch-s3c2410/osiris-map.h | 2 + trunk/include/asm-arm/arch-s3c2410/regs-adc.h | 3 + .../include/asm-arm/arch-s3c2410/regs-clock.h | 12 + .../include/asm-arm/arch-s3c2410/regs-gpio.h | 15 + .../include/asm-arm/arch-s3c2410/regs-gpioj.h | 4 + trunk/include/asm-arm/arch-s3c2410/regs-iic.h | 4 + trunk/include/asm-arm/arch-s3c2410/regs-iis.h | 12 +- trunk/include/asm-arm/arch-s3c2410/regs-irq.h | 9 +- trunk/include/asm-arm/arch-s3c2410/regs-lcd.h | 8 + trunk/include/asm-arm/arch-s3c2410/regs-mem.h | 6 + .../include/asm-arm/arch-s3c2410/regs-nand.h | 4 + .../include/asm-arm/arch-s3c2410/regs-power.h | 34 - trunk/include/asm-arm/arch-s3c2410/regs-rtc.h | 7 +- trunk/include/asm-arm/arch-s3c2410/regs-sdi.h | 5 + .../asm-arm/arch-s3c2410/regs-serial.h | 5 +- trunk/include/asm-arm/arch-s3c2410/regs-spi.h | 8 +- .../include/asm-arm/arch-s3c2410/regs-timer.h | 7 + trunk/include/asm-arm/arch-s3c2410/regs-udc.h | 8 +- .../asm-arm/arch-s3c2410/regs-watchdog.h | 7 +- trunk/include/asm-arm/arch-s3c2410/system.h | 9 +- trunk/include/asm-arm/arch-s3c2410/timex.h | 6 + .../include/asm-arm/arch-s3c2410/uncompress.h | 9 + .../asm-arm/arch-s3c2410/usb-control.h | 5 + trunk/include/asm-arm/arch-s3c2410/vmalloc.h | 6 +- .../asm-arm/arch-s3c2410/vr1000-cpld.h | 4 + .../include/asm-arm/arch-s3c2410/vr1000-irq.h | 6 +- .../include/asm-arm/arch-s3c2410/vr1000-map.h | 6 + trunk/include/asm-arm/cacheflush.h | 18 +- trunk/include/asm-arm/elf.h | 2 - trunk/include/asm-arm/hardware/ssp.h | 4 +- trunk/include/asm-arm/io.h | 7 - trunk/include/asm-arm/page.h | 4 +- trunk/include/asm-arm/procinfo.h | 1 - trunk/include/asm-arm/spinlock.h | 16 +- trunk/include/asm-generic/Kbuild | 15 +- trunk/include/asm-generic/Kbuild.asm | 38 +- trunk/include/asm-generic/audit_change_attr.h | 4 - trunk/include/asm-generic/audit_dir_write.h | 4 - trunk/include/asm-generic/audit_read.h | 8 - trunk/include/asm-generic/audit_write.h | 11 - trunk/include/asm-i386/Kbuild | 9 +- trunk/include/asm-i386/alternative.h | 20 + trunk/include/asm-i386/elf.h | 10 +- trunk/include/asm-i386/kprobes.h | 1 - .../asm-i386/mach-default/mach_mpspec.h | 4 - trunk/include/asm-i386/mmzone.h | 2 +- trunk/include/asm-i386/rwlock.h | 28 +- trunk/include/asm-i386/setup.h | 2 - trunk/include/asm-i386/signal.h | 4 +- trunk/include/asm-i386/spinlock.h | 17 +- trunk/include/asm-i386/system.h | 8 +- trunk/include/asm-i386/unwind.h | 1 - trunk/include/asm-ia64/Kbuild | 16 +- trunk/include/asm-ia64/kprobes.h | 1 - trunk/include/asm-ia64/meminit.h | 7 +- trunk/include/asm-ia64/mman.h | 8 - trunk/include/asm-ia64/page.h | 4 +- trunk/include/asm-ia64/pal.h | 7 +- trunk/include/asm-ia64/ptrace.h | 10 +- trunk/include/asm-ia64/sn/sn_sal.h | 6 + trunk/include/asm-ia64/sn/xp.h | 22 +- trunk/include/asm-ia64/sn/xpc.h | 8 +- trunk/include/asm-ia64/system.h | 2 +- trunk/include/asm-ia64/unistd.h | 3 +- trunk/include/asm-ia64/ustack.h | 7 +- trunk/include/asm-m68k/page.h | 8 +- trunk/include/asm-mips/page.h | 8 +- trunk/include/asm-parisc/page.h | 18 +- trunk/include/asm-powerpc/Kbuild | 45 +- trunk/include/asm-powerpc/backlight.h | 4 - trunk/include/asm-powerpc/cputable.h | 27 +- trunk/include/asm-powerpc/eeh.h | 3 - trunk/include/asm-powerpc/futex.h | 28 +- trunk/include/asm-powerpc/hvcall.h | 121 +- trunk/include/asm-powerpc/ibmebus.h | 2 +- trunk/include/asm-powerpc/ide.h | 12 +- trunk/include/asm-powerpc/io.h | 221 +- trunk/include/asm-powerpc/ipic.h | 12 +- trunk/include/asm-powerpc/irq.h | 24 +- .../include/asm-powerpc/iseries/hv_call_xm.h | 17 + .../asm-powerpc/iseries/hv_lp_config.h | 13 +- .../include/asm-powerpc/iseries/iseries_io.h | 60 + .../asm-powerpc}/iseries/it_exp_vpd_panel.h | 6 +- .../asm-powerpc}/iseries/it_lp_naca.h | 6 +- .../include/asm-powerpc/iseries/it_lp_queue.h | 2 + trunk/include/asm-powerpc/iseries/vio.h | 28 - trunk/include/asm-powerpc/kdump.h | 2 +- trunk/include/asm-powerpc/kexec.h | 3 +- trunk/include/asm-powerpc/kprobes.h | 1 - trunk/include/asm-powerpc/lppaca.h | 23 +- trunk/include/asm-powerpc/mpc86xx.h | 3 + trunk/include/asm-powerpc/mpic.h | 125 - trunk/include/asm-powerpc/paca.h | 4 - trunk/include/asm-powerpc/page.h | 6 + trunk/include/asm-powerpc/pgalloc.h | 2 +- trunk/include/asm-powerpc/ppc-pci.h | 11 - trunk/include/asm-powerpc/processor.h | 1 - trunk/include/asm-powerpc/prom.h | 40 +- trunk/include/asm-powerpc/ptrace.h | 4 + trunk/include/asm-powerpc/reg.h | 1 - trunk/include/asm-powerpc/rtas.h | 17 - trunk/include/asm-powerpc/smu.h | 2 +- trunk/include/asm-powerpc/spinlock.h | 17 - trunk/include/asm-powerpc/spu.h | 2 +- trunk/include/asm-powerpc/system.h | 14 +- trunk/include/asm-powerpc/time.h | 4 + trunk/include/asm-powerpc/tsi108.h | 14 +- trunk/include/asm-powerpc/tsi108_irq.h | 124 - trunk/include/asm-powerpc/vio.h | 4 +- trunk/include/asm-ppc/cpm2.h | 95 - trunk/include/asm-ppc/ibm4xx.h | 2 +- trunk/include/asm-ppc/io.h | 46 +- trunk/include/asm-ppc/mpc8260.h | 1 - trunk/include/asm-ppc/mpc8260_pci9.h | 4 + trunk/include/asm-ppc/mpc8xx.h | 1 - trunk/include/asm-ppc/reg_booke.h | 16 +- trunk/include/asm-s390/Kbuild | 12 +- trunk/include/asm-s390/appldata.h | 90 - trunk/include/asm-s390/cio.h | 7 - trunk/include/asm-s390/debug.h | 2 +- trunk/include/asm-s390/dma.h | 2 +- trunk/include/asm-s390/elf.h | 28 +- trunk/include/asm-s390/futex.h | 87 +- trunk/include/asm-s390/io.h | 2 +- trunk/include/asm-s390/kdebug.h | 59 - trunk/include/asm-s390/kprobes.h | 114 - trunk/include/asm-s390/lowcore.h | 14 +- trunk/include/asm-s390/monwriter.h | 33 - trunk/include/asm-s390/pgalloc.h | 67 +- trunk/include/asm-s390/pgtable.h | 124 +- trunk/include/asm-s390/processor.h | 17 - trunk/include/asm-s390/setup.h | 66 +- trunk/include/asm-s390/smp.h | 2 +- trunk/include/asm-s390/uaccess.h | 172 +- trunk/include/asm-s390/unistd.h | 170 +- trunk/include/asm-s390/z90crypt.h | 212 + trunk/include/asm-s390/zcrypt.h | 285 -- trunk/include/asm-sh/page.h | 2 +- trunk/include/asm-sh64/bug.h | 16 +- trunk/include/asm-sh64/byteorder.h | 4 +- trunk/include/asm-sh64/dma-mapping.h | 16 +- trunk/include/asm-sh64/io.h | 7 - trunk/include/asm-sh64/ptrace.h | 2 +- trunk/include/asm-sh64/system.h | 2 +- trunk/include/asm-sh64/uaccess.h | 19 +- trunk/include/asm-sparc/Kbuild | 24 +- trunk/include/asm-sparc/mman.h | 8 - trunk/include/asm-sparc64/Kbuild | 27 +- trunk/include/asm-sparc64/kprobes.h | 1 - trunk/include/asm-sparc64/mman.h | 8 - trunk/include/asm-sparc64/pgtable.h | 4 +- trunk/include/asm-sparc64/sfp-machine.h | 2 +- trunk/include/asm-x86_64/Kbuild | 18 +- trunk/include/asm-x86_64/alternative.h | 21 +- trunk/include/asm-x86_64/calgary.h | 5 + trunk/include/asm-x86_64/elf.h | 20 +- trunk/include/asm-x86_64/kprobes.h | 1 - trunk/include/asm-x86_64/page.h | 2 +- trunk/include/asm-x86_64/processor.h | 6 - trunk/include/asm-x86_64/signal.h | 2 +- trunk/include/asm-x86_64/spinlock.h | 11 +- trunk/include/asm-x86_64/swiotlb.h | 2 - trunk/include/asm-x86_64/unistd.h | 11 +- trunk/include/asm-x86_64/unwind.h | 1 - trunk/include/asm-x86_64/vsyscall.h | 3 +- trunk/include/crypto/algapi.h | 156 - trunk/include/crypto/twofish.h | 22 - trunk/include/linux/Kbuild | 400 +- trunk/include/linux/atmdev.h | 2 +- trunk/include/linux/audit.h | 54 +- trunk/include/linux/blkdev.h | 1 - trunk/include/linux/bootmem.h | 2 +- trunk/include/linux/byteorder/Kbuild | 9 +- trunk/include/linux/cn_proc.h | 3 +- trunk/include/linux/compat_ioctl.h | 1 - trunk/include/linux/crypto.h | 689 +-- trunk/include/linux/dcache.h | 1 - trunk/include/linux/dccp.h | 2 - trunk/include/linux/debug_locks.h | 2 - trunk/include/linux/delayacct.h | 16 +- trunk/include/linux/dvb/Kbuild | 11 +- trunk/include/linux/ext3_fs.h | 9 - trunk/include/linux/fb.h | 4 +- trunk/include/linux/fib_rules.h | 65 - trunk/include/linux/filter.h | 13 +- trunk/include/linux/fs.h | 3 +- trunk/include/linux/fs_enet_pd.h | 50 +- trunk/include/linux/fsnotify.h | 6 +- trunk/include/linux/futex.h | 3 +- trunk/include/linux/genetlink.h | 18 - trunk/include/linux/hrtimer.h | 1 - trunk/include/linux/ide.h | 1 - trunk/include/linux/if.h | 129 - trunk/include/linux/if_addr.h | 55 - trunk/include/linux/if_vlan.h | 5 - trunk/include/linux/in.h | 4 +- trunk/include/linux/in6.h | 2 - trunk/include/linux/inet.h | 2 - trunk/include/linux/input.h | 24 +- trunk/include/linux/ioprio.h | 23 +- trunk/include/linux/ip.h | 1 - trunk/include/linux/ipv6.h | 31 - trunk/include/linux/irq.h | 5 +- trunk/include/linux/jbd.h | 3 - trunk/include/linux/jiffies.h | 4 +- trunk/include/linux/kernel.h | 3 +- trunk/include/linux/kobject.h | 2 + trunk/include/linux/ktime.h | 7 +- trunk/include/linux/libata.h | 4 +- trunk/include/linux/lockd/lockd.h | 1 + trunk/include/linux/mm.h | 2 - trunk/include/linux/mmc/host.h | 2 +- trunk/include/linux/mmc/mmc.h | 2 - trunk/include/linux/mmzone.h | 1 - trunk/include/linux/mod_devicetable.h | 11 - trunk/include/linux/mtd/cfi.h | 13 - trunk/include/linux/neighbour.h | 159 - trunk/include/linux/net.h | 28 +- trunk/include/linux/netdevice.h | 31 +- trunk/include/linux/netfilter.h | 6 - trunk/include/linux/netfilter/Kbuild | 47 +- .../linux/netfilter/nf_conntrack_common.h | 4 - .../linux/netfilter/nf_conntrack_tcp.h | 1 - trunk/include/linux/netfilter/nfnetlink.h | 4 +- trunk/include/linux/netfilter/nfnetlink_log.h | 6 +- .../include/linux/netfilter/nfnetlink_queue.h | 8 +- trunk/include/linux/netfilter/x_tables.h | 52 +- trunk/include/linux/netfilter/xt_DSCP.h | 20 - trunk/include/linux/netfilter/xt_dscp.h | 23 - trunk/include/linux/netfilter_arp/Kbuild | 5 +- .../include/linux/netfilter_arp/arp_tables.h | 3 +- trunk/include/linux/netfilter_bridge.h | 33 +- trunk/include/linux/netfilter_bridge/Kbuild | 21 +- trunk/include/linux/netfilter_ipv4/Kbuild | 82 +- .../netfilter_ipv4/ip_conntrack_helper.h | 2 - .../linux/netfilter_ipv4/ip_conntrack_pptp.h | 45 +- .../netfilter_ipv4/ip_conntrack_proto_gre.h | 22 +- trunk/include/linux/netfilter_ipv4/ip_nat.h | 4 + .../linux/netfilter_ipv4/ip_nat_core.h | 8 +- .../linux/netfilter_ipv4/ip_nat_pptp.h | 4 +- .../include/linux/netfilter_ipv4/ip_tables.h | 3 +- trunk/include/linux/netfilter_ipv4/ipt_DSCP.h | 6 +- trunk/include/linux/netfilter_ipv4/ipt_dscp.h | 14 +- trunk/include/linux/netfilter_ipv4/listhelp.h | 123 + trunk/include/linux/netfilter_ipv6.h | 1 - trunk/include/linux/netfilter_ipv6/Kbuild | 27 +- .../include/linux/netfilter_ipv6/ip6_tables.h | 3 +- trunk/include/linux/netfilter_logging.h | 33 + trunk/include/linux/nfs_fs.h | 77 +- trunk/include/linux/nfs_fs_sb.h | 89 +- trunk/include/linux/nfs_idmap.h | 14 +- trunk/include/linux/nfs_xdr.h | 35 +- trunk/include/linux/nfsd/Kbuild | 9 +- trunk/include/linux/node.h | 10 +- trunk/include/linux/pci_ids.h | 7 - trunk/include/linux/phy.h | 1 - trunk/include/linux/pkt_cls.h | 1 - trunk/include/linux/pmu.h | 3 +- trunk/include/linux/raid/Kbuild | 3 +- trunk/include/linux/rtnetlink.h | 376 +- trunk/include/linux/scatterlist.h | 4 +- trunk/include/linux/sched.h | 9 +- trunk/include/linux/security.h | 279 +- trunk/include/linux/skbuff.h | 69 +- trunk/include/linux/snmp.h | 35 +- trunk/include/linux/sunrpc/Kbuild | 2 +- trunk/include/linux/sunrpc/clnt.h | 57 +- trunk/include/linux/sunrpc/gss_krb5.h | 19 +- trunk/include/linux/sunrpc/gss_spkm3.h | 4 +- trunk/include/linux/sunrpc/rpc_pipe_fs.h | 6 +- trunk/include/linux/sunrpc/sched.h | 5 + trunk/include/linux/sunrpc/xprt.h | 56 +- trunk/include/linux/sysctl.h | 5 - trunk/include/linux/tc_act/Kbuild | 5 +- trunk/include/linux/tc_ematch/Kbuild | 5 +- trunk/include/linux/timex.h | 3 +- trunk/include/linux/tty.h | 1 - trunk/include/linux/usb.h | 7 +- trunk/include/linux/usb_usual.h | 4 +- trunk/include/linux/videodev.h | 6 +- trunk/include/linux/videodev2.h | 4 +- trunk/include/linux/vmstat.h | 8 +- trunk/include/linux/vt.h | 1 - trunk/include/linux/writeback.h | 1 - trunk/include/linux/xfrm.h | 36 +- trunk/include/media/v4l2-dev.h | 16 +- trunk/include/mtd/Kbuild | 8 +- trunk/include/mtd/mtd-abi.h | 1 - trunk/include/net/act_api.h | 136 +- trunk/include/net/act_generic.h | 142 + trunk/include/net/addrconf.h | 13 +- trunk/include/net/af_unix.h | 6 +- trunk/include/net/ah.h | 30 +- trunk/include/net/cipso_ipv4.h | 246 - trunk/include/net/dn_fib.h | 18 +- trunk/include/net/dst.h | 1 - trunk/include/net/esp.h | 36 +- trunk/include/net/fib_rules.h | 97 - trunk/include/net/flow.h | 16 +- trunk/include/net/genetlink.h | 7 +- trunk/include/net/if_inet6.h | 1 - trunk/include/net/inet_connection_sock.h | 3 +- trunk/include/net/inet_hashtables.h | 48 +- trunk/include/net/inet_sock.h | 6 +- trunk/include/net/ip6_fib.h | 113 +- trunk/include/net/ip6_route.h | 49 +- trunk/include/net/ip_fib.h | 104 +- trunk/include/net/ipcomp.h | 5 +- trunk/include/net/ipv6.h | 8 +- trunk/include/net/mip6.h | 61 - trunk/include/net/neighbour.h | 42 +- trunk/include/net/netdma.h | 2 +- trunk/include/net/netevent.h | 33 - trunk/include/net/netlabel.h | 292 -- trunk/include/net/netlink.h | 124 +- trunk/include/net/nexthop.h | 33 - trunk/include/net/pkt_act.h | 273 ++ trunk/include/net/red.h | 2 +- trunk/include/net/request_sock.h | 1 - trunk/include/net/route.h | 3 - trunk/include/net/scm.h | 29 +- trunk/include/net/sctp/constants.h | 17 +- trunk/include/net/sctp/sctp.h | 81 +- trunk/include/net/sctp/sm.h | 3 +- trunk/include/net/sctp/structs.h | 15 +- trunk/include/net/snmp.h | 6 + trunk/include/net/sock.h | 48 +- trunk/include/net/tc_act/tc_defact.h | 13 +- trunk/include/net/tc_act/tc_gact.h | 18 +- trunk/include/net/tc_act/tc_ipt.h | 15 +- trunk/include/net/tc_act/tc_mirred.h | 17 +- trunk/include/net/tc_act/tc_pedit.h | 15 +- trunk/include/net/tcp.h | 3 - trunk/include/net/udp.h | 18 +- trunk/include/net/xfrm.h | 212 +- trunk/include/rdma/Kbuild | 2 +- trunk/include/rdma/ib_addr.h | 17 +- trunk/include/rdma/ib_sa.h | 45 +- trunk/include/rdma/ib_user_verbs.h | 2 - trunk/include/rdma/ib_verbs.h | 31 +- trunk/include/rdma/iw_cm.h | 258 - trunk/include/rdma/rdma_cm.h | 12 - trunk/include/scsi/Kbuild | 4 +- trunk/include/scsi/libiscsi.h | 19 +- trunk/include/scsi/scsi_transport_iscsi.h | 4 + trunk/include/sound/Kbuild | 12 +- trunk/include/sound/ac97_codec.h | 32 - trunk/include/sound/ad1848.h | 22 +- trunk/include/sound/ak4xxx-adda.h | 37 +- trunk/include/sound/asound.h | 19 +- trunk/include/sound/control.h | 13 - trunk/include/sound/core.h | 10 +- trunk/include/sound/emu10k1.h | 4 - trunk/include/sound/info.h | 7 +- trunk/include/sound/pcm.h | 4 +- trunk/include/sound/timer.h | 1 + trunk/include/sound/tlv.h | 60 - trunk/include/sound/vx_core.h | 1 - trunk/include/video/Kbuild | 2 +- trunk/init/Kconfig | 56 +- trunk/ipc/msg.c | 389 +- trunk/kernel/audit.c | 10 +- trunk/kernel/audit.h | 1 - trunk/kernel/auditfilter.c | 63 +- trunk/kernel/auditsc.c | 168 +- trunk/kernel/cpuset.c | 35 +- trunk/kernel/delayacct.c | 24 +- trunk/kernel/exit.c | 3 +- trunk/kernel/fork.c | 10 +- trunk/kernel/futex.c | 224 +- trunk/kernel/futex_compat.c | 34 +- trunk/kernel/hrtimer.c | 6 +- trunk/kernel/irq/chip.c | 6 +- trunk/kernel/irq/handle.c | 5 - trunk/kernel/irq/manage.c | 28 +- trunk/kernel/irq/resend.c | 3 +- trunk/kernel/kmod.c | 5 +- trunk/kernel/kprobes.c | 1 - trunk/kernel/lockdep_internals.h | 2 +- trunk/kernel/panic.c | 3 +- trunk/kernel/power/Kconfig | 6 +- trunk/kernel/power/process.c | 26 +- trunk/kernel/printk.c | 4 +- trunk/kernel/rcupdate.c | 10 +- trunk/kernel/resource.c | 9 +- trunk/kernel/rtmutex.c | 2 - trunk/kernel/sched.c | 26 +- trunk/kernel/signal.c | 25 +- trunk/kernel/softirq.c | 22 +- trunk/kernel/softlockup.c | 4 +- trunk/kernel/spinlock.c | 2 +- trunk/kernel/stop_machine.c | 1 + trunk/kernel/taskstats.c | 34 +- trunk/kernel/timer.c | 49 +- trunk/kernel/workqueue.c | 91 +- trunk/lib/Kconfig | 5 - trunk/lib/Makefile | 1 - trunk/lib/audit.c | 55 - trunk/lib/kobject_uevent.c | 4 + trunk/lib/spinlock_debug.c | 10 +- trunk/lib/ts_bm.c | 11 +- trunk/lib/zlib_inflate/inflate.c | 5 +- trunk/mm/fadvise.c | 3 +- trunk/mm/filemap.c | 2 + trunk/mm/memory_hotplug.c | 44 +- trunk/mm/mempolicy.c | 10 +- trunk/mm/mempool.c | 9 +- trunk/mm/mmap.c | 24 +- trunk/mm/page-writeback.c | 9 - trunk/mm/page_alloc.c | 2 +- trunk/mm/slab.c | 4 +- trunk/mm/swap.c | 20 - trunk/mm/swapfile.c | 3 +- trunk/mm/truncate.c | 11 +- trunk/mm/vmstat.c | 151 +- trunk/net/Kconfig | 7 +- trunk/net/Makefile | 1 - trunk/net/atm/atm_sysfs.c | 1 + trunk/net/atm/clip.c | 2 - trunk/net/atm/mpc.c | 11 + trunk/net/atm/mpc.h | 8 - trunk/net/atm/proc.c | 2 +- trunk/net/bridge/br_forward.c | 11 +- trunk/net/bridge/br_if.c | 7 +- trunk/net/bridge/br_netfilter.c | 50 +- trunk/net/bridge/br_netlink.c | 35 +- trunk/net/bridge/br_stp_bpdu.c | 2 +- trunk/net/bridge/netfilter/ebt_ulog.c | 3 - trunk/net/bridge/netfilter/ebtables.c | 97 +- trunk/net/core/Makefile | 3 +- trunk/net/core/datagram.c | 4 +- trunk/net/core/dev.c | 74 +- trunk/net/core/dev_mcast.c | 3 +- trunk/net/core/dst.c | 3 +- trunk/net/core/fib_rules.c | 421 -- trunk/net/core/filter.c | 8 +- trunk/net/core/flow.c | 13 +- trunk/net/core/neighbour.c | 613 ++- trunk/net/core/netevent.c | 69 - trunk/net/core/netpoll.c | 2 +- trunk/net/core/pktgen.c | 8 +- trunk/net/core/rtnetlink.c | 583 ++- trunk/net/core/skbuff.c | 70 +- trunk/net/core/sock.c | 34 +- trunk/net/core/utils.c | 220 +- trunk/net/core/wireless.c | 26 +- trunk/net/dccp/ackvec.c | 20 +- trunk/net/dccp/ackvec.h | 4 +- trunk/net/dccp/ccids/Kconfig | 8 - trunk/net/dccp/ccids/ccid2.c | 204 +- trunk/net/dccp/ccids/ccid2.h | 9 +- trunk/net/dccp/ccids/ccid3.c | 153 +- trunk/net/dccp/ccids/ccid3.h | 9 +- trunk/net/dccp/ccids/lib/loss_interval.c | 36 +- trunk/net/dccp/ccids/lib/loss_interval.h | 9 +- trunk/net/dccp/ccids/lib/packet_history.c | 168 +- trunk/net/dccp/ccids/lib/packet_history.h | 17 +- trunk/net/dccp/ccids/lib/tfrc.h | 2 +- trunk/net/dccp/ccids/lib/tfrc_equation.c | 2 +- trunk/net/dccp/dccp.h | 12 +- trunk/net/dccp/feat.h | 5 - trunk/net/dccp/ipv4.c | 14 +- trunk/net/dccp/ipv6.c | 15 +- trunk/net/dccp/options.c | 2 +- trunk/net/dccp/output.c | 90 +- trunk/net/dccp/proto.c | 16 +- trunk/net/dccp/sysctl.c | 8 +- trunk/net/decnet/Kconfig | 1 - trunk/net/decnet/af_decnet.c | 1 - trunk/net/decnet/dn_dev.c | 29 +- trunk/net/decnet/dn_fib.c | 76 +- trunk/net/decnet/dn_nsp_in.c | 2 +- trunk/net/decnet/dn_route.c | 28 +- trunk/net/decnet/dn_rules.c | 511 +- trunk/net/decnet/dn_table.c | 163 +- trunk/net/ethernet/eth.c | 196 +- trunk/net/ieee80211/Kconfig | 1 - trunk/net/ieee80211/ieee80211_crypt_ccmp.c | 32 +- trunk/net/ieee80211/ieee80211_crypt_tkip.c | 59 +- trunk/net/ieee80211/ieee80211_crypt_wep.c | 25 +- .../ieee80211/softmac/ieee80211softmac_auth.c | 28 +- trunk/net/ipv4/Kconfig | 2 - trunk/net/ipv4/Makefile | 1 - trunk/net/ipv4/af_inet.c | 11 +- trunk/net/ipv4/ah4.c | 40 +- trunk/net/ipv4/cipso_ipv4.c | 1607 ------- trunk/net/ipv4/devinet.c | 246 +- trunk/net/ipv4/esp4.c | 100 +- trunk/net/ipv4/fib_frontend.c | 472 +- trunk/net/ipv4/fib_hash.c | 126 +- trunk/net/ipv4/fib_lookup.h | 13 +- trunk/net/ipv4/fib_rules.c | 620 ++- trunk/net/ipv4/fib_semantics.c | 518 +- trunk/net/ipv4/fib_trie.c | 118 +- trunk/net/ipv4/icmp.c | 16 +- trunk/net/ipv4/igmp.c | 44 +- trunk/net/ipv4/inet_connection_sock.c | 3 - trunk/net/ipv4/inet_hashtables.c | 33 +- trunk/net/ipv4/inetpeer.c | 5 +- trunk/net/ipv4/ip_fragment.c | 12 +- trunk/net/ipv4/ip_gre.c | 27 +- trunk/net/ipv4/ip_options.c | 20 +- trunk/net/ipv4/ip_output.c | 37 +- trunk/net/ipv4/ip_sockglue.c | 9 +- trunk/net/ipv4/ipcomp.c | 33 +- trunk/net/ipv4/ipconfig.c | 1 + trunk/net/ipv4/ipip.c | 22 +- trunk/net/ipv4/ipmr.c | 12 +- trunk/net/ipv4/ipvs/ip_vs_ftp.c | 27 +- trunk/net/ipv4/ipvs/ip_vs_proto_tcp.c | 8 +- trunk/net/ipv4/ipvs/ip_vs_proto_udp.c | 8 +- trunk/net/ipv4/netfilter.c | 2 +- trunk/net/ipv4/netfilter/Kconfig | 22 + trunk/net/ipv4/netfilter/Makefile | 2 + trunk/net/ipv4/netfilter/arp_tables.c | 48 +- trunk/net/ipv4/netfilter/arpt_mangle.c | 4 +- trunk/net/ipv4/netfilter/arptable_filter.c | 2 +- trunk/net/ipv4/netfilter/ip_conntrack_core.c | 215 +- .../ipv4/netfilter/ip_conntrack_helper_pptp.c | 516 +- .../ipv4/netfilter/ip_conntrack_netbios_ns.c | 1 - .../net/ipv4/netfilter/ip_conntrack_netlink.c | 93 +- .../netfilter/ip_conntrack_proto_generic.c | 2 +- .../ipv4/netfilter/ip_conntrack_proto_gre.c | 52 +- .../ipv4/netfilter/ip_conntrack_proto_icmp.c | 2 +- .../ipv4/netfilter/ip_conntrack_proto_sctp.c | 14 +- .../ipv4/netfilter/ip_conntrack_proto_tcp.c | 31 +- .../ipv4/netfilter/ip_conntrack_proto_udp.c | 7 +- trunk/net/ipv4/netfilter/ip_conntrack_sip.c | 3 +- .../ipv4/netfilter/ip_conntrack_standalone.c | 5 +- trunk/net/ipv4/netfilter/ip_nat_core.c | 56 +- trunk/net/ipv4/netfilter/ip_nat_helper.c | 63 +- trunk/net/ipv4/netfilter/ip_nat_helper_pptp.c | 188 +- trunk/net/ipv4/netfilter/ip_nat_proto_gre.c | 27 +- trunk/net/ipv4/netfilter/ip_nat_proto_icmp.c | 8 +- trunk/net/ipv4/netfilter/ip_nat_proto_tcp.c | 7 +- trunk/net/ipv4/netfilter/ip_nat_proto_udp.c | 15 +- trunk/net/ipv4/netfilter/ip_nat_rule.c | 14 +- trunk/net/ipv4/netfilter/ip_nat_standalone.c | 13 +- trunk/net/ipv4/netfilter/ip_queue.c | 16 +- trunk/net/ipv4/netfilter/ip_tables.c | 220 +- trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c | 7 +- trunk/net/ipv4/netfilter/ipt_DSCP.c | 96 + trunk/net/ipv4/netfilter/ipt_ECN.c | 48 +- trunk/net/ipv4/netfilter/ipt_LOG.c | 4 +- trunk/net/ipv4/netfilter/ipt_MASQUERADE.c | 4 +- trunk/net/ipv4/netfilter/ipt_NETMAP.c | 4 +- trunk/net/ipv4/netfilter/ipt_REDIRECT.c | 4 +- trunk/net/ipv4/netfilter/ipt_REJECT.c | 6 +- trunk/net/ipv4/netfilter/ipt_SAME.c | 7 +- trunk/net/ipv4/netfilter/ipt_TCPMSS.c | 135 +- trunk/net/ipv4/netfilter/ipt_TOS.c | 26 +- trunk/net/ipv4/netfilter/ipt_TTL.c | 12 +- trunk/net/ipv4/netfilter/ipt_ULOG.c | 8 +- trunk/net/ipv4/netfilter/ipt_ah.c | 1 + trunk/net/ipv4/netfilter/ipt_dscp.c | 54 + trunk/net/ipv4/netfilter/ipt_ecn.c | 3 +- trunk/net/ipv4/netfilter/ipt_hashlimit.c | 47 +- trunk/net/ipv4/netfilter/ipt_owner.c | 1 + trunk/net/ipv4/netfilter/ipt_recent.c | 13 +- trunk/net/ipv4/netfilter/iptable_filter.c | 4 +- trunk/net/ipv4/netfilter/iptable_mangle.c | 4 +- trunk/net/ipv4/netfilter/iptable_raw.c | 2 +- .../ipv4/netfilter/nf_conntrack_proto_icmp.c | 2 +- trunk/net/ipv4/proc.c | 2 - trunk/net/ipv4/raw.c | 4 +- trunk/net/ipv4/route.c | 176 +- trunk/net/ipv4/syncookies.c | 5 - trunk/net/ipv4/sysctl_net_ipv4.c | 35 - trunk/net/ipv4/tcp.c | 26 +- trunk/net/ipv4/tcp_bic.c | 2 +- trunk/net/ipv4/tcp_cong.c | 2 +- trunk/net/ipv4/tcp_cubic.c | 2 +- trunk/net/ipv4/tcp_highspeed.c | 2 +- trunk/net/ipv4/tcp_htcp.c | 2 +- trunk/net/ipv4/tcp_hybla.c | 2 +- trunk/net/ipv4/tcp_input.c | 52 +- trunk/net/ipv4/tcp_ipv4.c | 27 +- trunk/net/ipv4/tcp_lp.c | 38 +- trunk/net/ipv4/tcp_minisocks.c | 8 +- trunk/net/ipv4/tcp_output.c | 43 +- trunk/net/ipv4/tcp_probe.c | 5 +- trunk/net/ipv4/tcp_timer.c | 16 +- trunk/net/ipv4/tcp_vegas.c | 2 +- trunk/net/ipv4/tcp_veno.c | 3 +- trunk/net/ipv4/tcp_westwood.c | 2 +- trunk/net/ipv4/udp.c | 120 +- trunk/net/ipv4/xfrm4_input.c | 2 +- trunk/net/ipv4/xfrm4_mode_transport.c | 4 +- trunk/net/ipv4/xfrm4_mode_tunnel.c | 3 +- trunk/net/ipv4/xfrm4_output.c | 10 +- trunk/net/ipv4/xfrm4_policy.c | 26 +- trunk/net/ipv4/xfrm4_state.c | 84 + trunk/net/ipv4/xfrm4_tunnel.c | 2 +- trunk/net/ipv6/Kconfig | 45 - trunk/net/ipv6/Makefile | 4 - trunk/net/ipv6/addrconf.c | 693 +-- trunk/net/ipv6/af_inet6.c | 21 +- trunk/net/ipv6/ah6.c | 124 +- trunk/net/ipv6/anycast.c | 8 +- trunk/net/ipv6/datagram.c | 22 +- trunk/net/ipv6/esp6.c | 106 +- trunk/net/ipv6/exthdrs.c | 262 +- trunk/net/ipv6/fib6_rules.c | 305 -- trunk/net/ipv6/icmp.c | 48 +- trunk/net/ipv6/inet6_connection_sock.c | 3 +- trunk/net/ipv6/ip6_fib.c | 463 +- trunk/net/ipv6/ip6_input.c | 2 +- trunk/net/ipv6/ip6_output.c | 223 +- trunk/net/ipv6/ipcomp6.c | 32 +- trunk/net/ipv6/ipv6_sockglue.c | 14 +- trunk/net/ipv6/ipv6_syms.c | 3 +- trunk/net/ipv6/mcast.c | 12 +- trunk/net/ipv6/mip6.c | 519 -- trunk/net/ipv6/ndisc.c | 53 +- trunk/net/ipv6/netfilter.c | 2 +- trunk/net/ipv6/netfilter/Makefile | 2 +- trunk/net/ipv6/netfilter/ip6_queue.c | 16 +- trunk/net/ipv6/netfilter/ip6_tables.c | 58 +- trunk/net/ipv6/netfilter/ip6t_HL.c | 9 +- trunk/net/ipv6/netfilter/ip6t_LOG.c | 4 +- trunk/net/ipv6/netfilter/ip6t_REJECT.c | 9 +- trunk/net/ipv6/netfilter/ip6t_ah.c | 1 + trunk/net/ipv6/netfilter/ip6t_dst.c | 220 + trunk/net/ipv6/netfilter/ip6t_frag.c | 1 + trunk/net/ipv6/netfilter/ip6t_hbh.c | 49 +- trunk/net/ipv6/netfilter/ip6t_ipv6header.c | 1 + trunk/net/ipv6/netfilter/ip6t_owner.c | 1 + trunk/net/ipv6/netfilter/ip6t_rt.c | 1 + trunk/net/ipv6/netfilter/ip6table_filter.c | 4 +- trunk/net/ipv6/netfilter/ip6table_mangle.c | 12 +- trunk/net/ipv6/netfilter/ip6table_raw.c | 2 +- .../netfilter/nf_conntrack_l3proto_ipv6.c | 2 +- .../netfilter/nf_conntrack_proto_icmpv6.c | 2 +- trunk/net/ipv6/netfilter/nf_conntrack_reasm.c | 12 +- trunk/net/ipv6/raw.c | 51 +- trunk/net/ipv6/reassembly.c | 14 +- trunk/net/ipv6/route.c | 1068 ++-- trunk/net/ipv6/tcp_ipv6.c | 27 +- trunk/net/ipv6/udp.c | 106 +- trunk/net/ipv6/xfrm6_input.c | 110 +- trunk/net/ipv6/xfrm6_mode_ro.c | 93 - trunk/net/ipv6/xfrm6_mode_transport.c | 5 +- trunk/net/ipv6/xfrm6_mode_tunnel.c | 3 +- trunk/net/ipv6/xfrm6_output.c | 20 +- trunk/net/ipv6/xfrm6_policy.c | 87 +- trunk/net/ipv6/xfrm6_state.c | 189 +- trunk/net/ipv6/xfrm6_tunnel.c | 2 +- trunk/net/ipx/af_ipx.c | 10 +- trunk/net/key/af_key.c | 61 +- trunk/net/lapb/lapb_iface.c | 12 +- trunk/net/llc/af_llc.c | 20 +- trunk/net/llc/llc_sap.c | 7 +- trunk/net/netfilter/Kconfig | 23 - trunk/net/netfilter/Makefile | 2 - trunk/net/netfilter/core.c | 24 +- trunk/net/netfilter/nf_conntrack_core.c | 211 +- trunk/net/netfilter/nf_conntrack_ftp.c | 98 +- trunk/net/netfilter/nf_conntrack_netlink.c | 97 +- .../netfilter/nf_conntrack_proto_generic.c | 2 +- trunk/net/netfilter/nf_conntrack_proto_sctp.c | 14 +- trunk/net/netfilter/nf_conntrack_proto_tcp.c | 31 +- trunk/net/netfilter/nf_conntrack_proto_udp.c | 7 +- trunk/net/netfilter/nf_conntrack_standalone.c | 3 +- trunk/net/netfilter/nf_internals.h | 2 +- trunk/net/netfilter/nf_queue.c | 80 +- trunk/net/netfilter/nfnetlink_log.c | 3 - trunk/net/netfilter/nfnetlink_queue.c | 10 +- trunk/net/netfilter/x_tables.c | 269 +- trunk/net/netfilter/xt_CLASSIFY.c | 63 +- trunk/net/netfilter/xt_CONNMARK.c | 148 +- trunk/net/netfilter/xt_CONNSECMARK.c | 61 +- trunk/net/netfilter/xt_DSCP.c | 118 - trunk/net/netfilter/xt_MARK.c | 120 +- trunk/net/netfilter/xt_NFQUEUE.c | 71 +- trunk/net/netfilter/xt_NOTRACK.c | 50 +- trunk/net/netfilter/xt_SECMARK.c | 61 +- trunk/net/netfilter/xt_comment.c | 45 +- trunk/net/netfilter/xt_connbytes.c | 48 +- trunk/net/netfilter/xt_connmark.c | 88 +- trunk/net/netfilter/xt_conntrack.c | 185 +- trunk/net/netfilter/xt_dccp.c | 52 +- trunk/net/netfilter/xt_dscp.c | 103 - trunk/net/netfilter/xt_esp.c | 52 +- trunk/net/netfilter/xt_helper.c | 55 +- trunk/net/netfilter/xt_length.c | 43 +- trunk/net/netfilter/xt_limit.c | 111 +- trunk/net/netfilter/xt_mac.c | 52 +- trunk/net/netfilter/xt_mark.c | 80 +- trunk/net/netfilter/xt_multiport.c | 115 +- trunk/net/netfilter/xt_physdev.c | 51 +- trunk/net/netfilter/xt_pkttype.c | 44 +- trunk/net/netfilter/xt_policy.c | 52 +- trunk/net/netfilter/xt_quota.c | 55 +- trunk/net/netfilter/xt_sctp.c | 52 +- trunk/net/netfilter/xt_state.c | 56 +- trunk/net/netfilter/xt_statistic.c | 55 +- trunk/net/netfilter/xt_string.c | 61 +- trunk/net/netfilter/xt_tcpmss.c | 97 +- trunk/net/netfilter/xt_tcpudp.c | 109 +- trunk/net/netlabel/Kconfig | 14 - trunk/net/netlabel/Makefile | 16 - trunk/net/netlabel/netlabel_cipso_v4.c | 542 --- trunk/net/netlabel/netlabel_cipso_v4.h | 217 - trunk/net/netlabel/netlabel_domainhash.c | 513 -- trunk/net/netlabel/netlabel_domainhash.h | 67 - trunk/net/netlabel/netlabel_kapi.c | 231 - trunk/net/netlabel/netlabel_mgmt.c | 624 --- trunk/net/netlabel/netlabel_mgmt.h | 246 - trunk/net/netlabel/netlabel_unlabeled.c | 253 - trunk/net/netlabel/netlabel_unlabeled.h | 98 - trunk/net/netlabel/netlabel_user.c | 158 - trunk/net/netlabel/netlabel_user.h | 215 - trunk/net/netlink/af_netlink.c | 94 +- trunk/net/netlink/attr.c | 124 +- trunk/net/netlink/genetlink.c | 54 +- trunk/net/packet/af_packet.c | 49 +- trunk/net/sched/act_api.c | 253 +- trunk/net/sched/act_gact.c | 142 +- trunk/net/sched/act_ipt.c | 179 +- trunk/net/sched/act_mirred.c | 159 +- trunk/net/sched/act_pedit.c | 166 +- trunk/net/sched/act_police.c | 508 +- trunk/net/sched/act_simple.c | 183 +- trunk/net/sched/cls_fw.c | 25 +- trunk/net/sched/cls_u32.c | 2 +- trunk/net/sched/sch_api.c | 2 +- trunk/net/sched/sch_generic.c | 2 + trunk/net/sched/sch_htb.c | 1363 +++--- trunk/net/sched/sch_netem.c | 4 +- trunk/net/sctp/endpointola.c | 2 +- trunk/net/sctp/input.c | 10 +- trunk/net/sctp/inqueue.c | 4 +- trunk/net/sctp/ipv6.c | 7 +- trunk/net/sctp/outqueue.c | 6 +- trunk/net/sctp/proc.c | 17 +- trunk/net/sctp/protocol.c | 11 +- trunk/net/sctp/sm_make_chunk.c | 67 +- trunk/net/sctp/sm_statefuns.c | 194 +- trunk/net/sctp/socket.c | 59 +- trunk/net/sctp/sysctl.c | 140 +- trunk/net/sctp/transport.c | 2 +- trunk/net/socket.c | 1027 ++-- trunk/net/sunrpc/auth_gss/auth_gss.c | 10 +- trunk/net/sunrpc/auth_gss/gss_krb5_crypto.c | 95 +- trunk/net/sunrpc/auth_gss/gss_krb5_mech.c | 24 +- trunk/net/sunrpc/auth_gss/gss_krb5_seqnum.c | 4 +- trunk/net/sunrpc/auth_gss/gss_krb5_wrap.c | 4 +- trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c | 29 +- trunk/net/sunrpc/cache.c | 6 +- trunk/net/sunrpc/clnt.c | 274 +- trunk/net/sunrpc/pmap_clnt.c | 266 +- trunk/net/sunrpc/rpc_pipe.c | 107 +- trunk/net/sunrpc/sched.c | 99 +- trunk/net/sunrpc/socklib.c | 2 +- trunk/net/sunrpc/sunrpc_syms.c | 3 + trunk/net/sunrpc/svcsock.c | 38 +- trunk/net/sunrpc/timer.c | 2 + trunk/net/sunrpc/xprt.c | 107 +- trunk/net/sunrpc/xprtsock.c | 150 +- trunk/net/unix/af_unix.c | 24 +- trunk/net/xfrm/Kconfig | 16 +- trunk/net/xfrm/Makefile | 3 +- trunk/net/xfrm/xfrm_algo.c | 94 +- trunk/net/xfrm/xfrm_hash.c | 41 - trunk/net/xfrm/xfrm_hash.h | 128 - trunk/net/xfrm/xfrm_input.c | 4 +- trunk/net/xfrm/xfrm_policy.c | 928 +--- trunk/net/xfrm/xfrm_state.c | 640 +-- trunk/net/xfrm/xfrm_user.c | 350 +- trunk/scripts/Kbuild.include | 10 +- trunk/scripts/Makefile.headersinst | 8 +- trunk/scripts/Makefile.host | 2 +- trunk/scripts/Makefile.modpost | 2 +- trunk/scripts/checkstack.pl | 2 - trunk/scripts/hdrcheck.sh | 4 +- trunk/scripts/kconfig/confdata.c | 2 +- trunk/scripts/kernel-doc | 1 - trunk/scripts/mod/file2alias.c | 76 +- trunk/security/dummy.c | 78 +- trunk/security/seclvl.c | 18 +- trunk/security/selinux/hooks.c | 279 +- .../selinux/include/av_perm_to_string.h | 1 - .../security/selinux/include/av_permissions.h | 1 - trunk/security/selinux/include/objsec.h | 9 - trunk/security/selinux/include/security.h | 2 - .../selinux/include/selinux_netlabel.h | 119 - trunk/security/selinux/include/xfrm.h | 43 +- trunk/security/selinux/ss/ebitmap.c | 140 - trunk/security/selinux/ss/ebitmap.h | 6 - trunk/security/selinux/ss/mls.c | 176 +- trunk/security/selinux/ss/mls.h | 41 - trunk/security/selinux/ss/policydb.c | 12 +- trunk/security/selinux/ss/services.c | 617 +-- trunk/security/selinux/xfrm.c | 216 +- trunk/sound/aoa/Kconfig | 2 +- trunk/sound/aoa/codecs/Kconfig | 4 - trunk/sound/aoa/codecs/snd-aoa-codec-tas.c | 96 +- trunk/sound/aoa/codecs/snd-aoa-codec-toonie.c | 17 +- trunk/sound/aoa/core/snd-aoa-gpio-feature.c | 9 +- trunk/sound/aoa/core/snd-aoa-gpio-pmf.c | 2 +- trunk/sound/core/control.c | 160 +- trunk/sound/core/control_compat.c | 4 - trunk/sound/core/device.c | 20 +- trunk/sound/core/hwdep.c | 12 +- trunk/sound/core/info.c | 108 +- trunk/sound/core/info_oss.c | 6 +- trunk/sound/core/init.c | 116 +- trunk/sound/core/oss/mixer_oss.c | 25 +- trunk/sound/core/oss/pcm_oss.c | 26 +- trunk/sound/core/pcm.c | 128 +- trunk/sound/core/pcm_compat.c | 2 +- trunk/sound/core/pcm_memory.c | 2 +- trunk/sound/core/pcm_native.c | 49 +- trunk/sound/core/rawmidi.c | 38 +- trunk/sound/core/rtctimer.c | 2 +- trunk/sound/core/seq/oss/seq_oss.c | 3 +- trunk/sound/core/seq/seq_device.c | 16 +- trunk/sound/core/seq/seq_info.c | 6 +- trunk/sound/core/sgbuf.c | 9 +- trunk/sound/core/sound.c | 59 +- trunk/sound/core/sound_oss.c | 3 +- trunk/sound/core/timer.c | 62 +- trunk/sound/drivers/Kconfig | 13 - trunk/sound/drivers/Makefile | 2 - trunk/sound/drivers/dummy.c | 20 +- trunk/sound/drivers/mpu401/mpu401.c | 2 +- trunk/sound/drivers/mts64.c | 1091 ----- trunk/sound/drivers/opl4/opl4_proc.c | 9 +- trunk/sound/drivers/vx/vx_mixer.c | 17 +- trunk/sound/drivers/vx/vx_pcm.c | 7 +- trunk/sound/i2c/other/ak4xxx-adda.c | 501 +- trunk/sound/isa/ad1816a/ad1816a_lib.c | 55 +- trunk/sound/isa/ad1848/ad1848_lib.c | 49 +- trunk/sound/isa/es18xx.c | 219 +- trunk/sound/isa/gus/gus_mem_proc.c | 6 +- trunk/sound/isa/opl3sa2.c | 26 +- trunk/sound/oss/Kconfig | 36 +- trunk/sound/oss/dmasound/dmasound_awacs.c | 11 +- trunk/sound/pci/Kconfig | 82 +- trunk/sound/pci/ac97/ac97_codec.c | 338 +- trunk/sound/pci/ac97/ac97_patch.c | 98 +- trunk/sound/pci/ac97/ac97_patch.h | 1 - trunk/sound/pci/ac97/ac97_pcm.c | 18 - trunk/sound/pci/ac97/ac97_proc.c | 18 +- trunk/sound/pci/ac97/ak4531_codec.c | 49 +- trunk/sound/pci/ca0106/ca0106_mixer.c | 10 - trunk/sound/pci/cs4281.c | 5 - trunk/sound/pci/cs46xx/dsp_spos.c | 52 +- trunk/sound/pci/cs46xx/dsp_spos_scb_lib.c | 2 +- trunk/sound/pci/cs5535audio/Makefile | 2 +- trunk/sound/pci/echoaudio/echoaudio.c | 4 +- trunk/sound/pci/emu10k1/emu10k1.c | 2 +- trunk/sound/pci/emu10k1/emu10k1_main.c | 12 - trunk/sound/pci/emu10k1/emu10k1x.c | 7 +- trunk/sound/pci/emu10k1/emufx.c | 12 - trunk/sound/pci/emu10k1/irq.c | 6 +- trunk/sound/pci/emu10k1/p16v.c | 5 - trunk/sound/pci/es1938.c | 104 +- trunk/sound/pci/es1968.c | 40 +- trunk/sound/pci/fm801.c | 63 +- trunk/sound/pci/hda/hda_codec.c | 76 +- trunk/sound/pci/hda/hda_codec.h | 2 +- trunk/sound/pci/hda/hda_generic.c | 199 +- trunk/sound/pci/hda/hda_intel.c | 132 +- trunk/sound/pci/hda/hda_local.h | 8 +- trunk/sound/pci/hda/hda_proc.c | 12 +- trunk/sound/pci/hda/patch_analog.c | 21 +- trunk/sound/pci/hda/patch_realtek.c | 330 +- trunk/sound/pci/hda/patch_si3054.c | 1 - trunk/sound/pci/hda/patch_sigmatel.c | 904 +--- trunk/sound/pci/ice1712/aureon.c | 104 +- trunk/sound/pci/ice1712/ice1712.c | 14 +- trunk/sound/pci/ice1712/phase.c | 39 +- trunk/sound/pci/ice1712/pontis.c | 9 - trunk/sound/pci/ice1712/prodigy192.c | 14 - trunk/sound/pci/ice1712/revo.c | 68 +- trunk/sound/pci/ice1712/revo.h | 2 +- trunk/sound/pci/intel8x0.c | 14 +- trunk/sound/pci/intel8x0m.c | 5 - trunk/sound/pci/mixart/mixart.c | 12 +- trunk/sound/pci/mixart/mixart_mixer.c | 14 - trunk/sound/pci/pcxhr/pcxhr_mixer.c | 16 - trunk/sound/pci/riptide/riptide.c | 10 +- trunk/sound/pci/rme9652/hdsp.c | 48 +- trunk/sound/pci/trident/trident_main.c | 10 - trunk/sound/pci/via82xx.c | 23 +- trunk/sound/pci/vx222/vx222.c | 7 - trunk/sound/pci/vx222/vx222_ops.c | 9 - trunk/sound/pci/ymfpci/ymfpci_main.c | 7 +- trunk/sound/pcmcia/pdaudiocf/pdaudiocf.c | 2 +- trunk/sound/pcmcia/vx/vxp_mixer.c | 6 - trunk/sound/pcmcia/vx/vxpocket.c | 9 +- trunk/sound/ppc/awacs.c | 3 +- trunk/sound/ppc/beep.c | 32 +- trunk/sound/ppc/daca.c | 3 +- trunk/sound/ppc/keywest.c | 6 +- trunk/sound/ppc/powermac.c | 13 +- trunk/sound/ppc/tumbler.c | 23 +- trunk/sound/sparc/dbri.c | 817 ++-- trunk/sound/synth/emux/emux_proc.c | 6 +- trunk/sound/usb/usbaudio.c | 60 +- trunk/sound/usb/usbmixer.c | 27 - trunk/sound/usb/usbmixer_maps.c | 24 - trunk/sound/usb/usbquirks.h | 5 - trunk/usr/Makefile | 3 - 2314 files changed, 45925 insertions(+), 114061 deletions(-) delete mode 100644 trunk/Documentation/connector/ucon.c delete mode 100644 trunk/Documentation/fb/imacfb.txt delete mode 100644 trunk/Documentation/filesystems/relay.txt create mode 100644 trunk/Documentation/filesystems/relayfs.txt delete mode 100644 trunk/Documentation/netlabel/00-INDEX delete mode 100644 trunk/Documentation/netlabel/cipso_ipv4.txt delete mode 100644 trunk/Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt delete mode 100644 trunk/Documentation/netlabel/introduction.txt delete mode 100644 trunk/Documentation/netlabel/lsm_interface.txt delete mode 100644 trunk/Documentation/networking/secid.txt delete mode 100644 trunk/arch/arm/mach-s3c2410/s3c2412-irq.c delete mode 100644 trunk/arch/i386/crypto/twofish-i586-asm.S delete mode 100644 trunk/arch/i386/crypto/twofish.c create mode 100644 trunk/arch/i386/kernel/audit.c delete mode 100644 trunk/arch/powerpc/boot/dts/mpc7448hpc2.dts delete mode 100644 trunk/arch/powerpc/boot/dts/mpc8349emds.dts delete mode 100644 trunk/arch/powerpc/boot/dts/mpc8540ads.dts delete mode 100644 trunk/arch/powerpc/boot/dts/mpc8541cds.dts delete mode 100644 trunk/arch/powerpc/boot/dts/mpc8548cds.dts delete mode 100644 trunk/arch/powerpc/boot/dts/mpc8555cds.dts delete mode 100644 trunk/arch/powerpc/boot/dts/mpc8641_hpcn.dts delete mode 100644 trunk/arch/powerpc/boot/flatdevtree.h delete mode 100644 trunk/arch/powerpc/boot/ops.h rename trunk/arch/powerpc/boot/{of.c => prom.c} (54%) create mode 100644 trunk/arch/powerpc/boot/prom.h delete mode 100644 trunk/arch/powerpc/boot/types.h rename trunk/arch/powerpc/configs/{mpc834x_mds_defconfig => mpc834x_sys_defconfig} (90%) delete mode 100644 trunk/arch/powerpc/kernel/audit.c delete mode 100644 trunk/arch/powerpc/kernel/compat_audit.c rename trunk/arch/powerpc/kernel/{cpu_setup_ppc970.S => cpu_setup_power4.S} (73%) delete mode 100644 trunk/arch/powerpc/kernel/io.c create mode 100644 trunk/arch/powerpc/lib/e2a.c delete mode 100644 trunk/arch/powerpc/platforms/pasemi/Makefile delete mode 100644 trunk/arch/powerpc/platforms/pasemi/pasemi.h delete mode 100644 trunk/arch/powerpc/platforms/pasemi/pci.c delete mode 100644 trunk/arch/powerpc/platforms/pasemi/setup.c delete mode 100644 trunk/arch/powerpc/platforms/pasemi/time.c delete mode 100644 trunk/arch/powerpc/platforms/pseries/hvCall_inst.c delete mode 100644 trunk/arch/ppc/syslib/ipic.c delete mode 100644 trunk/arch/ppc/syslib/ipic.h delete mode 100644 trunk/arch/s390/kernel/audit.c delete mode 100644 trunk/arch/s390/kernel/compat_audit.c delete mode 100644 trunk/arch/s390/kernel/ipl.c delete mode 100644 trunk/arch/s390/kernel/kprobes.c create mode 100644 trunk/arch/s390/kernel/reipl_diag.c create mode 100644 trunk/arch/s390/lib/uaccess.S create mode 100644 trunk/arch/s390/lib/uaccess64.S delete mode 100644 trunk/arch/s390/lib/uaccess_mvcos.c delete mode 100644 trunk/arch/s390/lib/uaccess_std.c delete mode 100644 trunk/arch/sparc64/kernel/audit.c delete mode 100644 trunk/arch/sparc64/kernel/compat_audit.c delete mode 100644 trunk/arch/x86_64/crypto/twofish-x86_64-asm.S delete mode 100644 trunk/arch/x86_64/crypto/twofish.c delete mode 100644 trunk/crypto/algapi.c delete mode 100644 trunk/crypto/blkcipher.c delete mode 100644 trunk/crypto/cbc.c delete mode 100644 trunk/crypto/cryptomgr.c delete mode 100644 trunk/crypto/ecb.c delete mode 100644 trunk/crypto/hash.c delete mode 100644 trunk/crypto/twofish_common.c delete mode 100644 trunk/drivers/char/briq_panel.c delete mode 100644 trunk/drivers/char/hvc_iseries.c create mode 100644 trunk/drivers/crypto/padlock-generic.c delete mode 100644 trunk/drivers/crypto/padlock-sha.c delete mode 100644 trunk/drivers/crypto/padlock.c delete mode 100644 trunk/drivers/infiniband/core/iwcm.c delete mode 100644 trunk/drivers/infiniband/core/iwcm.h delete mode 100644 trunk/drivers/infiniband/hw/amso1100/Kbuild delete mode 100644 trunk/drivers/infiniband/hw/amso1100/Kconfig delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2.c delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2.h delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_ae.c delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_ae.h delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_alloc.c delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_cm.c delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_cq.c delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_intr.c delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_mm.c delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_mq.c delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_mq.h delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_pd.c delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_provider.c delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_provider.h delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_qp.c delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_rnic.c delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_status.h delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_user.h delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_vq.c delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_vq.h delete mode 100644 trunk/drivers/infiniband/hw/amso1100/c2_wr.h delete mode 100644 trunk/drivers/infiniband/hw/ehca/Kconfig delete mode 100644 trunk/drivers/infiniband/hw/ehca/Makefile delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_av.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_classes.h delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_cq.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_eq.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_hca.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_irq.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_irq.h delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_main.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_mcast.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_mrmw.h delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_pd.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_qes.h delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_qp.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_reqs.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_sqp.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_tools.h delete mode 100644 trunk/drivers/infiniband/hw/ehca/ehca_uverbs.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/hcp_if.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/hcp_if.h delete mode 100644 trunk/drivers/infiniband/hw/ehca/hcp_phyp.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/hcp_phyp.h delete mode 100644 trunk/drivers/infiniband/hw/ehca/hipz_fns.h delete mode 100644 trunk/drivers/infiniband/hw/ehca/hipz_fns_core.h delete mode 100644 trunk/drivers/infiniband/hw/ehca/hipz_hw.h delete mode 100644 trunk/drivers/infiniband/hw/ehca/ipz_pt_fn.c delete mode 100644 trunk/drivers/infiniband/hw/ehca/ipz_pt_fn.h rename trunk/drivers/infiniband/hw/ipath/{ipath_iba6110.c => ipath_ht400.c} (97%) delete mode 100644 trunk/drivers/infiniband/hw/ipath/ipath_mmap.c rename trunk/drivers/infiniband/hw/ipath/{ipath_iba6120.c => ipath_pe800.c} (95%) delete mode 100644 trunk/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c create mode 100644 trunk/drivers/infiniband/hw/ipath/verbs_debug.h rename trunk/drivers/media/{radio => video}/dsbr100.c (100%) create mode 100644 trunk/drivers/mtd/maps/iq80310.c delete mode 100644 trunk/drivers/mtd/ssfdc.c delete mode 100644 trunk/drivers/net/fs_enet/fec.h create mode 100644 trunk/drivers/net/fs_enet/fs_enet-mii.c delete mode 100644 trunk/drivers/net/fs_enet/mii-fec.c create mode 100644 trunk/drivers/net/fs_enet/mii-fixed.c delete mode 100644 trunk/drivers/net/phy/fixed.c delete mode 100644 trunk/drivers/net/ucc_geth.c delete mode 100644 trunk/drivers/net/ucc_geth.h delete mode 100644 trunk/drivers/net/ucc_geth_phy.c delete mode 100644 trunk/drivers/net/ucc_geth_phy.h delete mode 100644 trunk/drivers/s390/char/monwriter.c delete mode 100644 trunk/drivers/s390/crypto/ap_bus.c delete mode 100644 trunk/drivers/s390/crypto/ap_bus.h create mode 100644 trunk/drivers/s390/crypto/z90common.h create mode 100644 trunk/drivers/s390/crypto/z90crypt.h create mode 100644 trunk/drivers/s390/crypto/z90hardware.c create mode 100644 trunk/drivers/s390/crypto/z90main.c delete mode 100644 trunk/drivers/s390/crypto/zcrypt_api.c delete mode 100644 trunk/drivers/s390/crypto/zcrypt_api.h delete mode 100644 trunk/drivers/s390/crypto/zcrypt_cca_key.h delete mode 100644 trunk/drivers/s390/crypto/zcrypt_cex2a.c delete mode 100644 trunk/drivers/s390/crypto/zcrypt_cex2a.h delete mode 100644 trunk/drivers/s390/crypto/zcrypt_error.h delete mode 100644 trunk/drivers/s390/crypto/zcrypt_mono.c delete mode 100644 trunk/drivers/s390/crypto/zcrypt_pcica.c delete mode 100644 trunk/drivers/s390/crypto/zcrypt_pcica.h delete mode 100644 trunk/drivers/s390/crypto/zcrypt_pcicc.c delete mode 100644 trunk/drivers/s390/crypto/zcrypt_pcicc.h delete mode 100644 trunk/drivers/s390/crypto/zcrypt_pcixcc.c delete mode 100644 trunk/drivers/s390/crypto/zcrypt_pcixcc.h create mode 100644 trunk/drivers/usb/serial/anydata.c delete mode 100644 trunk/drivers/video/fb_notify.c delete mode 100644 trunk/fs/nfs/client.c delete mode 100644 trunk/fs/nfs/getroot.c delete mode 100644 trunk/fs/ocfs2/ioctl.c delete mode 100644 trunk/fs/ocfs2/ioctl.h delete mode 100644 trunk/include/asm-arm/arch-s3c2410/regs-power.h delete mode 100644 trunk/include/asm-generic/audit_read.h delete mode 100644 trunk/include/asm-generic/audit_write.h create mode 100644 trunk/include/asm-powerpc/iseries/iseries_io.h rename trunk/{arch/powerpc/platforms => include/asm-powerpc}/iseries/it_exp_vpd_panel.h (89%) rename trunk/{arch/powerpc/platforms => include/asm-powerpc}/iseries/it_lp_naca.h (96%) delete mode 100644 trunk/include/asm-powerpc/tsi108_irq.h delete mode 100644 trunk/include/asm-s390/appldata.h delete mode 100644 trunk/include/asm-s390/kdebug.h delete mode 100644 trunk/include/asm-s390/kprobes.h delete mode 100644 trunk/include/asm-s390/monwriter.h create mode 100644 trunk/include/asm-s390/z90crypt.h delete mode 100644 trunk/include/asm-s390/zcrypt.h delete mode 100644 trunk/include/crypto/algapi.h delete mode 100644 trunk/include/crypto/twofish.h delete mode 100644 trunk/include/linux/fib_rules.h delete mode 100644 trunk/include/linux/if_addr.h delete mode 100644 trunk/include/linux/neighbour.h delete mode 100644 trunk/include/linux/netfilter/xt_DSCP.h delete mode 100644 trunk/include/linux/netfilter/xt_dscp.h create mode 100644 trunk/include/linux/netfilter_ipv4/listhelp.h create mode 100644 trunk/include/linux/netfilter_logging.h create mode 100644 trunk/include/net/act_generic.h delete mode 100644 trunk/include/net/cipso_ipv4.h delete mode 100644 trunk/include/net/fib_rules.h delete mode 100644 trunk/include/net/mip6.h delete mode 100644 trunk/include/net/netevent.h delete mode 100644 trunk/include/net/netlabel.h delete mode 100644 trunk/include/net/nexthop.h create mode 100644 trunk/include/net/pkt_act.h delete mode 100644 trunk/include/rdma/iw_cm.h delete mode 100644 trunk/include/sound/tlv.h delete mode 100644 trunk/lib/audit.c delete mode 100644 trunk/net/core/fib_rules.c delete mode 100644 trunk/net/core/netevent.c delete mode 100644 trunk/net/ipv4/cipso_ipv4.c create mode 100644 trunk/net/ipv4/netfilter/ipt_DSCP.c create mode 100644 trunk/net/ipv4/netfilter/ipt_dscp.c delete mode 100644 trunk/net/ipv6/fib6_rules.c delete mode 100644 trunk/net/ipv6/mip6.c create mode 100644 trunk/net/ipv6/netfilter/ip6t_dst.c delete mode 100644 trunk/net/ipv6/xfrm6_mode_ro.c delete mode 100644 trunk/net/netfilter/xt_DSCP.c delete mode 100644 trunk/net/netfilter/xt_dscp.c delete mode 100644 trunk/net/netlabel/Kconfig delete mode 100644 trunk/net/netlabel/Makefile delete mode 100644 trunk/net/netlabel/netlabel_cipso_v4.c delete mode 100644 trunk/net/netlabel/netlabel_cipso_v4.h delete mode 100644 trunk/net/netlabel/netlabel_domainhash.c delete mode 100644 trunk/net/netlabel/netlabel_domainhash.h delete mode 100644 trunk/net/netlabel/netlabel_kapi.c delete mode 100644 trunk/net/netlabel/netlabel_mgmt.c delete mode 100644 trunk/net/netlabel/netlabel_mgmt.h delete mode 100644 trunk/net/netlabel/netlabel_unlabeled.c delete mode 100644 trunk/net/netlabel/netlabel_unlabeled.h delete mode 100644 trunk/net/netlabel/netlabel_user.c delete mode 100644 trunk/net/netlabel/netlabel_user.h delete mode 100644 trunk/net/xfrm/xfrm_hash.c delete mode 100644 trunk/net/xfrm/xfrm_hash.h delete mode 100644 trunk/security/selinux/include/selinux_netlabel.h delete mode 100644 trunk/sound/drivers/mts64.c diff --git a/[refs] b/[refs] index 080404605305..13c4e78748ae 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6973dddee264723720e18ad2be5a0a454c0f52d9 +refs/heads/master: f4c8aa1107969c26b1984eb2996a58f816dea71f diff --git a/trunk/.gitignore b/trunk/.gitignore index e1d5c17c12c2..27fd37621255 100644 --- a/trunk/.gitignore +++ b/trunk/.gitignore @@ -12,9 +12,6 @@ *.ko *.so *.mod.c -*.i -*.lst -*.symtypes # # Top-level generic files @@ -33,11 +30,6 @@ include/config include/linux/autoconf.h include/linux/compile.h include/linux/version.h -include/linux/utsrelease.h # stgit generated dirs patches-* - -# quilt's files -patches -series diff --git a/trunk/CREDITS b/trunk/CREDITS index cc3453a55fb9..29be6d1fdf49 100644 --- a/trunk/CREDITS +++ b/trunk/CREDITS @@ -2209,7 +2209,7 @@ S: (address available on request) S: USA N: Ian McDonald -E: ian.mcdonald@jandi.co.nz +E: iam4@cs.waikato.ac.nz E: imcdnzl@gmail.com W: http://wand.net.nz/~iam4 W: http://imcdnzl.blogspot.com @@ -2384,13 +2384,6 @@ N: Thomas Molina E: tmolina@cablespeed.com D: bug fixes, documentation, minor hackery -N: Paul Moore -E: paul.moore@hp.com -D: NetLabel author -S: Hewlett-Packard -S: 110 Spit Brook Road -S: Nashua, NH 03062 - N: James Morris E: jmorris@namei.org W: http://namei.org/ diff --git a/trunk/Documentation/00-INDEX b/trunk/Documentation/00-INDEX index 02457ec9c94f..5f7f7d7f77d2 100644 --- a/trunk/Documentation/00-INDEX +++ b/trunk/Documentation/00-INDEX @@ -184,8 +184,6 @@ mtrr.txt - how to use PPro Memory Type Range Registers to increase performance. nbd.txt - info on a TCP implementation of a network block device. -netlabel/ - - directory with information on the NetLabel subsystem. networking/ - directory with info on various aspects of networking with Linux. nfsroot.txt diff --git a/trunk/Documentation/DocBook/kernel-api.tmpl b/trunk/Documentation/DocBook/kernel-api.tmpl index f8fe882e33dc..1ae4dc0fd856 100644 --- a/trunk/Documentation/DocBook/kernel-api.tmpl +++ b/trunk/Documentation/DocBook/kernel-api.tmpl @@ -58,9 +58,6 @@ !Iinclude/linux/ktime.h !Iinclude/linux/hrtimer.h !Ekernel/hrtimer.c - - Workqueues and Kevents -!Ekernel/workqueue.c Internal Functions !Ikernel/exit.c @@ -303,7 +300,7 @@ X!Ekernel/module.c Resources Management -!Ikernel/resource.c +!Ekernel/resource.c MTRR Handling @@ -315,7 +312,9 @@ X!Ekernel/module.c !Edrivers/pci/pci-driver.c !Edrivers/pci/remove.c !Edrivers/pci/pci-acpi.c -!Edrivers/pci/search.c + !Edrivers/pci/msi.c !Edrivers/pci/bus.c no irq is pending */ - return NO_IRQ; + irq = -1; - return irq_linear_revmap(primary_ipic->irqhost, irq); + return irq; } static struct sysdev_class ipic_sysclass = { diff --git a/trunk/arch/powerpc/sysdev/ipic.h b/trunk/arch/powerpc/sysdev/ipic.h index c28e589877eb..a60c9d18bb7f 100644 --- a/trunk/arch/powerpc/sysdev/ipic.h +++ b/trunk/arch/powerpc/sysdev/ipic.h @@ -15,18 +15,7 @@ #include -#define NR_IPIC_INTS 128 - -/* External IRQS */ -#define IPIC_IRQ_EXT0 48 -#define IPIC_IRQ_EXT1 17 -#define IPIC_IRQ_EXT7 23 - -/* Default Priority Registers */ -#define IPIC_SIPRR_A_DEFAULT 0x05309770 -#define IPIC_SIPRR_D_DEFAULT 0x05309770 -#define IPIC_SMPRR_A_DEFAULT 0x05309770 -#define IPIC_SMPRR_B_DEFAULT 0x05309770 +#define MPC83xx_IPIC_SIZE (0x00100) /* System Global Interrupt Configuration Register */ #define SICFR_IPSA 0x00010000 @@ -42,15 +31,7 @@ struct ipic { volatile u32 __iomem *regs; - - /* The remapper for this IPIC */ - struct irq_host *irqhost; - - /* The "linux" controller struct */ - struct irq_chip hc_irq; - - /* The device node of the interrupt controller */ - struct device_node *of_node; + unsigned int irq_offset; }; struct ipic_info { diff --git a/trunk/arch/powerpc/sysdev/mmio_nvram.c b/trunk/arch/powerpc/sysdev/mmio_nvram.c index ff23f5a4d4b9..615350d46b52 100644 --- a/trunk/arch/powerpc/sysdev/mmio_nvram.c +++ b/trunk/arch/powerpc/sysdev/mmio_nvram.c @@ -80,7 +80,7 @@ static ssize_t mmio_nvram_get_size(void) int __init mmio_nvram_init(void) { struct device_node *nvram_node; - const unsigned long *buffer; + unsigned long *buffer; int proplen; unsigned long nvram_addr; int ret; @@ -91,7 +91,7 @@ int __init mmio_nvram_init(void) goto out; ret = -EIO; - buffer = get_property(nvram_node, "reg", &proplen); + buffer = (unsigned long *)get_property(nvram_node, "reg", &proplen); if (proplen != 2*sizeof(unsigned long)) goto out; diff --git a/trunk/arch/powerpc/sysdev/mpic.c b/trunk/arch/powerpc/sysdev/mpic.c index b604926401f5..6e0281afa6c3 100644 --- a/trunk/arch/powerpc/sysdev/mpic.c +++ b/trunk/arch/powerpc/sysdev/mpic.c @@ -54,94 +54,6 @@ static DEFINE_SPINLOCK(mpic_lock); #endif #endif -#ifdef CONFIG_MPIC_WEIRD -static u32 mpic_infos[][MPIC_IDX_END] = { - [0] = { /* Original OpenPIC compatible MPIC */ - MPIC_GREG_BASE, - MPIC_GREG_FEATURE_0, - MPIC_GREG_GLOBAL_CONF_0, - MPIC_GREG_VENDOR_ID, - MPIC_GREG_IPI_VECTOR_PRI_0, - MPIC_GREG_IPI_STRIDE, - MPIC_GREG_SPURIOUS, - MPIC_GREG_TIMER_FREQ, - - MPIC_TIMER_BASE, - MPIC_TIMER_STRIDE, - MPIC_TIMER_CURRENT_CNT, - MPIC_TIMER_BASE_CNT, - MPIC_TIMER_VECTOR_PRI, - MPIC_TIMER_DESTINATION, - - MPIC_CPU_BASE, - MPIC_CPU_STRIDE, - MPIC_CPU_IPI_DISPATCH_0, - MPIC_CPU_IPI_DISPATCH_STRIDE, - MPIC_CPU_CURRENT_TASK_PRI, - MPIC_CPU_WHOAMI, - MPIC_CPU_INTACK, - MPIC_CPU_EOI, - - MPIC_IRQ_BASE, - MPIC_IRQ_STRIDE, - MPIC_IRQ_VECTOR_PRI, - MPIC_VECPRI_VECTOR_MASK, - MPIC_VECPRI_POLARITY_POSITIVE, - MPIC_VECPRI_POLARITY_NEGATIVE, - MPIC_VECPRI_SENSE_LEVEL, - MPIC_VECPRI_SENSE_EDGE, - MPIC_VECPRI_POLARITY_MASK, - MPIC_VECPRI_SENSE_MASK, - MPIC_IRQ_DESTINATION - }, - [1] = { /* Tsi108/109 PIC */ - TSI108_GREG_BASE, - TSI108_GREG_FEATURE_0, - TSI108_GREG_GLOBAL_CONF_0, - TSI108_GREG_VENDOR_ID, - TSI108_GREG_IPI_VECTOR_PRI_0, - TSI108_GREG_IPI_STRIDE, - TSI108_GREG_SPURIOUS, - TSI108_GREG_TIMER_FREQ, - - TSI108_TIMER_BASE, - TSI108_TIMER_STRIDE, - TSI108_TIMER_CURRENT_CNT, - TSI108_TIMER_BASE_CNT, - TSI108_TIMER_VECTOR_PRI, - TSI108_TIMER_DESTINATION, - - TSI108_CPU_BASE, - TSI108_CPU_STRIDE, - TSI108_CPU_IPI_DISPATCH_0, - TSI108_CPU_IPI_DISPATCH_STRIDE, - TSI108_CPU_CURRENT_TASK_PRI, - TSI108_CPU_WHOAMI, - TSI108_CPU_INTACK, - TSI108_CPU_EOI, - - TSI108_IRQ_BASE, - TSI108_IRQ_STRIDE, - TSI108_IRQ_VECTOR_PRI, - TSI108_VECPRI_VECTOR_MASK, - TSI108_VECPRI_POLARITY_POSITIVE, - TSI108_VECPRI_POLARITY_NEGATIVE, - TSI108_VECPRI_SENSE_LEVEL, - TSI108_VECPRI_SENSE_EDGE, - TSI108_VECPRI_POLARITY_MASK, - TSI108_VECPRI_SENSE_MASK, - TSI108_IRQ_DESTINATION - }, -}; - -#define MPIC_INFO(name) mpic->hw_set[MPIC_IDX_##name] - -#else /* CONFIG_MPIC_WEIRD */ - -#define MPIC_INFO(name) MPIC_##name - -#endif /* CONFIG_MPIC_WEIRD */ - /* * Register accessor functions */ @@ -168,8 +80,7 @@ static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base, static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) { unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0; - unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + - (ipi * MPIC_INFO(GREG_IPI_STRIDE)); + unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10); if (mpic->flags & MPIC_BROKEN_IPI) be = !be; @@ -178,8 +89,7 @@ static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value) { - unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + - (ipi * MPIC_INFO(GREG_IPI_STRIDE)); + unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10); _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value); } @@ -210,7 +120,7 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne unsigned int idx = src_no & mpic->isu_mask; return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], - reg + (idx * MPIC_INFO(IRQ_STRIDE))); + reg + (idx * MPIC_IRQ_STRIDE)); } static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, @@ -220,7 +130,7 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, unsigned int idx = src_no & mpic->isu_mask; _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], - reg + (idx * MPIC_INFO(IRQ_STRIDE)), value); + reg + (idx * MPIC_IRQ_STRIDE), value); } #define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r)) @@ -246,8 +156,8 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic) { u32 r; - mpic_write(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0), MPIC_VECPRI_MASK); - r = mpic_read(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0)); + mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK); + r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0); if (r == le32_to_cpu(MPIC_VECPRI_MASK)) { printk(KERN_INFO "mpic: Detected reversed IPI registers\n"); @@ -484,8 +394,8 @@ static inline struct mpic * mpic_from_irq(unsigned int irq) /* Send an EOI */ static inline void mpic_eoi(struct mpic *mpic) { - mpic_cpu_write(MPIC_INFO(CPU_EOI), 0); - (void)mpic_cpu_read(MPIC_INFO(CPU_WHOAMI)); + mpic_cpu_write(MPIC_CPU_EOI, 0); + (void)mpic_cpu_read(MPIC_CPU_WHOAMI); } #ifdef CONFIG_SMP @@ -509,8 +419,8 @@ static void mpic_unmask_irq(unsigned int irq) DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src); - mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), - mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & + mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, + mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & ~MPIC_VECPRI_MASK); /* make sure mask gets to controller before we return to user */ do { @@ -518,7 +428,7 @@ static void mpic_unmask_irq(unsigned int irq) printk(KERN_ERR "mpic_enable_irq timeout\n"); break; } - } while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK); + } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK); } static void mpic_mask_irq(unsigned int irq) @@ -529,8 +439,8 @@ static void mpic_mask_irq(unsigned int irq) DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src); - mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), - mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) | + mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, + mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) | MPIC_VECPRI_MASK); /* make sure mask gets to controller before we return to user */ @@ -539,7 +449,7 @@ static void mpic_mask_irq(unsigned int irq) printk(KERN_ERR "mpic_enable_irq timeout\n"); break; } - } while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK)); + } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK)); } static void mpic_end_irq(unsigned int irq) @@ -650,28 +560,24 @@ static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) cpus_and(tmp, cpumask, cpu_online_map); - mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), + mpic_irq_write(src, MPIC_IRQ_DESTINATION, mpic_physmask(cpus_addr(tmp)[0])); } -static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type) +static unsigned int mpic_type_to_vecpri(unsigned int type) { /* Now convert sense value */ switch(type & IRQ_TYPE_SENSE_MASK) { case IRQ_TYPE_EDGE_RISING: - return MPIC_INFO(VECPRI_SENSE_EDGE) | - MPIC_INFO(VECPRI_POLARITY_POSITIVE); + return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_POSITIVE; case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_EDGE_BOTH: - return MPIC_INFO(VECPRI_SENSE_EDGE) | - MPIC_INFO(VECPRI_POLARITY_NEGATIVE); + return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_NEGATIVE; case IRQ_TYPE_LEVEL_HIGH: - return MPIC_INFO(VECPRI_SENSE_LEVEL) | - MPIC_INFO(VECPRI_POLARITY_POSITIVE); + return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_POSITIVE; case IRQ_TYPE_LEVEL_LOW: default: - return MPIC_INFO(VECPRI_SENSE_LEVEL) | - MPIC_INFO(VECPRI_POLARITY_NEGATIVE); + return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_NEGATIVE; } } @@ -703,14 +609,13 @@ static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type) vecpri = MPIC_VECPRI_POLARITY_POSITIVE | MPIC_VECPRI_SENSE_EDGE; else - vecpri = mpic_type_to_vecpri(mpic, flow_type); + vecpri = mpic_type_to_vecpri(flow_type); - vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); - vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) | - MPIC_INFO(VECPRI_SENSE_MASK)); + vold = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI); + vnew = vold & ~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK); vnew |= vecpri; if (vold != vnew) - mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew); + mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, vnew); return 0; } @@ -893,22 +798,17 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic->irq_count = irq_count; mpic->num_sources = 0; /* so far */ -#ifdef CONFIG_MPIC_WEIRD - mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; -#endif - /* Map the global registers */ - mpic->gregs = ioremap(phys_addr + MPIC_INFO(GREG_BASE), 0x1000); - mpic->tmregs = mpic->gregs + - ((MPIC_INFO(TIMER_BASE) - MPIC_INFO(GREG_BASE)) >> 2); + mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000); + mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2); BUG_ON(mpic->gregs == NULL); /* Reset */ if (flags & MPIC_WANTS_RESET) { - mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), - mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) + mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0, + mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0) | MPIC_GREG_GCONF_RESET); - while( mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) + while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0) & MPIC_GREG_GCONF_RESET) mb(); } @@ -917,7 +817,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, * MPICs, num sources as well. On ISU MPICs, sources are counted * as ISUs are added */ - reg = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0)); + reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0); mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK) >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1; if (isu_size == 0) @@ -926,16 +826,16 @@ struct mpic * __init mpic_alloc(struct device_node *node, /* Map the per-CPU registers */ for (i = 0; i < mpic->num_cpus; i++) { - mpic->cpuregs[i] = ioremap(phys_addr + MPIC_INFO(CPU_BASE) + - i * MPIC_INFO(CPU_STRIDE), 0x1000); + mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE + + i * MPIC_CPU_STRIDE, 0x1000); BUG_ON(mpic->cpuregs[i] == NULL); } /* Initialize main ISU if none provided */ if (mpic->isu_size == 0) { mpic->isu_size = mpic->num_sources; - mpic->isus[0] = ioremap(phys_addr + MPIC_INFO(IRQ_BASE), - MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); + mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE, + MPIC_IRQ_STRIDE * mpic->isu_size); BUG_ON(mpic->isus[0] == NULL); } mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); @@ -979,8 +879,7 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, BUG_ON(isu_num >= MPIC_MAX_ISU); - mpic->isus[isu_num] = ioremap(phys_addr, - MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); + mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size); if ((isu_first + mpic->isu_size) > mpic->num_sources) mpic->num_sources = isu_first + mpic->isu_size; } @@ -1005,16 +904,14 @@ void __init mpic_init(struct mpic *mpic) printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); /* Set current processor priority to max */ - mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf); + mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf); /* Initialize timers: just disable them all */ for (i = 0; i < 4; i++) { mpic_write(mpic->tmregs, - i * MPIC_INFO(TIMER_STRIDE) + - MPIC_INFO(TIMER_DESTINATION), 0); + i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0); mpic_write(mpic->tmregs, - i * MPIC_INFO(TIMER_STRIDE) + - MPIC_INFO(TIMER_VECTOR_PRI), + i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI, MPIC_VECPRI_MASK | (MPIC_VEC_TIMER_0 + i)); } @@ -1043,22 +940,21 @@ void __init mpic_init(struct mpic *mpic) (8 << MPIC_VECPRI_PRIORITY_SHIFT); /* init hw */ - mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); - mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), + mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri); + mpic_irq_write(i, MPIC_IRQ_DESTINATION, 1 << hard_smp_processor_id()); } /* Init spurrious vector */ - mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), MPIC_VEC_SPURRIOUS); + mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS); - /* Disable 8259 passthrough, if supported */ - if (!(mpic->flags & MPIC_NO_PTHROU_DIS)) - mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), - mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) - | MPIC_GREG_GCONF_8259_PTHROU_DIS); + /* Disable 8259 passthrough */ + mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0, + mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0) + | MPIC_GREG_GCONF_8259_PTHROU_DIS); /* Set current processor priority to 0 */ - mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0); + mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0); } void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio) @@ -1101,9 +997,9 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri) mpic_ipi_write(src - MPIC_VEC_IPI_0, reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); } else { - reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) + reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & ~MPIC_VECPRI_PRIORITY_MASK; - mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), + mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); } spin_unlock_irqrestore(&mpic_lock, flags); @@ -1121,7 +1017,7 @@ unsigned int mpic_irq_get_priority(unsigned int irq) if (is_ipi) reg = mpic_ipi_read(src = MPIC_VEC_IPI_0); else - reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); + reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI); spin_unlock_irqrestore(&mpic_lock, flags); return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT; } @@ -1147,12 +1043,12 @@ void mpic_setup_this_cpu(void) */ if (distribute_irqs) { for (i = 0; i < mpic->num_sources ; i++) - mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), - mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) | msk); + mpic_irq_write(i, MPIC_IRQ_DESTINATION, + mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk); } /* Set current processor priority to 0 */ - mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0); + mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0); spin_unlock_irqrestore(&mpic_lock, flags); #endif /* CONFIG_SMP */ @@ -1162,7 +1058,7 @@ int mpic_cpu_get_priority(void) { struct mpic *mpic = mpic_primary; - return mpic_cpu_read(MPIC_INFO(CPU_CURRENT_TASK_PRI)); + return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI); } void mpic_cpu_set_priority(int prio) @@ -1170,7 +1066,7 @@ void mpic_cpu_set_priority(int prio) struct mpic *mpic = mpic_primary; prio &= MPIC_CPU_TASKPRI_MASK; - mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), prio); + mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio); } /* @@ -1192,11 +1088,11 @@ void mpic_teardown_this_cpu(int secondary) /* let the mpic know we don't want intrs. */ for (i = 0; i < mpic->num_sources ; i++) - mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), - mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) & ~msk); + mpic_irq_write(i, MPIC_IRQ_DESTINATION, + mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk); /* Set current processor priority to max */ - mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf); + mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf); spin_unlock_irqrestore(&mpic_lock, flags); } @@ -1212,8 +1108,7 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask) DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no); #endif - mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) + - ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE), + mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10, mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); } @@ -1221,7 +1116,7 @@ unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs) { u32 src; - src = mpic_cpu_read(MPIC_INFO(CPU_INTACK)) & MPIC_INFO(VECPRI_VECTOR_MASK); + src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK; #ifdef DEBUG_LOW DBG("%s: get_one_irq(): %d\n", mpic->name, src); #endif diff --git a/trunk/arch/powerpc/sysdev/tsi108_dev.c b/trunk/arch/powerpc/sysdev/tsi108_dev.c index f3038461d4c0..26a0cc820cde 100644 --- a/trunk/arch/powerpc/sysdev/tsi108_dev.c +++ b/trunk/arch/powerpc/sysdev/tsi108_dev.c @@ -93,15 +93,13 @@ static int __init tsi108_eth_of_init(void) goto err; r[1].name = "tx"; - r[1].start = irq_of_parse_and_map(np, 0); - r[1].end = irq_of_parse_and_map(np, 0); + r[1].start = np->intrs[0].line; + r[1].end = np->intrs[0].line; r[1].flags = IORESOURCE_IRQ; - DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n", - __FUNCTION__,r[1].name, r[1].start, r[1].end); tsi_eth_dev = platform_device_register_simple("tsi-ethernet", i, &r[0], - 1); + np->n_intrs + 1); if (IS_ERR(tsi_eth_dev)) { ret = PTR_ERR(tsi_eth_dev); @@ -129,7 +127,7 @@ static int __init tsi108_eth_of_init(void) tsi_eth_data.regs = r[0].start; tsi_eth_data.phyregs = res.start; tsi_eth_data.phy = *phy_id; - tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0); + tsi_eth_data.irq_num = np->intrs[0].line; of_node_put(phy); ret = platform_device_add_data(tsi_eth_dev, &tsi_eth_data, diff --git a/trunk/arch/powerpc/sysdev/tsi108_pci.c b/trunk/arch/powerpc/sysdev/tsi108_pci.c index c28f69bef8e2..3265d54c82ed 100644 --- a/trunk/arch/powerpc/sysdev/tsi108_pci.c +++ b/trunk/arch/powerpc/sysdev/tsi108_pci.c @@ -26,6 +26,7 @@ #include #include + #include #include #include @@ -194,7 +195,7 @@ int __init tsi108_setup_pci(struct device_node *dev) int len; struct pci_controller *hose; struct resource rsrc; - const int *bus_range; + int *bus_range; int primary = 0, has_address = 0; /* PCI Config mapping */ @@ -207,7 +208,7 @@ int __init tsi108_setup_pci(struct device_node *dev) has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); /* Get bus range if any */ - bus_range = get_property(dev, "bus-range", &len); + bus_range = (int *)get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { printk(KERN_WARNING "Can't get bus-range for %s, assume" " bus 0\n", dev->full_name); @@ -227,7 +228,7 @@ int __init tsi108_setup_pci(struct device_node *dev) (hose)->ops = &tsi108_direct_pci_ops; - printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08x. " + printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08lx. " "Firmware bus number: %d->%d\n", rsrc.start, hose->first_busno, hose->last_busno); @@ -277,7 +278,7 @@ static void init_pci_source(void) mb(); } -static inline unsigned int get_pci_source(void) +static inline int get_pci_source(void) { u_int temp = 0; int irq = -1; @@ -370,12 +371,12 @@ static void tsi108_pci_irq_end(u_int irq) * Interrupt controller descriptor for cascaded PCI interrupt controller. */ -static struct irq_chip tsi108_pci_irq = { +struct hw_interrupt_type tsi108_pci_irq = { .typename = "tsi108_PCI_int", - .mask = tsi108_pci_irq_disable, + .enable = tsi108_pci_irq_enable, + .disable = tsi108_pci_irq_disable, .ack = tsi108_pci_irq_ack, .end = tsi108_pci_irq_end, - .unmask = tsi108_pci_irq_enable, }; /* @@ -398,18 +399,14 @@ void __init tsi108_pci_int_init(void) DBG("Tsi108_pci_int_init: initializing PCI interrupts\n"); for (i = 0; i < NUM_PCI_IRQS; i++) { - irq_desc[i + IRQ_PCI_INTAD_BASE].chip = &tsi108_pci_irq; + irq_desc[i + IRQ_PCI_INTAD_BASE].handler = &tsi108_pci_irq; irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL; } init_pci_source(); } -void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc, - struct pt_regs *regs) +int tsi108_irq_cascade(struct pt_regs *regs, void *unused) { - unsigned int cascade_irq = get_pci_source(); - if (cascade_irq != NO_IRQ) - generic_handle_irq(cascade_irq, regs); - desc->chip->eoi(irq); + return get_pci_source(); } diff --git a/trunk/arch/powerpc/xmon/xmon.c b/trunk/arch/powerpc/xmon/xmon.c index 8adad1444a51..179b10ced8c7 100644 --- a/trunk/arch/powerpc/xmon/xmon.c +++ b/trunk/arch/powerpc/xmon/xmon.c @@ -137,14 +137,10 @@ static void bootcmds(void); static void proccall(void); void dump_segments(void); static void symbol_lookup(void); -static void xmon_show_stack(unsigned long sp, unsigned long lr, - unsigned long pc); static void xmon_print_symbol(unsigned long address, const char *mid, const char *after); static const char *getvecname(unsigned long vec); -int xmon_no_auto_backtrace; - extern int print_insn_powerpc(unsigned long, unsigned long, int); extern void xmon_enter(void); @@ -740,12 +736,6 @@ cmds(struct pt_regs *excp) last_cmd = NULL; xmon_regs = excp; - - if (!xmon_no_auto_backtrace) { - xmon_no_auto_backtrace = 1; - xmon_show_stack(excp->gpr[1], excp->link, excp->nip); - } - for(;;) { #ifdef CONFIG_SMP printf("%x:", smp_processor_id()); diff --git a/trunk/arch/ppc/Kconfig b/trunk/arch/ppc/Kconfig index 8fa10cf661a8..a04cdf01596b 100644 --- a/trunk/arch/ppc/Kconfig +++ b/trunk/arch/ppc/Kconfig @@ -1204,7 +1204,7 @@ config PCI_DOMAINS default PCI config MPC83xx_PCI2 - bool "Support for 2nd PCI host controller" + bool " Supprt for 2nd PCI host controller" depends on PCI && MPC834x default y if MPC834x_SYS @@ -1223,12 +1223,12 @@ config PCI_8260 default y config 8260_PCI9 - bool "Enable workaround for MPC826x erratum PCI 9" + bool " Enable workaround for MPC826x erratum PCI 9" depends on PCI_8260 && !ADS8272 default y choice - prompt "IDMA channel for PCI 9 workaround" + prompt " IDMA channel for PCI 9 workaround" depends on 8260_PCI9 config 8260_PCI9_IDMA1 diff --git a/trunk/arch/ppc/configs/prep_defconfig b/trunk/arch/ppc/configs/prep_defconfig index 0aa333178b2a..4d33bee23a89 100644 --- a/trunk/arch/ppc/configs/prep_defconfig +++ b/trunk/arch/ppc/configs/prep_defconfig @@ -1,63 +1,56 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18-rc6 -# Wed Sep 6 15:09:32 2006 +# Linux kernel version: 2.6.13-rc3 +# Wed Jul 13 13:34:24 2005 # CONFIG_MMU=y CONFIG_GENERIC_HARDIRQS=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_HAVE_DEC_LOCK=y CONFIG_PPC=y CONFIG_PPC32=y CONFIG_GENERIC_NVRAM=y -CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y -CONFIG_ARCH_MAY_HAVE_PC_FDC=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # -CONFIG_LOCALVERSION="-prep" -CONFIG_LOCALVERSION_AUTO=y +CONFIG_LOCALVERSION="" CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_TASKSTATS is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +CONFIG_KOBJECT_UEVENT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y -# CONFIG_RELAY is not set -CONFIG_INITRAMFS_SOURCE="" -CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y -CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y -CONFIG_RT_MUTEXES=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_SLAB=y -CONFIG_VM_EVENT_COUNTERS=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set # # Loadable module support @@ -65,68 +58,69 @@ CONFIG_BASE_SMALL=0 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y -# -# Block layer -# -CONFIG_LBD=y -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_DEFAULT_AS is not set -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" - # # Processor # CONFIG_6xx=y # CONFIG_40x is not set # CONFIG_44x is not set +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set # CONFIG_8xx is not set # CONFIG_E200 is not set # CONFIG_E500 is not set CONFIG_PPC_FPU=y -# CONFIG_ALTIVEC is not set -# CONFIG_TAU is not set +CONFIG_ALTIVEC=y +CONFIG_TAU=y +# CONFIG_TAU_INT is not set +# CONFIG_TAU_AVERAGE is not set # CONFIG_KEXEC is not set -# CONFIG_CPU_FREQ is not set +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +# CONFIG_CPU_FREQ_DEBUG is not set +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=m +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_PMAC=y CONFIG_PPC601_SYNC_FIX=y -# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_PM=y CONFIG_PPC_STD_MMU=y # # Platform options # -CONFIG_PPC_PREP=y +CONFIG_PPC_MULTIPLATFORM=y # CONFIG_APUS is not set # CONFIG_KATANA is not set # CONFIG_WILLOW is not set # CONFIG_CPCI690 is not set +# CONFIG_PCORE is not set # CONFIG_POWERPMC250 is not set # CONFIG_CHESTNUT is not set # CONFIG_SPRUCE is not set # CONFIG_HDPU is not set # CONFIG_EV64260 is not set # CONFIG_LOPEC is not set +# CONFIG_MCPN765 is not set # CONFIG_MVME5100 is not set # CONFIG_PPLUS is not set # CONFIG_PRPMC750 is not set # CONFIG_PRPMC800 is not set # CONFIG_SANDPOINT is not set # CONFIG_RADSTONE_PPC7D is not set +# CONFIG_ADIR is not set +# CONFIG_K2 is not set # CONFIG_PAL4 is not set # CONFIG_GEMINI is not set # CONFIG_EST8260 is not set @@ -138,7 +132,10 @@ CONFIG_PPC_PREP=y # CONFIG_PQ2FADS is not set # CONFIG_LITE5200 is not set # CONFIG_MPC834x_SYS is not set -# CONFIG_EV64360 is not set +CONFIG_PPC_CHRP=y +CONFIG_PPC_PMAC=y +CONFIG_PPC_PREP=y +CONFIG_PPC_OF=y CONFIG_PPCBUG_NVRAM=y # CONFIG_SMP is not set # CONFIG_HIGHMEM is not set @@ -155,16 +152,12 @@ CONFIG_FLATMEM_MANUAL=y # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_RESOURCES_64BIT is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m +CONFIG_PROC_DEVICETREE=y CONFIG_PREP_RESIDUAL=y CONFIG_PROC_PREPRESIDUAL=y # CONFIG_CMDLINE_BOOL is not set -CONFIG_PM=y -# CONFIG_PM_LEGACY is not set # CONFIG_PM_DEBUG is not set CONFIG_SOFTWARE_SUSPEND=y CONFIG_PM_STD_PARTITION="" @@ -176,10 +169,10 @@ CONFIG_ISA_DMA_API=y # CONFIG_ISA=y CONFIG_GENERIC_ISA_DMA=y -CONFIG_PPC_I8259=y -CONFIG_PPC_INDIRECT_PCI=y CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +# CONFIG_PCI_LEGACY_PROC is not set +# CONFIG_PCI_NAMES is not set # CONFIG_PCI_DEBUG is not set # @@ -194,11 +187,6 @@ CONFIG_CARDBUS=y # PC-card bridges # CONFIG_YENTA=m -CONFIG_YENTA_O2=y -CONFIG_YENTA_RICOH=y -CONFIG_YENTA_TI=y -CONFIG_YENTA_ENE_TUNE=y -CONFIG_YENTA_TOSHIBA=y CONFIG_PCMCIA_PROBE=y CONFIG_PCCARD_NONSTATIC=m @@ -224,7 +212,6 @@ CONFIG_NET=y # # Networking options # -# CONFIG_NETDEBUG is not set CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y @@ -242,11 +229,9 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set -# CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_DIAG is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_BIC=y @@ -255,77 +240,80 @@ CONFIG_TCP_CONG_BIC=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -# CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set -# -# Core Netfilter Configuration -# -CONFIG_NETFILTER_NETLINK=m -CONFIG_NETFILTER_NETLINK_QUEUE=m -CONFIG_NETFILTER_NETLINK_LOG=m -CONFIG_NETFILTER_XTABLES=m -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m -CONFIG_NETFILTER_XT_TARGET_MARK=m -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m -CONFIG_NETFILTER_XT_MATCH_COMMENT=m -CONFIG_NETFILTER_XT_MATCH_CONNMARK=m -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m -CONFIG_NETFILTER_XT_MATCH_DCCP=m -CONFIG_NETFILTER_XT_MATCH_ESP=m -CONFIG_NETFILTER_XT_MATCH_HELPER=m -CONFIG_NETFILTER_XT_MATCH_LENGTH=m -CONFIG_NETFILTER_XT_MATCH_LIMIT=m -CONFIG_NETFILTER_XT_MATCH_MAC=m -CONFIG_NETFILTER_XT_MATCH_MARK=m -CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m -CONFIG_NETFILTER_XT_MATCH_QUOTA=m -CONFIG_NETFILTER_XT_MATCH_REALM=m -CONFIG_NETFILTER_XT_MATCH_SCTP=m -CONFIG_NETFILTER_XT_MATCH_STATE=m -CONFIG_NETFILTER_XT_MATCH_STATISTIC=m -CONFIG_NETFILTER_XT_MATCH_STRING=m -CONFIG_NETFILTER_XT_MATCH_TCPMSS=m - # # IP: Netfilter Configuration # CONFIG_IP_NF_CONNTRACK=m # CONFIG_IP_NF_CT_ACCT is not set CONFIG_IP_NF_CONNTRACK_MARK=y -# CONFIG_IP_NF_CONNTRACK_EVENTS is not set -# CONFIG_IP_NF_CONNTRACK_NETLINK is not set # CONFIG_IP_NF_CT_PROTO_SCTP is not set CONFIG_IP_NF_FTP=m CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_NETBIOS_NS is not set CONFIG_IP_NF_TFTP=m CONFIG_IP_NF_AMANDA=m -# CONFIG_IP_NF_PPTP is not set -# CONFIG_IP_NF_H323 is not set -# CONFIG_IP_NF_SIP is not set CONFIG_IP_NF_QUEUE=m -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_ARPTABLES is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_DCCP is not set +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_MAC=m +CONFIG_IP_NF_MATCH_PKTTYPE=m +CONFIG_IP_NF_MATCH_MARK=m +CONFIG_IP_NF_MATCH_MULTIPORT=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH_ESP=m +CONFIG_IP_NF_MATCH_LENGTH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_TCPMSS=m +CONFIG_IP_NF_MATCH_HELPER=m +CONFIG_IP_NF_MATCH_STATE=m +CONFIG_IP_NF_MATCH_CONNTRACK=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_REALM=m +CONFIG_IP_NF_MATCH_SCTP=m +CONFIG_IP_NF_MATCH_COMMENT=m +CONFIG_IP_NF_MATCH_CONNMARK=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +CONFIG_IP_NF_NAT_SNMP_BASIC=m +CONFIG_IP_NF_NAT_IRC=m +CONFIG_IP_NF_NAT_FTP=m +CONFIG_IP_NF_NAT_TFTP=m +CONFIG_IP_NF_NAT_AMANDA=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_CLASSIFY=m +CONFIG_IP_NF_TARGET_CONNMARK=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_TARGET_NOTRACK=m +CONFIG_IP_NF_ARPTABLES=m +# CONFIG_IP_NF_ARPFILTER is not set +# CONFIG_IP_NF_ARP_MANGLE is not set # # SCTP Configuration (EXPERIMENTAL) # # CONFIG_IP_SCTP is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# -# CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set @@ -338,10 +326,6 @@ CONFIG_IP_NF_QUEUE=m # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# # CONFIG_NET_SCHED is not set CONFIG_NET_CLS_ROUTE=y @@ -349,11 +333,13 @@ CONFIG_NET_CLS_ROUTE=y # Network testing # # CONFIG_NET_PKTGEN is not set +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set -# CONFIG_IEEE80211 is not set -CONFIG_WIRELESS_EXT=y # # Device Drivers @@ -366,12 +352,6 @@ CONFIG_WIRELESS_EXT=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=m # CONFIG_DEBUG_DRIVER is not set -# CONFIG_SYS_HYPERVISOR is not set - -# -# Connector - unified userspace <-> kernelspace linker -# -# CONFIG_CONNECTOR is not set # # Memory Technology Devices (MTD) @@ -387,7 +367,6 @@ CONFIG_PARPORT_SERIAL=m CONFIG_PARPORT_PC_FIFO=y CONFIG_PARPORT_PC_SUPERIO=y # CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_AX88796 is not set CONFIG_PARPORT_1284=y # @@ -399,6 +378,7 @@ CONFIG_PARPORT_1284=y # Block devices # CONFIG_BLK_DEV_FD=m +CONFIG_MAC_FLOPPY=m # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set @@ -414,9 +394,18 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_LBD=y # CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y # CONFIG_ATA_OVER_ETH is not set # @@ -433,7 +422,7 @@ CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set +CONFIG_BLK_DEV_IDEFLOPPY=y CONFIG_BLK_DEV_IDESCSI=y # CONFIG_IDE_TASK_IOCTL is not set @@ -446,7 +435,7 @@ CONFIG_IDEPCI_SHARE_IRQ=y # CONFIG_BLK_DEV_OFFBOARD is not set CONFIG_BLK_DEV_GENERIC=y # CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_SL82C105=y +# CONFIG_BLK_DEV_SL82C105 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set CONFIG_IDEDMA_PCI_AUTO=y @@ -454,7 +443,7 @@ CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_BLK_DEV_CMD64X is not set +CONFIG_BLK_DEV_CMD64X=y # CONFIG_BLK_DEV_TRIFLEX is not set # CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CS5520 is not set @@ -466,12 +455,17 @@ CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_BLK_DEV_IT821X is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +# CONFIG_PDC202XX_FORCE is not set # CONFIG_BLK_DEV_SVWKS is not set # CONFIG_BLK_DEV_SIIMAGE is not set # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_BLK_DEV_IDE_PMAC=y +CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y +CONFIG_BLK_DEV_IDEDMA_PMAC=y +CONFIG_BLK_DEV_IDE_PMAC_BLINK=y # CONFIG_IDE_ARM is not set # CONFIG_IDE_CHIPSETS is not set CONFIG_BLK_DEV_IDEDMA=y @@ -482,7 +476,6 @@ CONFIG_IDEDMA_AUTO=y # # SCSI device support # -# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_PROC_FS=y @@ -510,12 +503,10 @@ CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_ATTRS is not set # # SCSI low-level drivers # -# CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_7000FASST is not set @@ -523,16 +514,19 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_AHA152X is not set # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +CONFIG_AIC7XXX_DEBUG_ENABLE=y +CONFIG_AIC7XXX_DEBUG_MASK=0 +CONFIG_AIC7XXX_REG_PRETTY_PRINT=y +CONFIG_SCSI_AIC7XXX_OLD=m # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_MEGARAID_NEWGEN is not set # CONFIG_MEGARAID_LEGACY is not set -# CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_SATA is not set -# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DTC3280 is not set @@ -551,13 +545,19 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_QLA_FC is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_DC395x is not set @@ -566,6 +566,10 @@ CONFIG_SCSI_SYM53C8XX_MMIO=y # CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set +CONFIG_SCSI_MESH=y +CONFIG_SCSI_MESH_SYNC_RATE=5 +CONFIG_SCSI_MESH_RESET_DELAY_MS=4000 +CONFIG_SCSI_MAC53C94=y # # Old CD-ROM drivers (not SCSI, not IDE) @@ -583,7 +587,6 @@ CONFIG_SCSI_SYM53C8XX_MMIO=y # CONFIG_FUSION is not set # CONFIG_FUSION_SPI is not set # CONFIG_FUSION_FC is not set -# CONFIG_FUSION_SAS is not set # # IEEE 1394 (FireWire) support @@ -610,9 +613,12 @@ CONFIG_IEEE1394_OHCI1394=m # CONFIG_IEEE1394_VIDEO1394=m CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set CONFIG_IEEE1394_ETH1394=m CONFIG_IEEE1394_DV1394=m CONFIG_IEEE1394_RAWIO=m +CONFIG_IEEE1394_CMP=m +CONFIG_IEEE1394_AMDTP=m # # I2O device support @@ -622,7 +628,18 @@ CONFIG_IEEE1394_RAWIO=m # # Macintosh device drivers # -# CONFIG_WINDFARM is not set +CONFIG_ADB=y +CONFIG_ADB_CUDA=y +CONFIG_ADB_PMU=y +CONFIG_PMAC_APM_EMU=y +CONFIG_PMAC_MEDIABAY=y +CONFIG_PMAC_BACKLIGHT=y +CONFIG_ADB_MACIO=y +CONFIG_INPUT_ADBHID=y +CONFIG_MAC_EMUMOUSEBTN=y +CONFIG_THERM_WINDTUNNEL=m +CONFIG_THERM_ADT746X=m +# CONFIG_ANSLCD is not set # # Network device support @@ -638,19 +655,16 @@ CONFIG_TUN=m # # CONFIG_ARCNET is not set -# -# PHY device support -# -# CONFIG_PHYLIB is not set - # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y +CONFIG_MACE=y +# CONFIG_MACE_AAUI_PORT is not set +CONFIG_BMAC=y # CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_CASSINI is not set +CONFIG_SUNGEM=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set @@ -668,7 +682,6 @@ CONFIG_TULIP_MMIO=y CONFIG_DE4X5=m # CONFIG_WINBOND_840 is not set # CONFIG_DM9102 is not set -# CONFIG_ULI526X is not set # CONFIG_PCMCIA_XIRCOM is not set # CONFIG_PCMCIA_XIRTULIP is not set # CONFIG_AT1700 is not set @@ -709,21 +722,18 @@ CONFIG_PCNET32=y # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set # CONFIG_SKGE is not set -# CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set # CONFIG_TIGON3 is not set # CONFIG_BNX2 is not set +# CONFIG_MV643XX_ETH is not set # # Ethernet (10000 Mbit) # -# CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set -# CONFIG_MYRI10GE is not set # # Token Ring devices @@ -734,7 +744,6 @@ CONFIG_PCNET32=y # Wireless LAN (non-hamradio) # CONFIG_NET_RADIO=y -# CONFIG_NET_WIRELESS_RTNETLINK is not set # # Obsolete Wireless cards support (pre-802.11) @@ -746,13 +755,11 @@ CONFIG_NET_RADIO=y # # Wireless 802.11b ISA/PCI cards support # -# CONFIG_IPW2100 is not set -# CONFIG_IPW2200 is not set # CONFIG_AIRO is not set CONFIG_HERMES=m +CONFIG_APPLE_AIRPORT=m # CONFIG_PLX_HERMES is not set # CONFIG_TMD_HERMES is not set -# CONFIG_NORTEL_HERMES is not set # CONFIG_PCI_HERMES is not set # CONFIG_ATMEL is not set @@ -760,8 +767,6 @@ CONFIG_HERMES=m # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support # # CONFIG_PRISM54 is not set -# CONFIG_USB_ZD1201 is not set -# CONFIG_HOSTAP is not set CONFIG_NET_WIRELESS=y # @@ -778,16 +783,11 @@ CONFIG_PPP_ASYNC=y # CONFIG_PPP_SYNC_TTY is not set CONFIG_PPP_DEFLATE=y CONFIG_PPP_BSDCOMP=m -# CONFIG_PPP_MPPE is not set CONFIG_PPPOE=m # CONFIG_SLIP is not set # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set CONFIG_NETCONSOLE=m -CONFIG_NETPOLL=y -# CONFIG_NETPOLL_RX is not set -# CONFIG_NETPOLL_TRAP is not set -CONFIG_NET_POLL_CONTROLLER=y # # ISDN subsystem @@ -835,7 +835,7 @@ CONFIG_MOUSE_PS2=y # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set CONFIG_INPUT_MISC=y -CONFIG_INPUT_PCSPKR=m +# CONFIG_INPUT_PCSPKR is not set CONFIG_INPUT_UINPUT=m # @@ -856,7 +856,6 @@ CONFIG_SERIO_LIBPS2=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -864,9 +863,7 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_PCI=y CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -874,6 +871,8 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4 # CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_PMACZILOG=y +CONFIG_SERIAL_PMACZILOG_CONSOLE=y # CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y @@ -891,7 +890,6 @@ CONFIG_LEGACY_PTY_COUNT=256 # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_HW_RANDOM is not set CONFIG_NVRAM=y CONFIG_GEN_RTC=y # CONFIG_GEN_RTC_X is not set @@ -902,15 +900,21 @@ CONFIG_GEN_RTC=y # # Ftape, the floppy tape device driver # -# CONFIG_AGP is not set -# CONFIG_DRM is not set +CONFIG_AGP=m +CONFIG_AGP_UNINORTH=m +CONFIG_DRM=m +# CONFIG_DRM_TDFX is not set +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +# CONFIG_DRM_MGA is not set +# CONFIG_DRM_SIS is not set +# CONFIG_DRM_VIA is not set # CONFIG_RAW_DRIVER is not set # # TPM devices # # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set # # I2C support @@ -934,16 +938,19 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_AMD756 is not set # CONFIG_I2C_AMD8111 is not set # CONFIG_I2C_ELEKTOR is not set +CONFIG_I2C_HYDRA=y # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_ISA is not set +CONFIG_I2C_KEYWEST=m # CONFIG_I2C_MPC is not set # CONFIG_I2C_NFORCE2 is not set -# CONFIG_I2C_OCORES is not set # CONFIG_I2C_PARPORT is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set @@ -952,6 +959,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_VIAPRO is not set # CONFIG_I2C_VOODOO3 is not set # CONFIG_I2C_PCA_ISA is not set +# CONFIG_I2C_SENSOR is not set # # Miscellaneous I2C Chip support @@ -962,6 +970,7 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_RTC8564 is not set # CONFIG_SENSORS_M41T00 is not set # CONFIG_SENSORS_MAX6875 is not set # CONFIG_I2C_DEBUG_CORE is not set @@ -969,21 +978,15 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set -# -# SPI support -# -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set - # # Dallas's 1-wire bus # +# CONFIG_W1 is not set # # Hardware Monitoring support # # CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set # # Misc devices @@ -993,36 +996,38 @@ CONFIG_I2C_ALGOBIT=y # Multimedia devices # # CONFIG_VIDEO_DEV is not set -CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set -# CONFIG_USB_DABUSB is not set # # Graphics support # -# CONFIG_FIRMWARE_EDID is not set CONFIG_FB=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_SOFT_CURSOR=y +CONFIG_FB_MACMODES=y CONFIG_FB_MODE_HELPERS=y CONFIG_FB_TILEBLITTING=y # CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_CT65550 is not set +CONFIG_FB_OF=y +CONFIG_FB_CONTROL=y +CONFIG_FB_PLATINUM=y +CONFIG_FB_VALKYRIE=y +CONFIG_FB_CT65550=y # CONFIG_FB_ASILIANT is not set -# CONFIG_FB_IMSTT is not set +CONFIG_FB_IMSTT=y # CONFIG_FB_VGA16 is not set -# CONFIG_FB_S1D13XXX is not set # CONFIG_FB_NVIDIA is not set -# CONFIG_FB_RIVA is not set +CONFIG_FB_RIVA=y +CONFIG_FB_RIVA_I2C=y +# CONFIG_FB_RIVA_DEBUG is not set CONFIG_FB_MATROX=y CONFIG_FB_MATROX_MILLENIUM=y CONFIG_FB_MATROX_MYSTIQUE=y @@ -1030,27 +1035,34 @@ CONFIG_FB_MATROX_G=y CONFIG_FB_MATROX_I2C=y CONFIG_FB_MATROX_MAVEN=m # CONFIG_FB_MATROX_MULTIHEAD is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set +# CONFIG_FB_RADEON_OLD is not set +CONFIG_FB_RADEON=y +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=y +CONFIG_FB_ATY=y +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_XL_INIT=y +CONFIG_FB_ATY_GX=y # CONFIG_FB_SAVAGE is not set # CONFIG_FB_SIS is not set # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_KYRO is not set -# CONFIG_FB_3DFX is not set +CONFIG_FB_3DFX=y +# CONFIG_FB_3DFX_ACCEL is not set # CONFIG_FB_VOODOO1 is not set # CONFIG_FB_TRIDENT is not set +# CONFIG_FB_S1D13XXX is not set # CONFIG_FB_VIRTUAL is not set # # Console display driver support # CONFIG_VGA_CONSOLE=y -# CONFIG_VGACON_SOFT_SCROLLBACK is not set # CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set # CONFIG_FONTS is not set CONFIG_FONT_8x8=y CONFIG_FONT_8x16=y @@ -1068,6 +1080,8 @@ CONFIG_LOGO_LINUX_CLUT224=y # Sound # CONFIG_SOUND=m +CONFIG_DMASOUND_PMAC=m +CONFIG_DMASOUND=m # # Advanced Linux Sound Architecture @@ -1082,13 +1096,10 @@ CONFIG_SND_SEQUENCER=m CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=m CONFIG_SND_PCM_OSS=m -CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y -# CONFIG_SND_DYNAMIC_MINORS is not set -CONFIG_SND_SUPPORT_OLD_API=y -CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set +CONFIG_SND_GENERIC_PM=y # # Generic devices @@ -1105,9 +1116,7 @@ CONFIG_SND_OPL3_LIB=m # ISA devices # CONFIG_SND_CS4231_LIB=m -# CONFIG_SND_ADLIB is not set # CONFIG_SND_AD1848 is not set -# CONFIG_SND_CMI8330 is not set # CONFIG_SND_CS4231 is not set CONFIG_SND_CS4232=m # CONFIG_SND_CS4236 is not set @@ -1116,24 +1125,23 @@ CONFIG_SND_CS4232=m # CONFIG_SND_GUSCLASSIC is not set # CONFIG_SND_GUSEXTREME is not set # CONFIG_SND_GUSMAX is not set -# CONFIG_SND_OPL3SA2 is not set +# CONFIG_SND_INTERWAVE is not set +# CONFIG_SND_INTERWAVE_STB is not set # CONFIG_SND_OPTI92X_AD1848 is not set # CONFIG_SND_OPTI92X_CS4231 is not set # CONFIG_SND_OPTI93X is not set -# CONFIG_SND_MIRO is not set # CONFIG_SND_SB8 is not set # CONFIG_SND_SB16 is not set # CONFIG_SND_SBAWE is not set +# CONFIG_SND_WAVEFRONT is not set +# CONFIG_SND_CMI8330 is not set +# CONFIG_SND_OPL3SA2 is not set # CONFIG_SND_SGALAXY is not set # CONFIG_SND_SSCAPE is not set -# CONFIG_SND_WAVEFRONT is not set # # PCI devices # -# CONFIG_SND_AD1889 is not set -# CONFIG_SND_ALS300 is not set -# CONFIG_SND_ALS4000 is not set # CONFIG_SND_ALI5451 is not set # CONFIG_SND_ATIIXP is not set # CONFIG_SND_ATIIXP_MODEM is not set @@ -1142,61 +1150,43 @@ CONFIG_SND_CS4232=m # CONFIG_SND_AU8830 is not set # CONFIG_SND_AZT3328 is not set # CONFIG_SND_BT87X is not set -# CONFIG_SND_CA0106 is not set -# CONFIG_SND_CMIPCI is not set -# CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set -# CONFIG_SND_DARLA20 is not set -# CONFIG_SND_GINA20 is not set -# CONFIG_SND_LAYLA20 is not set -# CONFIG_SND_DARLA24 is not set -# CONFIG_SND_GINA24 is not set -# CONFIG_SND_LAYLA24 is not set -# CONFIG_SND_MONA is not set -# CONFIG_SND_MIA is not set -# CONFIG_SND_ECHO3G is not set -# CONFIG_SND_INDIGO is not set -# CONFIG_SND_INDIGOIO is not set -# CONFIG_SND_INDIGODJ is not set +# CONFIG_SND_CS4281 is not set # CONFIG_SND_EMU10K1 is not set # CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_YMFPCI is not set +# CONFIG_SND_ALS4000 is not set +# CONFIG_SND_CMIPCI is not set # CONFIG_SND_ENS1370 is not set # CONFIG_SND_ENS1371 is not set # CONFIG_SND_ES1938 is not set # CONFIG_SND_ES1968 is not set +# CONFIG_SND_MAESTRO3 is not set # CONFIG_SND_FM801 is not set -# CONFIG_SND_HDA_INTEL is not set -# CONFIG_SND_HDSP is not set -# CONFIG_SND_HDSPM is not set # CONFIG_SND_ICE1712 is not set # CONFIG_SND_ICE1724 is not set # CONFIG_SND_INTEL8X0 is not set # CONFIG_SND_INTEL8X0M is not set -# CONFIG_SND_KORG1212 is not set -# CONFIG_SND_MAESTRO3 is not set -# CONFIG_SND_MIXART is not set -# CONFIG_SND_NM256 is not set -# CONFIG_SND_PCXHR is not set -# CONFIG_SND_RIPTIDE is not set -# CONFIG_SND_RME32 is not set -# CONFIG_SND_RME96 is not set -# CONFIG_SND_RME9652 is not set # CONFIG_SND_SONICVIBES is not set -# CONFIG_SND_TRIDENT is not set # CONFIG_SND_VIA82XX is not set # CONFIG_SND_VIA82XX_MODEM is not set # CONFIG_SND_VX222 is not set -# CONFIG_SND_YMFPCI is not set +# CONFIG_SND_HDA_INTEL is not set # # ALSA PowerMac devices # - -# -# Apple Onboard Audio driver -# -# CONFIG_SND_AOA is not set -# CONFIG_SND_AOA_SOUNDBUS is not set +CONFIG_SND_POWERMAC=m # # USB devices @@ -1214,7 +1204,6 @@ CONFIG_SND_USB_AUDIO=m # CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y -CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -1233,7 +1222,6 @@ CONFIG_USB_DEVICEFS=y CONFIG_USB_EHCI_HCD=m CONFIG_USB_EHCI_SPLIT_ISO=y CONFIG_USB_EHCI_ROOT_HUB_TT=y -# CONFIG_USB_EHCI_TT_NEWSCHED is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -1244,15 +1232,14 @@ CONFIG_USB_UHCI_HCD=m # # USB Device Class drivers # +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_MIDI is not set CONFIG_USB_ACM=m CONFIG_USB_PRINTER=m # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -# - -# -# may also be needed; see USB_STORAGE Help for more information +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information # CONFIG_USB_STORAGE=m # CONFIG_USB_STORAGE_DEBUG is not set @@ -1264,15 +1251,12 @@ CONFIG_USB_STORAGE_USBAT=y CONFIG_USB_STORAGE_SDDR09=y CONFIG_USB_STORAGE_SDDR55=y CONFIG_USB_STORAGE_JUMPSHOT=y -# CONFIG_USB_STORAGE_ALAUDA is not set -# CONFIG_USB_LIBUSUAL is not set # # USB Input Devices # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set # CONFIG_HID_FF is not set CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set @@ -1280,13 +1264,12 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -# CONFIG_USB_TOUCHSCREEN is not set -# CONFIG_USB_YEALINK is not set +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_ITMTOUCH is not set +# CONFIG_USB_EGALAX is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set -# CONFIG_USB_ATI_REMOTE2 is not set # CONFIG_USB_KEYSPAN_REMOTE is not set -# CONFIG_USB_APPLETOUCH is not set # # USB Imaging devices @@ -1294,6 +1277,15 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + # # USB Network Adapters # @@ -1302,6 +1294,7 @@ CONFIG_USB_HIDDEV=y CONFIG_USB_PEGASUS=m # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set +# CONFIG_USB_ZD1201 is not set # CONFIG_USB_MON is not set # @@ -1315,7 +1308,6 @@ CONFIG_USB_PEGASUS=m CONFIG_USB_SERIAL=m # CONFIG_USB_SERIAL_GENERIC is not set # CONFIG_USB_SERIAL_AIRPRIME is not set -# CONFIG_USB_SERIAL_ARK3116 is not set # CONFIG_USB_SERIAL_BELKIN is not set # CONFIG_USB_SERIAL_WHITEHEAT is not set # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set @@ -1323,7 +1315,6 @@ CONFIG_USB_SERIAL=m # CONFIG_USB_SERIAL_CYPRESS_M8 is not set # CONFIG_USB_SERIAL_EMPEG is not set # CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_FUNSOFT is not set CONFIG_USB_SERIAL_VISOR=m # CONFIG_USB_SERIAL_IPAQ is not set # CONFIG_USB_SERIAL_IR is not set @@ -1348,11 +1339,9 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y # CONFIG_USB_SERIAL_KLSI is not set # CONFIG_USB_SERIAL_KOBIL_SCT is not set # CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_NAVMAN is not set # CONFIG_USB_SERIAL_PL2303 is not set # CONFIG_USB_SERIAL_HP4X is not set # CONFIG_USB_SERIAL_SAFE is not set -# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set # CONFIG_USB_SERIAL_TI is not set # CONFIG_USB_SERIAL_CYBERJACK is not set # CONFIG_USB_SERIAL_XIRCOM is not set @@ -1370,12 +1359,10 @@ CONFIG_USB_EZUSB=y # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set -# CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set -# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TEST is not set @@ -1394,44 +1381,13 @@ CONFIG_USB_EZUSB=y # # CONFIG_MMC is not set -# -# LED devices -# -# CONFIG_NEW_LEDS is not set - -# -# LED drivers -# - -# -# LED Triggers -# - # # InfiniBand support # # CONFIG_INFINIBAND is not set # -# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) -# - -# -# Real Time Clock -# -# CONFIG_RTC_CLASS is not set - -# -# DMA Engine support -# -# CONFIG_DMA_ENGINE is not set - -# -# DMA Clients -# - -# -# DMA Devices +# SN Devices # # @@ -1461,21 +1417,23 @@ CONFIG_JFS_SECURITY=y # CONFIG_JFS_DEBUG is not set # CONFIG_JFS_STATISTICS is not set CONFIG_FS_POSIX_ACL=y + +# +# XFS support +# CONFIG_XFS_FS=m +CONFIG_XFS_EXPORT=y +# CONFIG_XFS_RT is not set # CONFIG_XFS_QUOTA is not set CONFIG_XFS_SECURITY=y CONFIG_XFS_POSIX_ACL=y -# CONFIG_XFS_RT is not set -# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=m -# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -1502,10 +1460,13 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y +CONFIG_TMPFS_XATTR=y +CONFIG_TMPFS_SECURITY=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -1524,7 +1485,6 @@ CONFIG_CRAMFS=m # CONFIG_SYSV_FS is not set CONFIG_UFS_FS=m # CONFIG_UFS_FS_WRITE is not set -# CONFIG_UFS_DEBUG is not set # # Network File Systems @@ -1553,7 +1513,6 @@ CONFIG_SUNRPC=y # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set # # Partition Types @@ -1573,7 +1532,6 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set -# CONFIG_KARMA_PARTITION is not set # CONFIG_EFI_PARTITION is not set # @@ -1624,44 +1582,33 @@ CONFIG_NLS_UTF8=m # Library routines # CONFIG_CRC_CCITT=y -# CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y -CONFIG_TEXTSEARCH=y -CONFIG_TEXTSEARCH_KMP=m -CONFIG_TEXTSEARCH_BM=m -CONFIG_TEXTSEARCH_FSM=m -CONFIG_PLIST=y + +# +# Profiling support +# # CONFIG_PROFILING is not set # # Kernel hacking # # CONFIG_PRINTK_TIME is not set -CONFIG_MAGIC_SYSRQ=y -# CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_KERNEL=y +CONFIG_MAGIC_SYSRQ=y CONFIG_LOG_BUF_SHIFT=14 -CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_RWSEMS is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_FS is not set -# CONFIG_DEBUG_VM is not set -CONFIG_FORCED_INLINING=y -# CONFIG_RCU_TORTURE_TEST is not set # CONFIG_XMON is not set # CONFIG_BDI_SWITCH is not set +CONFIG_BOOTX_TEXT=y # # Security options diff --git a/trunk/arch/ppc/kernel/misc.S b/trunk/arch/ppc/kernel/misc.S index 50b4bbd06804..2fa0075f2b5f 100644 --- a/trunk/arch/ppc/kernel/misc.S +++ b/trunk/arch/ppc/kernel/misc.S @@ -768,6 +768,91 @@ _GLOBAL(_outsb) bdnz 00b blr +_GLOBAL(_insw) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,2 + blelr- +00: lhbrx r5,0,r3 +01: eieio +02: sthu r5,2(r4) + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text + bdnz 00b + blr + +_GLOBAL(_outsw) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,2 + blelr- +00: lhzu r5,2(r4) +01: eieio +02: sthbrx r5,0,r3 + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text + bdnz 00b + blr + +_GLOBAL(_insl) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,4 + blelr- +00: lwbrx r5,0,r3 +01: eieio +02: stwu r5,4(r4) + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text + bdnz 00b + blr + +_GLOBAL(_outsl) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,4 + blelr- +00: lwzu r5,4(r4) +01: stwbrx r5,0,r3 +02: eieio + ISYNC_8xx + .section .fixup,"ax" +03: blr + .text + .section __ex_table, "a" + .align 2 + .long 00b, 03b + .long 01b, 03b + .long 02b, 03b + .text + bdnz 00b + blr + +_GLOBAL(__ide_mm_insw) _GLOBAL(_insw_ns) cmpwi 0,r5,0 mtctr r5 @@ -789,6 +874,7 @@ _GLOBAL(_insw_ns) bdnz 00b blr +_GLOBAL(__ide_mm_outsw) _GLOBAL(_outsw_ns) cmpwi 0,r5,0 mtctr r5 @@ -810,6 +896,7 @@ _GLOBAL(_outsw_ns) bdnz 00b blr +_GLOBAL(__ide_mm_insl) _GLOBAL(_insl_ns) cmpwi 0,r5,0 mtctr r5 @@ -831,6 +918,7 @@ _GLOBAL(_insl_ns) bdnz 00b blr +_GLOBAL(__ide_mm_outsl) _GLOBAL(_outsl_ns) cmpwi 0,r5,0 mtctr r5 diff --git a/trunk/arch/ppc/kernel/ppc_ksyms.c b/trunk/arch/ppc/kernel/ppc_ksyms.c index c8b65ca8a350..d1735401384c 100644 --- a/trunk/arch/ppc/kernel/ppc_ksyms.c +++ b/trunk/arch/ppc/kernel/ppc_ksyms.c @@ -115,8 +115,17 @@ EXPORT_SYMBOL(outw); EXPORT_SYMBOL(outl); EXPORT_SYMBOL(outsl);*/ +EXPORT_SYMBOL(__ide_mm_insl); +EXPORT_SYMBOL(__ide_mm_outsw); +EXPORT_SYMBOL(__ide_mm_insw); +EXPORT_SYMBOL(__ide_mm_outsl); + EXPORT_SYMBOL(_insb); EXPORT_SYMBOL(_outsb); +EXPORT_SYMBOL(_insw); +EXPORT_SYMBOL(_outsw); +EXPORT_SYMBOL(_insl); +EXPORT_SYMBOL(_outsl); EXPORT_SYMBOL(_insw_ns); EXPORT_SYMBOL(_outsw_ns); EXPORT_SYMBOL(_insl_ns); diff --git a/trunk/arch/ppc/kernel/setup.c b/trunk/arch/ppc/kernel/setup.c index 5458ac5da7c3..a74f46d9826f 100644 --- a/trunk/arch/ppc/kernel/setup.c +++ b/trunk/arch/ppc/kernel/setup.c @@ -127,8 +127,11 @@ void machine_restart(char *cmd) ppc_md.restart(cmd); } -static void ppc_generic_power_off(void) +void machine_power_off(void) { +#ifdef CONFIG_NVRAM + nvram_sync(); +#endif ppc_md.power_off(); } @@ -140,17 +143,7 @@ void machine_halt(void) ppc_md.halt(); } -void (*pm_power_off)(void) = ppc_generic_power_off; - -void machine_power_off(void) -{ -#ifdef CONFIG_NVRAM - nvram_sync(); -#endif - if (pm_power_off) - pm_power_off(); - ppc_generic_power_off(); -} +void (*pm_power_off)(void) = machine_power_off; #ifdef CONFIG_TAU extern u32 cpu_temp(unsigned long cpu); diff --git a/trunk/arch/ppc/kernel/smp-tbsync.c b/trunk/arch/ppc/kernel/smp-tbsync.c index d0cf3f86931d..1576758debaf 100644 --- a/trunk/arch/ppc/kernel/smp-tbsync.c +++ b/trunk/arch/ppc/kernel/smp-tbsync.c @@ -47,9 +47,8 @@ void __devinit smp_generic_take_timebase( void ) { int cmd, tbl, tbu; - unsigned long flags; - local_irq_save(flags); + local_irq_disable(); while( !running ) ; rmb(); @@ -65,7 +64,7 @@ smp_generic_take_timebase( void ) tbu = tbsync->tbu; tbsync->ack = 0; if( cmd == kExit ) - break; + return; if( cmd == kSetAndTest ) { while( tbsync->handshake ) @@ -78,7 +77,7 @@ smp_generic_take_timebase( void ) } enter_contest( tbsync->mark, -1 ); } - local_irq_restore(flags); + local_irq_enable(); } static int __devinit diff --git a/trunk/arch/ppc/kernel/vmlinux.lds.S b/trunk/arch/ppc/kernel/vmlinux.lds.S index 095fd3323323..09c6525cfa61 100644 --- a/trunk/arch/ppc/kernel/vmlinux.lds.S +++ b/trunk/arch/ppc/kernel/vmlinux.lds.S @@ -8,7 +8,6 @@ SECTIONS . = + SIZEOF_HEADERS; .interp : { *(.interp) } .hash : { *(.hash) } - .gnu.hash : { *(.gnu.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .rel.text : { *(.rel.text) } diff --git a/trunk/arch/ppc/platforms/85xx/mpc8560_ads.c b/trunk/arch/ppc/platforms/85xx/mpc8560_ads.c index 94badafe4ef1..d90cd24d018e 100644 --- a/trunk/arch/ppc/platforms/85xx/mpc8560_ads.c +++ b/trunk/arch/ppc/platforms/85xx/mpc8560_ads.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -59,71 +58,6 @@ * Setup the architecture * */ -static void init_fcc_ioports(void) -{ - struct immap *immap; - struct io_port *io; - u32 tempval; - - immap = cpm2_immr; - - io = &immap->im_ioport; - /* FCC2/3 are on the ports B/C. */ - tempval = in_be32(&io->iop_pdirb); - tempval &= ~PB2_DIRB0; - tempval |= PB2_DIRB1; - out_be32(&io->iop_pdirb, tempval); - - tempval = in_be32(&io->iop_psorb); - tempval &= ~PB2_PSORB0; - tempval |= PB2_PSORB1; - out_be32(&io->iop_psorb, tempval); - - tempval = in_be32(&io->iop_pparb); - tempval |= (PB2_DIRB0 | PB2_DIRB1); - out_be32(&io->iop_pparb, tempval); - - tempval = in_be32(&io->iop_pdirb); - tempval &= ~PB3_DIRB0; - tempval |= PB3_DIRB1; - out_be32(&io->iop_pdirb, tempval); - - tempval = in_be32(&io->iop_psorb); - tempval &= ~PB3_PSORB0; - tempval |= PB3_PSORB1; - out_be32(&io->iop_psorb, tempval); - - tempval = in_be32(&io->iop_pparb); - tempval |= (PB3_DIRB0 | PB3_DIRB1); - out_be32(&io->iop_pparb, tempval); - - tempval = in_be32(&io->iop_pdirc); - tempval |= PC3_DIRC1; - out_be32(&io->iop_pdirc, tempval); - - tempval = in_be32(&io->iop_pparc); - tempval |= PC3_DIRC1; - out_be32(&io->iop_pparc, tempval); - - /* Port C has clocks...... */ - tempval = in_be32(&io->iop_psorc); - tempval &= ~(CLK_TRX); - out_be32(&io->iop_psorc, tempval); - - tempval = in_be32(&io->iop_pdirc); - tempval &= ~(CLK_TRX); - out_be32(&io->iop_pdirc, tempval); - tempval = in_be32(&io->iop_pparc); - tempval |= (CLK_TRX); - out_be32(&io->iop_pparc, tempval); - - /* Configure Serial Interface clock routing. - * First, clear all FCC bits to zero, - * then set the ones we want. - */ - immap->im_cpmux.cmx_fcr &= ~(CPMUX_CLK_MASK); - immap->im_cpmux.cmx_fcr |= CPMUX_CLK_ROUTE; -} static void __init mpc8560ads_setup_arch(void) @@ -132,7 +66,6 @@ mpc8560ads_setup_arch(void) unsigned int freq; struct gianfar_platform_data *pdata; struct gianfar_mdio_data *mdata; - struct fs_platform_info *fpi; cpm2_reset(); @@ -177,28 +110,6 @@ mpc8560ads_setup_arch(void) memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); } - init_fcc_ioports(); - ppc_sys_device_remove(MPC85xx_CPM_FCC1); - - fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC2); - if (fpi) { - memcpy(fpi->macaddr, binfo->bi_enet2addr, 6); - fpi->bus_id = "0:02"; - fpi->phy_addr = 2; - fpi->dpram_offset = (u32)cpm2_immr->im_dprambase; - fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[1]; - } - - fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC3); - if (fpi) { - memcpy(fpi->macaddr, binfo->bi_enet2addr, 6); - fpi->macaddr[5] += 1; - fpi->bus_id = "0:03"; - fpi->phy_addr = 3; - fpi->dpram_offset = (u32)cpm2_immr->im_dprambase; - fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[2]; - } - #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) ROOT_DEV = Root_RAM0; diff --git a/trunk/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/trunk/arch/ppc/platforms/85xx/mpc85xx_ads_common.h index c8c322fe3680..abf32281655d 100644 --- a/trunk/arch/ppc/platforms/85xx/mpc85xx_ads_common.h +++ b/trunk/arch/ppc/platforms/85xx/mpc85xx_ads_common.h @@ -45,23 +45,4 @@ extern void mpc85xx_ads_map_io(void) __init; #define MPC85XX_PCI1_IO_SIZE 0x01000000 -/* FCC1 Clock Source Configuration. These can be - * redefined in the board specific file. - * Can only choose from CLK9-12 */ -#define F1_RXCLK 12 -#define F1_TXCLK 11 - -/* FCC2 Clock Source Configuration. These can be - * redefined in the board specific file. - * Can only choose from CLK13-16 */ -#define F2_RXCLK 13 -#define F2_TXCLK 14 - -/* FCC3 Clock Source Configuration. These can be - * redefined in the board specific file. - * Can only choose from CLK13-16 */ -#define F3_RXCLK 15 -#define F3_TXCLK 16 - - #endif /* __MACH_MPC85XX_ADS_H__ */ diff --git a/trunk/arch/ppc/platforms/85xx/sbc8560.h b/trunk/arch/ppc/platforms/85xx/sbc8560.h index e5e156f60100..c7d61cf3a449 100644 --- a/trunk/arch/ppc/platforms/85xx/sbc8560.h +++ b/trunk/arch/ppc/platforms/85xx/sbc8560.h @@ -14,7 +14,6 @@ #define __MACH_SBC8560_H__ #include -#include #define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET) diff --git a/trunk/arch/ppc/platforms/85xx/sbc85xx.h b/trunk/arch/ppc/platforms/85xx/sbc85xx.h index 51df4dc04e22..21ea7a55639b 100644 --- a/trunk/arch/ppc/platforms/85xx/sbc85xx.h +++ b/trunk/arch/ppc/platforms/85xx/sbc85xx.h @@ -49,22 +49,4 @@ extern void sbc8560_init_IRQ(void) __init; #define MPC85XX_PCI1_IO_SIZE 0x01000000 -/* FCC1 Clock Source Configuration. These can be - * redefined in the board specific file. - * Can only choose from CLK9-12 */ -#define F1_RXCLK 12 -#define F1_TXCLK 11 - -/* FCC2 Clock Source Configuration. These can be - * redefined in the board specific file. - * Can only choose from CLK13-16 */ -#define F2_RXCLK 13 -#define F2_TXCLK 14 - -/* FCC3 Clock Source Configuration. These can be - * redefined in the board specific file. - * Can only choose from CLK13-16 */ -#define F3_RXCLK 15 -#define F3_TXCLK 16 - #endif /* __PLATFORMS_85XX_SBC85XX_H__ */ diff --git a/trunk/arch/ppc/platforms/mpc8272ads_setup.c b/trunk/arch/ppc/platforms/mpc8272ads_setup.c index 2a35fe2b9b96..abb7154de2c7 100644 --- a/trunk/arch/ppc/platforms/mpc8272ads_setup.c +++ b/trunk/arch/ppc/platforms/mpc8272ads_setup.c @@ -56,51 +56,64 @@ static struct fs_uart_platform_info mpc8272_uart_pdata[] = { }, }; -static struct fs_mii_bb_platform_info m82xx_mii_bb_pdata = { - .mdio_dat.bit = 18, - .mdio_dir.bit = 18, - .mdc_dat.bit = 19, - .delay = 1, +static struct fs_mii_bus_info mii_bus_info = { + .method = fsmii_bitbang, + .id = 0, + .i.bitbang = { + .mdio_port = fsiop_portc, + .mdio_bit = 18, + .mdc_port = fsiop_portc, + .mdc_bit = 19, + .delay = 1, + }, }; -static struct fs_platform_info mpc82xx_enet_pdata[] = { - [fsid_fcc1] = { - .fs_no = fsid_fcc1, - .cp_page = CPM_CR_FCC1_PAGE, - .cp_block = CPM_CR_FCC1_SBLOCK, - - .clk_trx = (PC_F1RXCLK | PC_F1TXCLK), - .clk_route = CMX1_CLK_ROUTE, - .clk_mask = CMX1_CLK_MASK, - .init_ioports = init_fcc1_ioports, - - .mem_offset = FCC1_MEM_OFFSET, - - .rx_ring = 32, - .tx_ring = 32, - .rx_copybreak = 240, - .use_napi = 0, - .napi_weight = 17, - .bus_id = "0:00", - }, - [fsid_fcc2] = { - .fs_no = fsid_fcc2, - .cp_page = CPM_CR_FCC2_PAGE, - .cp_block = CPM_CR_FCC2_SBLOCK, - .clk_trx = (PC_F2RXCLK | PC_F2TXCLK), - .clk_route = CMX2_CLK_ROUTE, - .clk_mask = CMX2_CLK_MASK, - .init_ioports = init_fcc2_ioports, - - .mem_offset = FCC2_MEM_OFFSET, - - .rx_ring = 32, - .tx_ring = 32, - .rx_copybreak = 240, - .use_napi = 0, - .napi_weight = 17, - .bus_id = "0:03", - }, +static struct fs_platform_info mpc82xx_fcc1_pdata = { + .fs_no = fsid_fcc1, + .cp_page = CPM_CR_FCC1_PAGE, + .cp_block = CPM_CR_FCC1_SBLOCK, + .clk_trx = (PC_F1RXCLK | PC_F1TXCLK), + .clk_route = CMX1_CLK_ROUTE, + .clk_mask = CMX1_CLK_MASK, + .init_ioports = init_fcc1_ioports, + + .phy_addr = 0, +#ifdef PHY_INTERRUPT + .phy_irq = PHY_INTERRUPT, +#else + .phy_irq = -1; +#endif + .mem_offset = FCC1_MEM_OFFSET, + .bus_info = &mii_bus_info, + .rx_ring = 32, + .tx_ring = 32, + .rx_copybreak = 240, + .use_napi = 0, + .napi_weight = 17, +}; + +static struct fs_platform_info mpc82xx_fcc2_pdata = { + .fs_no = fsid_fcc2, + .cp_page = CPM_CR_FCC2_PAGE, + .cp_block = CPM_CR_FCC2_SBLOCK, + .clk_trx = (PC_F2RXCLK | PC_F2TXCLK), + .clk_route = CMX2_CLK_ROUTE, + .clk_mask = CMX2_CLK_MASK, + .init_ioports = init_fcc2_ioports, + + .phy_addr = 3, +#ifdef PHY_INTERRUPT + .phy_irq = PHY_INTERRUPT, +#else + .phy_irq = -1; +#endif + .mem_offset = FCC2_MEM_OFFSET, + .bus_info = &mii_bus_info, + .rx_ring = 32, + .tx_ring = 32, + .rx_copybreak = 240, + .use_napi = 0, + .napi_weight = 17, }; static void init_fcc1_ioports(void) @@ -196,21 +209,20 @@ static void __init mpc8272ads_fixup_enet_pdata(struct platform_device *pdev, bd_t* bi = (void*)__res; int fs_no = fsid_fcc1+pdev->id-1; - if(fs_no > ARRAY_SIZE(mpc82xx_enet_pdata)) { - return; + mpc82xx_fcc1_pdata.dpram_offset = mpc82xx_fcc2_pdata.dpram_offset = (u32)cpm2_immr->im_dprambase; + mpc82xx_fcc1_pdata.fcc_regs_c = mpc82xx_fcc2_pdata.fcc_regs_c = (u32)cpm2_immr->im_fcc_c; + + switch(fs_no) { + case fsid_fcc1: + memcpy(&mpc82xx_fcc1_pdata.macaddr,bi->bi_enetaddr,6); + pdev->dev.platform_data = &mpc82xx_fcc1_pdata; + break; + case fsid_fcc2: + memcpy(&mpc82xx_fcc2_pdata.macaddr,bi->bi_enetaddr,6); + mpc82xx_fcc2_pdata.macaddr[5] ^= 1; + pdev->dev.platform_data = &mpc82xx_fcc2_pdata; + break; } - - mpc82xx_enet_pdata[fs_no].dpram_offset= - (u32)cpm2_immr->im_dprambase; - mpc82xx_enet_pdata[fs_no].fcc_regs_c = - (u32)cpm2_immr->im_fcc_c; - memcpy(&mpc82xx_enet_pdata[fs_no].macaddr,bi->bi_enetaddr,6); - - /* prevent dup mac */ - if(fs_no == fsid_fcc2) - mpc82xx_enet_pdata[fs_no].macaddr[5] ^= 1; - - pdev->dev.platform_data = &mpc82xx_enet_pdata[fs_no]; } static void mpc8272ads_fixup_uart_pdata(struct platform_device *pdev, @@ -262,29 +274,6 @@ static void init_scc4_uart_ioports(void) iounmap(immap); } -static void __init mpc8272ads_fixup_mdio_pdata(struct platform_device *pdev, - int idx) -{ - m82xx_mii_bb_pdata.irq[0] = PHY_INTERRUPT; - m82xx_mii_bb_pdata.irq[1] = -1; - m82xx_mii_bb_pdata.irq[2] = -1; - m82xx_mii_bb_pdata.irq[3] = PHY_INTERRUPT; - m82xx_mii_bb_pdata.irq[31] = -1; - - - m82xx_mii_bb_pdata.mdio_dat.offset = - (u32)&cpm2_immr->im_ioport.iop_pdatc; - - m82xx_mii_bb_pdata.mdio_dir.offset = - (u32)&cpm2_immr->im_ioport.iop_pdirc; - - m82xx_mii_bb_pdata.mdc_dat.offset = - (u32)&cpm2_immr->im_ioport.iop_pdatc; - - - pdev->dev.platform_data = &m82xx_mii_bb_pdata; -} - static int mpc8272ads_platform_notify(struct device *dev) { static const struct platform_notify_dev_map dev_map[] = { @@ -296,10 +285,6 @@ static int mpc8272ads_platform_notify(struct device *dev) .bus_id = "fsl-cpm-scc:uart", .rtn = mpc8272ads_fixup_uart_pdata, }, - { - .bus_id = "fsl-bb-mdio", - .rtn = mpc8272ads_fixup_mdio_pdata, - }, { .bus_id = NULL } @@ -334,7 +319,6 @@ int __init mpc8272ads_init(void) ppc_sys_device_enable(MPC82xx_CPM_SCC4); #endif - ppc_sys_device_enable(MPC82xx_MDIO_BB); return 0; } diff --git a/trunk/arch/ppc/platforms/mpc866ads_setup.c b/trunk/arch/ppc/platforms/mpc866ads_setup.c index e12cece4c9fd..f19b6167c770 100644 --- a/trunk/arch/ppc/platforms/mpc866ads_setup.c +++ b/trunk/arch/ppc/platforms/mpc866ads_setup.c @@ -1,10 +1,10 @@ -/*arch/ppc/platforms/mpc866ads-setup.c +/*arch/ppc/platforms/mpc885ads-setup.c * - * Platform setup for the Freescale mpc866ads board + * Platform setup for the Freescale mpc885ads board * * Vitaly Bordug * - * Copyright 2005-2006 MontaVista Software Inc. + * Copyright 2005 MontaVista Software Inc. * * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any @@ -42,36 +42,49 @@ static void setup_scc1_ioports(void); static void setup_smc1_ioports(void); static void setup_smc2_ioports(void); -static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata; +static struct fs_mii_bus_info fec_mii_bus_info = { + .method = fsmii_fec, + .id = 0, +}; + +static struct fs_mii_bus_info scc_mii_bus_info = { + .method = fsmii_fixed, + .id = 0, + .i.fixed.speed = 10, + .i.fixed.duplex = 0, +}; -static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata; +static struct fs_platform_info mpc8xx_fec_pdata[] = { + { + .rx_ring = 128, + .tx_ring = 16, + .rx_copybreak = 240, -static struct fs_platform_info mpc8xx_enet_pdata[] = { - [fsid_fec1] = { - .rx_ring = 128, - .tx_ring = 16, - .rx_copybreak = 240, + .use_napi = 1, + .napi_weight = 17, - .use_napi = 1, - .napi_weight = 17, + .phy_addr = 15, + .phy_irq = -1, - .init_ioports = setup_fec1_ioports, + .use_rmii = 0, - .bus_id = "0:0f", - .has_phy = 1, - }, - [fsid_scc1] = { - .rx_ring = 64, - .tx_ring = 8, - .rx_copybreak = 240, - .use_napi = 1, - .napi_weight = 17, + .bus_info = &fec_mii_bus_info, + } +}; +static struct fs_platform_info mpc8xx_scc_pdata = { + .rx_ring = 64, + .tx_ring = 8, + .rx_copybreak = 240, - .init_ioports = setup_scc1_ioports, + .use_napi = 1, + .napi_weight = 17, + + .phy_addr = -1, + .phy_irq = -1, + + .bus_info = &scc_mii_bus_info, - .bus_id = "fixed@100:1", - }, }; static struct fs_uart_platform_info mpc866_uart_pdata[] = { @@ -194,6 +207,63 @@ static void setup_scc1_ioports(void) } +static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no) +{ + struct fs_platform_info *fpi = pdev->dev.platform_data; + + volatile cpm8xx_t *cp; + bd_t *bd = (bd_t *) __res; + char *e; + int i; + + /* Get pointer to Communication Processor */ + cp = cpmp; + switch (fs_no) { + case fsid_fec1: + fpi = &mpc8xx_fec_pdata[0]; + fpi->init_ioports = &setup_fec1_ioports; + + break; + case fsid_scc1: + fpi = &mpc8xx_scc_pdata; + fpi->init_ioports = &setup_scc1_ioports; + + break; + default: + printk(KERN_WARNING"Device %s is not supported!\n", pdev->name); + return; + } + + pdev->dev.platform_data = fpi; + fpi->fs_no = fs_no; + + e = (unsigned char *)&bd->bi_enetaddr; + for (i = 0; i < 6; i++) + fpi->macaddr[i] = *e++; + + fpi->macaddr[5 - pdev->id]++; + +} + +static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev, + int idx) +{ + /* This is for FEC devices only */ + if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec"))) + return; + mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1); +} + +static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev, + int idx) +{ + /* This is for SCC devices only */ + if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc"))) + return; + + mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1); +} + static void setup_smc1_ioports(void) { immap_t *immap = (immap_t *) IMAP_ADDR; @@ -245,56 +315,6 @@ static void setup_smc2_ioports(void) } -static int ma_count = 0; - -static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no) -{ - struct fs_platform_info *fpi; - - volatile cpm8xx_t *cp; - bd_t *bd = (bd_t *) __res; - char *e; - int i; - - /* Get pointer to Communication Processor */ - cp = cpmp; - - if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) { - printk(KERN_ERR"No network-suitable #%d device on bus", fs_no); - return; - } - - - fpi = &mpc8xx_enet_pdata[fs_no]; - fpi->fs_no = fs_no; - pdev->dev.platform_data = fpi; - - e = (unsigned char *)&bd->bi_enetaddr; - for (i = 0; i < 6; i++) - fpi->macaddr[i] = *e++; - - fpi->macaddr[5] += ma_count++; -} - -static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev, - int idx) -{ - /* This is for FEC devices only */ - if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec"))) - return; - mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1); -} - -static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev, - int idx) -{ - /* This is for SCC devices only */ - if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc"))) - return; - - mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1); -} - static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev, int idx) { @@ -339,9 +359,6 @@ static int mpc866ads_platform_notify(struct device *dev) int __init mpc866ads_init(void) { - bd_t *bd = (bd_t *) __res; - struct fs_mii_fec_platform_info* fmpi; - printk(KERN_NOTICE "mpc866ads: Init\n"); platform_notify = mpc866ads_platform_notify; @@ -349,20 +366,11 @@ int __init mpc866ads_init(void) ppc_sys_device_initfunc(); ppc_sys_device_disable_all(); -#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC1 +#ifdef MPC8xx_SECOND_ETH_SCC1 ppc_sys_device_enable(MPC8xx_CPM_SCC1); #endif ppc_sys_device_enable(MPC8xx_CPM_FEC1); - ppc_sys_device_enable(MPC8xx_MDIO_FEC); - - fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data = - &mpc8xx_mdio_fec_pdata; - - fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; - /* No PHY interrupt line here */ - fmpi->irq[0xf] = -1; - /* Since either of the uarts could be used as console, they need to ready */ #ifdef CONFIG_SERIAL_CPM_SMC1 ppc_sys_device_enable(MPC8xx_CPM_SMC1); @@ -373,14 +381,6 @@ int __init mpc866ads_init(void) ppc_sys_device_enable(MPC8xx_CPM_SMC2); ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART); #endif - ppc_sys_device_enable(MPC8xx_MDIO_FEC); - - fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data = - &mpc8xx_mdio_fec_pdata; - - fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; - /* No PHY interrupt line here */ - fmpi->irq[0xf] = -1; return 0; } diff --git a/trunk/arch/ppc/platforms/mpc885ads_setup.c b/trunk/arch/ppc/platforms/mpc885ads_setup.c index 5dfa4e6c2af0..c1fc4a16fea9 100644 --- a/trunk/arch/ppc/platforms/mpc885ads_setup.c +++ b/trunk/arch/ppc/platforms/mpc885ads_setup.c @@ -38,10 +38,7 @@ extern unsigned char __res[]; static void setup_smc1_ioports(void); static void setup_smc2_ioports(void); -static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata; -static void setup_fec1_ioports(void); -static void setup_fec2_ioports(void); -static void setup_scc3_ioports(void); +static void __init mpc885ads_scc_phy_init(char); static struct fs_uart_platform_info mpc885_uart_pdata[] = { [fsid_smc1_uart] = { @@ -64,8 +61,23 @@ static struct fs_uart_platform_info mpc885_uart_pdata[] = { }, }; -static struct fs_platform_info mpc8xx_enet_pdata[] = { - [fsid_fec1] = { +static struct fs_mii_bus_info fec_mii_bus_info = { + .method = fsmii_fec, + .id = 0, +}; + +static struct fs_mii_bus_info scc_mii_bus_info = { +#ifdef CONFIG_SCC_ENET_8xx_FIXED + .method = fsmii_fixed, +#else + .method = fsmii_fec, +#endif + + .id = 0, +}; + +static struct fs_platform_info mpc8xx_fec_pdata[] = { + { .rx_ring = 128, .tx_ring = 16, .rx_copybreak = 240, @@ -73,12 +85,11 @@ static struct fs_platform_info mpc8xx_enet_pdata[] = { .use_napi = 1, .napi_weight = 17, - .init_ioports = setup_fec1_ioports, + .phy_addr = 0, + .phy_irq = SIU_IRQ7, - .bus_id = "0:00", - .has_phy = 1, - }, - [fsid_fec2] = { + .bus_info = &fec_mii_bus_info, + }, { .rx_ring = 128, .tx_ring = 16, .rx_copybreak = 240, @@ -86,32 +97,35 @@ static struct fs_platform_info mpc8xx_enet_pdata[] = { .use_napi = 1, .napi_weight = 17, - .init_ioports = setup_fec2_ioports, + .phy_addr = 1, + .phy_irq = SIU_IRQ7, + + .bus_info = &fec_mii_bus_info, + } +}; - .bus_id = "0:01", - .has_phy = 1, - }, - [fsid_scc3] = { - .rx_ring = 64, - .tx_ring = 8, - .rx_copybreak = 240, +static struct fs_platform_info mpc8xx_scc_pdata = { + .rx_ring = 64, + .tx_ring = 8, + .rx_copybreak = 240, - .use_napi = 1, - .napi_weight = 17, + .use_napi = 1, + .napi_weight = 17, - .init_ioports = setup_scc3_ioports, -#ifdef CONFIG_FIXED_MII_10_FDX - .bus_id = "fixed@100:1", + .phy_addr = 2, +#ifdef CONFIG_MPC8xx_SCC_ENET_FIXED + .phy_irq = -1, #else - .bus_id = "0:02", - #endif - }, + .phy_irq = SIU_IRQ7, +#endif + + .bus_info = &scc_mii_bus_info, }; void __init board_init(void) { - cpm8xx_t *cp = cpmp; - unsigned int *bcsr_io; + volatile cpm8xx_t *cp = cpmp; + unsigned int *bcsr_io; #ifdef CONFIG_FS_ENET immap_t *immap = (immap_t *) IMAP_ADDR; @@ -150,14 +164,6 @@ void __init board_init(void) /* use MDC for MII (common) */ setbits16(&immap->im_ioport.iop_pdpar, 0x0080); clrbits16(&immap->im_ioport.iop_pddir, 0x0080); - bcsr_io = ioremap(BCSR5, sizeof(unsigned long)); - clrbits32(bcsr_io,BCSR5_MII1_EN); - clrbits32(bcsr_io,BCSR5_MII1_RST); -#ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2 - clrbits32(bcsr_io,BCSR5_MII2_EN); - clrbits32(bcsr_io,BCSR5_MII2_RST); -#endif - iounmap(bcsr_io); #endif } @@ -188,8 +194,8 @@ static void setup_fec2_ioports(void) /* configure FEC2 pins */ setbits32(&immap->im_cpm.cp_pepar, 0x0003fffc); setbits32(&immap->im_cpm.cp_pedir, 0x0003fffc); - clrbits32(&immap->im_cpm.cp_peso, 0x000087fc); setbits32(&immap->im_cpm.cp_peso, 0x00037800); + clrbits32(&immap->im_cpm.cp_peso, 0x000087fc); clrbits32(&immap->im_cpm.cp_cptr, 0x00000080); } @@ -207,8 +213,6 @@ static void setup_scc3_ioports(void) /* Enable the PHY. */ - clrbits32(bcsr_io+4, BCSR4_ETH10_RST); - udelay(1000); setbits32(bcsr_io+4, BCSR4_ETH10_RST); /* Configure port A pins for Txd and Rxd. */ @@ -250,38 +254,37 @@ static void setup_scc3_ioports(void) clrbits32(&immap->im_cpm.cp_pedir, PE_ENET_TENA); setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA); - setbits32(bcsr_io+4, BCSR1_ETHEN); + setbits32(bcsr_io+1, BCSR1_ETHEN); iounmap(bcsr_io); } -static int mac_count = 0; - static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no) { - struct fs_platform_info *fpi; + struct fs_platform_info *fpi = pdev->dev.platform_data; + + volatile cpm8xx_t *cp; bd_t *bd = (bd_t *) __res; char *e; int i; - if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) { - printk(KERN_ERR"No network-suitable #%d device on bus", fs_no); - return; - } - - fpi = &mpc8xx_enet_pdata[fs_no]; - + /* Get pointer to Communication Processor */ + cp = cpmp; switch (fs_no) { case fsid_fec1: + fpi = &mpc8xx_fec_pdata[0]; fpi->init_ioports = &setup_fec1_ioports; break; case fsid_fec2: + fpi = &mpc8xx_fec_pdata[1]; fpi->init_ioports = &setup_fec2_ioports; break; case fsid_scc3: + fpi = &mpc8xx_scc_pdata; fpi->init_ioports = &setup_scc3_ioports; + mpc885ads_scc_phy_init(fpi->phy_addr); break; default: - printk(KERN_WARNING "Device %s is not supported!\n", pdev->name); + printk(KERN_WARNING"Device %s is not supported!\n", pdev->name); return; } @@ -292,7 +295,7 @@ static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no) for (i = 0; i < 6; i++) fpi->macaddr[i] = *e++; - fpi->macaddr[5] += mac_count++; + fpi->macaddr[5 - pdev->id]++; } @@ -315,6 +318,58 @@ static void __init mpc885ads_fixup_scc_enet_pdata(struct platform_device *pdev, mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1); } +/* SCC ethernet controller does not have MII management channel. FEC1 MII + * channel is used to communicate with the 10Mbit PHY. + */ + +#define MII_ECNTRL_PINMUX 0x4 +#define FEC_ECNTRL_PINMUX 0x00000004 +#define FEC_RCNTRL_MII_MODE 0x00000004 + +/* Make MII read/write commands. + */ +#define mk_mii_write(REG, VAL, PHY_ADDR) (0x50020000 | (((REG) & 0x1f) << 18) | \ + ((VAL) & 0xffff) | ((PHY_ADDR) << 23)) + +static void mpc885ads_scc_phy_init(char phy_addr) +{ + volatile immap_t *immap; + volatile fec_t *fecp; + bd_t *bd; + + bd = (bd_t *) __res; + immap = (immap_t *) IMAP_ADDR; /* pointer to internal registers */ + fecp = &(immap->im_cpm.cp_fec); + + /* Enable MII pins of the FEC1 + */ + setbits16(&immap->im_ioport.iop_pdpar, 0x0080); + clrbits16(&immap->im_ioport.iop_pddir, 0x0080); + /* Set MII speed to 2.5 MHz + */ + out_be32(&fecp->fec_mii_speed, + ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1); + + /* Enable FEC pin MUX + */ + setbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX); + setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE); + + out_be32(&fecp->fec_mii_data, + mk_mii_write(MII_BMCR, BMCR_ISOLATE, phy_addr)); + udelay(100); + out_be32(&fecp->fec_mii_data, + mk_mii_write(MII_ADVERTISE, + ADVERTISE_10HALF | ADVERTISE_CSMA, phy_addr)); + udelay(100); + + /* Disable FEC MII settings + */ + clrbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX); + clrbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE); + out_be32(&fecp->fec_mii_speed, 0); +} + static void setup_smc1_ioports(void) { immap_t *immap = (immap_t *) IMAP_ADDR; @@ -407,9 +462,6 @@ static int mpc885ads_platform_notify(struct device *dev) int __init mpc885ads_init(void) { - struct fs_mii_fec_platform_info* fmpi; - bd_t *bd = (bd_t *) __res; - printk(KERN_NOTICE "mpc885ads: Init\n"); platform_notify = mpc885ads_platform_notify; @@ -419,17 +471,8 @@ int __init mpc885ads_init(void) ppc_sys_device_enable(MPC8xx_CPM_FEC1); - ppc_sys_device_enable(MPC8xx_MDIO_FEC); - fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data = - &mpc8xx_mdio_fec_pdata; - - fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1; - - /* No PHY interrupt line here */ - fmpi->irq[0xf] = SIU_IRQ7; - #ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3 - ppc_sys_device_enable(MPC8xx_CPM_SCC3); + ppc_sys_device_enable(MPC8xx_CPM_SCC1); #endif #ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2 diff --git a/trunk/arch/ppc/platforms/pq2ads_pd.h b/trunk/arch/ppc/platforms/pq2ads_pd.h index 672483df8079..8f14a43eafec 100644 --- a/trunk/arch/ppc/platforms/pq2ads_pd.h +++ b/trunk/arch/ppc/platforms/pq2ads_pd.h @@ -29,4 +29,86 @@ #define F3_RXCLK 13 #define F3_TXCLK 14 +/* Automatically generates register configurations */ +#define PC_CLK(x) ((uint)(1<<(x-1))) /* FCC CLK I/O ports */ + +#define CMXFCR_RF1CS(x) ((uint)((x-5)<<27)) /* FCC1 Receive Clock Source */ +#define CMXFCR_TF1CS(x) ((uint)((x-5)<<24)) /* FCC1 Transmit Clock Source */ +#define CMXFCR_RF2CS(x) ((uint)((x-9)<<19)) /* FCC2 Receive Clock Source */ +#define CMXFCR_TF2CS(x) ((uint)((x-9)<<16)) /* FCC2 Transmit Clock Source */ +#define CMXFCR_RF3CS(x) ((uint)((x-9)<<11)) /* FCC3 Receive Clock Source */ +#define CMXFCR_TF3CS(x) ((uint)((x-9)<<8)) /* FCC3 Transmit Clock Source */ + +#define PC_F1RXCLK PC_CLK(F1_RXCLK) +#define PC_F1TXCLK PC_CLK(F1_TXCLK) +#define CMX1_CLK_ROUTE (CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK)) +#define CMX1_CLK_MASK ((uint)0xff000000) + +#define PC_F2RXCLK PC_CLK(F2_RXCLK) +#define PC_F2TXCLK PC_CLK(F2_TXCLK) +#define CMX2_CLK_ROUTE (CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK)) +#define CMX2_CLK_MASK ((uint)0x00ff0000) + +#define PC_F3RXCLK PC_CLK(F3_RXCLK) +#define PC_F3TXCLK PC_CLK(F3_TXCLK) +#define CMX3_CLK_ROUTE (CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK)) +#define CMX3_CLK_MASK ((uint)0x0000ff00) + +/* I/O Pin assignment for FCC1. I don't yet know the best way to do this, + * but there is little variation among the choices. + */ +#define PA1_COL 0x00000001U +#define PA1_CRS 0x00000002U +#define PA1_TXER 0x00000004U +#define PA1_TXEN 0x00000008U +#define PA1_RXDV 0x00000010U +#define PA1_RXER 0x00000020U +#define PA1_TXDAT 0x00003c00U +#define PA1_RXDAT 0x0003c000U +#define PA1_PSORA0 (PA1_RXDAT | PA1_TXDAT) +#define PA1_PSORA1 (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \ + PA1_RXDV | PA1_RXER) +#define PA1_DIRA0 (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV) +#define PA1_DIRA1 (PA1_TXDAT | PA1_TXEN | PA1_TXER) + + +/* I/O Pin assignment for FCC2. I don't yet know the best way to do this, + * but there is little variation among the choices. + */ +#define PB2_TXER 0x00000001U +#define PB2_RXDV 0x00000002U +#define PB2_TXEN 0x00000004U +#define PB2_RXER 0x00000008U +#define PB2_COL 0x00000010U +#define PB2_CRS 0x00000020U +#define PB2_TXDAT 0x000003c0U +#define PB2_RXDAT 0x00003c00U +#define PB2_PSORB0 (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \ + PB2_RXER | PB2_RXDV | PB2_TXER) +#define PB2_PSORB1 (PB2_TXEN) +#define PB2_DIRB0 (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV) +#define PB2_DIRB1 (PB2_TXDAT | PB2_TXEN | PB2_TXER) + + +/* I/O Pin assignment for FCC3. I don't yet know the best way to do this, + * but there is little variation among the choices. + */ +#define PB3_RXDV 0x00004000U +#define PB3_RXER 0x00008000U +#define PB3_TXER 0x00010000U +#define PB3_TXEN 0x00020000U +#define PB3_COL 0x00040000U +#define PB3_CRS 0x00080000U +#define PB3_TXDAT 0x0f000000U +#define PB3_RXDAT 0x00f00000U +#define PB3_PSORB0 (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \ + PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN) +#define PB3_PSORB1 0 +#define PB3_DIRB0 (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV) +#define PB3_DIRB1 (PB3_TXDAT | PB3_TXEN | PB3_TXER) + +#define FCC_MEM_OFFSET(x) (CPM_FCC_SPECIAL_BASE + (x*128)) +#define FCC1_MEM_OFFSET FCC_MEM_OFFSET(0) +#define FCC2_MEM_OFFSET FCC_MEM_OFFSET(1) + #endif diff --git a/trunk/arch/ppc/syslib/Makefile b/trunk/arch/ppc/syslib/Makefile index dca23f2ef851..2497bbc07e76 100644 --- a/trunk/arch/ppc/syslib/Makefile +++ b/trunk/arch/ppc/syslib/Makefile @@ -93,7 +93,7 @@ obj-$(CONFIG_PCI) += pci_auto.o endif obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o obj-$(CONFIG_83xx) += ppc83xx_setup.o ppc_sys.o \ - mpc83xx_sys.o mpc83xx_devices.o ipic.o + mpc83xx_sys.o mpc83xx_devices.o ifeq ($(CONFIG_83xx),y) obj-$(CONFIG_PCI) += pci_auto.o endif diff --git a/trunk/arch/ppc/syslib/ipic.c b/trunk/arch/ppc/syslib/ipic.c deleted file mode 100644 index 46801f5ec03f..000000000000 --- a/trunk/arch/ppc/syslib/ipic.c +++ /dev/null @@ -1,646 +0,0 @@ -/* - * include/asm-ppc/ipic.c - * - * IPIC routines implementations. - * - * Copyright 2005 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ipic.h" - -static struct ipic p_ipic; -static struct ipic * primary_ipic; - -static struct ipic_info ipic_info[] = { - [9] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_D, - .force = IPIC_SIFCR_H, - .bit = 24, - .prio_mask = 0, - }, - [10] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_D, - .force = IPIC_SIFCR_H, - .bit = 25, - .prio_mask = 1, - }, - [11] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_D, - .force = IPIC_SIFCR_H, - .bit = 26, - .prio_mask = 2, - }, - [14] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_D, - .force = IPIC_SIFCR_H, - .bit = 29, - .prio_mask = 5, - }, - [15] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_D, - .force = IPIC_SIFCR_H, - .bit = 30, - .prio_mask = 6, - }, - [16] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_D, - .force = IPIC_SIFCR_H, - .bit = 31, - .prio_mask = 7, - }, - [17] = { - .pend = IPIC_SEPNR, - .mask = IPIC_SEMSR, - .prio = IPIC_SMPRR_A, - .force = IPIC_SEFCR, - .bit = 1, - .prio_mask = 5, - }, - [18] = { - .pend = IPIC_SEPNR, - .mask = IPIC_SEMSR, - .prio = IPIC_SMPRR_A, - .force = IPIC_SEFCR, - .bit = 2, - .prio_mask = 6, - }, - [19] = { - .pend = IPIC_SEPNR, - .mask = IPIC_SEMSR, - .prio = IPIC_SMPRR_A, - .force = IPIC_SEFCR, - .bit = 3, - .prio_mask = 7, - }, - [20] = { - .pend = IPIC_SEPNR, - .mask = IPIC_SEMSR, - .prio = IPIC_SMPRR_B, - .force = IPIC_SEFCR, - .bit = 4, - .prio_mask = 4, - }, - [21] = { - .pend = IPIC_SEPNR, - .mask = IPIC_SEMSR, - .prio = IPIC_SMPRR_B, - .force = IPIC_SEFCR, - .bit = 5, - .prio_mask = 5, - }, - [22] = { - .pend = IPIC_SEPNR, - .mask = IPIC_SEMSR, - .prio = IPIC_SMPRR_B, - .force = IPIC_SEFCR, - .bit = 6, - .prio_mask = 6, - }, - [23] = { - .pend = IPIC_SEPNR, - .mask = IPIC_SEMSR, - .prio = IPIC_SMPRR_B, - .force = IPIC_SEFCR, - .bit = 7, - .prio_mask = 7, - }, - [32] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_A, - .force = IPIC_SIFCR_H, - .bit = 0, - .prio_mask = 0, - }, - [33] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_A, - .force = IPIC_SIFCR_H, - .bit = 1, - .prio_mask = 1, - }, - [34] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_A, - .force = IPIC_SIFCR_H, - .bit = 2, - .prio_mask = 2, - }, - [35] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_A, - .force = IPIC_SIFCR_H, - .bit = 3, - .prio_mask = 3, - }, - [36] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_A, - .force = IPIC_SIFCR_H, - .bit = 4, - .prio_mask = 4, - }, - [37] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_A, - .force = IPIC_SIFCR_H, - .bit = 5, - .prio_mask = 5, - }, - [38] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_A, - .force = IPIC_SIFCR_H, - .bit = 6, - .prio_mask = 6, - }, - [39] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_H, - .prio = IPIC_SIPRR_A, - .force = IPIC_SIFCR_H, - .bit = 7, - .prio_mask = 7, - }, - [48] = { - .pend = IPIC_SEPNR, - .mask = IPIC_SEMSR, - .prio = IPIC_SMPRR_A, - .force = IPIC_SEFCR, - .bit = 0, - .prio_mask = 4, - }, - [64] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = IPIC_SMPRR_A, - .force = IPIC_SIFCR_L, - .bit = 0, - .prio_mask = 0, - }, - [65] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = IPIC_SMPRR_A, - .force = IPIC_SIFCR_L, - .bit = 1, - .prio_mask = 1, - }, - [66] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = IPIC_SMPRR_A, - .force = IPIC_SIFCR_L, - .bit = 2, - .prio_mask = 2, - }, - [67] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = IPIC_SMPRR_A, - .force = IPIC_SIFCR_L, - .bit = 3, - .prio_mask = 3, - }, - [68] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = IPIC_SMPRR_B, - .force = IPIC_SIFCR_L, - .bit = 4, - .prio_mask = 0, - }, - [69] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = IPIC_SMPRR_B, - .force = IPIC_SIFCR_L, - .bit = 5, - .prio_mask = 1, - }, - [70] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = IPIC_SMPRR_B, - .force = IPIC_SIFCR_L, - .bit = 6, - .prio_mask = 2, - }, - [71] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = IPIC_SMPRR_B, - .force = IPIC_SIFCR_L, - .bit = 7, - .prio_mask = 3, - }, - [72] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = 0, - .force = IPIC_SIFCR_L, - .bit = 8, - }, - [73] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = 0, - .force = IPIC_SIFCR_L, - .bit = 9, - }, - [74] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = 0, - .force = IPIC_SIFCR_L, - .bit = 10, - }, - [75] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = 0, - .force = IPIC_SIFCR_L, - .bit = 11, - }, - [76] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = 0, - .force = IPIC_SIFCR_L, - .bit = 12, - }, - [77] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = 0, - .force = IPIC_SIFCR_L, - .bit = 13, - }, - [78] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = 0, - .force = IPIC_SIFCR_L, - .bit = 14, - }, - [79] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = 0, - .force = IPIC_SIFCR_L, - .bit = 15, - }, - [80] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = 0, - .force = IPIC_SIFCR_L, - .bit = 16, - }, - [84] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = 0, - .force = IPIC_SIFCR_L, - .bit = 20, - }, - [85] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = 0, - .force = IPIC_SIFCR_L, - .bit = 21, - }, - [90] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = 0, - .force = IPIC_SIFCR_L, - .bit = 26, - }, - [91] = { - .pend = IPIC_SIPNR_H, - .mask = IPIC_SIMSR_L, - .prio = 0, - .force = IPIC_SIFCR_L, - .bit = 27, - }, -}; - -static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg) -{ - return in_be32(base + (reg >> 2)); -} - -static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value) -{ - out_be32(base + (reg >> 2), value); -} - -static inline struct ipic * ipic_from_irq(unsigned int irq) -{ - return primary_ipic; -} - -static void ipic_enable_irq(unsigned int irq) -{ - struct ipic *ipic = ipic_from_irq(irq); - unsigned int src = irq - ipic->irq_offset; - u32 temp; - - temp = ipic_read(ipic->regs, ipic_info[src].mask); - temp |= (1 << (31 - ipic_info[src].bit)); - ipic_write(ipic->regs, ipic_info[src].mask, temp); -} - -static void ipic_disable_irq(unsigned int irq) -{ - struct ipic *ipic = ipic_from_irq(irq); - unsigned int src = irq - ipic->irq_offset; - u32 temp; - - temp = ipic_read(ipic->regs, ipic_info[src].mask); - temp &= ~(1 << (31 - ipic_info[src].bit)); - ipic_write(ipic->regs, ipic_info[src].mask, temp); -} - -static void ipic_disable_irq_and_ack(unsigned int irq) -{ - struct ipic *ipic = ipic_from_irq(irq); - unsigned int src = irq - ipic->irq_offset; - u32 temp; - - ipic_disable_irq(irq); - - temp = ipic_read(ipic->regs, ipic_info[src].pend); - temp |= (1 << (31 - ipic_info[src].bit)); - ipic_write(ipic->regs, ipic_info[src].pend, temp); -} - -static void ipic_end_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - ipic_enable_irq(irq); -} - -struct hw_interrupt_type ipic = { - .typename = " IPIC ", - .enable = ipic_enable_irq, - .disable = ipic_disable_irq, - .ack = ipic_disable_irq_and_ack, - .end = ipic_end_irq, -}; - -void __init ipic_init(phys_addr_t phys_addr, - unsigned int flags, - unsigned int irq_offset, - unsigned char *senses, - unsigned int senses_count) -{ - u32 i, temp = 0; - - primary_ipic = &p_ipic; - primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE); - - primary_ipic->irq_offset = irq_offset; - - ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0); - - /* default priority scheme is grouped. If spread mode is required - * configure SICFR accordingly */ - if (flags & IPIC_SPREADMODE_GRP_A) - temp |= SICFR_IPSA; - if (flags & IPIC_SPREADMODE_GRP_D) - temp |= SICFR_IPSD; - if (flags & IPIC_SPREADMODE_MIX_A) - temp |= SICFR_MPSA; - if (flags & IPIC_SPREADMODE_MIX_B) - temp |= SICFR_MPSB; - - ipic_write(primary_ipic->regs, IPIC_SICNR, temp); - - /* handle MCP route */ - temp = 0; - if (flags & IPIC_DISABLE_MCP_OUT) - temp = SERCR_MCPR; - ipic_write(primary_ipic->regs, IPIC_SERCR, temp); - - /* handle routing of IRQ0 to MCP */ - temp = ipic_read(primary_ipic->regs, IPIC_SEMSR); - - if (flags & IPIC_IRQ0_MCP) - temp |= SEMSR_SIRQ0; - else - temp &= ~SEMSR_SIRQ0; - - ipic_write(primary_ipic->regs, IPIC_SEMSR, temp); - - for (i = 0 ; i < NR_IPIC_INTS ; i++) { - irq_desc[i+irq_offset].chip = &ipic; - irq_desc[i+irq_offset].status = IRQ_LEVEL; - } - - temp = 0; - for (i = 0 ; i < senses_count ; i++) { - if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) { - temp |= 1 << (15 - i); - if (i != 0) - irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0; - else - irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0; - } - } - ipic_write(primary_ipic->regs, IPIC_SECNR, temp); - - printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS, - senses_count, primary_ipic->regs); -} - -int ipic_set_priority(unsigned int irq, unsigned int priority) -{ - struct ipic *ipic = ipic_from_irq(irq); - unsigned int src = irq - ipic->irq_offset; - u32 temp; - - if (priority > 7) - return -EINVAL; - if (src > 127) - return -EINVAL; - if (ipic_info[src].prio == 0) - return -EINVAL; - - temp = ipic_read(ipic->regs, ipic_info[src].prio); - - if (priority < 4) { - temp &= ~(0x7 << (20 + (3 - priority) * 3)); - temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3); - } else { - temp &= ~(0x7 << (4 + (7 - priority) * 3)); - temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3); - } - - ipic_write(ipic->regs, ipic_info[src].prio, temp); - - return 0; -} - -void ipic_set_highest_priority(unsigned int irq) -{ - struct ipic *ipic = ipic_from_irq(irq); - unsigned int src = irq - ipic->irq_offset; - u32 temp; - - temp = ipic_read(ipic->regs, IPIC_SICFR); - - /* clear and set HPI */ - temp &= 0x7f000000; - temp |= (src & 0x7f) << 24; - - ipic_write(ipic->regs, IPIC_SICFR, temp); -} - -void ipic_set_default_priority(void) -{ - ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0); - ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1); - ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2); - ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3); - ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4); - ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5); - ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6); - ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7); - - ipic_set_priority(MPC83xx_IRQ_UART1, 0); - ipic_set_priority(MPC83xx_IRQ_UART2, 1); - ipic_set_priority(MPC83xx_IRQ_SEC2, 2); - ipic_set_priority(MPC83xx_IRQ_IIC1, 5); - ipic_set_priority(MPC83xx_IRQ_IIC2, 6); - ipic_set_priority(MPC83xx_IRQ_SPI, 7); - ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0); - ipic_set_priority(MPC83xx_IRQ_PIT, 1); - ipic_set_priority(MPC83xx_IRQ_PCI1, 2); - ipic_set_priority(MPC83xx_IRQ_PCI2, 3); - ipic_set_priority(MPC83xx_IRQ_EXT0, 4); - ipic_set_priority(MPC83xx_IRQ_EXT1, 5); - ipic_set_priority(MPC83xx_IRQ_EXT2, 6); - ipic_set_priority(MPC83xx_IRQ_EXT3, 7); - ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0); - ipic_set_priority(MPC83xx_IRQ_MU, 1); - ipic_set_priority(MPC83xx_IRQ_SBA, 2); - ipic_set_priority(MPC83xx_IRQ_DMA, 3); - ipic_set_priority(MPC83xx_IRQ_EXT4, 4); - ipic_set_priority(MPC83xx_IRQ_EXT5, 5); - ipic_set_priority(MPC83xx_IRQ_EXT6, 6); - ipic_set_priority(MPC83xx_IRQ_EXT7, 7); -} - -void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) -{ - struct ipic *ipic = primary_ipic; - u32 temp; - - temp = ipic_read(ipic->regs, IPIC_SERMR); - temp |= (1 << (31 - mcp_irq)); - ipic_write(ipic->regs, IPIC_SERMR, temp); -} - -void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq) -{ - struct ipic *ipic = primary_ipic; - u32 temp; - - temp = ipic_read(ipic->regs, IPIC_SERMR); - temp &= (1 << (31 - mcp_irq)); - ipic_write(ipic->regs, IPIC_SERMR, temp); -} - -u32 ipic_get_mcp_status(void) -{ - return ipic_read(primary_ipic->regs, IPIC_SERMR); -} - -void ipic_clear_mcp_status(u32 mask) -{ - ipic_write(primary_ipic->regs, IPIC_SERMR, mask); -} - -/* Return an interrupt vector or -1 if no interrupt is pending. */ -int ipic_get_irq(struct pt_regs *regs) -{ - int irq; - - irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f; - - if (irq == 0) /* 0 --> no irq is pending */ - irq = -1; - - return irq; -} - -static struct sysdev_class ipic_sysclass = { - set_kset_name("ipic"), -}; - -static struct sys_device device_ipic = { - .id = 0, - .cls = &ipic_sysclass, -}; - -static int __init init_ipic_sysfs(void) -{ - int rc; - - if (!primary_ipic->regs) - return -ENODEV; - printk(KERN_DEBUG "Registering ipic with sysfs...\n"); - - rc = sysdev_class_register(&ipic_sysclass); - if (rc) { - printk(KERN_ERR "Failed registering ipic sys class\n"); - return -ENODEV; - } - rc = sysdev_register(&device_ipic); - if (rc) { - printk(KERN_ERR "Failed registering ipic sys device\n"); - return -ENODEV; - } - return 0; -} - -subsys_initcall(init_ipic_sysfs); diff --git a/trunk/arch/ppc/syslib/ipic.h b/trunk/arch/ppc/syslib/ipic.h deleted file mode 100644 index a60c9d18bb7f..000000000000 --- a/trunk/arch/ppc/syslib/ipic.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * IPIC private definitions and structure. - * - * Maintainer: Kumar Gala - * - * Copyright 2005 Freescale Semiconductor, Inc - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#ifndef __IPIC_H__ -#define __IPIC_H__ - -#include - -#define MPC83xx_IPIC_SIZE (0x00100) - -/* System Global Interrupt Configuration Register */ -#define SICFR_IPSA 0x00010000 -#define SICFR_IPSD 0x00080000 -#define SICFR_MPSA 0x00200000 -#define SICFR_MPSB 0x00400000 - -/* System External Interrupt Mask Register */ -#define SEMSR_SIRQ0 0x00008000 - -/* System Error Control Register */ -#define SERCR_MCPR 0x00000001 - -struct ipic { - volatile u32 __iomem *regs; - unsigned int irq_offset; -}; - -struct ipic_info { - u8 pend; /* pending register offset from base */ - u8 mask; /* mask register offset from base */ - u8 prio; /* priority register offset from base */ - u8 force; /* force register offset from base */ - u8 bit; /* register bit position (as per doc) - bit mask = 1 << (31 - bit) */ - u8 prio_mask; /* priority mask value */ -}; - -#endif /* __IPIC_H__ */ diff --git a/trunk/arch/ppc/syslib/m8260_pci_erratum9.c b/trunk/arch/ppc/syslib/m8260_pci_erratum9.c index 5475709ce07b..974581ea4849 100644 --- a/trunk/arch/ppc/syslib/m8260_pci_erratum9.c +++ b/trunk/arch/ppc/syslib/m8260_pci_erratum9.c @@ -339,6 +339,20 @@ void insl(unsigned port, void *buf, int nl) idma_pci9_read((u8 *)buf, (u8 *)addr, nl*sizeof(u32), sizeof(u32), 0); } +void insw_ns(unsigned port, void *buf, int ns) +{ + u8 *addr = (u8 *)(port + _IO_BASE); + + idma_pci9_read((u8 *)buf, (u8 *)addr, ns*sizeof(u16), sizeof(u16), 0); +} + +void insl_ns(unsigned port, void *buf, int nl) +{ + u8 *addr = (u8 *)(port + _IO_BASE); + + idma_pci9_read((u8 *)buf, (u8 *)addr, nl*sizeof(u32), sizeof(u32), 0); +} + void *memcpy_fromio(void *dest, unsigned long src, size_t count) { unsigned long pa = iopa((unsigned long) src); @@ -359,6 +373,8 @@ EXPORT_SYMBOL(inl); EXPORT_SYMBOL(insb); EXPORT_SYMBOL(insw); EXPORT_SYMBOL(insl); +EXPORT_SYMBOL(insw_ns); +EXPORT_SYMBOL(insl_ns); EXPORT_SYMBOL(memcpy_fromio); #endif /* ifdef CONFIG_8260_PCI9 */ diff --git a/trunk/arch/ppc/syslib/mpc85xx_devices.c b/trunk/arch/ppc/syslib/mpc85xx_devices.c index 325136e5aee0..7735336f5b8f 100644 --- a/trunk/arch/ppc/syslib/mpc85xx_devices.c +++ b/trunk/arch/ppc/syslib/mpc85xx_devices.c @@ -16,11 +16,9 @@ #include #include #include -#include #include #include #include -#include /* We use offsets for IORESOURCE_MEM since we do not know at compile time * what CCSRBAR is, will get fixed up by mach_mpc85xx_fixup @@ -84,60 +82,6 @@ static struct fsl_i2c_platform_data mpc85xx_fsl_i2c2_pdata = { .device_flags = FSL_I2C_DEV_SEPARATE_DFSRR, }; -static struct fs_platform_info mpc85xx_fcc1_pdata = { - .fs_no = fsid_fcc1, - .cp_page = CPM_CR_FCC1_PAGE, - .cp_block = CPM_CR_FCC1_SBLOCK, - - .rx_ring = 32, - .tx_ring = 32, - .rx_copybreak = 240, - .use_napi = 0, - .napi_weight = 17, - - .clk_mask = CMX1_CLK_MASK, - .clk_route = CMX1_CLK_ROUTE, - .clk_trx = (PC_F1RXCLK | PC_F1TXCLK), - - .mem_offset = FCC1_MEM_OFFSET, -}; - -static struct fs_platform_info mpc85xx_fcc2_pdata = { - .fs_no = fsid_fcc2, - .cp_page = CPM_CR_FCC2_PAGE, - .cp_block = CPM_CR_FCC2_SBLOCK, - - .rx_ring = 32, - .tx_ring = 32, - .rx_copybreak = 240, - .use_napi = 0, - .napi_weight = 17, - - .clk_mask = CMX2_CLK_MASK, - .clk_route = CMX2_CLK_ROUTE, - .clk_trx = (PC_F2RXCLK | PC_F2TXCLK), - - .mem_offset = FCC2_MEM_OFFSET, -}; - -static struct fs_platform_info mpc85xx_fcc3_pdata = { - .fs_no = fsid_fcc3, - .cp_page = CPM_CR_FCC3_PAGE, - .cp_block = CPM_CR_FCC3_SBLOCK, - - .rx_ring = 32, - .tx_ring = 32, - .rx_copybreak = 240, - .use_napi = 0, - .napi_weight = 17, - - .clk_mask = CMX3_CLK_MASK, - .clk_route = CMX3_CLK_ROUTE, - .clk_trx = (PC_F3RXCLK | PC_F3TXCLK), - - .mem_offset = FCC3_MEM_OFFSET, -}; - static struct plat_serial8250_port serial_platform_data[] = { [0] = { .mapbase = 0x4500, @@ -374,27 +318,18 @@ struct platform_device ppc_sys_platform_devices[] = { [MPC85xx_CPM_FCC1] = { .name = "fsl-cpm-fcc", .id = 1, - .num_resources = 4, - .dev.platform_data = &mpc85xx_fcc1_pdata, + .num_resources = 3, .resource = (struct resource[]) { { - .name = "fcc_regs", .start = 0x91300, .end = 0x9131F, .flags = IORESOURCE_MEM, }, { - .name = "fcc_regs_c", .start = 0x91380, .end = 0x9139F, .flags = IORESOURCE_MEM, }, - { - .name = "fcc_pram", - .start = 0x88400, - .end = 0x884ff, - .flags = IORESOURCE_MEM, - }, { .start = SIU_INT_FCC1, .end = SIU_INT_FCC1, @@ -405,27 +340,18 @@ struct platform_device ppc_sys_platform_devices[] = { [MPC85xx_CPM_FCC2] = { .name = "fsl-cpm-fcc", .id = 2, - .num_resources = 4, - .dev.platform_data = &mpc85xx_fcc2_pdata, + .num_resources = 3, .resource = (struct resource[]) { { - .name = "fcc_regs", .start = 0x91320, .end = 0x9133F, .flags = IORESOURCE_MEM, }, { - .name = "fcc_regs_c", .start = 0x913A0, .end = 0x913CF, .flags = IORESOURCE_MEM, }, - { - .name = "fcc_pram", - .start = 0x88500, - .end = 0x885ff, - .flags = IORESOURCE_MEM, - }, { .start = SIU_INT_FCC2, .end = SIU_INT_FCC2, @@ -436,27 +362,18 @@ struct platform_device ppc_sys_platform_devices[] = { [MPC85xx_CPM_FCC3] = { .name = "fsl-cpm-fcc", .id = 3, - .num_resources = 4, - .dev.platform_data = &mpc85xx_fcc3_pdata, + .num_resources = 3, .resource = (struct resource[]) { { - .name = "fcc_regs", .start = 0x91340, .end = 0x9135F, .flags = IORESOURCE_MEM, }, { - .name = "fcc_regs_c", .start = 0x913D0, .end = 0x913FF, .flags = IORESOURCE_MEM, }, - { - .name = "fcc_pram", - .start = 0x88600, - .end = 0x886ff, - .flags = IORESOURCE_MEM, - }, { .start = SIU_INT_FCC3, .end = SIU_INT_FCC3, diff --git a/trunk/arch/ppc/syslib/mpc8xx_devices.c b/trunk/arch/ppc/syslib/mpc8xx_devices.c index cf5ab47487a7..6f536383866e 100644 --- a/trunk/arch/ppc/syslib/mpc8xx_devices.c +++ b/trunk/arch/ppc/syslib/mpc8xx_devices.c @@ -218,14 +218,6 @@ struct platform_device ppc_sys_platform_devices[] = { }, }, }, - - [MPC8xx_MDIO_FEC] = { - .name = "fsl-cpm-fec-mdio", - .id = 0, - .num_resources = 0, - - }, - }; static int __init mach_mpc8xx_fixup(struct platform_device *pdev) diff --git a/trunk/arch/ppc/syslib/mpc8xx_sys.c b/trunk/arch/ppc/syslib/mpc8xx_sys.c index 18ba1d7ff9f1..eee213284855 100644 --- a/trunk/arch/ppc/syslib/mpc8xx_sys.c +++ b/trunk/arch/ppc/syslib/mpc8xx_sys.c @@ -22,7 +22,7 @@ struct ppc_sys_spec ppc_sys_specs[] = { .ppc_sys_name = "MPC86X", .mask = 0xFFFFFFFF, .value = 0x00000000, - .num_devices = 8, + .num_devices = 7, .device_list = (enum ppc_sys_devices[]) { MPC8xx_CPM_FEC1, @@ -32,14 +32,13 @@ struct ppc_sys_spec ppc_sys_specs[] = { MPC8xx_CPM_SCC4, MPC8xx_CPM_SMC1, MPC8xx_CPM_SMC2, - MPC8xx_MDIO_FEC, }, }, { .ppc_sys_name = "MPC885", .mask = 0xFFFFFFFF, .value = 0x00000000, - .num_devices = 9, + .num_devices = 8, .device_list = (enum ppc_sys_devices[]) { MPC8xx_CPM_FEC1, @@ -50,7 +49,6 @@ struct ppc_sys_spec ppc_sys_specs[] = { MPC8xx_CPM_SCC4, MPC8xx_CPM_SMC1, MPC8xx_CPM_SMC2, - MPC8xx_MDIO_FEC, }, }, { /* default match */ diff --git a/trunk/arch/ppc/syslib/pq2_devices.c b/trunk/arch/ppc/syslib/pq2_devices.c index fefbc217a56d..8692d00c08c4 100644 --- a/trunk/arch/ppc/syslib/pq2_devices.c +++ b/trunk/arch/ppc/syslib/pq2_devices.c @@ -369,11 +369,6 @@ struct platform_device ppc_sys_platform_devices[] = { }, }, }, - [MPC82xx_MDIO_BB] = { - .name = "fsl-bb-mdio", - .id = 0, - .num_resources = 0, - }, }; static int __init mach_mpc82xx_fixup(struct platform_device *pdev) diff --git a/trunk/arch/ppc/syslib/pq2_sys.c b/trunk/arch/ppc/syslib/pq2_sys.c index f52600c0db20..fee8948162b9 100644 --- a/trunk/arch/ppc/syslib/pq2_sys.c +++ b/trunk/arch/ppc/syslib/pq2_sys.c @@ -139,14 +139,13 @@ struct ppc_sys_spec ppc_sys_specs[] = { .ppc_sys_name = "8272", .mask = 0x0000ff00, .value = 0x00000c00, - .num_devices = 13, + .num_devices = 12, .device_list = (enum ppc_sys_devices[]) { MPC82xx_CPM_FCC1, MPC82xx_CPM_FCC2, MPC82xx_CPM_SCC1, MPC82xx_CPM_SCC2, MPC82xx_CPM_SCC3, MPC82xx_CPM_SCC4, MPC82xx_CPM_SMC1, MPC82xx_CPM_SMC2, MPC82xx_CPM_SPI, MPC82xx_CPM_I2C, MPC82xx_CPM_USB, MPC82xx_SEC1, - MPC82xx_MDIO_BB, }, }, /* below is a list of the 8280 family of processors */ diff --git a/trunk/arch/ppc/xmon/start.c b/trunk/arch/ppc/xmon/start.c index d74a883e5bde..f7e92986952a 100644 --- a/trunk/arch/ppc/xmon/start.c +++ b/trunk/arch/ppc/xmon/start.c @@ -15,7 +15,6 @@ #include #include #include -#include static volatile unsigned char *sccc, *sccd; unsigned int TXRDY, RXRDY, DLAB; @@ -58,30 +57,23 @@ static struct sysrq_key_op sysrq_xmon_op = void xmon_map_scc(void) { -#if defined(CONFIG_GEMINI) +#ifdef CONFIG_PPC_PREP + volatile unsigned char *base; + +#elif defined(CONFIG_GEMINI) /* should already be mapped by the kernel boot */ + sccc = (volatile unsigned char *) 0xffeffb0d; sccd = (volatile unsigned char *) 0xffeffb08; + TXRDY = 0x20; + RXRDY = 1; + DLAB = 0x80; #elif defined(CONFIG_405GP) + sccc = (volatile unsigned char *)0xef600305; sccd = (volatile unsigned char *)0xef600300; -#elif defined(CONFIG_440EP) - sccd = (volatile unsigned char *) ioremap(PPC440EP_UART0_ADDR, 8); -#elif defined(CONFIG_440SP) - sccd = (volatile unsigned char *) ioremap64(PPC440SP_UART0_ADDR, 8); -#elif defined(CONFIG_440SPE) - sccd = (volatile unsigned char *) ioremap64(PPC440SPE_UART0_ADDR, 8); -#elif defined(CONFIG_44x) - /* This is the default for 44x platforms. Any boards that have a - different UART address need to be put in cases before this or the - port will be mapped incorrectly */ - sccd = (volatile unsigned char *) ioremap64(PPC440GP_UART0_ADDR, 8); -#endif /* platform */ - -#ifndef CONFIG_PPC_PREP - sccc = sccd + 5; TXRDY = 0x20; RXRDY = 1; DLAB = 0x80; -#endif +#endif /* platform */ register_sysrq_key('x', &sysrq_xmon_op); } diff --git a/trunk/arch/ppc/xmon/xmon.c b/trunk/arch/ppc/xmon/xmon.c index b1a91744fd2d..37d234f93394 100644 --- a/trunk/arch/ppc/xmon/xmon.c +++ b/trunk/arch/ppc/xmon/xmon.c @@ -153,12 +153,6 @@ static int xmon_trace[NR_CPUS]; #define SSTEP 1 /* stepping because of 's' command */ #define BRSTEP 2 /* stepping over breakpoint */ -#ifdef CONFIG_4xx -#define MSR_SSTEP_ENABLE 0x200 -#else -#define MSR_SSTEP_ENABLE 0x400 -#endif - static struct pt_regs *xmon_regs[NR_CPUS]; extern inline void sync(void) @@ -217,14 +211,6 @@ static void get_tb(unsigned *p) p[1] = lo; } -static inline void xmon_enable_sstep(struct pt_regs *regs) -{ - regs->msr |= MSR_SSTEP_ENABLE; -#ifdef CONFIG_4xx - mtspr(SPRN_DBCR0, mfspr(SPRN_DBCR0) | DBCR0_IC | DBCR0_IDM); -#endif -} - int xmon(struct pt_regs *excp) { struct pt_regs regs; @@ -268,10 +254,10 @@ int xmon(struct pt_regs *excp) cmd = cmds(excp); if (cmd == 's') { xmon_trace[smp_processor_id()] = SSTEP; - xmon_enable_sstep(excp); + excp->msr |= 0x400; } else if (at_breakpoint(excp->nip)) { xmon_trace[smp_processor_id()] = BRSTEP; - xmon_enable_sstep(excp); + excp->msr |= 0x400; } else { xmon_trace[smp_processor_id()] = 0; insert_bpts(); @@ -312,7 +298,7 @@ xmon_bpt(struct pt_regs *regs) remove_bpts(); excprint(regs); xmon_trace[smp_processor_id()] = BRSTEP; - xmon_enable_sstep(regs); + regs->msr |= 0x400; } else { xmon(regs); } @@ -399,7 +385,7 @@ insert_bpts(void) } store_inst((void *) bp->address); } -#if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx)) +#if !defined(CONFIG_8xx) if (dabr.enabled) set_dabr(dabr.address); if (iabr.enabled) @@ -414,7 +400,7 @@ remove_bpts(void) struct bpt *bp; unsigned instr; -#if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx)) +#if !defined(CONFIG_8xx) set_dabr(0); set_iabr(0); #endif @@ -691,7 +677,7 @@ bpt_cmds(void) cmd = inchar(); switch (cmd) { -#if ! (defined(CONFIG_8xx) || defined(CONFIG_4xx)) +#if !defined(CONFIG_8xx) case 'd': mode = 7; cmd = inchar(); @@ -806,7 +792,7 @@ backtrace(struct pt_regs *excp) for (; sp != 0; sp = stack[0]) { if (mread(sp, stack, sizeof(stack)) != sizeof(stack)) break; - printf("[%.8lx] ", stack[0]); + printf("[%.8lx] ", stack); xmon_print_symbol(stack[1], " ", "\n"); if (stack[1] == (unsigned) &ret_from_except || stack[1] == (unsigned) &ret_from_except_full diff --git a/trunk/arch/s390/Kconfig b/trunk/arch/s390/Kconfig index b216ca659cdf..ae071a11ce71 100644 --- a/trunk/arch/s390/Kconfig +++ b/trunk/arch/s390/Kconfig @@ -118,10 +118,6 @@ config SYSVIPC_COMPAT depends on COMPAT && SYSVIPC default y -config AUDIT_ARCH - bool - default y - comment "Code generation options" choice @@ -460,7 +456,8 @@ config S390_HYPFS_FS information in an s390 hypervisor environment. config KEXEC - bool "kexec system call" + bool "kexec system call (EXPERIMENTAL)" + depends on EXPERIMENTAL help kexec is a system call that implements the ability to shutdown your current kernel, and to start another kernel. It is like a reboot @@ -486,22 +483,8 @@ source "drivers/net/Kconfig" source "fs/Kconfig" -menu "Instrumentation Support" - source "arch/s390/oprofile/Kconfig" -config KPROBES - bool "Kprobes (EXPERIMENTAL)" - depends on EXPERIMENTAL && MODULES - help - Kprobes allows you to trap at almost any kernel address and - execute a callback function. register_kprobe() establishes - a probepoint and specifies the callback. Kprobes is useful - for kernel debugging, non-intrusive instrumentation and testing. - If in doubt, say "N". - -endmenu - source "arch/s390/Kconfig.debug" source "security/Kconfig" diff --git a/trunk/arch/s390/appldata/appldata.h b/trunk/arch/s390/appldata/appldata.h index 0429481dea63..71d65eb30650 100644 --- a/trunk/arch/s390/appldata/appldata.h +++ b/trunk/arch/s390/appldata/appldata.h @@ -29,6 +29,22 @@ #define CTL_APPLDATA_NET_SUM 2125 #define CTL_APPLDATA_PROC 2126 +#ifndef CONFIG_64BIT + +#define APPLDATA_START_INTERVAL_REC 0x00 /* Function codes for */ +#define APPLDATA_STOP_REC 0x01 /* DIAG 0xDC */ +#define APPLDATA_GEN_EVENT_RECORD 0x02 +#define APPLDATA_START_CONFIG_REC 0x03 + +#else + +#define APPLDATA_START_INTERVAL_REC 0x80 +#define APPLDATA_STOP_REC 0x81 +#define APPLDATA_GEN_EVENT_RECORD 0x82 +#define APPLDATA_START_CONFIG_REC 0x83 + +#endif /* CONFIG_64BIT */ + #define P_INFO(x...) printk(KERN_INFO MY_PRINT_NAME " info: " x) #define P_ERROR(x...) printk(KERN_ERR MY_PRINT_NAME " error: " x) #define P_WARNING(x...) printk(KERN_WARNING MY_PRINT_NAME " status: " x) diff --git a/trunk/arch/s390/appldata/appldata_base.c b/trunk/arch/s390/appldata/appldata_base.c index b69ed742f981..d0f82c995af6 100644 --- a/trunk/arch/s390/appldata/appldata_base.c +++ b/trunk/arch/s390/appldata/appldata_base.c @@ -14,20 +14,20 @@ #include #include #include +#include +#include +#include #include #include #include #include #include #include +#include +//#include #include #include #include -#include -#include -#include -#include -#include #include "appldata.h" @@ -39,6 +39,34 @@ #define TOD_MICRO 0x01000 /* nr. of TOD clock units for 1 microsecond */ + +/* + * Parameter list for DIAGNOSE X'DC' + */ +#ifndef CONFIG_64BIT +struct appldata_parameter_list { + u16 diag; /* The DIAGNOSE code X'00DC' */ + u8 function; /* The function code for the DIAGNOSE */ + u8 parlist_length; /* Length of the parameter list */ + u32 product_id_addr; /* Address of the 16-byte product ID */ + u16 reserved; + u16 buffer_length; /* Length of the application data buffer */ + u32 buffer_addr; /* Address of the application data buffer */ +}; +#else +struct appldata_parameter_list { + u16 diag; + u8 function; + u8 parlist_length; + u32 unused01; + u16 reserved; + u16 buffer_length; + u32 unused02; + u64 product_id_addr; + u64 buffer_addr; +}; +#endif /* CONFIG_64BIT */ + /* * /proc entries (sysctl) */ @@ -153,17 +181,46 @@ static void appldata_work_fn(void *data) int appldata_diag(char record_nr, u16 function, unsigned long buffer, u16 length, char *mod_lvl) { - struct appldata_product_id id = { + unsigned long ry; + struct appldata_product_id { + char prod_nr[7]; /* product nr. */ + char prod_fn[2]; /* product function */ + char record_nr; /* record nr. */ + char version_nr[2]; /* version */ + char release_nr[2]; /* release */ + char mod_lvl[2]; /* modification lvl. */ + } appldata_product_id = { + /* all strings are EBCDIC, record_nr is byte */ .prod_nr = {0xD3, 0xC9, 0xD5, 0xE4, - 0xE7, 0xD2, 0xD9}, /* "LINUXKR" */ - .prod_fn = 0xD5D3, /* "NL" */ + 0xE7, 0xD2, 0xD9}, /* "LINUXKR" */ + .prod_fn = {0xD5, 0xD3}, /* "NL" */ .record_nr = record_nr, - .version_nr = 0xF2F6, /* "26" */ - .release_nr = 0xF0F1, /* "01" */ - .mod_lvl = (mod_lvl[0]) << 8 | mod_lvl[1], + .version_nr = {0xF2, 0xF6}, /* "26" */ + .release_nr = {0xF0, 0xF1}, /* "01" */ + .mod_lvl = {mod_lvl[0], mod_lvl[1]}, + }; + struct appldata_parameter_list appldata_parameter_list = { + .diag = 0xDC, + .function = function, + .parlist_length = + sizeof(appldata_parameter_list), + .buffer_length = length, + .product_id_addr = + (unsigned long) &appldata_product_id, + .buffer_addr = virt_to_phys((void *) buffer) }; - return appldata_asm(&id, function, (void *) buffer, length); + if (!MACHINE_IS_VM) + return -ENOSYS; + ry = -1; + asm volatile( + "diag %1,%0,0xDC\n\t" + : "=d" (ry) + : "d" (&appldata_parameter_list), + "m" (appldata_parameter_list), + "m" (appldata_product_id) + : "cc"); + return (int) ry; } /************************ timer, work, DIAG ****************************/ @@ -560,7 +617,6 @@ appldata_offline_cpu(int cpu) spin_unlock(&appldata_timer_lock); } -#ifdef CONFIG_HOTPLUG_CPU static int __cpuinit appldata_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) @@ -569,19 +625,20 @@ appldata_cpu_notify(struct notifier_block *self, case CPU_ONLINE: appldata_online_cpu((long) hcpu); break; +#ifdef CONFIG_HOTPLUG_CPU case CPU_DEAD: appldata_offline_cpu((long) hcpu); break; +#endif default: break; } return NOTIFY_OK; } -static struct notifier_block appldata_nb = { +static struct notifier_block __devinitdata appldata_nb = { .notifier_call = appldata_cpu_notify, }; -#endif /* * appldata_init() @@ -605,7 +662,7 @@ static int __init appldata_init(void) appldata_online_cpu(i); /* Register cpu hotplug notifier */ - register_hotcpu_notifier(&appldata_nb); + register_cpu_notifier(&appldata_nb); appldata_sysctl_header = register_sysctl_table(appldata_dir_table, 1); #ifdef MODULE diff --git a/trunk/arch/s390/appldata/appldata_os.c b/trunk/arch/s390/appldata/appldata_os.c index 76a15523ae9e..161acc5c8a1b 100644 --- a/trunk/arch/s390/appldata/appldata_os.c +++ b/trunk/arch/s390/appldata/appldata_os.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include "appldata.h" diff --git a/trunk/arch/s390/crypto/aes_s390.c b/trunk/arch/s390/crypto/aes_s390.c index 15c9eec02928..5713c7e5bd16 100644 --- a/trunk/arch/s390/crypto/aes_s390.c +++ b/trunk/arch/s390/crypto/aes_s390.c @@ -16,9 +16,9 @@ * */ -#include #include #include +#include #include "crypt_s390.h" #define AES_MIN_KEY_SIZE 16 @@ -34,16 +34,13 @@ int has_aes_256 = 0; struct s390_aes_ctx { u8 iv[AES_BLOCK_SIZE]; u8 key[AES_MAX_KEY_SIZE]; - long enc; - long dec; int key_len; }; static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) + unsigned int key_len, u32 *flags) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); - u32 *flags = &tfm->crt_flags; switch (key_len) { case 16: @@ -113,206 +110,133 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) } } - -static struct crypto_alg aes_alg = { - .cra_name = "aes", - .cra_driver_name = "aes-s390", - .cra_priority = CRYPT_S390_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct s390_aes_ctx), - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), - .cra_u = { - .cipher = { - .cia_min_keysize = AES_MIN_KEY_SIZE, - .cia_max_keysize = AES_MAX_KEY_SIZE, - .cia_setkey = aes_set_key, - .cia_encrypt = aes_encrypt, - .cia_decrypt = aes_decrypt, - } - } -}; - -static int ecb_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) +static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) { - struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; - switch (key_len) { + /* only use complete blocks */ + nbytes &= ~(AES_BLOCK_SIZE - 1); + + switch (sctx->key_len) { case 16: - sctx->enc = KM_AES_128_ENCRYPT; - sctx->dec = KM_AES_128_DECRYPT; + ret = crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; case 24: - sctx->enc = KM_AES_192_ENCRYPT; - sctx->dec = KM_AES_192_DECRYPT; + ret = crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; case 32: - sctx->enc = KM_AES_256_ENCRYPT; - sctx->dec = KM_AES_256_DECRYPT; + ret = crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; } - - return aes_set_key(tfm, in_key, key_len); + return nbytes; } -static int ecb_aes_crypt(struct blkcipher_desc *desc, long func, void *param, - struct blkcipher_walk *walk) +static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) { - int ret = blkcipher_walk_virt(desc, walk); - unsigned int nbytes; - - while ((nbytes = walk->nbytes)) { - /* only use complete blocks */ - unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1); - u8 *out = walk->dst.virt.addr; - u8 *in = walk->src.virt.addr; + struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; - ret = crypt_s390_km(func, param, out, in, n); - BUG_ON((ret < 0) || (ret != n)); + /* only use complete blocks */ + nbytes &= ~(AES_BLOCK_SIZE - 1); - nbytes &= AES_BLOCK_SIZE - 1; - ret = blkcipher_walk_done(desc, walk, nbytes); + switch (sctx->key_len) { + case 16: + ret = crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + break; + case 24: + ret = crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + break; + case 32: + ret = crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + break; } - - return ret; + return nbytes; } -static int ecb_aes_encrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) +static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) { - struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; - - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_aes_crypt(desc, sctx->enc, sctx->key, &walk); -} - -static int ecb_aes_decrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) -{ - struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; - - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_aes_crypt(desc, sctx->dec, sctx->key, &walk); -} - -static struct crypto_alg ecb_aes_alg = { - .cra_name = "ecb(aes)", - .cra_driver_name = "ecb-aes-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct s390_aes_ctx), - .cra_type = &crypto_blkcipher_type, - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(ecb_aes_alg.cra_list), - .cra_u = { - .blkcipher = { - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .setkey = ecb_aes_set_key, - .encrypt = ecb_aes_encrypt, - .decrypt = ecb_aes_decrypt, - } - } -}; + struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; -static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) -{ - struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); + /* only use complete blocks */ + nbytes &= ~(AES_BLOCK_SIZE - 1); - switch (key_len) { + memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE); + switch (sctx->key_len) { case 16: - sctx->enc = KMC_AES_128_ENCRYPT; - sctx->dec = KMC_AES_128_DECRYPT; + ret = crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; case 24: - sctx->enc = KMC_AES_192_ENCRYPT; - sctx->dec = KMC_AES_192_DECRYPT; + ret = crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; case 32: - sctx->enc = KMC_AES_256_ENCRYPT; - sctx->dec = KMC_AES_256_DECRYPT; + ret = crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); break; } + memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE); - return aes_set_key(tfm, in_key, key_len); + return nbytes; } -static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param, - struct blkcipher_walk *walk) +static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) { - int ret = blkcipher_walk_virt(desc, walk); - unsigned int nbytes = walk->nbytes; - - if (!nbytes) - goto out; - - memcpy(param, walk->iv, AES_BLOCK_SIZE); - do { - /* only use complete blocks */ - unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1); - u8 *out = walk->dst.virt.addr; - u8 *in = walk->src.virt.addr; - - ret = crypt_s390_kmc(func, param, out, in, n); - BUG_ON((ret < 0) || (ret != n)); - - nbytes &= AES_BLOCK_SIZE - 1; - ret = blkcipher_walk_done(desc, walk, nbytes); - } while ((nbytes = walk->nbytes)); - memcpy(walk->iv, param, AES_BLOCK_SIZE); - -out: - return ret; -} + struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; -static int cbc_aes_encrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) -{ - struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; + /* only use complete blocks */ + nbytes &= ~(AES_BLOCK_SIZE - 1); - blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk); + memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE); + switch (sctx->key_len) { + case 16: + ret = crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + break; + case 24: + ret = crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + break; + case 32: + ret = crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + break; + } + return nbytes; } -static int cbc_aes_decrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) -{ - struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; - - blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk); -} -static struct crypto_alg cbc_aes_alg = { - .cra_name = "cbc(aes)", - .cra_driver_name = "cbc-aes-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, +static struct crypto_alg aes_alg = { + .cra_name = "aes", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s390_aes_ctx), - .cra_type = &crypto_blkcipher_type, .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(cbc_aes_alg.cra_list), + .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), .cra_u = { - .blkcipher = { - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = cbc_aes_set_key, - .encrypt = cbc_aes_encrypt, - .decrypt = cbc_aes_decrypt, + .cipher = { + .cia_min_keysize = AES_MIN_KEY_SIZE, + .cia_max_keysize = AES_MAX_KEY_SIZE, + .cia_setkey = aes_set_key, + .cia_encrypt = aes_encrypt, + .cia_decrypt = aes_decrypt, + .cia_encrypt_ecb = aes_encrypt_ecb, + .cia_decrypt_ecb = aes_decrypt_ecb, + .cia_encrypt_cbc = aes_encrypt_cbc, + .cia_decrypt_cbc = aes_decrypt_cbc, } } }; @@ -332,40 +256,13 @@ static int __init aes_init(void) return -ENOSYS; ret = crypto_register_alg(&aes_alg); - if (ret != 0) { - printk(KERN_INFO "crypt_s390: aes-s390 couldn't be loaded.\n"); - goto aes_err; - } - - ret = crypto_register_alg(&ecb_aes_alg); - if (ret != 0) { - printk(KERN_INFO - "crypt_s390: ecb-aes-s390 couldn't be loaded.\n"); - goto ecb_aes_err; - } - - ret = crypto_register_alg(&cbc_aes_alg); - if (ret != 0) { - printk(KERN_INFO - "crypt_s390: cbc-aes-s390 couldn't be loaded.\n"); - goto cbc_aes_err; - } - -out: + if (ret != 0) + printk(KERN_INFO "crypt_s390: aes_s390 couldn't be loaded.\n"); return ret; - -cbc_aes_err: - crypto_unregister_alg(&ecb_aes_alg); -ecb_aes_err: - crypto_unregister_alg(&aes_alg); -aes_err: - goto out; } static void __exit aes_fini(void) { - crypto_unregister_alg(&cbc_aes_alg); - crypto_unregister_alg(&ecb_aes_alg); crypto_unregister_alg(&aes_alg); } diff --git a/trunk/arch/s390/crypto/crypt_s390.h b/trunk/arch/s390/crypto/crypt_s390.h index efd836c2e4a6..d1c259a7fe33 100644 --- a/trunk/arch/s390/crypto/crypt_s390.h +++ b/trunk/arch/s390/crypto/crypt_s390.h @@ -20,9 +20,6 @@ #define CRYPT_S390_OP_MASK 0xFF00 #define CRYPT_S390_FUNC_MASK 0x00FF -#define CRYPT_S390_PRIORITY 300 -#define CRYPT_S390_COMPOSITE_PRIORITY 400 - /* s930 cryptographic operations */ enum crypt_s390_operations { CRYPT_S390_KM = 0x0100, diff --git a/trunk/arch/s390/crypto/des_s390.c b/trunk/arch/s390/crypto/des_s390.c index 2aba04852fe3..b3f7496a79b4 100644 --- a/trunk/arch/s390/crypto/des_s390.c +++ b/trunk/arch/s390/crypto/des_s390.c @@ -13,10 +13,9 @@ * (at your option) any later version. * */ - -#include #include #include +#include #include "crypt_s390.h" #include "crypto_des.h" @@ -46,10 +45,9 @@ struct crypt_s390_des3_192_ctx { }; static int des_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) + unsigned int keylen, u32 *flags) { struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm); - u32 *flags = &tfm->crt_flags; int ret; /* test if key is valid (not a weak key) */ @@ -73,159 +71,85 @@ static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) crypt_s390_km(KM_DEA_DECRYPT, dctx->key, out, in, DES_BLOCK_SIZE); } -static struct crypto_alg des_alg = { - .cra_name = "des", - .cra_driver_name = "des-s390", - .cra_priority = CRYPT_S390_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = DES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_s390_des_ctx), - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(des_alg.cra_list), - .cra_u = { - .cipher = { - .cia_min_keysize = DES_KEY_SIZE, - .cia_max_keysize = DES_KEY_SIZE, - .cia_setkey = des_setkey, - .cia_encrypt = des_encrypt, - .cia_decrypt = des_decrypt, - } - } -}; - -static int ecb_desall_crypt(struct blkcipher_desc *desc, long func, - void *param, struct blkcipher_walk *walk) +static unsigned int des_encrypt_ecb(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) { - int ret = blkcipher_walk_virt(desc, walk); - unsigned int nbytes; - - while ((nbytes = walk->nbytes)) { - /* only use complete blocks */ - unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1); - u8 *out = walk->dst.virt.addr; - u8 *in = walk->src.virt.addr; + struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; - ret = crypt_s390_km(func, param, out, in, n); - BUG_ON((ret < 0) || (ret != n)); + /* only use complete blocks */ + nbytes &= ~(DES_BLOCK_SIZE - 1); + ret = crypt_s390_km(KM_DEA_ENCRYPT, sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); - nbytes &= DES_BLOCK_SIZE - 1; - ret = blkcipher_walk_done(desc, walk, nbytes); - } - - return ret; + return nbytes; } -static int cbc_desall_crypt(struct blkcipher_desc *desc, long func, - void *param, struct blkcipher_walk *walk) +static unsigned int des_decrypt_ecb(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) { - int ret = blkcipher_walk_virt(desc, walk); - unsigned int nbytes = walk->nbytes; - - if (!nbytes) - goto out; - - memcpy(param, walk->iv, DES_BLOCK_SIZE); - do { - /* only use complete blocks */ - unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1); - u8 *out = walk->dst.virt.addr; - u8 *in = walk->src.virt.addr; - - ret = crypt_s390_kmc(func, param, out, in, n); - BUG_ON((ret < 0) || (ret != n)); + struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; - nbytes &= DES_BLOCK_SIZE - 1; - ret = blkcipher_walk_done(desc, walk, nbytes); - } while ((nbytes = walk->nbytes)); - memcpy(walk->iv, param, DES_BLOCK_SIZE); + /* only use complete blocks */ + nbytes &= ~(DES_BLOCK_SIZE - 1); + ret = crypt_s390_km(KM_DEA_DECRYPT, sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); -out: - return ret; + return nbytes; } -static int ecb_des_encrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) +static unsigned int des_encrypt_cbc(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) { - struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; + struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_desall_crypt(desc, KM_DEA_ENCRYPT, sctx->key, &walk); -} + /* only use complete blocks */ + nbytes &= ~(DES_BLOCK_SIZE - 1); -static int ecb_des_decrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) -{ - struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; + memcpy(sctx->iv, desc->info, DES_BLOCK_SIZE); + ret = crypt_s390_kmc(KMC_DEA_ENCRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_desall_crypt(desc, KM_DEA_DECRYPT, sctx->key, &walk); + memcpy(desc->info, sctx->iv, DES_BLOCK_SIZE); + return nbytes; } -static struct crypto_alg ecb_des_alg = { - .cra_name = "ecb(des)", - .cra_driver_name = "ecb-des-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, - .cra_blocksize = DES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_s390_des_ctx), - .cra_type = &crypto_blkcipher_type, - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(ecb_des_alg.cra_list), - .cra_u = { - .blkcipher = { - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - .setkey = des_setkey, - .encrypt = ecb_des_encrypt, - .decrypt = ecb_des_decrypt, - } - } -}; - -static int cbc_des_encrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) +static unsigned int des_decrypt_cbc(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) { - struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; + struct crypt_s390_des_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; - blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, sctx->iv, &walk); -} + /* only use complete blocks */ + nbytes &= ~(DES_BLOCK_SIZE - 1); -static int cbc_des_decrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) -{ - struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; + memcpy(&sctx->iv, desc->info, DES_BLOCK_SIZE); + ret = crypt_s390_kmc(KMC_DEA_DECRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); - blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, sctx->iv, &walk); + return nbytes; } -static struct crypto_alg cbc_des_alg = { - .cra_name = "cbc(des)", - .cra_driver_name = "cbc-des-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, +static struct crypto_alg des_alg = { + .cra_name = "des", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = DES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct crypt_s390_des_ctx), - .cra_type = &crypto_blkcipher_type, .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(cbc_des_alg.cra_list), + .cra_list = LIST_HEAD_INIT(des_alg.cra_list), .cra_u = { - .blkcipher = { - .min_keysize = DES_KEY_SIZE, - .max_keysize = DES_KEY_SIZE, - .ivsize = DES_BLOCK_SIZE, - .setkey = des_setkey, - .encrypt = cbc_des_encrypt, - .decrypt = cbc_des_decrypt, + .cipher = { + .cia_min_keysize = DES_KEY_SIZE, + .cia_max_keysize = DES_KEY_SIZE, + .cia_setkey = des_setkey, + .cia_encrypt = des_encrypt, + .cia_decrypt = des_decrypt, + .cia_encrypt_ecb = des_encrypt_ecb, + .cia_decrypt_ecb = des_decrypt_ecb, + .cia_encrypt_cbc = des_encrypt_cbc, + .cia_decrypt_cbc = des_decrypt_cbc, } } }; @@ -243,12 +167,11 @@ static struct crypto_alg cbc_des_alg = { * */ static int des3_128_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) + unsigned int keylen, u32 *flags) { int i, ret; struct crypt_s390_des3_128_ctx *dctx = crypto_tfm_ctx(tfm); - const u8 *temp_key = key; - u32 *flags = &tfm->crt_flags; + const u8* temp_key = key; if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) { *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; @@ -279,111 +202,89 @@ static void des3_128_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) DES3_128_BLOCK_SIZE); } -static struct crypto_alg des3_128_alg = { - .cra_name = "des3_ede128", - .cra_driver_name = "des3_ede128-s390", - .cra_priority = CRYPT_S390_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = DES3_128_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx), - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list), - .cra_u = { - .cipher = { - .cia_min_keysize = DES3_128_KEY_SIZE, - .cia_max_keysize = DES3_128_KEY_SIZE, - .cia_setkey = des3_128_setkey, - .cia_encrypt = des3_128_encrypt, - .cia_decrypt = des3_128_decrypt, - } - } -}; - -static int ecb_des3_128_encrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static unsigned int des3_128_encrypt_ecb(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) { - struct crypt_s390_des3_128_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; + struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_desall_crypt(desc, KM_TDEA_128_ENCRYPT, sctx->key, &walk); + /* only use complete blocks */ + nbytes &= ~(DES3_128_BLOCK_SIZE - 1); + ret = crypt_s390_km(KM_TDEA_128_ENCRYPT, sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + return nbytes; } -static int ecb_des3_128_decrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static unsigned int des3_128_decrypt_ecb(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) { - struct crypt_s390_des3_128_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; + struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_desall_crypt(desc, KM_TDEA_128_DECRYPT, sctx->key, &walk); -} + /* only use complete blocks */ + nbytes &= ~(DES3_128_BLOCK_SIZE - 1); + ret = crypt_s390_km(KM_TDEA_128_DECRYPT, sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); -static struct crypto_alg ecb_des3_128_alg = { - .cra_name = "ecb(des3_ede128)", - .cra_driver_name = "ecb-des3_ede128-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, - .cra_blocksize = DES3_128_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx), - .cra_type = &crypto_blkcipher_type, - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT( - ecb_des3_128_alg.cra_list), - .cra_u = { - .blkcipher = { - .min_keysize = DES3_128_KEY_SIZE, - .max_keysize = DES3_128_KEY_SIZE, - .setkey = des3_128_setkey, - .encrypt = ecb_des3_128_encrypt, - .decrypt = ecb_des3_128_decrypt, - } - } -}; + return nbytes; +} -static int cbc_des3_128_encrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static unsigned int des3_128_encrypt_cbc(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) { - struct crypt_s390_des3_128_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; + struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES3_128_BLOCK_SIZE - 1); + + memcpy(sctx->iv, desc->info, DES3_128_BLOCK_SIZE); + ret = crypt_s390_kmc(KMC_TDEA_128_ENCRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); - blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_desall_crypt(desc, KMC_TDEA_128_ENCRYPT, sctx->iv, &walk); + memcpy(desc->info, sctx->iv, DES3_128_BLOCK_SIZE); + return nbytes; } -static int cbc_des3_128_decrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static unsigned int des3_128_decrypt_cbc(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) { - struct crypt_s390_des3_128_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; + struct crypt_s390_des3_128_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES3_128_BLOCK_SIZE - 1); + + memcpy(&sctx->iv, desc->info, DES3_128_BLOCK_SIZE); + ret = crypt_s390_kmc(KMC_TDEA_128_DECRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); - blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_desall_crypt(desc, KMC_TDEA_128_DECRYPT, sctx->iv, &walk); + return nbytes; } -static struct crypto_alg cbc_des3_128_alg = { - .cra_name = "cbc(des3_ede128)", - .cra_driver_name = "cbc-des3_ede128-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, +static struct crypto_alg des3_128_alg = { + .cra_name = "des3_ede128", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = DES3_128_BLOCK_SIZE, .cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx), - .cra_type = &crypto_blkcipher_type, .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT( - cbc_des3_128_alg.cra_list), + .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list), .cra_u = { - .blkcipher = { - .min_keysize = DES3_128_KEY_SIZE, - .max_keysize = DES3_128_KEY_SIZE, - .ivsize = DES3_128_BLOCK_SIZE, - .setkey = des3_128_setkey, - .encrypt = cbc_des3_128_encrypt, - .decrypt = cbc_des3_128_decrypt, + .cipher = { + .cia_min_keysize = DES3_128_KEY_SIZE, + .cia_max_keysize = DES3_128_KEY_SIZE, + .cia_setkey = des3_128_setkey, + .cia_encrypt = des3_128_encrypt, + .cia_decrypt = des3_128_decrypt, + .cia_encrypt_ecb = des3_128_encrypt_ecb, + .cia_decrypt_ecb = des3_128_decrypt_ecb, + .cia_encrypt_cbc = des3_128_encrypt_cbc, + .cia_decrypt_cbc = des3_128_decrypt_cbc, } } }; @@ -402,12 +303,11 @@ static struct crypto_alg cbc_des3_128_alg = { * */ static int des3_192_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) + unsigned int keylen, u32 *flags) { int i, ret; struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm); - const u8 *temp_key = key; - u32 *flags = &tfm->crt_flags; + const u8* temp_key = key; if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], @@ -441,111 +341,89 @@ static void des3_192_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) DES3_192_BLOCK_SIZE); } -static struct crypto_alg des3_192_alg = { - .cra_name = "des3_ede", - .cra_driver_name = "des3_ede-s390", - .cra_priority = CRYPT_S390_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = DES3_192_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx), - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list), - .cra_u = { - .cipher = { - .cia_min_keysize = DES3_192_KEY_SIZE, - .cia_max_keysize = DES3_192_KEY_SIZE, - .cia_setkey = des3_192_setkey, - .cia_encrypt = des3_192_encrypt, - .cia_decrypt = des3_192_decrypt, - } - } -}; - -static int ecb_des3_192_encrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static unsigned int des3_192_encrypt_ecb(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) { - struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; + struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES3_192_BLOCK_SIZE - 1); + ret = crypt_s390_km(KM_TDEA_192_ENCRYPT, sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_desall_crypt(desc, KM_TDEA_192_ENCRYPT, sctx->key, &walk); + return nbytes; } -static int ecb_des3_192_decrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static unsigned int des3_192_decrypt_ecb(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) { - struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; + struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; - blkcipher_walk_init(&walk, dst, src, nbytes); - return ecb_desall_crypt(desc, KM_TDEA_192_DECRYPT, sctx->key, &walk); -} + /* only use complete blocks */ + nbytes &= ~(DES3_192_BLOCK_SIZE - 1); + ret = crypt_s390_km(KM_TDEA_192_DECRYPT, sctx->key, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); -static struct crypto_alg ecb_des3_192_alg = { - .cra_name = "ecb(des3_ede)", - .cra_driver_name = "ecb-des3_ede-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, - .cra_blocksize = DES3_192_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx), - .cra_type = &crypto_blkcipher_type, - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT( - ecb_des3_192_alg.cra_list), - .cra_u = { - .blkcipher = { - .min_keysize = DES3_192_KEY_SIZE, - .max_keysize = DES3_192_KEY_SIZE, - .setkey = des3_192_setkey, - .encrypt = ecb_des3_192_encrypt, - .decrypt = ecb_des3_192_decrypt, - } - } -}; + return nbytes; +} -static int cbc_des3_192_encrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static unsigned int des3_192_encrypt_cbc(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) { - struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; + struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; + + /* only use complete blocks */ + nbytes &= ~(DES3_192_BLOCK_SIZE - 1); - blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, sctx->iv, &walk); + memcpy(sctx->iv, desc->info, DES3_192_BLOCK_SIZE); + ret = crypt_s390_kmc(KMC_TDEA_192_ENCRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + memcpy(desc->info, sctx->iv, DES3_192_BLOCK_SIZE); + return nbytes; } -static int cbc_des3_192_decrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes) +static unsigned int des3_192_decrypt_cbc(const struct cipher_desc *desc, + u8 *out, const u8 *in, + unsigned int nbytes) { - struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm); - struct blkcipher_walk walk; + struct crypt_s390_des3_192_ctx *sctx = crypto_tfm_ctx(desc->tfm); + int ret; - blkcipher_walk_init(&walk, dst, src, nbytes); - return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, sctx->iv, &walk); + /* only use complete blocks */ + nbytes &= ~(DES3_192_BLOCK_SIZE - 1); + + memcpy(&sctx->iv, desc->info, DES3_192_BLOCK_SIZE); + ret = crypt_s390_kmc(KMC_TDEA_192_DECRYPT, &sctx->iv, out, in, nbytes); + BUG_ON((ret < 0) || (ret != nbytes)); + + return nbytes; } -static struct crypto_alg cbc_des3_192_alg = { - .cra_name = "cbc(des3_ede)", - .cra_driver_name = "cbc-des3_ede-s390", - .cra_priority = CRYPT_S390_COMPOSITE_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, +static struct crypto_alg des3_192_alg = { + .cra_name = "des3_ede", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = DES3_192_BLOCK_SIZE, .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx), - .cra_type = &crypto_blkcipher_type, .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT( - cbc_des3_192_alg.cra_list), + .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list), .cra_u = { - .blkcipher = { - .min_keysize = DES3_192_KEY_SIZE, - .max_keysize = DES3_192_KEY_SIZE, - .ivsize = DES3_192_BLOCK_SIZE, - .setkey = des3_192_setkey, - .encrypt = cbc_des3_192_encrypt, - .decrypt = cbc_des3_192_decrypt, + .cipher = { + .cia_min_keysize = DES3_192_KEY_SIZE, + .cia_max_keysize = DES3_192_KEY_SIZE, + .cia_setkey = des3_192_setkey, + .cia_encrypt = des3_192_encrypt, + .cia_decrypt = des3_192_decrypt, + .cia_encrypt_ecb = des3_192_encrypt_ecb, + .cia_decrypt_ecb = des3_192_decrypt_ecb, + .cia_encrypt_cbc = des3_192_encrypt_cbc, + .cia_decrypt_cbc = des3_192_decrypt_cbc, } } }; @@ -559,69 +437,22 @@ static int init(void) !crypt_s390_func_available(KM_TDEA_192_ENCRYPT)) return -ENOSYS; - ret = crypto_register_alg(&des_alg); - if (ret) - goto des_err; - ret = crypto_register_alg(&ecb_des_alg); - if (ret) - goto ecb_des_err; - ret = crypto_register_alg(&cbc_des_alg); - if (ret) - goto cbc_des_err; - - ret = crypto_register_alg(&des3_128_alg); - if (ret) - goto des3_128_err; - ret = crypto_register_alg(&ecb_des3_128_alg); - if (ret) - goto ecb_des3_128_err; - ret = crypto_register_alg(&cbc_des3_128_alg); - if (ret) - goto cbc_des3_128_err; - - ret = crypto_register_alg(&des3_192_alg); - if (ret) - goto des3_192_err; - ret = crypto_register_alg(&ecb_des3_192_alg); - if (ret) - goto ecb_des3_192_err; - ret = crypto_register_alg(&cbc_des3_192_alg); - if (ret) - goto cbc_des3_192_err; - -out: - return ret; - -cbc_des3_192_err: - crypto_unregister_alg(&ecb_des3_192_alg); -ecb_des3_192_err: - crypto_unregister_alg(&des3_192_alg); -des3_192_err: - crypto_unregister_alg(&cbc_des3_128_alg); -cbc_des3_128_err: - crypto_unregister_alg(&ecb_des3_128_alg); -ecb_des3_128_err: - crypto_unregister_alg(&des3_128_alg); -des3_128_err: - crypto_unregister_alg(&cbc_des_alg); -cbc_des_err: - crypto_unregister_alg(&ecb_des_alg); -ecb_des_err: - crypto_unregister_alg(&des_alg); -des_err: - goto out; + ret |= (crypto_register_alg(&des_alg) == 0) ? 0:1; + ret |= (crypto_register_alg(&des3_128_alg) == 0) ? 0:2; + ret |= (crypto_register_alg(&des3_192_alg) == 0) ? 0:4; + if (ret) { + crypto_unregister_alg(&des3_192_alg); + crypto_unregister_alg(&des3_128_alg); + crypto_unregister_alg(&des_alg); + return -EEXIST; + } + return 0; } static void __exit fini(void) { - crypto_unregister_alg(&cbc_des3_192_alg); - crypto_unregister_alg(&ecb_des3_192_alg); crypto_unregister_alg(&des3_192_alg); - crypto_unregister_alg(&cbc_des3_128_alg); - crypto_unregister_alg(&ecb_des3_128_alg); crypto_unregister_alg(&des3_128_alg); - crypto_unregister_alg(&cbc_des_alg); - crypto_unregister_alg(&ecb_des_alg); crypto_unregister_alg(&des_alg); } diff --git a/trunk/arch/s390/crypto/sha1_s390.c b/trunk/arch/s390/crypto/sha1_s390.c index 49ca8690ee39..9d34a35b1aa5 100644 --- a/trunk/arch/s390/crypto/sha1_s390.c +++ b/trunk/arch/s390/crypto/sha1_s390.c @@ -126,8 +126,6 @@ static void sha1_final(struct crypto_tfm *tfm, u8 *out) static struct crypto_alg alg = { .cra_name = "sha1", - .cra_driver_name = "sha1-s390", - .cra_priority = CRYPT_S390_PRIORITY, .cra_flags = CRYPTO_ALG_TYPE_DIGEST, .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct crypt_s390_sha1_ctx), diff --git a/trunk/arch/s390/crypto/sha256_s390.c b/trunk/arch/s390/crypto/sha256_s390.c index 8e4e67503fe7..f573df30f31d 100644 --- a/trunk/arch/s390/crypto/sha256_s390.c +++ b/trunk/arch/s390/crypto/sha256_s390.c @@ -127,8 +127,6 @@ static void sha256_final(struct crypto_tfm *tfm, u8 *out) static struct crypto_alg alg = { .cra_name = "sha256", - .cra_driver_name = "sha256-s390", - .cra_priority = CRYPT_S390_PRIORITY, .cra_flags = CRYPTO_ALG_TYPE_DIGEST, .cra_blocksize = SHA256_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s390_sha256_ctx), diff --git a/trunk/arch/s390/defconfig b/trunk/arch/s390/defconfig index 35da53986b1b..f4dfc10026d2 100644 --- a/trunk/arch/s390/defconfig +++ b/trunk/arch/s390/defconfig @@ -1,16 +1,13 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18-rc2 -# Thu Jul 27 13:51:07 2006 +# Linux kernel version: 2.6.17-rc1 +# Mon Apr 3 14:34:15 2006 # CONFIG_MMU=y -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_STACKTRACE_SUPPORT=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_S390=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # # Code maturity level options @@ -28,7 +25,6 @@ CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_TASKSTATS is not set CONFIG_SYSCTL=y CONFIG_AUDIT=y # CONFIG_AUDITSYSCALL is not set @@ -47,12 +43,10 @@ CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y -CONFIG_RT_MUTEXES=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y CONFIG_SLAB=y -CONFIG_VM_EVENT_COUNTERS=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -100,6 +94,7 @@ CONFIG_HOTPLUG_CPU=y CONFIG_DEFAULT_MIGRATION_COST=1000000 CONFIG_COMPAT=y CONFIG_SYSVIPC_COMPAT=y +CONFIG_BINFMT_ELF32=y # # Code generation options @@ -120,7 +115,6 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_RESOURCES_64BIT=y # # I/O subsystem configuration @@ -148,7 +142,6 @@ CONFIG_VIRT_CPU_ACCOUNTING=y # CONFIG_APPLDATA_BASE is not set CONFIG_NO_IDLE_HZ=y CONFIG_NO_IDLE_HZ_INIT=y -CONFIG_S390_HYPFS_FS=y CONFIG_KEXEC=y # @@ -181,8 +174,6 @@ CONFIG_IP_FIB_HASH=y # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -195,10 +186,7 @@ CONFIG_IPV6=y # CONFIG_INET6_IPCOMP is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set -CONFIG_INET6_XFRM_MODE_TRANSPORT=y -CONFIG_INET6_XFRM_MODE_TUNNEL=y # CONFIG_IPV6_TUNNEL is not set -# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # @@ -275,7 +263,6 @@ CONFIG_NET_ESTIMATOR=y # Network testing # # CONFIG_NET_PKTGEN is not set -# CONFIG_NET_TCPPROBE is not set # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set @@ -289,7 +276,6 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set -CONFIG_SYS_HYPERVISOR=y # # Connector - unified userspace <-> kernelspace linker @@ -348,7 +334,6 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set @@ -374,7 +359,9 @@ CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set -# CONFIG_MD_RAID456 is not set +CONFIG_MD_RAID5=m +# CONFIG_MD_RAID5_RESHAPE is not set +# CONFIG_MD_RAID6 is not set CONFIG_MD_MULTIPATH=m # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=y @@ -428,13 +415,11 @@ CONFIG_S390_TAPE_34XX=m # CONFIG_VMLOGRDR is not set # CONFIG_VMCP is not set # CONFIG_MONREADER is not set -CONFIG_MONWRITER=m # # Cryptographic devices # -CONFIG_ZCRYPT=m -# CONFIG_ZCRYPT_MONOLITHIC is not set +CONFIG_Z90CRYPT=m # # Network device support @@ -524,7 +509,6 @@ CONFIG_FS_MBCACHE=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -630,36 +614,26 @@ CONFIG_MSDOS_PARTITION=y # Instrumentation Support # # CONFIG_PROFILING is not set -CONFIG_STATISTICS=y -CONFIG_KPROBES=y +# CONFIG_STATISTICS is not set # # Kernel hacking # -CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set CONFIG_MAGIC_SYSRQ=y -# CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=17 # CONFIG_DETECT_SOFTLOCKUP is not set # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set CONFIG_DEBUG_PREEMPT=y -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_MUTEXES=y -# CONFIG_DEBUG_RWSEMS is not set -# CONFIG_DEBUG_LOCK_ALLOC is not set -# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_SPINLOCK_SLEEP=y -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set -# CONFIG_FRAME_POINTER is not set # CONFIG_UNWIND_INFO is not set CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set @@ -714,4 +688,3 @@ CONFIG_CRYPTO=y # CONFIG_CRC16 is not set CONFIG_CRC32=m # CONFIG_LIBCRC32C is not set -CONFIG_PLIST=y diff --git a/trunk/arch/s390/hypfs/hypfs.h b/trunk/arch/s390/hypfs/hypfs.h index f3dbd91965c6..ea5567be00fc 100644 --- a/trunk/arch/s390/hypfs/hypfs.h +++ b/trunk/arch/s390/hypfs/hypfs.h @@ -1,5 +1,5 @@ /* - * arch/s390/hypfs/hypfs.h + * fs/hypfs/hypfs.h * Hypervisor filesystem for Linux on s390. * * Copyright (C) IBM Corp. 2006 diff --git a/trunk/arch/s390/hypfs/hypfs_diag.c b/trunk/arch/s390/hypfs/hypfs_diag.c index 75144efbb92b..1785bce2b919 100644 --- a/trunk/arch/s390/hypfs/hypfs_diag.c +++ b/trunk/arch/s390/hypfs/hypfs_diag.c @@ -1,5 +1,5 @@ /* - * arch/s390/hypfs/hypfs_diag.c + * fs/hypfs/hypfs_diag.c * Hypervisor filesystem for Linux on s390. Diag 204 and 224 * implementation. * @@ -432,14 +432,12 @@ static int diag204_probe(void) buf = diag204_get_buffer(INFO_EXT, &pages); if (!IS_ERR(buf)) { - if (diag204((unsigned long)SUBC_STIB7 | - (unsigned long)INFO_EXT, pages, buf) >= 0) { + if (diag204(SUBC_STIB7 | INFO_EXT, pages, buf) >= 0) { diag204_store_sc = SUBC_STIB7; diag204_info_type = INFO_EXT; goto out; } - if (diag204((unsigned long)SUBC_STIB6 | - (unsigned long)INFO_EXT, pages, buf) >= 0) { + if (diag204(SUBC_STIB6 | INFO_EXT, pages, buf) >= 0) { diag204_store_sc = SUBC_STIB7; diag204_info_type = INFO_EXT; goto out; @@ -454,8 +452,7 @@ static int diag204_probe(void) rc = PTR_ERR(buf); goto fail_alloc; } - if (diag204((unsigned long)SUBC_STIB4 | - (unsigned long)INFO_SIMPLE, pages, buf) >= 0) { + if (diag204(SUBC_STIB4 | INFO_SIMPLE, pages, buf) >= 0) { diag204_store_sc = SUBC_STIB4; diag204_info_type = INFO_SIMPLE; goto out; @@ -479,8 +476,7 @@ static void *diag204_store(void) buf = diag204_get_buffer(diag204_info_type, &pages); if (IS_ERR(buf)) goto out; - if (diag204((unsigned long)diag204_store_sc | - (unsigned long)diag204_info_type, pages, buf) < 0) + if (diag204(diag204_store_sc | diag204_info_type, pages, buf) < 0) return ERR_PTR(-ENOSYS); out: return buf; @@ -535,7 +531,7 @@ __init int hypfs_diag_init(void) return rc; } -void hypfs_diag_exit(void) +__exit void hypfs_diag_exit(void) { diag224_delete_name_table(); diag204_free_buffer(); diff --git a/trunk/arch/s390/hypfs/hypfs_diag.h b/trunk/arch/s390/hypfs/hypfs_diag.h index 256b384aebe1..793dea6b9bb6 100644 --- a/trunk/arch/s390/hypfs/hypfs_diag.h +++ b/trunk/arch/s390/hypfs/hypfs_diag.h @@ -1,5 +1,5 @@ /* - * arch/s390/hypfs_diag.h + * fs/hypfs/hypfs_diag.h * Hypervisor filesystem for Linux on s390. * * Copyright (C) IBM Corp. 2006 diff --git a/trunk/arch/s390/hypfs/inode.c b/trunk/arch/s390/hypfs/inode.c index bdade5f2e325..18c091925ea5 100644 --- a/trunk/arch/s390/hypfs/inode.c +++ b/trunk/arch/s390/hypfs/inode.c @@ -1,5 +1,5 @@ /* - * arch/s390/hypfs/inode.c + * fs/hypfs/inode.c * Hypervisor filesystem for Linux on s390. * * Copyright (C) IBM Corp. 2006 @@ -312,12 +312,10 @@ static void hypfs_kill_super(struct super_block *sb) { struct hypfs_sb_info *sb_info = sb->s_fs_info; - if (sb->s_root) { - hypfs_delete_tree(sb->s_root); - hypfs_remove(sb_info->update_file); - kfree(sb->s_fs_info); - sb->s_fs_info = NULL; - } + hypfs_delete_tree(sb->s_root); + hypfs_remove(sb_info->update_file); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; kill_litter_super(sb); } diff --git a/trunk/arch/s390/kernel/Makefile b/trunk/arch/s390/kernel/Makefile index aa978978d3d1..86601a945709 100644 --- a/trunk/arch/s390/kernel/Makefile +++ b/trunk/arch/s390/kernel/Makefile @@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional obj-y := bitmap.o traps.o time.o process.o \ setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ - semaphore.o s390_ext.o debug.o profile.o irq.o ipl.o + semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) @@ -16,15 +16,12 @@ extra-y += head.o init_task.o vmlinux.lds obj-$(CONFIG_MODULES) += s390_ksyms.o module.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_AUDIT) += audit.o -compat-obj-$(CONFIG_AUDIT) += compat_audit.o obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o \ compat_wrapper.o compat_exec_domain.o \ - binfmt_elf32.o $(compat-obj-y) + binfmt_elf32.o obj-$(CONFIG_VIRT_TIMER) += vtime.o obj-$(CONFIG_STACKTRACE) += stacktrace.o -obj-$(CONFIG_KPROBES) += kprobes.o # Kexec part S390_KEXEC_OBJS := machine_kexec.o crash.o diff --git a/trunk/arch/s390/kernel/audit.c b/trunk/arch/s390/kernel/audit.c deleted file mode 100644 index 0741d9193390..000000000000 --- a/trunk/arch/s390/kernel/audit.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include -#include - -static unsigned dir_class[] = { -#include -~0U -}; - -static unsigned read_class[] = { -#include -~0U -}; - -static unsigned write_class[] = { -#include -~0U -}; - -static unsigned chattr_class[] = { -#include -~0U -}; - -int audit_classify_syscall(int abi, unsigned syscall) -{ -#ifdef CONFIG_COMPAT - extern int s390_classify_syscall(unsigned); - if (abi == AUDIT_ARCH_S390) - return s390_classify_syscall(syscall); -#endif - switch(syscall) { - case __NR_open: - return 2; - case __NR_openat: - return 3; - case __NR_socketcall: - return 4; - case __NR_execve: - return 5; - default: - return 0; - } -} - -static int __init audit_classes_init(void) -{ -#ifdef CONFIG_COMPAT - extern __u32 s390_dir_class[]; - extern __u32 s390_write_class[]; - extern __u32 s390_read_class[]; - extern __u32 s390_chattr_class[]; - audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class); - audit_register_class(AUDIT_CLASS_READ_32, s390_read_class); - audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class); - audit_register_class(AUDIT_CLASS_CHATTR_32, s390_chattr_class); -#endif - audit_register_class(AUDIT_CLASS_WRITE, write_class); - audit_register_class(AUDIT_CLASS_READ, read_class); - audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); - audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); - return 0; -} - -__initcall(audit_classes_init); diff --git a/trunk/arch/s390/kernel/compat_audit.c b/trunk/arch/s390/kernel/compat_audit.c deleted file mode 100644 index 16d9436bfa91..000000000000 --- a/trunk/arch/s390/kernel/compat_audit.c +++ /dev/null @@ -1,38 +0,0 @@ -#undef __s390x__ -#include - -unsigned s390_dir_class[] = { -#include -~0U -}; - -unsigned s390_chattr_class[] = { -#include -~0U -}; - -unsigned s390_write_class[] = { -#include -~0U -}; - -unsigned s390_read_class[] = { -#include -~0U -}; - -int s390_classify_syscall(unsigned syscall) -{ - switch(syscall) { - case __NR_open: - return 2; - case __NR_openat: - return 3; - case __NR_socketcall: - return 4; - case __NR_execve: - return 5; - default: - return 1; - } -} diff --git a/trunk/arch/s390/kernel/entry.S b/trunk/arch/s390/kernel/entry.S index 0c712b78a7e8..5b5799ac8f83 100644 --- a/trunk/arch/s390/kernel/entry.S +++ b/trunk/arch/s390/kernel/entry.S @@ -505,8 +505,6 @@ pgm_no_vtime2: mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP - tm SP_PSW+1(%r15),0x01 # kernel per event ? - bz BASED(kernel_per) l %r3,__LC_PGM_ILC # load program interruption code la %r8,0x7f nr %r8,%r3 # clear per-event-bit and ilc @@ -538,16 +536,6 @@ pgm_no_vtime3: stosm __SF_EMPTY(%r15),0x03 # reenable interrupts b BASED(sysc_do_svc) -# -# per was called from kernel, must be kprobes -# -kernel_per: - mvi SP_TRAP+1(%r15),0x28 # set trap indication to pgm check - la %r2,SP_PTREGS(%r15) # address of register-save area - l %r1,BASED(.Lhandle_per) # load adr. of per handler - la %r14,BASED(sysc_leave) # load adr. of system return - br %r1 # branch to do_single_step - /* * IO interrupt handler routine */ diff --git a/trunk/arch/s390/kernel/entry64.S b/trunk/arch/s390/kernel/entry64.S index 29bbfbab7332..56f5f613b868 100644 --- a/trunk/arch/s390/kernel/entry64.S +++ b/trunk/arch/s390/kernel/entry64.S @@ -518,8 +518,6 @@ pgm_no_vtime2: #endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct lg %r1,__TI_task(%r9) - tm SP_PSW+1(%r15),0x01 # kernel per event ? - jz kernel_per mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID @@ -555,16 +553,6 @@ pgm_no_vtime3: stosm __SF_EMPTY(%r15),0x03 # reenable interrupts j sysc_do_svc -# -# per was called from kernel, must be kprobes -# -kernel_per: - lhi %r0,__LC_PGM_OLD_PSW - sth %r0,SP_TRAP(%r15) # set trap indication to pgm check - la %r2,SP_PTREGS(%r15) # address of register-save area - larl %r14,sysc_leave # load adr. of system ret, no work - jg do_single_step # branch to do_single_step - /* * IO interrupt handler routine */ @@ -827,7 +815,7 @@ restart_go: */ stack_overflow: lg %r15,__LC_PANIC_STACK # change to panic stack - aghi %r15,-SP_SIZE + aghi %r1,-SP_SIZE mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack stmg %r0,%r11,SP_R0(%r15) # store gprs %r0-%r11 to kernel stack la %r1,__LC_SAVE_AREA @@ -835,7 +823,7 @@ stack_overflow: je 0f chi %r12,__LC_PGM_OLD_PSW je 0f - la %r1,__LC_SAVE_AREA+32 + la %r1,__LC_SAVE_AREA+16 0: mvc SP_R12(32,%r15),0(%r1) # move %r12-%r15 to stack xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) # clear back chain la %r2,SP_PTREGS(%r15) # load pt_regs diff --git a/trunk/arch/s390/kernel/head.S b/trunk/arch/s390/kernel/head.S index 0f1db268a8a9..adad8863ee2f 100644 --- a/trunk/arch/s390/kernel/head.S +++ b/trunk/arch/s390/kernel/head.S @@ -272,7 +272,7 @@ iplstart: # load parameter file from ipl device # .Lagain1: - l %r2,.Linitrd # ramdisk loc. is temp + l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # ramdisk loc. is temp bas %r14,.Lloader # load parameter file ltr %r2,%r2 # got anything ? bz .Lnopf @@ -280,7 +280,7 @@ iplstart: bnh .Lnotrunc la %r2,895 .Lnotrunc: - l %r4,.Linitrd + l %r4,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) clc 0(3,%r4),.L_hdr # if it is HDRx bz .Lagain1 # skip dataset header clc 0(3,%r4),.L_eof # if it is EOFx @@ -323,15 +323,14 @@ iplstart: # load ramdisk from ipl device # .Lagain2: - l %r2,.Linitrd # addr of ramdisk - st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) + l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # addr of ramdisk bas %r14,.Lloader # load ramdisk st %r2,INITRD_SIZE+ARCH_OFFSET-PARMAREA(%r12) # store size of ramdisk ltr %r2,%r2 bnz .Lrdcont st %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) # no ramdisk found .Lrdcont: - l %r2,.Linitrd + l %r2,INITRD_START+ARCH_OFFSET-PARMAREA(%r12) clc 0(3,%r2),.L_hdr # skip HDRx and EOFx bz .Lagain2 @@ -380,7 +379,6 @@ iplstart: l %r1,.Lstartup br %r1 -.Linitrd:.long _end + 0x400000 # default address of initrd .Lparm: .long PARMAREA .Lstartup: .long startup .Lcvtab:.long _ebcasc # ebcdic to ascii table @@ -481,6 +479,65 @@ start: .byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7 .byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff +.macro GET_IPL_DEVICE +.Lget_ipl_device: + l %r1,0xb8 # get sid + sll %r1,15 # test if subchannel is enabled + srl %r1,31 + ltr %r1,%r1 + bz 2f-.LPG1(%r13) # subchannel disabled + l %r1,0xb8 + la %r5,.Lipl_schib-.LPG1(%r13) + stsch 0(%r5) # get schib of subchannel + bnz 2f-.LPG1(%r13) # schib not available + tm 5(%r5),0x01 # devno valid? + bno 2f-.LPG1(%r13) + la %r6,ipl_parameter_flags-.LPG1(%r13) + oi 3(%r6),0x01 # set flag + la %r2,ipl_devno-.LPG1(%r13) + mvc 0(2,%r2),6(%r5) # store devno + tm 4(%r5),0x80 # qdio capable device? + bno 2f-.LPG1(%r13) + oi 3(%r6),0x02 # set flag + + # copy ipl parameters + + lhi %r0,4096 + l %r2,20(%r0) # get address of parameter list + lhi %r3,IPL_PARMBLOCK_ORIGIN + st %r3,20(%r0) + lhi %r4,1 + cr %r2,%r3 # start parameters < destination ? + jl 0f + lhi %r1,1 # copy direction is upwards + j 1f +0: lhi %r1,-1 # copy direction is downwards + ar %r2,%r0 + ar %r3,%r0 + ar %r2,%r1 + ar %r3,%r1 +1: mvc 0(1,%r3),0(%r2) # finally copy ipl parameters + ar %r3,%r1 + ar %r2,%r1 + sr %r0,%r4 + jne 1b + b 2f-.LPG1(%r13) + + .align 4 +.Lipl_schib: + .rept 13 + .long 0 + .endr + + .globl ipl_parameter_flags +ipl_parameter_flags: + .long 0 + .globl ipl_devno +ipl_devno: + .word 0 +2: +.endm + #ifdef CONFIG_64BIT #include "head64.S" #else diff --git a/trunk/arch/s390/kernel/head31.S b/trunk/arch/s390/kernel/head31.S index 1fa9fa1ca740..a4dc61f3285e 100644 --- a/trunk/arch/s390/kernel/head31.S +++ b/trunk/arch/s390/kernel/head31.S @@ -26,8 +26,8 @@ startup:basr %r13,0 # get base # .org PARMAREA .long 0,0 # IPL_DEVICE - .long 0,0 # INITRD_START - .long 0,0 # INITRD_SIZE + .long 0,RAMDISK_ORIGIN # INITRD_START + .long 0,RAMDISK_SIZE # INITRD_SIZE .org COMMAND_LINE .byte "root=/dev/ram0 ro" @@ -37,23 +37,12 @@ startup:basr %r13,0 # get base startup_continue: basr %r13,0 # get base -.LPG1: mvi __LC_AR_MODE_ID,0 # set ESA flag (mode 0) +.LPG1: GET_IPL_DEVICE lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area # move IPL device to lowcore mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12) -# -# Setup stack -# - l %r15,.Linittu-.LPG1(%r13) - mvc __LC_CURRENT(4),__TI_task(%r15) - ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union+THREAD_SIZE - st %r15,__LC_KERNEL_STACK # set end of kernel stack - ahi %r15,-96 - xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain - l %r14,.Lipl_save_parameters-.LPG1(%r13) - basr %r14,%r14 # # clear bss memory # @@ -125,10 +114,6 @@ startup_continue: b .Lfchunk-.LPG1(%r13) .align 4 -.Lipl_save_parameters: - .long ipl_save_parameters -.Linittu: - .long init_thread_union .Lpmask: .byte 0 .align 8 @@ -288,23 +273,7 @@ startup_continue: .Lbss_end: .long _end .Lparmaddr: .long PARMAREA .Lsccbaddr: .long .Lsccb - - .globl ipl_schib -ipl_schib: - .rept 13 - .long 0 - .endr - - .globl ipl_flags -ipl_flags: - .long 0 - .globl ipl_devno -ipl_devno: - .word 0 - .org 0x12000 -.globl s390_readinfo_sccb -s390_readinfo_sccb: .Lsccb: .hword 0x1000 # length, one page .byte 0x00,0x00,0x00 @@ -333,6 +302,16 @@ s390_readinfo_sccb: .globl _stext _stext: basr %r13,0 # get base .LPG3: +# +# Setup stack +# + l %r15,.Linittu-.LPG3(%r13) + mvc __LC_CURRENT(4),__TI_task(%r15) + ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union+THREAD_SIZE + st %r15,__LC_KERNEL_STACK # set end of kernel stack + ahi %r15,-96 + xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain + # check control registers stctl %c0,%c15,0(%r15) oi 2(%r15),0x40 # enable sigp emergency signal @@ -351,5 +330,6 @@ _stext: basr %r13,0 # get base # .align 8 .Ldw: .long 0x000a0000,0x00000000 +.Linittu:.long init_thread_union .Lstart:.long start_kernel .Laregs:.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 diff --git a/trunk/arch/s390/kernel/head64.S b/trunk/arch/s390/kernel/head64.S index a8bdd96494c7..9d80c5b1ef95 100644 --- a/trunk/arch/s390/kernel/head64.S +++ b/trunk/arch/s390/kernel/head64.S @@ -26,8 +26,8 @@ startup:basr %r13,0 # get base # .org PARMAREA .quad 0 # IPL_DEVICE - .quad 0 # INITRD_START - .quad 0 # INITRD_SIZE + .quad RAMDISK_ORIGIN # INITRD_START + .quad RAMDISK_SIZE # INITRD_SIZE .org COMMAND_LINE .byte "root=/dev/ram0 ro" @@ -39,8 +39,8 @@ startup_continue: basr %r13,0 # get base .LPG1: sll %r13,1 # remove high order bit srl %r13,1 + GET_IPL_DEVICE lhi %r1,1 # mode 1 = esame - mvi __LC_AR_MODE_ID,1 # set esame flag slr %r0,%r0 # set cpuid to zero sigp %r1,%r0,0x12 # switch to esame mode sam64 # switch to 64 bit mode @@ -48,18 +48,7 @@ startup_continue: lg %r12,.Lparmaddr-.LPG1(%r13)# pointer to parameter area # move IPL device to lowcore mvc __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12) -# -# Setup stack -# - larl %r15,init_thread_union - lg %r14,__TI_task(%r15) # cache current in lowcore - stg %r14,__LC_CURRENT - aghi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE - stg %r15,__LC_KERNEL_STACK # set end of kernel stack - aghi %r15,-160 - xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain - brasl %r14,ipl_save_parameters # # clear bss memory # @@ -250,19 +239,6 @@ startup_continue: oi 7(%r12),0x80 # set IDTE flag 0: -# -# find out if we have the MVCOS instruction -# - la %r1,0f-.LPG1(%r13) # set program check address - stg %r1,__LC_PGM_NEW_PSW+8 - .short 0xc800 # mvcos 0(%r0),0(%r0),%r0 - .short 0x0000 - .short 0x0000 -0: tm 0x8f,0x13 # special-operation exception? - bno 1f-.LPG1(%r13) # if yes, MVCOS is present - oi 6(%r12),2 # set MVCOS flag -1: - lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space, # virtual and never return ... .align 16 @@ -292,22 +268,7 @@ startup_continue: .Lparmaddr: .quad PARMAREA - .globl ipl_schib -ipl_schib: - .rept 13 - .long 0 - .endr - - .globl ipl_flags -ipl_flags: - .long 0 - .globl ipl_devno -ipl_devno: - .word 0 - .org 0x12000 -.globl s390_readinfo_sccb -s390_readinfo_sccb: .Lsccb: .hword 0x1000 # length, one page .byte 0x00,0x00,0x00 @@ -336,12 +297,24 @@ s390_readinfo_sccb: .globl _stext _stext: basr %r13,0 # get base .LPG3: +# +# Setup stack +# + larl %r15,init_thread_union + lg %r14,__TI_task(%r15) # cache current in lowcore + stg %r14,__LC_CURRENT + aghi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) # init_task_union + THREAD_SIZE + stg %r15,__LC_KERNEL_STACK # set end of kernel stack + aghi %r15,-160 + xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) # clear backchain + # check control registers stctg %c0,%c15,0(%r15) oi 6(%r15),0x40 # enable sigp emergency signal oi 4(%r15),0x10 # switch on low address proctection lctlg %c0,%c15,0(%r15) +# lam 0,15,.Laregs-.LPG3(%r13) # load access regs needed by uaccess brasl %r14,start_kernel # go to C code # @@ -349,7 +322,7 @@ _stext: basr %r13,0 # get base # basr %r13,0 lpswe .Ldw-.(%r13) # load disabled wait psw - +# .align 8 .Ldw: .quad 0x0002000180000000,0x0000000000000000 .Laregs: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 diff --git a/trunk/arch/s390/kernel/ipl.c b/trunk/arch/s390/kernel/ipl.c deleted file mode 100644 index 6555cc48e28f..000000000000 --- a/trunk/arch/s390/kernel/ipl.c +++ /dev/null @@ -1,942 +0,0 @@ -/* - * arch/s390/kernel/ipl.c - * ipl/reipl/dump support for Linux on s390. - * - * Copyright (C) IBM Corp. 2005,2006 - * Author(s): Michael Holzheu - * Heiko Carstens - * Volker Sameske - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define IPL_PARM_BLOCK_VERSION 0 - -enum ipl_type { - IPL_TYPE_NONE = 1, - IPL_TYPE_UNKNOWN = 2, - IPL_TYPE_CCW = 4, - IPL_TYPE_FCP = 8, -}; - -#define IPL_NONE_STR "none" -#define IPL_UNKNOWN_STR "unknown" -#define IPL_CCW_STR "ccw" -#define IPL_FCP_STR "fcp" - -static char *ipl_type_str(enum ipl_type type) -{ - switch (type) { - case IPL_TYPE_NONE: - return IPL_NONE_STR; - case IPL_TYPE_CCW: - return IPL_CCW_STR; - case IPL_TYPE_FCP: - return IPL_FCP_STR; - case IPL_TYPE_UNKNOWN: - default: - return IPL_UNKNOWN_STR; - } -} - -enum ipl_method { - IPL_METHOD_NONE, - IPL_METHOD_CCW_CIO, - IPL_METHOD_CCW_DIAG, - IPL_METHOD_CCW_VM, - IPL_METHOD_FCP_RO_DIAG, - IPL_METHOD_FCP_RW_DIAG, - IPL_METHOD_FCP_RO_VM, -}; - -enum shutdown_action { - SHUTDOWN_REIPL, - SHUTDOWN_DUMP, - SHUTDOWN_STOP, -}; - -#define SHUTDOWN_REIPL_STR "reipl" -#define SHUTDOWN_DUMP_STR "dump" -#define SHUTDOWN_STOP_STR "stop" - -static char *shutdown_action_str(enum shutdown_action action) -{ - switch (action) { - case SHUTDOWN_REIPL: - return SHUTDOWN_REIPL_STR; - case SHUTDOWN_DUMP: - return SHUTDOWN_DUMP_STR; - case SHUTDOWN_STOP: - return SHUTDOWN_STOP_STR; - default: - BUG(); - } -} - -enum diag308_subcode { - DIAG308_IPL = 3, - DIAG308_DUMP = 4, - DIAG308_SET = 5, - DIAG308_STORE = 6, -}; - -enum diag308_ipl_type { - DIAG308_IPL_TYPE_FCP = 0, - DIAG308_IPL_TYPE_CCW = 2, -}; - -enum diag308_opt { - DIAG308_IPL_OPT_IPL = 0x10, - DIAG308_IPL_OPT_DUMP = 0x20, -}; - -enum diag308_rc { - DIAG308_RC_OK = 1, -}; - -static int diag308_set_works = 0; - -static int reipl_capabilities = IPL_TYPE_UNKNOWN; -static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN; -static enum ipl_method reipl_method = IPL_METHOD_NONE; -static struct ipl_parameter_block *reipl_block_fcp; -static struct ipl_parameter_block *reipl_block_ccw; - -static int dump_capabilities = IPL_TYPE_NONE; -static enum ipl_type dump_type = IPL_TYPE_NONE; -static enum ipl_method dump_method = IPL_METHOD_NONE; -static struct ipl_parameter_block *dump_block_fcp; -static struct ipl_parameter_block *dump_block_ccw; - -static enum shutdown_action on_panic_action = SHUTDOWN_STOP; - -static int diag308(unsigned long subcode, void *addr) -{ - register unsigned long _addr asm("0") = (unsigned long)addr; - register unsigned long _rc asm("1") = 0; - - asm volatile ( - " diag %0,%2,0x308\n" - "0: \n" - ".section __ex_table,\"a\"\n" -#ifdef CONFIG_64BIT - " .align 8\n" - " .quad 0b, 0b\n" -#else - " .align 4\n" - " .long 0b, 0b\n" -#endif - ".previous\n" - : "+d" (_addr), "+d" (_rc) - : "d" (subcode) : "cc", "memory" ); - - return _rc; -} - -/* SYSFS */ - -#define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value) \ -static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \ - char *page) \ -{ \ - return sprintf(page, _format, _value); \ -} \ -static struct subsys_attribute sys_##_prefix##_##_name##_attr = \ - __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL); - -#define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value) \ -static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \ - char *page) \ -{ \ - return sprintf(page, _fmt_out, \ - (unsigned long long) _value); \ -} \ -static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\ - const char *buf, size_t len) \ -{ \ - unsigned long long value; \ - if (sscanf(buf, _fmt_in, &value) != 1) \ - return -EINVAL; \ - _value = value; \ - return len; \ -} \ -static struct subsys_attribute sys_##_prefix##_##_name##_attr = \ - __ATTR(_name,(S_IRUGO | S_IWUSR), \ - sys_##_prefix##_##_name##_show, \ - sys_##_prefix##_##_name##_store); - -static void make_attrs_ro(struct attribute **attrs) -{ - while (*attrs) { - (*attrs)->mode = S_IRUGO; - attrs++; - } -} - -/* - * ipl section - */ - -static enum ipl_type ipl_get_type(void) -{ - struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; - - if (!(ipl_flags & IPL_DEVNO_VALID)) - return IPL_TYPE_UNKNOWN; - if (!(ipl_flags & IPL_PARMBLOCK_VALID)) - return IPL_TYPE_CCW; - if (ipl->hdr.version > IPL_MAX_SUPPORTED_VERSION) - return IPL_TYPE_UNKNOWN; - if (ipl->hdr.pbt != DIAG308_IPL_TYPE_FCP) - return IPL_TYPE_UNKNOWN; - return IPL_TYPE_FCP; -} - -static ssize_t ipl_type_show(struct subsystem *subsys, char *page) -{ - return sprintf(page, "%s\n", ipl_type_str(ipl_get_type())); -} - -static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type); - -static ssize_t sys_ipl_device_show(struct subsystem *subsys, char *page) -{ - struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; - - switch (ipl_get_type()) { - case IPL_TYPE_CCW: - return sprintf(page, "0.0.%04x\n", ipl_devno); - case IPL_TYPE_FCP: - return sprintf(page, "0.0.%04x\n", ipl->ipl_info.fcp.devno); - default: - return 0; - } -} - -static struct subsys_attribute sys_ipl_device_attr = - __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL); - -static ssize_t ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off, - size_t count) -{ - unsigned int size = IPL_PARMBLOCK_SIZE; - - if (off > size) - return 0; - if (off + count > size) - count = size - off; - memcpy(buf, (void *)IPL_PARMBLOCK_START + off, count); - return count; -} - -static struct bin_attribute ipl_parameter_attr = { - .attr = { - .name = "binary_parameter", - .mode = S_IRUGO, - .owner = THIS_MODULE, - }, - .size = PAGE_SIZE, - .read = &ipl_parameter_read, -}; - -static ssize_t ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off, - size_t count) -{ - unsigned int size = IPL_PARMBLOCK_START->ipl_info.fcp.scp_data_len; - void *scp_data = &IPL_PARMBLOCK_START->ipl_info.fcp.scp_data; - - if (off > size) - return 0; - if (off + count > size) - count = size - off; - memcpy(buf, scp_data + off, count); - return count; -} - -static struct bin_attribute ipl_scp_data_attr = { - .attr = { - .name = "scp_data", - .mode = S_IRUGO, - .owner = THIS_MODULE, - }, - .size = PAGE_SIZE, - .read = &ipl_scp_data_read, -}; - -/* FCP ipl device attributes */ - -DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n", (unsigned long long) - IPL_PARMBLOCK_START->ipl_info.fcp.wwpn); -DEFINE_IPL_ATTR_RO(ipl_fcp, lun, "0x%016llx\n", (unsigned long long) - IPL_PARMBLOCK_START->ipl_info.fcp.lun); -DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long) - IPL_PARMBLOCK_START->ipl_info.fcp.bootprog); -DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long) - IPL_PARMBLOCK_START->ipl_info.fcp.br_lba); - -static struct attribute *ipl_fcp_attrs[] = { - &sys_ipl_type_attr.attr, - &sys_ipl_device_attr.attr, - &sys_ipl_fcp_wwpn_attr.attr, - &sys_ipl_fcp_lun_attr.attr, - &sys_ipl_fcp_bootprog_attr.attr, - &sys_ipl_fcp_br_lba_attr.attr, - NULL, -}; - -static struct attribute_group ipl_fcp_attr_group = { - .attrs = ipl_fcp_attrs, -}; - -/* CCW ipl device attributes */ - -static struct attribute *ipl_ccw_attrs[] = { - &sys_ipl_type_attr.attr, - &sys_ipl_device_attr.attr, - NULL, -}; - -static struct attribute_group ipl_ccw_attr_group = { - .attrs = ipl_ccw_attrs, -}; - -/* UNKNOWN ipl device attributes */ - -static struct attribute *ipl_unknown_attrs[] = { - &sys_ipl_type_attr.attr, - NULL, -}; - -static struct attribute_group ipl_unknown_attr_group = { - .attrs = ipl_unknown_attrs, -}; - -static decl_subsys(ipl, NULL, NULL); - -/* - * reipl section - */ - -/* FCP reipl device attributes */ - -DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n", - reipl_block_fcp->ipl_info.fcp.wwpn); -DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%016llx\n", - reipl_block_fcp->ipl_info.fcp.lun); -DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n", - reipl_block_fcp->ipl_info.fcp.bootprog); -DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n", - reipl_block_fcp->ipl_info.fcp.br_lba); -DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n", - reipl_block_fcp->ipl_info.fcp.devno); - -static struct attribute *reipl_fcp_attrs[] = { - &sys_reipl_fcp_device_attr.attr, - &sys_reipl_fcp_wwpn_attr.attr, - &sys_reipl_fcp_lun_attr.attr, - &sys_reipl_fcp_bootprog_attr.attr, - &sys_reipl_fcp_br_lba_attr.attr, - NULL, -}; - -static struct attribute_group reipl_fcp_attr_group = { - .name = IPL_FCP_STR, - .attrs = reipl_fcp_attrs, -}; - -/* CCW reipl device attributes */ - -DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n", - reipl_block_ccw->ipl_info.ccw.devno); - -static struct attribute *reipl_ccw_attrs[] = { - &sys_reipl_ccw_device_attr.attr, - NULL, -}; - -static struct attribute_group reipl_ccw_attr_group = { - .name = IPL_CCW_STR, - .attrs = reipl_ccw_attrs, -}; - -/* reipl type */ - -static int reipl_set_type(enum ipl_type type) -{ - if (!(reipl_capabilities & type)) - return -EINVAL; - - switch(type) { - case IPL_TYPE_CCW: - if (MACHINE_IS_VM) - reipl_method = IPL_METHOD_CCW_VM; - else - reipl_method = IPL_METHOD_CCW_CIO; - break; - case IPL_TYPE_FCP: - if (diag308_set_works) - reipl_method = IPL_METHOD_FCP_RW_DIAG; - else if (MACHINE_IS_VM) - reipl_method = IPL_METHOD_FCP_RO_VM; - else - reipl_method = IPL_METHOD_FCP_RO_DIAG; - break; - default: - reipl_method = IPL_METHOD_NONE; - } - reipl_type = type; - return 0; -} - -static ssize_t reipl_type_show(struct subsystem *subsys, char *page) -{ - return sprintf(page, "%s\n", ipl_type_str(reipl_type)); -} - -static ssize_t reipl_type_store(struct subsystem *subsys, const char *buf, - size_t len) -{ - int rc = -EINVAL; - - if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0) - rc = reipl_set_type(IPL_TYPE_CCW); - else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0) - rc = reipl_set_type(IPL_TYPE_FCP); - return (rc != 0) ? rc : len; -} - -static struct subsys_attribute reipl_type_attr = - __ATTR(reipl_type, 0644, reipl_type_show, reipl_type_store); - -static decl_subsys(reipl, NULL, NULL); - -/* - * dump section - */ - -/* FCP dump device attributes */ - -DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n", - dump_block_fcp->ipl_info.fcp.wwpn); -DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n", - dump_block_fcp->ipl_info.fcp.lun); -DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n", - dump_block_fcp->ipl_info.fcp.bootprog); -DEFINE_IPL_ATTR_RW(dump_fcp, br_lba, "%lld\n", "%lld\n", - dump_block_fcp->ipl_info.fcp.br_lba); -DEFINE_IPL_ATTR_RW(dump_fcp, device, "0.0.%04llx\n", "0.0.%llx\n", - dump_block_fcp->ipl_info.fcp.devno); - -static struct attribute *dump_fcp_attrs[] = { - &sys_dump_fcp_device_attr.attr, - &sys_dump_fcp_wwpn_attr.attr, - &sys_dump_fcp_lun_attr.attr, - &sys_dump_fcp_bootprog_attr.attr, - &sys_dump_fcp_br_lba_attr.attr, - NULL, -}; - -static struct attribute_group dump_fcp_attr_group = { - .name = IPL_FCP_STR, - .attrs = dump_fcp_attrs, -}; - -/* CCW dump device attributes */ - -DEFINE_IPL_ATTR_RW(dump_ccw, device, "0.0.%04llx\n", "0.0.%llx\n", - dump_block_ccw->ipl_info.ccw.devno); - -static struct attribute *dump_ccw_attrs[] = { - &sys_dump_ccw_device_attr.attr, - NULL, -}; - -static struct attribute_group dump_ccw_attr_group = { - .name = IPL_CCW_STR, - .attrs = dump_ccw_attrs, -}; - -/* dump type */ - -static int dump_set_type(enum ipl_type type) -{ - if (!(dump_capabilities & type)) - return -EINVAL; - switch(type) { - case IPL_TYPE_CCW: - if (MACHINE_IS_VM) - dump_method = IPL_METHOD_CCW_VM; - else - dump_method = IPL_METHOD_CCW_CIO; - break; - case IPL_TYPE_FCP: - dump_method = IPL_METHOD_FCP_RW_DIAG; - break; - default: - dump_method = IPL_METHOD_NONE; - } - dump_type = type; - return 0; -} - -static ssize_t dump_type_show(struct subsystem *subsys, char *page) -{ - return sprintf(page, "%s\n", ipl_type_str(dump_type)); -} - -static ssize_t dump_type_store(struct subsystem *subsys, const char *buf, - size_t len) -{ - int rc = -EINVAL; - - if (strncmp(buf, IPL_NONE_STR, strlen(IPL_NONE_STR)) == 0) - rc = dump_set_type(IPL_TYPE_NONE); - else if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0) - rc = dump_set_type(IPL_TYPE_CCW); - else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0) - rc = dump_set_type(IPL_TYPE_FCP); - return (rc != 0) ? rc : len; -} - -static struct subsys_attribute dump_type_attr = - __ATTR(dump_type, 0644, dump_type_show, dump_type_store); - -static decl_subsys(dump, NULL, NULL); - -#ifdef CONFIG_SMP -static void dump_smp_stop_all(void) -{ - int cpu; - preempt_disable(); - for_each_online_cpu(cpu) { - if (cpu == smp_processor_id()) - continue; - while (signal_processor(cpu, sigp_stop) == sigp_busy) - udelay(10); - } - preempt_enable(); -} -#else -#define dump_smp_stop_all() do { } while (0) -#endif - -/* - * Shutdown actions section - */ - -static decl_subsys(shutdown_actions, NULL, NULL); - -/* on panic */ - -static ssize_t on_panic_show(struct subsystem *subsys, char *page) -{ - return sprintf(page, "%s\n", shutdown_action_str(on_panic_action)); -} - -static ssize_t on_panic_store(struct subsystem *subsys, const char *buf, - size_t len) -{ - if (strncmp(buf, SHUTDOWN_REIPL_STR, strlen(SHUTDOWN_REIPL_STR)) == 0) - on_panic_action = SHUTDOWN_REIPL; - else if (strncmp(buf, SHUTDOWN_DUMP_STR, - strlen(SHUTDOWN_DUMP_STR)) == 0) - on_panic_action = SHUTDOWN_DUMP; - else if (strncmp(buf, SHUTDOWN_STOP_STR, - strlen(SHUTDOWN_STOP_STR)) == 0) - on_panic_action = SHUTDOWN_STOP; - else - return -EINVAL; - - return len; -} - -static struct subsys_attribute on_panic_attr = - __ATTR(on_panic, 0644, on_panic_show, on_panic_store); - -static void print_fcp_block(struct ipl_parameter_block *fcp_block) -{ - printk(KERN_EMERG "wwpn: %016llx\n", - (unsigned long long)fcp_block->ipl_info.fcp.wwpn); - printk(KERN_EMERG "lun: %016llx\n", - (unsigned long long)fcp_block->ipl_info.fcp.lun); - printk(KERN_EMERG "bootprog: %lld\n", - (unsigned long long)fcp_block->ipl_info.fcp.bootprog); - printk(KERN_EMERG "br_lba: %lld\n", - (unsigned long long)fcp_block->ipl_info.fcp.br_lba); - printk(KERN_EMERG "device: %llx\n", - (unsigned long long)fcp_block->ipl_info.fcp.devno); - printk(KERN_EMERG "opt: %x\n", fcp_block->ipl_info.fcp.opt); -} - -void do_reipl(void) -{ - struct ccw_dev_id devid; - static char buf[100]; - - switch (reipl_type) { - case IPL_TYPE_CCW: - printk(KERN_EMERG "reboot on ccw device: 0.0.%04x\n", - reipl_block_ccw->ipl_info.ccw.devno); - break; - case IPL_TYPE_FCP: - printk(KERN_EMERG "reboot on fcp device:\n"); - print_fcp_block(reipl_block_fcp); - break; - default: - break; - } - - switch (reipl_method) { - case IPL_METHOD_CCW_CIO: - devid.devno = reipl_block_ccw->ipl_info.ccw.devno; - devid.ssid = 0; - reipl_ccw_dev(&devid); - break; - case IPL_METHOD_CCW_VM: - sprintf(buf, "IPL %X", reipl_block_ccw->ipl_info.ccw.devno); - cpcmd(buf, NULL, 0, NULL); - break; - case IPL_METHOD_CCW_DIAG: - diag308(DIAG308_SET, reipl_block_ccw); - diag308(DIAG308_IPL, NULL); - break; - case IPL_METHOD_FCP_RW_DIAG: - diag308(DIAG308_SET, reipl_block_fcp); - diag308(DIAG308_IPL, NULL); - break; - case IPL_METHOD_FCP_RO_DIAG: - diag308(DIAG308_IPL, NULL); - break; - case IPL_METHOD_FCP_RO_VM: - cpcmd("IPL", NULL, 0, NULL); - break; - case IPL_METHOD_NONE: - default: - if (MACHINE_IS_VM) - cpcmd("IPL", NULL, 0, NULL); - diag308(DIAG308_IPL, NULL); - break; - } - panic("reipl failed!\n"); -} - -static void do_dump(void) -{ - struct ccw_dev_id devid; - static char buf[100]; - - switch (dump_type) { - case IPL_TYPE_CCW: - printk(KERN_EMERG "Automatic dump on ccw device: 0.0.%04x\n", - dump_block_ccw->ipl_info.ccw.devno); - break; - case IPL_TYPE_FCP: - printk(KERN_EMERG "Automatic dump on fcp device:\n"); - print_fcp_block(dump_block_fcp); - break; - default: - return; - } - - switch (dump_method) { - case IPL_METHOD_CCW_CIO: - dump_smp_stop_all(); - devid.devno = dump_block_ccw->ipl_info.ccw.devno; - devid.ssid = 0; - reipl_ccw_dev(&devid); - break; - case IPL_METHOD_CCW_VM: - dump_smp_stop_all(); - sprintf(buf, "STORE STATUS"); - cpcmd(buf, NULL, 0, NULL); - sprintf(buf, "IPL %X", dump_block_ccw->ipl_info.ccw.devno); - cpcmd(buf, NULL, 0, NULL); - break; - case IPL_METHOD_CCW_DIAG: - diag308(DIAG308_SET, dump_block_ccw); - diag308(DIAG308_DUMP, NULL); - break; - case IPL_METHOD_FCP_RW_DIAG: - diag308(DIAG308_SET, dump_block_fcp); - diag308(DIAG308_DUMP, NULL); - break; - case IPL_METHOD_NONE: - default: - return; - } - printk(KERN_EMERG "Dump failed!\n"); -} - -/* init functions */ - -static int __init ipl_register_fcp_files(void) -{ - int rc; - - rc = sysfs_create_group(&ipl_subsys.kset.kobj, - &ipl_fcp_attr_group); - if (rc) - goto out; - rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj, - &ipl_parameter_attr); - if (rc) - goto out_ipl_parm; - rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj, - &ipl_scp_data_attr); - if (!rc) - goto out; - - sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr); - -out_ipl_parm: - sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group); -out: - return rc; -} - -static int __init ipl_init(void) -{ - int rc; - - rc = firmware_register(&ipl_subsys); - if (rc) - return rc; - switch (ipl_get_type()) { - case IPL_TYPE_CCW: - rc = sysfs_create_group(&ipl_subsys.kset.kobj, - &ipl_ccw_attr_group); - break; - case IPL_TYPE_FCP: - rc = ipl_register_fcp_files(); - break; - default: - rc = sysfs_create_group(&ipl_subsys.kset.kobj, - &ipl_unknown_attr_group); - break; - } - if (rc) - firmware_unregister(&ipl_subsys); - return rc; -} - -static void __init reipl_probe(void) -{ - void *buffer; - - buffer = (void *) get_zeroed_page(GFP_KERNEL); - if (!buffer) - return; - if (diag308(DIAG308_STORE, buffer) == DIAG308_RC_OK) - diag308_set_works = 1; - free_page((unsigned long)buffer); -} - -static int __init reipl_ccw_init(void) -{ - int rc; - - reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL); - if (!reipl_block_ccw) - return -ENOMEM; - rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_ccw_attr_group); - if (rc) { - free_page((unsigned long)reipl_block_ccw); - return rc; - } - reipl_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN; - reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION; - reipl_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw); - reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; - if (ipl_get_type() == IPL_TYPE_CCW) - reipl_block_ccw->ipl_info.ccw.devno = ipl_devno; - reipl_capabilities |= IPL_TYPE_CCW; - return 0; -} - -static int __init reipl_fcp_init(void) -{ - int rc; - - if ((!diag308_set_works) && (ipl_get_type() != IPL_TYPE_FCP)) - return 0; - if ((!diag308_set_works) && (ipl_get_type() == IPL_TYPE_FCP)) - make_attrs_ro(reipl_fcp_attrs); - - reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); - if (!reipl_block_fcp) - return -ENOMEM; - rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_fcp_attr_group); - if (rc) { - free_page((unsigned long)reipl_block_fcp); - return rc; - } - if (ipl_get_type() == IPL_TYPE_FCP) { - memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE); - } else { - reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN; - reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION; - reipl_block_fcp->hdr.blk0_len = - sizeof(reipl_block_fcp->ipl_info.fcp); - reipl_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP; - reipl_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_IPL; - } - reipl_capabilities |= IPL_TYPE_FCP; - return 0; -} - -static int __init reipl_init(void) -{ - int rc; - - rc = firmware_register(&reipl_subsys); - if (rc) - return rc; - rc = subsys_create_file(&reipl_subsys, &reipl_type_attr); - if (rc) { - firmware_unregister(&reipl_subsys); - return rc; - } - rc = reipl_ccw_init(); - if (rc) - return rc; - rc = reipl_fcp_init(); - if (rc) - return rc; - rc = reipl_set_type(ipl_get_type()); - if (rc) - return rc; - return 0; -} - -static int __init dump_ccw_init(void) -{ - int rc; - - dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL); - if (!dump_block_ccw) - return -ENOMEM; - rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_ccw_attr_group); - if (rc) { - free_page((unsigned long)dump_block_ccw); - return rc; - } - dump_block_ccw->hdr.len = IPL_PARM_BLK_CCW_LEN; - dump_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION; - dump_block_ccw->hdr.blk0_len = sizeof(reipl_block_ccw->ipl_info.ccw); - dump_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW; - dump_capabilities |= IPL_TYPE_CCW; - return 0; -} - -extern char s390_readinfo_sccb[]; - -static int __init dump_fcp_init(void) -{ - int rc; - - if(!(s390_readinfo_sccb[91] & 0x2)) - return 0; /* LDIPL DUMP is not installed */ - if (!diag308_set_works) - return 0; - dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL); - if (!dump_block_fcp) - return -ENOMEM; - rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_fcp_attr_group); - if (rc) { - free_page((unsigned long)dump_block_fcp); - return rc; - } - dump_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN; - dump_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION; - dump_block_fcp->hdr.blk0_len = sizeof(dump_block_fcp->ipl_info.fcp); - dump_block_fcp->hdr.pbt = DIAG308_IPL_TYPE_FCP; - dump_block_fcp->ipl_info.fcp.opt = DIAG308_IPL_OPT_DUMP; - dump_capabilities |= IPL_TYPE_FCP; - return 0; -} - -#define SHUTDOWN_ON_PANIC_PRIO 0 - -static int shutdown_on_panic_notify(struct notifier_block *self, - unsigned long event, void *data) -{ - if (on_panic_action == SHUTDOWN_DUMP) - do_dump(); - else if (on_panic_action == SHUTDOWN_REIPL) - do_reipl(); - return NOTIFY_OK; -} - -static struct notifier_block shutdown_on_panic_nb = { - .notifier_call = shutdown_on_panic_notify, - .priority = SHUTDOWN_ON_PANIC_PRIO -}; - -static int __init dump_init(void) -{ - int rc; - - rc = firmware_register(&dump_subsys); - if (rc) - return rc; - rc = subsys_create_file(&dump_subsys, &dump_type_attr); - if (rc) { - firmware_unregister(&dump_subsys); - return rc; - } - rc = dump_ccw_init(); - if (rc) - return rc; - rc = dump_fcp_init(); - if (rc) - return rc; - dump_set_type(IPL_TYPE_NONE); - return 0; -} - -static int __init shutdown_actions_init(void) -{ - int rc; - - rc = firmware_register(&shutdown_actions_subsys); - if (rc) - return rc; - rc = subsys_create_file(&shutdown_actions_subsys, &on_panic_attr); - if (rc) { - firmware_unregister(&shutdown_actions_subsys); - return rc; - } - atomic_notifier_chain_register(&panic_notifier_list, - &shutdown_on_panic_nb); - return 0; -} - -static int __init s390_ipl_init(void) -{ - int rc; - - reipl_probe(); - rc = ipl_init(); - if (rc) - return rc; - rc = reipl_init(); - if (rc) - return rc; - rc = dump_init(); - if (rc) - return rc; - rc = shutdown_actions_init(); - if (rc) - return rc; - return 0; -} - -__initcall(s390_ipl_init); diff --git a/trunk/arch/s390/kernel/kprobes.c b/trunk/arch/s390/kernel/kprobes.c deleted file mode 100644 index ca28fb0b3790..000000000000 --- a/trunk/arch/s390/kernel/kprobes.c +++ /dev/null @@ -1,657 +0,0 @@ -/* - * Kernel Probes (KProbes) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Copyright (C) IBM Corporation, 2002, 2006 - * - * s390 port, used ppc64 as template. Mike Grundy - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; -DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); - -int __kprobes arch_prepare_kprobe(struct kprobe *p) -{ - /* Make sure the probe isn't going on a difficult instruction */ - if (is_prohibited_opcode((kprobe_opcode_t *) p->addr)) - return -EINVAL; - - if ((unsigned long)p->addr & 0x01) { - printk("Attempt to register kprobe at an unaligned address\n"); - return -EINVAL; - } - - /* Use the get_insn_slot() facility for correctness */ - if (!(p->ainsn.insn = get_insn_slot())) - return -ENOMEM; - - memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); - - get_instruction_type(&p->ainsn); - p->opcode = *p->addr; - return 0; -} - -int __kprobes is_prohibited_opcode(kprobe_opcode_t *instruction) -{ - switch (*(__u8 *) instruction) { - case 0x0c: /* bassm */ - case 0x0b: /* bsm */ - case 0x83: /* diag */ - case 0x44: /* ex */ - return -EINVAL; - } - switch (*(__u16 *) instruction) { - case 0x0101: /* pr */ - case 0xb25a: /* bsa */ - case 0xb240: /* bakr */ - case 0xb258: /* bsg */ - case 0xb218: /* pc */ - case 0xb228: /* pt */ - return -EINVAL; - } - return 0; -} - -void __kprobes get_instruction_type(struct arch_specific_insn *ainsn) -{ - /* default fixup method */ - ainsn->fixup = FIXUP_PSW_NORMAL; - - /* save r1 operand */ - ainsn->reg = (*ainsn->insn & 0xf0) >> 4; - - /* save the instruction length (pop 5-5) in bytes */ - switch (*(__u8 *) (ainsn->insn) >> 4) { - case 0: - ainsn->ilen = 2; - break; - case 1: - case 2: - ainsn->ilen = 4; - break; - case 3: - ainsn->ilen = 6; - break; - } - - switch (*(__u8 *) ainsn->insn) { - case 0x05: /* balr */ - case 0x0d: /* basr */ - ainsn->fixup = FIXUP_RETURN_REGISTER; - /* if r2 = 0, no branch will be taken */ - if ((*ainsn->insn & 0x0f) == 0) - ainsn->fixup |= FIXUP_BRANCH_NOT_TAKEN; - break; - case 0x06: /* bctr */ - case 0x07: /* bcr */ - ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN; - break; - case 0x45: /* bal */ - case 0x4d: /* bas */ - ainsn->fixup = FIXUP_RETURN_REGISTER; - break; - case 0x47: /* bc */ - case 0x46: /* bct */ - case 0x86: /* bxh */ - case 0x87: /* bxle */ - ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN; - break; - case 0x82: /* lpsw */ - ainsn->fixup = FIXUP_NOT_REQUIRED; - break; - case 0xb2: /* lpswe */ - if (*(((__u8 *) ainsn->insn) + 1) == 0xb2) { - ainsn->fixup = FIXUP_NOT_REQUIRED; - } - break; - case 0xa7: /* bras */ - if ((*ainsn->insn & 0x0f) == 0x05) { - ainsn->fixup |= FIXUP_RETURN_REGISTER; - } - break; - case 0xc0: - if ((*ainsn->insn & 0x0f) == 0x00 /* larl */ - || (*ainsn->insn & 0x0f) == 0x05) /* brasl */ - ainsn->fixup |= FIXUP_RETURN_REGISTER; - break; - case 0xeb: - if (*(((__u8 *) ainsn->insn) + 5 ) == 0x44 || /* bxhg */ - *(((__u8 *) ainsn->insn) + 5) == 0x45) {/* bxleg */ - ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN; - } - break; - case 0xe3: /* bctg */ - if (*(((__u8 *) ainsn->insn) + 5) == 0x46) { - ainsn->fixup = FIXUP_BRANCH_NOT_TAKEN; - } - break; - } -} - -static int __kprobes swap_instruction(void *aref) -{ - struct ins_replace_args *args = aref; - int err = -EFAULT; - - asm volatile( - "0: mvc 0(2,%2),0(%3)\n" - "1: la %0,0\n" - "2:\n" - EX_TABLE(0b,2b) - : "+d" (err), "=m" (*args->ptr) - : "a" (args->ptr), "a" (&args->new), "m" (args->new)); - return err; -} - -void __kprobes arch_arm_kprobe(struct kprobe *p) -{ - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - unsigned long status = kcb->kprobe_status; - struct ins_replace_args args; - - args.ptr = p->addr; - args.old = p->opcode; - args.new = BREAKPOINT_INSTRUCTION; - - kcb->kprobe_status = KPROBE_SWAP_INST; - stop_machine_run(swap_instruction, &args, NR_CPUS); - kcb->kprobe_status = status; -} - -void __kprobes arch_disarm_kprobe(struct kprobe *p) -{ - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - unsigned long status = kcb->kprobe_status; - struct ins_replace_args args; - - args.ptr = p->addr; - args.old = BREAKPOINT_INSTRUCTION; - args.new = p->opcode; - - kcb->kprobe_status = KPROBE_SWAP_INST; - stop_machine_run(swap_instruction, &args, NR_CPUS); - kcb->kprobe_status = status; -} - -void __kprobes arch_remove_kprobe(struct kprobe *p) -{ - mutex_lock(&kprobe_mutex); - free_insn_slot(p->ainsn.insn); - mutex_unlock(&kprobe_mutex); -} - -static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs) -{ - per_cr_bits kprobe_per_regs[1]; - - memset(kprobe_per_regs, 0, sizeof(per_cr_bits)); - regs->psw.addr = (unsigned long)p->ainsn.insn | PSW_ADDR_AMODE; - - /* Set up the per control reg info, will pass to lctl */ - kprobe_per_regs[0].em_instruction_fetch = 1; - kprobe_per_regs[0].starting_addr = (unsigned long)p->ainsn.insn; - kprobe_per_regs[0].ending_addr = (unsigned long)p->ainsn.insn + 1; - - /* Set the PER control regs, turns on single step for this address */ - __ctl_load(kprobe_per_regs, 9, 11); - regs->psw.mask |= PSW_MASK_PER; - regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK); -} - -static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb) -{ - kcb->prev_kprobe.kp = kprobe_running(); - kcb->prev_kprobe.status = kcb->kprobe_status; - kcb->prev_kprobe.kprobe_saved_imask = kcb->kprobe_saved_imask; - memcpy(kcb->prev_kprobe.kprobe_saved_ctl, kcb->kprobe_saved_ctl, - sizeof(kcb->kprobe_saved_ctl)); -} - -static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb) -{ - __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp; - kcb->kprobe_status = kcb->prev_kprobe.status; - kcb->kprobe_saved_imask = kcb->prev_kprobe.kprobe_saved_imask; - memcpy(kcb->kprobe_saved_ctl, kcb->prev_kprobe.kprobe_saved_ctl, - sizeof(kcb->kprobe_saved_ctl)); -} - -static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs, - struct kprobe_ctlblk *kcb) -{ - __get_cpu_var(current_kprobe) = p; - /* Save the interrupt and per flags */ - kcb->kprobe_saved_imask = regs->psw.mask & - (PSW_MASK_PER | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK); - /* Save the control regs that govern PER */ - __ctl_store(kcb->kprobe_saved_ctl, 9, 11); -} - -/* Called with kretprobe_lock held */ -void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, - struct pt_regs *regs) -{ - struct kretprobe_instance *ri; - - if ((ri = get_free_rp_inst(rp)) != NULL) { - ri->rp = rp; - ri->task = current; - ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14]; - - /* Replace the return addr with trampoline addr */ - regs->gprs[14] = (unsigned long)&kretprobe_trampoline; - - add_rp_inst(ri); - } else { - rp->nmissed++; - } -} - -static int __kprobes kprobe_handler(struct pt_regs *regs) -{ - struct kprobe *p; - int ret = 0; - unsigned long *addr = (unsigned long *) - ((regs->psw.addr & PSW_ADDR_INSN) - 2); - struct kprobe_ctlblk *kcb; - - /* - * We don't want to be preempted for the entire - * duration of kprobe processing - */ - preempt_disable(); - kcb = get_kprobe_ctlblk(); - - /* Check we're not actually recursing */ - if (kprobe_running()) { - p = get_kprobe(addr); - if (p) { - if (kcb->kprobe_status == KPROBE_HIT_SS && - *p->ainsn.insn == BREAKPOINT_INSTRUCTION) { - regs->psw.mask &= ~PSW_MASK_PER; - regs->psw.mask |= kcb->kprobe_saved_imask; - goto no_kprobe; - } - /* We have reentered the kprobe_handler(), since - * another probe was hit while within the handler. - * We here save the original kprobes variables and - * just single step on the instruction of the new probe - * without calling any user handlers. - */ - save_previous_kprobe(kcb); - set_current_kprobe(p, regs, kcb); - kprobes_inc_nmissed_count(p); - prepare_singlestep(p, regs); - kcb->kprobe_status = KPROBE_REENTER; - return 1; - } else { - p = __get_cpu_var(current_kprobe); - if (p->break_handler && p->break_handler(p, regs)) { - goto ss_probe; - } - } - goto no_kprobe; - } - - p = get_kprobe(addr); - if (!p) { - if (*addr != BREAKPOINT_INSTRUCTION) { - /* - * The breakpoint instruction was removed right - * after we hit it. Another cpu has removed - * either a probepoint or a debugger breakpoint - * at this address. In either case, no further - * handling of this interrupt is appropriate. - * - */ - ret = 1; - } - /* Not one of ours: let kernel handle it */ - goto no_kprobe; - } - - kcb->kprobe_status = KPROBE_HIT_ACTIVE; - set_current_kprobe(p, regs, kcb); - if (p->pre_handler && p->pre_handler(p, regs)) - /* handler has already set things up, so skip ss setup */ - return 1; - -ss_probe: - prepare_singlestep(p, regs); - kcb->kprobe_status = KPROBE_HIT_SS; - return 1; - -no_kprobe: - preempt_enable_no_resched(); - return ret; -} - -/* - * Function return probe trampoline: - * - init_kprobes() establishes a probepoint here - * - When the probed function returns, this probe - * causes the handlers to fire - */ -void __kprobes kretprobe_trampoline_holder(void) -{ - asm volatile(".global kretprobe_trampoline\n" - "kretprobe_trampoline: bcr 0,0\n"); -} - -/* - * Called when the probe at kretprobe trampoline is hit - */ -int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) -{ - struct kretprobe_instance *ri = NULL; - struct hlist_head *head; - struct hlist_node *node, *tmp; - unsigned long flags, orig_ret_address = 0; - unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; - - spin_lock_irqsave(&kretprobe_lock, flags); - head = kretprobe_inst_table_head(current); - - /* - * It is possible to have multiple instances associated with a given - * task either because an multiple functions in the call path - * have a return probe installed on them, and/or more then one return - * return probe was registered for a target function. - * - * We can handle this because: - * - instances are always inserted at the head of the list - * - when multiple return probes are registered for the same - * function, the first instance's ret_addr will point to the - * real return address, and all the rest will point to - * kretprobe_trampoline - */ - hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { - if (ri->task != current) - /* another task is sharing our hash bucket */ - continue; - - if (ri->rp && ri->rp->handler) - ri->rp->handler(ri, regs); - - orig_ret_address = (unsigned long)ri->ret_addr; - recycle_rp_inst(ri); - - if (orig_ret_address != trampoline_address) { - /* - * This is the real return address. Any other - * instances associated with this task are for - * other calls deeper on the call stack - */ - break; - } - } - BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address)); - regs->psw.addr = orig_ret_address | PSW_ADDR_AMODE; - - reset_current_kprobe(); - spin_unlock_irqrestore(&kretprobe_lock, flags); - preempt_enable_no_resched(); - - /* - * By returning a non-zero value, we are telling - * kprobe_handler() that we don't want the post_handler - * to run (and have re-enabled preemption) - */ - return 1; -} - -/* - * Called after single-stepping. p->addr is the address of the - * instruction whose first byte has been replaced by the "breakpoint" - * instruction. To avoid the SMP problems that can occur when we - * temporarily put back the original opcode to single-step, we - * single-stepped a copy of the instruction. The address of this - * copy is p->ainsn.insn. - */ -static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) -{ - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - - regs->psw.addr &= PSW_ADDR_INSN; - - if (p->ainsn.fixup & FIXUP_PSW_NORMAL) - regs->psw.addr = (unsigned long)p->addr + - ((unsigned long)regs->psw.addr - - (unsigned long)p->ainsn.insn); - - if (p->ainsn.fixup & FIXUP_BRANCH_NOT_TAKEN) - if ((unsigned long)regs->psw.addr - - (unsigned long)p->ainsn.insn == p->ainsn.ilen) - regs->psw.addr = (unsigned long)p->addr + p->ainsn.ilen; - - if (p->ainsn.fixup & FIXUP_RETURN_REGISTER) - regs->gprs[p->ainsn.reg] = ((unsigned long)p->addr + - (regs->gprs[p->ainsn.reg] - - (unsigned long)p->ainsn.insn)) - | PSW_ADDR_AMODE; - - regs->psw.addr |= PSW_ADDR_AMODE; - /* turn off PER mode */ - regs->psw.mask &= ~PSW_MASK_PER; - /* Restore the original per control regs */ - __ctl_load(kcb->kprobe_saved_ctl, 9, 11); - regs->psw.mask |= kcb->kprobe_saved_imask; -} - -static int __kprobes post_kprobe_handler(struct pt_regs *regs) -{ - struct kprobe *cur = kprobe_running(); - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - - if (!cur) - return 0; - - if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) { - kcb->kprobe_status = KPROBE_HIT_SSDONE; - cur->post_handler(cur, regs, 0); - } - - resume_execution(cur, regs); - - /*Restore back the original saved kprobes variables and continue. */ - if (kcb->kprobe_status == KPROBE_REENTER) { - restore_previous_kprobe(kcb); - goto out; - } - reset_current_kprobe(); -out: - preempt_enable_no_resched(); - - /* - * if somebody else is singlestepping across a probe point, psw mask - * will have PER set, in which case, continue the remaining processing - * of do_single_step, as if this is not a probe hit. - */ - if (regs->psw.mask & PSW_MASK_PER) { - return 0; - } - - return 1; -} - -static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr) -{ - struct kprobe *cur = kprobe_running(); - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - const struct exception_table_entry *entry; - - switch(kcb->kprobe_status) { - case KPROBE_SWAP_INST: - /* We are here because the instruction replacement failed */ - return 0; - case KPROBE_HIT_SS: - case KPROBE_REENTER: - /* - * We are here because the instruction being single - * stepped caused a page fault. We reset the current - * kprobe and the nip points back to the probe address - * and allow the page fault handler to continue as a - * normal page fault. - */ - regs->psw.addr = (unsigned long)cur->addr | PSW_ADDR_AMODE; - regs->psw.mask &= ~PSW_MASK_PER; - regs->psw.mask |= kcb->kprobe_saved_imask; - if (kcb->kprobe_status == KPROBE_REENTER) - restore_previous_kprobe(kcb); - else - reset_current_kprobe(); - preempt_enable_no_resched(); - break; - case KPROBE_HIT_ACTIVE: - case KPROBE_HIT_SSDONE: - /* - * We increment the nmissed count for accounting, - * we can also use npre/npostfault count for accouting - * these specific fault cases. - */ - kprobes_inc_nmissed_count(cur); - - /* - * We come here because instructions in the pre/post - * handler caused the page_fault, this could happen - * if handler tries to access user space by - * copy_from_user(), get_user() etc. Let the - * user-specified handler try to fix it first. - */ - if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) - return 1; - - /* - * In case the user-specified fault handler returned - * zero, try to fix up. - */ - entry = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); - if (entry) { - regs->psw.addr = entry->fixup | PSW_ADDR_AMODE; - return 1; - } - - /* - * fixup_exception() could not handle it, - * Let do_page_fault() fix it. - */ - break; - default: - break; - } - return 0; -} - -/* - * Wrapper routine to for handling exceptions. - */ -int __kprobes kprobe_exceptions_notify(struct notifier_block *self, - unsigned long val, void *data) -{ - struct die_args *args = (struct die_args *)data; - int ret = NOTIFY_DONE; - - switch (val) { - case DIE_BPT: - if (kprobe_handler(args->regs)) - ret = NOTIFY_STOP; - break; - case DIE_SSTEP: - if (post_kprobe_handler(args->regs)) - ret = NOTIFY_STOP; - break; - case DIE_TRAP: - case DIE_PAGE_FAULT: - /* kprobe_running() needs smp_processor_id() */ - preempt_disable(); - if (kprobe_running() && - kprobe_fault_handler(args->regs, args->trapnr)) - ret = NOTIFY_STOP; - preempt_enable(); - break; - default: - break; - } - return ret; -} - -int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) -{ - struct jprobe *jp = container_of(p, struct jprobe, kp); - unsigned long addr; - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - - memcpy(&kcb->jprobe_saved_regs, regs, sizeof(struct pt_regs)); - - /* setup return addr to the jprobe handler routine */ - regs->psw.addr = (unsigned long)(jp->entry) | PSW_ADDR_AMODE; - - /* r14 is the function return address */ - kcb->jprobe_saved_r14 = (unsigned long)regs->gprs[14]; - /* r15 is the stack pointer */ - kcb->jprobe_saved_r15 = (unsigned long)regs->gprs[15]; - addr = (unsigned long)kcb->jprobe_saved_r15; - - memcpy(kcb->jprobes_stack, (kprobe_opcode_t *) addr, - MIN_STACK_SIZE(addr)); - return 1; -} - -void __kprobes jprobe_return(void) -{ - asm volatile(".word 0x0002"); -} - -void __kprobes jprobe_return_end(void) -{ - asm volatile("bcr 0,0"); -} - -int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) -{ - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - unsigned long stack_addr = (unsigned long)(kcb->jprobe_saved_r15); - - /* Put the regs back */ - memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); - /* put the stack back */ - memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack, - MIN_STACK_SIZE(stack_addr)); - preempt_enable_no_resched(); - return 1; -} - -static struct kprobe trampoline_p = { - .addr = (kprobe_opcode_t *) & kretprobe_trampoline, - .pre_handler = trampoline_probe_handler -}; - -int __init arch_init_kprobes(void) -{ - return register_kprobe(&trampoline_p); -} diff --git a/trunk/arch/s390/kernel/reipl.S b/trunk/arch/s390/kernel/reipl.S index 4562cdbce8eb..658e5ac484f9 100644 --- a/trunk/arch/s390/kernel/reipl.S +++ b/trunk/arch/s390/kernel/reipl.S @@ -8,30 +8,13 @@ #include - .globl do_reipl_asm -do_reipl_asm: basr %r13,0 + .globl do_reipl +do_reipl: basr %r13,0 .Lpg0: lpsw .Lnewpsw-.Lpg0(%r13) - - # switch off lowcore protection - -.Lpg1: stctl %c0,%c0,.Lctlsave1-.Lpg0(%r13) - stctl %c0,%c0,.Lctlsave2-.Lpg0(%r13) - ni .Lctlsave1-.Lpg0(%r13),0xef - lctl %c0,%c0,.Lctlsave1-.Lpg0(%r13) - - # do store status of all registers - - stm %r0,%r15,__LC_GPREGS_SAVE_AREA - stctl %c0,%c15,__LC_CREGS_SAVE_AREA - mvc __LC_CREGS_SAVE_AREA(4),.Lctlsave2-.Lpg0(%r13) - stam %a0,%a15,__LC_AREGS_SAVE_AREA - stpx __LC_PREFIX_SAVE_AREA - stckc .Lclkcmp-.Lpg0(%r13) - mvc __LC_CLOCK_COMP_SAVE_AREA(8),.Lclkcmp-.Lpg0(%r13) - stpt __LC_CPU_TIMER_SAVE_AREA - st %r13, __LC_PSW_SAVE_AREA+4 - - lctl %c6,%c6,.Lall-.Lpg0(%r13) +.Lpg1: lctl %c6,%c6,.Lall-.Lpg0(%r13) + stctl %c0,%c0,.Lctlsave-.Lpg0(%r13) + ni .Lctlsave-.Lpg0(%r13),0xef + lctl %c0,%c0,.Lctlsave-.Lpg0(%r13) lr %r1,%r2 mvc __LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13) stsch .Lschib-.Lpg0(%r13) @@ -63,11 +46,9 @@ do_reipl_asm: basr %r13,0 .Ldisab: st %r14,.Ldispsw+4-.Lpg0(%r13) lpsw .Ldispsw-.Lpg0(%r13) .align 8 -.Lclkcmp: .quad 0x0000000000000000 .Lall: .long 0xff000000 .Lnull: .long 0x00000000 -.Lctlsave1: .long 0x00000000 -.Lctlsave2: .long 0x00000000 +.Lctlsave: .long 0x00000000 .align 8 .Lnewpsw: .long 0x00080000,0x80000000+.Lpg1 .Lpcnew: .long 0x00080000,0x80000000+.Lecs diff --git a/trunk/arch/s390/kernel/reipl64.S b/trunk/arch/s390/kernel/reipl64.S index 95bd1e234f63..4d090d60f3ef 100644 --- a/trunk/arch/s390/kernel/reipl64.S +++ b/trunk/arch/s390/kernel/reipl64.S @@ -8,30 +8,13 @@ */ #include - .globl do_reipl_asm -do_reipl_asm: basr %r13,0 - - # do store status of all registers - -.Lpg0: stg %r1,.Lregsave-.Lpg0(%r13) - lghi %r1,0x1000 - stmg %r0,%r15,__LC_GPREGS_SAVE_AREA-0x1000(%r1) - lg %r0,.Lregsave-.Lpg0(%r13) - stg %r0,__LC_GPREGS_SAVE_AREA-0x1000+8(%r1) - stctg %c0,%c15,__LC_CREGS_SAVE_AREA-0x1000(%r1) - stam %a0,%a15,__LC_AREGS_SAVE_AREA-0x1000(%r1) - stpx __LC_PREFIX_SAVE_AREA-0x1000(%r1) - stfpc __LC_FP_CREG_SAVE_AREA-0x1000(%r1) - stckc .Lclkcmp-.Lpg0(%r13) - mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(8,%r1),.Lclkcmp-.Lpg0(%r13) - stpt __LC_CPU_TIMER_SAVE_AREA-0x1000(%r1) - stg %r13, __LC_PSW_SAVE_AREA-0x1000+8(%r1) - - lpswe .Lnewpsw-.Lpg0(%r13) + .globl do_reipl +do_reipl: basr %r13,0 +.Lpg0: lpswe .Lnewpsw-.Lpg0(%r13) .Lpg1: lctlg %c6,%c6,.Lall-.Lpg0(%r13) - stctg %c0,%c0,.Lregsave-.Lpg0(%r13) - ni .Lregsave+4-.Lpg0(%r13),0xef - lctlg %c0,%c0,.Lregsave-.Lpg0(%r13) + stctg %c0,%c0,.Lctlsave-.Lpg0(%r13) + ni .Lctlsave+4-.Lpg0(%r13),0xef + lctlg %c0,%c0,.Lctlsave-.Lpg0(%r13) lgr %r1,%r2 mvc __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13) stsch .Lschib-.Lpg0(%r13) @@ -67,9 +50,8 @@ do_reipl_asm: basr %r13,0 st %r14,.Ldispsw+12-.Lpg0(%r13) lpswe .Ldispsw-.Lpg0(%r13) .align 8 -.Lclkcmp: .quad 0x0000000000000000 .Lall: .quad 0x00000000ff000000 -.Lregsave: .quad 0x0000000000000000 +.Lctlsave: .quad 0x0000000000000000 .Lnull: .long 0x0000000000000000 .align 16 /* @@ -110,3 +92,5 @@ do_reipl_asm: basr %r13,0 .long 0x00000000,0x00000000 .long 0x00000000,0x00000000 + + diff --git a/trunk/arch/s390/kernel/reipl_diag.c b/trunk/arch/s390/kernel/reipl_diag.c new file mode 100644 index 000000000000..1f33951ba439 --- /dev/null +++ b/trunk/arch/s390/kernel/reipl_diag.c @@ -0,0 +1,39 @@ +/* + * This file contains the implementation of the + * Linux re-IPL support + * + * (C) Copyright IBM Corp. 2005 + * + * Author(s): Volker Sameske (sameske@de.ibm.com) + * + */ + +#include + +static unsigned int reipl_diag_rc1; +static unsigned int reipl_diag_rc2; + +/* + * re-IPL the system using the last used IPL parameters + */ +void reipl_diag(void) +{ + asm volatile ( + " la %%r4,0\n" + " la %%r5,0\n" + " diag %%r4,%2,0x308\n" + "0:\n" + " st %%r4,%0\n" + " st %%r5,%1\n" + ".section __ex_table,\"a\"\n" +#ifdef CONFIG_64BIT + " .align 8\n" + " .quad 0b, 0b\n" +#else + " .align 4\n" + " .long 0b, 0b\n" +#endif + ".previous\n" + : "=m" (reipl_diag_rc1), "=m" (reipl_diag_rc2) + : "d" (3) : "cc", "4", "5" ); +} diff --git a/trunk/arch/s390/kernel/s390_ksyms.c b/trunk/arch/s390/kernel/s390_ksyms.c index 9f19e833a562..c73a45467fa4 100644 --- a/trunk/arch/s390/kernel/s390_ksyms.c +++ b/trunk/arch/s390/kernel/s390_ksyms.c @@ -25,6 +25,12 @@ EXPORT_SYMBOL(_oi_bitmap); EXPORT_SYMBOL(_ni_bitmap); EXPORT_SYMBOL(_zb_findmap); EXPORT_SYMBOL(_sb_findmap); +EXPORT_SYMBOL(__copy_from_user_asm); +EXPORT_SYMBOL(__copy_to_user_asm); +EXPORT_SYMBOL(__copy_in_user_asm); +EXPORT_SYMBOL(__clear_user_asm); +EXPORT_SYMBOL(__strncpy_from_user_asm); +EXPORT_SYMBOL(__strnlen_user_asm); EXPORT_SYMBOL(diag10); /* diff --git a/trunk/arch/s390/kernel/setup.c b/trunk/arch/s390/kernel/setup.c index e3d9325f6022..c902f059c7aa 100644 --- a/trunk/arch/s390/kernel/setup.c +++ b/trunk/arch/s390/kernel/setup.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include @@ -50,12 +49,6 @@ #include #include -/* - * User copy operations. - */ -struct uaccess_ops uaccess; -EXPORT_SYMBOL_GPL(uaccess); - /* * Machine setup.. */ @@ -291,9 +284,16 @@ void (*_machine_power_off)(void) = machine_power_off_smp; /* * Reboot, halt and power_off routines for non SMP. */ +extern void reipl(unsigned long devno); +extern void reipl_diag(void); static void do_machine_restart_nonsmp(char * __unused) { - do_reipl(); + reipl_diag(); + + if (MACHINE_IS_VM) + cpcmd ("IPL", NULL, 0, NULL); + else + reipl (0x10000 | S390_lowcore.ipl_device); } static void do_machine_halt_nonsmp(void) @@ -501,47 +501,13 @@ setup_memory(void) * partially used pages are not usable - thus * we are rounding upwards: */ - start_pfn = PFN_UP(__pa(&_end)); - end_pfn = max_pfn = PFN_DOWN(memory_end); + start_pfn = (__pa(&_end) + PAGE_SIZE - 1) >> PAGE_SHIFT; + end_pfn = max_pfn = memory_end >> PAGE_SHIFT; /* Initialize storage key for kernel pages */ for (init_pfn = 0 ; init_pfn < start_pfn; init_pfn++) page_set_storage_key(init_pfn << PAGE_SHIFT, PAGE_DEFAULT_KEY); -#ifdef CONFIG_BLK_DEV_INITRD - /* - * Move the initrd in case the bitmap of the bootmem allocater - * would overwrite it. - */ - - if (INITRD_START && INITRD_SIZE) { - unsigned long bmap_size; - unsigned long start; - - bmap_size = bootmem_bootmap_pages(end_pfn - start_pfn + 1); - bmap_size = PFN_PHYS(bmap_size); - - if (PFN_PHYS(start_pfn) + bmap_size > INITRD_START) { - start = PFN_PHYS(start_pfn) + bmap_size + PAGE_SIZE; - - if (start + INITRD_SIZE > memory_end) { - printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx)\n" - "disabling initrd\n", - start + INITRD_SIZE, memory_end); - INITRD_START = INITRD_SIZE = 0; - } else { - printk("Moving initrd (0x%08lx -> 0x%08lx, " - "size: %ld)\n", - INITRD_START, start, INITRD_SIZE); - memmove((void *) start, (void *) INITRD_START, - INITRD_SIZE); - INITRD_START = start; - } - } - } -#endif - /* * Initialize the boot-time allocator (with low memory only): */ @@ -593,7 +559,7 @@ setup_memory(void) reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size); #ifdef CONFIG_BLK_DEV_INITRD - if (INITRD_START && INITRD_SIZE) { + if (INITRD_START) { if (INITRD_START + INITRD_SIZE <= memory_end) { reserve_bootmem(INITRD_START, INITRD_SIZE); initrd_start = INITRD_START; @@ -647,11 +613,6 @@ setup_arch(char **cmdline_p) memory_end = memory_size; - if (MACHINE_HAS_MVCOS) - memcpy(&uaccess, &uaccess_mvcos, sizeof(uaccess)); - else - memcpy(&uaccess, &uaccess_std, sizeof(uaccess)); - parse_early_param(); #ifndef CONFIG_64BIT @@ -759,3 +720,214 @@ struct seq_operations cpuinfo_op = { .show = show_cpuinfo, }; +#define DEFINE_IPL_ATTR(_name, _format, _value) \ +static ssize_t ipl_##_name##_show(struct subsystem *subsys, \ + char *page) \ +{ \ + return sprintf(page, _format, _value); \ +} \ +static struct subsys_attribute ipl_##_name##_attr = \ + __ATTR(_name, S_IRUGO, ipl_##_name##_show, NULL); + +DEFINE_IPL_ATTR(wwpn, "0x%016llx\n", (unsigned long long) + IPL_PARMBLOCK_START->fcp.wwpn); +DEFINE_IPL_ATTR(lun, "0x%016llx\n", (unsigned long long) + IPL_PARMBLOCK_START->fcp.lun); +DEFINE_IPL_ATTR(bootprog, "%lld\n", (unsigned long long) + IPL_PARMBLOCK_START->fcp.bootprog); +DEFINE_IPL_ATTR(br_lba, "%lld\n", (unsigned long long) + IPL_PARMBLOCK_START->fcp.br_lba); + +enum ipl_type_type { + ipl_type_unknown, + ipl_type_ccw, + ipl_type_fcp, +}; + +static enum ipl_type_type +get_ipl_type(void) +{ + struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; + + if (!IPL_DEVNO_VALID) + return ipl_type_unknown; + if (!IPL_PARMBLOCK_VALID) + return ipl_type_ccw; + if (ipl->hdr.header.version > IPL_MAX_SUPPORTED_VERSION) + return ipl_type_unknown; + if (ipl->fcp.pbt != IPL_TYPE_FCP) + return ipl_type_unknown; + return ipl_type_fcp; +} + +static ssize_t +ipl_type_show(struct subsystem *subsys, char *page) +{ + switch (get_ipl_type()) { + case ipl_type_ccw: + return sprintf(page, "ccw\n"); + case ipl_type_fcp: + return sprintf(page, "fcp\n"); + default: + return sprintf(page, "unknown\n"); + } +} + +static struct subsys_attribute ipl_type_attr = __ATTR_RO(ipl_type); + +static ssize_t +ipl_device_show(struct subsystem *subsys, char *page) +{ + struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; + + switch (get_ipl_type()) { + case ipl_type_ccw: + return sprintf(page, "0.0.%04x\n", ipl_devno); + case ipl_type_fcp: + return sprintf(page, "0.0.%04x\n", ipl->fcp.devno); + default: + return 0; + } +} + +static struct subsys_attribute ipl_device_attr = + __ATTR(device, S_IRUGO, ipl_device_show, NULL); + +static struct attribute *ipl_fcp_attrs[] = { + &ipl_type_attr.attr, + &ipl_device_attr.attr, + &ipl_wwpn_attr.attr, + &ipl_lun_attr.attr, + &ipl_bootprog_attr.attr, + &ipl_br_lba_attr.attr, + NULL, +}; + +static struct attribute_group ipl_fcp_attr_group = { + .attrs = ipl_fcp_attrs, +}; + +static struct attribute *ipl_ccw_attrs[] = { + &ipl_type_attr.attr, + &ipl_device_attr.attr, + NULL, +}; + +static struct attribute_group ipl_ccw_attr_group = { + .attrs = ipl_ccw_attrs, +}; + +static struct attribute *ipl_unknown_attrs[] = { + &ipl_type_attr.attr, + NULL, +}; + +static struct attribute_group ipl_unknown_attr_group = { + .attrs = ipl_unknown_attrs, +}; + +static ssize_t +ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + unsigned int size = IPL_PARMBLOCK_SIZE; + + if (off > size) + return 0; + if (off + count > size) + count = size - off; + + memcpy(buf, (void *) IPL_PARMBLOCK_START + off, count); + return count; +} + +static struct bin_attribute ipl_parameter_attr = { + .attr = { + .name = "binary_parameter", + .mode = S_IRUGO, + .owner = THIS_MODULE, + }, + .size = PAGE_SIZE, + .read = &ipl_parameter_read, +}; + +static ssize_t +ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off, size_t count) +{ + unsigned int size = IPL_PARMBLOCK_START->fcp.scp_data_len; + void *scp_data = &IPL_PARMBLOCK_START->fcp.scp_data; + + if (off > size) + return 0; + if (off + count > size) + count = size - off; + + memcpy(buf, scp_data + off, count); + return count; +} + +static struct bin_attribute ipl_scp_data_attr = { + .attr = { + .name = "scp_data", + .mode = S_IRUGO, + .owner = THIS_MODULE, + }, + .size = PAGE_SIZE, + .read = &ipl_scp_data_read, +}; + +static decl_subsys(ipl, NULL, NULL); + +static int ipl_register_fcp_files(void) +{ + int rc; + + rc = sysfs_create_group(&ipl_subsys.kset.kobj, + &ipl_fcp_attr_group); + if (rc) + goto out; + rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj, + &ipl_parameter_attr); + if (rc) + goto out_ipl_parm; + rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj, + &ipl_scp_data_attr); + if (!rc) + goto out; + + sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr); + +out_ipl_parm: + sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group); +out: + return rc; +} + +static int __init +ipl_device_sysfs_register(void) { + int rc; + + rc = firmware_register(&ipl_subsys); + if (rc) + goto out; + + switch (get_ipl_type()) { + case ipl_type_ccw: + rc = sysfs_create_group(&ipl_subsys.kset.kobj, + &ipl_ccw_attr_group); + break; + case ipl_type_fcp: + rc = ipl_register_fcp_files(); + break; + default: + rc = sysfs_create_group(&ipl_subsys.kset.kobj, + &ipl_unknown_attr_group); + break; + } + + if (rc) + firmware_unregister(&ipl_subsys); +out: + return rc; +} + +__initcall(ipl_device_sysfs_register); diff --git a/trunk/arch/s390/kernel/signal.c b/trunk/arch/s390/kernel/signal.c index 642095ec7c07..a887b686f279 100644 --- a/trunk/arch/s390/kernel/signal.c +++ b/trunk/arch/s390/kernel/signal.c @@ -114,26 +114,29 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs) { unsigned long old_mask = regs->psw.mask; - _sigregs user_sregs; - + int err; + save_access_regs(current->thread.acrs); /* Copy a 'clean' PSW mask to the user to avoid leaking information about whether PER is currently on. */ regs->psw.mask = PSW_MASK_MERGE(PSW_USER_BITS, regs->psw.mask); - memcpy(&user_sregs.regs.psw, ®s->psw, sizeof(sregs->regs.psw) + - sizeof(sregs->regs.gprs)); + err = __copy_to_user(&sregs->regs.psw, ®s->psw, + sizeof(sregs->regs.psw)+sizeof(sregs->regs.gprs)); regs->psw.mask = old_mask; - memcpy(&user_sregs.regs.acrs, current->thread.acrs, - sizeof(sregs->regs.acrs)); + if (err != 0) + return err; + err = __copy_to_user(&sregs->regs.acrs, current->thread.acrs, + sizeof(sregs->regs.acrs)); + if (err != 0) + return err; /* * We have to store the fp registers to current->thread.fp_regs * to merge them with the emulated registers. */ save_fp_regs(¤t->thread.fp_regs); - memcpy(&user_sregs.fpregs, ¤t->thread.fp_regs, - sizeof(s390_fp_regs)); - return __copy_to_user(sregs, &user_sregs, sizeof(_sigregs)); + return __copy_to_user(&sregs->fpregs, ¤t->thread.fp_regs, + sizeof(s390_fp_regs)); } /* Returns positive number on error */ @@ -141,25 +144,27 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) { unsigned long old_mask = regs->psw.mask; int err; - _sigregs user_sregs; /* Alwys make any pending restarted system call return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; - err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs)); + err = __copy_from_user(®s->psw, &sregs->regs.psw, + sizeof(sregs->regs.psw)+sizeof(sregs->regs.gprs)); regs->psw.mask = PSW_MASK_MERGE(old_mask, regs->psw.mask); regs->psw.addr |= PSW_ADDR_AMODE; if (err) return err; - memcpy(®s->psw, &user_sregs.regs.psw, sizeof(sregs->regs.psw) + - sizeof(sregs->regs.gprs)); - memcpy(¤t->thread.acrs, &user_sregs.regs.acrs, - sizeof(sregs->regs.acrs)); + err = __copy_from_user(¤t->thread.acrs, &sregs->regs.acrs, + sizeof(sregs->regs.acrs)); + if (err) + return err; restore_access_regs(current->thread.acrs); - memcpy(¤t->thread.fp_regs, &user_sregs.fpregs, - sizeof(s390_fp_regs)); + err = __copy_from_user(¤t->thread.fp_regs, &sregs->fpregs, + sizeof(s390_fp_regs)); current->thread.fp_regs.fpc &= FPC_VALID_MASK; + if (err) + return err; restore_fp_regs(¤t->thread.fp_regs); regs->trap = -1; /* disable syscall checks */ @@ -452,7 +457,6 @@ void do_signal(struct pt_regs *regs) case -ERESTART_RESTARTBLOCK: regs->gprs[2] = -EINTR; } - regs->trap = -1; /* Don't deal with this again. */ } /* Get signal to deliver. When running under ptrace, at this point diff --git a/trunk/arch/s390/kernel/smp.c b/trunk/arch/s390/kernel/smp.c index b2e6f4c8d382..8e03219eea76 100644 --- a/trunk/arch/s390/kernel/smp.c +++ b/trunk/arch/s390/kernel/smp.c @@ -59,6 +59,9 @@ static struct task_struct *current_set[NR_CPUS]; extern char vmhalt_cmd[]; extern char vmpoff_cmd[]; +extern void reipl(unsigned long devno); +extern void reipl_diag(void); + static void smp_ext_bitcall(int, ec_bit_sig); static void smp_ext_bitcall_others(ec_bit_sig); @@ -276,7 +279,12 @@ static void do_machine_restart(void * __unused) * interrupted by an external interrupt and s390irq * locks are always held disabled). */ - do_reipl(); + reipl_diag(); + + if (MACHINE_IS_VM) + cpcmd ("IPL", NULL, 0, NULL); + else + reipl (0x10000 | S390_lowcore.ipl_device); } void machine_restart_smp(char * __unused) diff --git a/trunk/arch/s390/kernel/traps.c b/trunk/arch/s390/kernel/traps.c index c4982c963424..bde1d1d59858 100644 --- a/trunk/arch/s390/kernel/traps.c +++ b/trunk/arch/s390/kernel/traps.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -40,7 +39,6 @@ #include #include #include -#include /* Called from entry.S only */ extern void handle_per_exception(struct pt_regs *regs); @@ -76,20 +74,6 @@ static int kstack_depth_to_print = 12; static int kstack_depth_to_print = 20; #endif /* CONFIG_64BIT */ -ATOMIC_NOTIFIER_HEAD(s390die_chain); - -int register_die_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_register(&s390die_chain, nb); -} -EXPORT_SYMBOL(register_die_notifier); - -int unregister_die_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(&s390die_chain, nb); -} -EXPORT_SYMBOL(unregister_die_notifier); - /* * For show_trace we have tree different stack to consider: * - the panic stack which is used if the kernel stack has overflown @@ -321,9 +305,8 @@ report_user_fault(long interruption_code, struct pt_regs *regs) #endif } -static void __kprobes inline do_trap(long interruption_code, int signr, - char *str, struct pt_regs *regs, - siginfo_t *info) +static void inline do_trap(long interruption_code, int signr, char *str, + struct pt_regs *regs, siginfo_t *info) { /* * We got all needed information from the lowcore and can @@ -332,10 +315,6 @@ static void __kprobes inline do_trap(long interruption_code, int signr, if (regs->psw.mask & PSW_MASK_PSTATE) local_irq_enable(); - if (notify_die(DIE_TRAP, str, regs, interruption_code, - interruption_code, signr) == NOTIFY_STOP) - return; - if (regs->psw.mask & PSW_MASK_PSTATE) { struct task_struct *tsk = current; @@ -357,12 +336,8 @@ static inline void __user *get_check_address(struct pt_regs *regs) return (void __user *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN); } -void __kprobes do_single_step(struct pt_regs *regs) +void do_single_step(struct pt_regs *regs) { - if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, - SIGTRAP) == NOTIFY_STOP){ - return; - } if ((current->ptrace & PT_PTRACED) != 0) force_sig(SIGTRAP, current); } diff --git a/trunk/arch/s390/kernel/vmlinux.lds.S b/trunk/arch/s390/kernel/vmlinux.lds.S index af9e69a03011..ff5f7bb34f75 100644 --- a/trunk/arch/s390/kernel/vmlinux.lds.S +++ b/trunk/arch/s390/kernel/vmlinux.lds.S @@ -24,7 +24,6 @@ SECTIONS *(.text) SCHED_TEXT LOCK_TEXT - KPROBES_TEXT *(.fixup) *(.gnu.warning) } = 0x0700 @@ -118,7 +117,7 @@ SECTIONS /* Sections to be discarded */ /DISCARD/ : { - *(.exit.text) *(.exit.data) *(.exitcall.exit) + *(.exitcall.exit) } /* Stabs debugging sections. */ diff --git a/trunk/arch/s390/lib/Makefile b/trunk/arch/s390/lib/Makefile index c42ffedfdb49..e05d087a6eae 100644 --- a/trunk/arch/s390/lib/Makefile +++ b/trunk/arch/s390/lib/Makefile @@ -4,6 +4,6 @@ EXTRA_AFLAGS := -traditional -lib-y += delay.o string.o uaccess_std.o -lib-$(CONFIG_64BIT) += uaccess_mvcos.o +lib-y += delay.o string.o +lib-y += $(if $(CONFIG_64BIT),uaccess64.o,uaccess.o) lib-$(CONFIG_SMP) += spinlock.o diff --git a/trunk/arch/s390/lib/uaccess.S b/trunk/arch/s390/lib/uaccess.S new file mode 100644 index 000000000000..5d59e2625048 --- /dev/null +++ b/trunk/arch/s390/lib/uaccess.S @@ -0,0 +1,210 @@ +/* + * arch/s390/lib/uaccess.S + * __copy_{from|to}_user functions. + * + * s390 + * Copyright (C) 2000,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com) + * + * These functions have standard call interface + */ + +#include +#include +#include + + .text + .align 4 + .globl __copy_from_user_asm + # %r2 = to, %r3 = n, %r4 = from +__copy_from_user_asm: + slr %r0,%r0 +0: mvcp 0(%r3,%r2),0(%r4),%r0 + jnz 1f + slr %r2,%r2 + br %r14 +1: la %r2,256(%r2) + la %r4,256(%r4) + ahi %r3,-256 +2: mvcp 0(%r3,%r2),0(%r4),%r0 + jnz 1b +3: slr %r2,%r2 + br %r14 +4: lhi %r0,-4096 + lr %r5,%r4 + slr %r5,%r0 + nr %r5,%r0 # %r5 = (%r4 + 4096) & -4096 + slr %r5,%r4 # %r5 = #bytes to next user page boundary + clr %r3,%r5 # copy crosses next page boundary ? + jnh 6f # no, the current page faulted + # move with the reduced length which is < 256 +5: mvcp 0(%r5,%r2),0(%r4),%r0 + slr %r3,%r5 +6: lr %r2,%r3 + br %r14 + .section __ex_table,"a" + .long 0b,4b + .long 2b,4b + .long 5b,6b + .previous + + .align 4 + .text + .globl __copy_to_user_asm + # %r2 = from, %r3 = n, %r4 = to +__copy_to_user_asm: + slr %r0,%r0 +0: mvcs 0(%r3,%r4),0(%r2),%r0 + jnz 1f + slr %r2,%r2 + br %r14 +1: la %r2,256(%r2) + la %r4,256(%r4) + ahi %r3,-256 +2: mvcs 0(%r3,%r4),0(%r2),%r0 + jnz 1b +3: slr %r2,%r2 + br %r14 +4: lhi %r0,-4096 + lr %r5,%r4 + slr %r5,%r0 + nr %r5,%r0 # %r5 = (%r4 + 4096) & -4096 + slr %r5,%r4 # %r5 = #bytes to next user page boundary + clr %r3,%r5 # copy crosses next page boundary ? + jnh 6f # no, the current page faulted + # move with the reduced length which is < 256 +5: mvcs 0(%r5,%r4),0(%r2),%r0 + slr %r3,%r5 +6: lr %r2,%r3 + br %r14 + .section __ex_table,"a" + .long 0b,4b + .long 2b,4b + .long 5b,6b + .previous + + .align 4 + .text + .globl __copy_in_user_asm + # %r2 = from, %r3 = n, %r4 = to +__copy_in_user_asm: + sacf 256 + bras 1,1f + mvc 0(1,%r4),0(%r2) +0: mvc 0(256,%r4),0(%r2) + la %r2,256(%r2) + la %r4,256(%r4) +1: ahi %r3,-256 + jnm 0b +2: ex %r3,0(%r1) + sacf 0 + slr %r2,%r2 + br 14 +3: mvc 0(1,%r4),0(%r2) + la %r2,1(%r2) + la %r4,1(%r4) + ahi %r3,-1 + jnm 3b +4: lr %r2,%r3 + sacf 0 + br %r14 + .section __ex_table,"a" + .long 0b,3b + .long 2b,3b + .long 3b,4b + .previous + + .align 4 + .text + .globl __clear_user_asm + # %r2 = to, %r3 = n +__clear_user_asm: + bras %r5,0f + .long empty_zero_page +0: l %r5,0(%r5) + slr %r0,%r0 +1: mvcs 0(%r3,%r2),0(%r5),%r0 + jnz 2f + slr %r2,%r2 + br %r14 +2: la %r2,256(%r2) + ahi %r3,-256 +3: mvcs 0(%r3,%r2),0(%r5),%r0 + jnz 2b +4: slr %r2,%r2 + br %r14 +5: lhi %r0,-4096 + lr %r4,%r2 + slr %r4,%r0 + nr %r4,%r0 # %r4 = (%r2 + 4096) & -4096 + slr %r4,%r2 # %r4 = #bytes to next user page boundary + clr %r3,%r4 # clear crosses next page boundary ? + jnh 7f # no, the current page faulted + # clear with the reduced length which is < 256 +6: mvcs 0(%r4,%r2),0(%r5),%r0 + slr %r3,%r4 +7: lr %r2,%r3 + br %r14 + .section __ex_table,"a" + .long 1b,5b + .long 3b,5b + .long 6b,7b + .previous + + .align 4 + .text + .globl __strncpy_from_user_asm + # %r2 = count, %r3 = dst, %r4 = src +__strncpy_from_user_asm: + lhi %r0,0 + lr %r1,%r4 + la %r4,0(%r4) # clear high order bit from %r4 + la %r2,0(%r2,%r4) # %r2 points to first byte after string + sacf 256 +0: srst %r2,%r1 + jo 0b + sacf 0 + lr %r1,%r2 + jh 1f # \0 found in string ? + ahi %r1,1 # include \0 in copy +1: slr %r1,%r4 # %r1 = copy length (without \0) + slr %r2,%r4 # %r2 = return length (including \0) +2: mvcp 0(%r1,%r3),0(%r4),%r0 + jnz 3f + br %r14 +3: la %r3,256(%r3) + la %r4,256(%r4) + ahi %r1,-256 + mvcp 0(%r1,%r3),0(%r4),%r0 + jnz 3b + br %r14 +4: sacf 0 + lhi %r2,-EFAULT + br %r14 + .section __ex_table,"a" + .long 0b,4b + .previous + + .align 4 + .text + .globl __strnlen_user_asm + # %r2 = count, %r3 = src +__strnlen_user_asm: + lhi %r0,0 + lr %r1,%r3 + la %r3,0(%r3) # clear high order bit from %r4 + la %r2,0(%r2,%r3) # %r2 points to first byte after string + sacf 256 +0: srst %r2,%r1 + jo 0b + sacf 0 + ahi %r2,1 # strnlen_user result includes the \0 + # or return count+1 if \0 not found + slr %r2,%r3 + br %r14 +2: sacf 0 + slr %r2,%r2 # return 0 on exception + br %r14 + .section __ex_table,"a" + .long 0b,2b + .previous diff --git a/trunk/arch/s390/lib/uaccess64.S b/trunk/arch/s390/lib/uaccess64.S new file mode 100644 index 000000000000..19b41a33c230 --- /dev/null +++ b/trunk/arch/s390/lib/uaccess64.S @@ -0,0 +1,206 @@ +/* + * arch/s390x/lib/uaccess.S + * __copy_{from|to}_user functions. + * + * s390 + * Copyright (C) 2000,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com) + * + * These functions have standard call interface + */ + +#include +#include +#include + + .text + .align 4 + .globl __copy_from_user_asm + # %r2 = to, %r3 = n, %r4 = from +__copy_from_user_asm: + slgr %r0,%r0 +0: mvcp 0(%r3,%r2),0(%r4),%r0 + jnz 1f + slgr %r2,%r2 + br %r14 +1: la %r2,256(%r2) + la %r4,256(%r4) + aghi %r3,-256 +2: mvcp 0(%r3,%r2),0(%r4),%r0 + jnz 1b +3: slgr %r2,%r2 + br %r14 +4: lghi %r0,-4096 + lgr %r5,%r4 + slgr %r5,%r0 + ngr %r5,%r0 # %r5 = (%r4 + 4096) & -4096 + slgr %r5,%r4 # %r5 = #bytes to next user page boundary + clgr %r3,%r5 # copy crosses next page boundary ? + jnh 6f # no, the current page faulted + # move with the reduced length which is < 256 +5: mvcp 0(%r5,%r2),0(%r4),%r0 + slgr %r3,%r5 +6: lgr %r2,%r3 + br %r14 + .section __ex_table,"a" + .quad 0b,4b + .quad 2b,4b + .quad 5b,6b + .previous + + .align 4 + .text + .globl __copy_to_user_asm + # %r2 = from, %r3 = n, %r4 = to +__copy_to_user_asm: + slgr %r0,%r0 +0: mvcs 0(%r3,%r4),0(%r2),%r0 + jnz 1f + slgr %r2,%r2 + br %r14 +1: la %r2,256(%r2) + la %r4,256(%r4) + aghi %r3,-256 +2: mvcs 0(%r3,%r4),0(%r2),%r0 + jnz 1b +3: slgr %r2,%r2 + br %r14 +4: lghi %r0,-4096 + lgr %r5,%r4 + slgr %r5,%r0 + ngr %r5,%r0 # %r5 = (%r4 + 4096) & -4096 + slgr %r5,%r4 # %r5 = #bytes to next user page boundary + clgr %r3,%r5 # copy crosses next page boundary ? + jnh 6f # no, the current page faulted + # move with the reduced length which is < 256 +5: mvcs 0(%r5,%r4),0(%r2),%r0 + slgr %r3,%r5 +6: lgr %r2,%r3 + br %r14 + .section __ex_table,"a" + .quad 0b,4b + .quad 2b,4b + .quad 5b,6b + .previous + + .align 4 + .text + .globl __copy_in_user_asm + # %r2 = from, %r3 = n, %r4 = to +__copy_in_user_asm: + sacf 256 + bras 1,1f + mvc 0(1,%r4),0(%r2) +0: mvc 0(256,%r4),0(%r2) + la %r2,256(%r2) + la %r4,256(%r4) +1: aghi %r3,-256 + jnm 0b +2: ex %r3,0(%r1) + sacf 0 + slgr %r2,%r2 + br 14 +3: mvc 0(1,%r4),0(%r2) + la %r2,1(%r2) + la %r4,1(%r4) + aghi %r3,-1 + jnm 3b +4: lgr %r2,%r3 + sacf 0 + br %r14 + .section __ex_table,"a" + .quad 0b,3b + .quad 2b,3b + .quad 3b,4b + .previous + + .align 4 + .text + .globl __clear_user_asm + # %r2 = to, %r3 = n +__clear_user_asm: + slgr %r0,%r0 + larl %r5,empty_zero_page +1: mvcs 0(%r3,%r2),0(%r5),%r0 + jnz 2f + slgr %r2,%r2 + br %r14 +2: la %r2,256(%r2) + aghi %r3,-256 +3: mvcs 0(%r3,%r2),0(%r5),%r0 + jnz 2b +4: slgr %r2,%r2 + br %r14 +5: lghi %r0,-4096 + lgr %r4,%r2 + slgr %r4,%r0 + ngr %r4,%r0 # %r4 = (%r2 + 4096) & -4096 + slgr %r4,%r2 # %r4 = #bytes to next user page boundary + clgr %r3,%r4 # clear crosses next page boundary ? + jnh 7f # no, the current page faulted + # clear with the reduced length which is < 256 +6: mvcs 0(%r4,%r2),0(%r5),%r0 + slgr %r3,%r4 +7: lgr %r2,%r3 + br %r14 + .section __ex_table,"a" + .quad 1b,5b + .quad 3b,5b + .quad 6b,7b + .previous + + .align 4 + .text + .globl __strncpy_from_user_asm + # %r2 = count, %r3 = dst, %r4 = src +__strncpy_from_user_asm: + lghi %r0,0 + lgr %r1,%r4 + la %r2,0(%r2,%r4) # %r2 points to first byte after string + sacf 256 +0: srst %r2,%r1 + jo 0b + sacf 0 + lgr %r1,%r2 + jh 1f # \0 found in string ? + aghi %r1,1 # include \0 in copy +1: slgr %r1,%r4 # %r1 = copy length (without \0) + slgr %r2,%r4 # %r2 = return length (including \0) +2: mvcp 0(%r1,%r3),0(%r4),%r0 + jnz 3f + br %r14 +3: la %r3,256(%r3) + la %r4,256(%r4) + aghi %r1,-256 + mvcp 0(%r1,%r3),0(%r4),%r0 + jnz 3b + br %r14 +4: sacf 0 + lghi %r2,-EFAULT + br %r14 + .section __ex_table,"a" + .quad 0b,4b + .previous + + .align 4 + .text + .globl __strnlen_user_asm + # %r2 = count, %r3 = src +__strnlen_user_asm: + lghi %r0,0 + lgr %r1,%r3 + la %r2,0(%r2,%r3) # %r2 points to first byte after string + sacf 256 +0: srst %r2,%r1 + jo 0b + sacf 0 + aghi %r2,1 # strnlen_user result includes the \0 + # or return count+1 if \0 not found + slgr %r2,%r3 + br %r14 +2: sacf 0 + slgr %r2,%r2 # return 0 on exception + br %r14 + .section __ex_table,"a" + .quad 0b,2b + .previous diff --git a/trunk/arch/s390/lib/uaccess_mvcos.c b/trunk/arch/s390/lib/uaccess_mvcos.c deleted file mode 100644 index 86c96d6c191a..000000000000 --- a/trunk/arch/s390/lib/uaccess_mvcos.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * arch/s390/lib/uaccess_mvcos.c - * - * Optimized user space space access functions based on mvcos. - * - * Copyright (C) IBM Corp. 2006 - * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), - * Gerald Schaefer (gerald.schaefer@de.ibm.com) - */ - -#include -#include -#include -#include - -#ifndef __s390x__ -#define AHI "ahi" -#define ALR "alr" -#define CLR "clr" -#define LHI "lhi" -#define SLR "slr" -#else -#define AHI "aghi" -#define ALR "algr" -#define CLR "clgr" -#define LHI "lghi" -#define SLR "slgr" -#endif - -size_t copy_from_user_mvcos(size_t size, const void __user *ptr, void *x) -{ - register unsigned long reg0 asm("0") = 0x81UL; - unsigned long tmp1, tmp2; - - tmp1 = -4096UL; - asm volatile( - "0: .insn ss,0xc80000000000,0(%0,%2),0(%1),0\n" - " jz 4f\n" - "1:"ALR" %0,%3\n" - " "SLR" %1,%3\n" - " "SLR" %2,%3\n" - " j 0b\n" - "2: la %4,4095(%1)\n"/* %4 = ptr + 4095 */ - " nr %4,%3\n" /* %4 = (ptr + 4095) & -4096 */ - " "SLR" %4,%1\n" - " "CLR" %0,%4\n" /* copy crosses next page boundary? */ - " jnh 5f\n" - "3: .insn ss,0xc80000000000,0(%4,%2),0(%1),0\n" - " "SLR" %0,%4\n" - " j 5f\n" - "4:"SLR" %0,%0\n" - "5: \n" - EX_TABLE(0b,2b) EX_TABLE(3b,5b) - : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2) - : "d" (reg0) : "cc", "memory"); - return size; -} - -size_t copy_to_user_mvcos(size_t size, void __user *ptr, const void *x) -{ - register unsigned long reg0 asm("0") = 0x810000UL; - unsigned long tmp1, tmp2; - - tmp1 = -4096UL; - asm volatile( - "0: .insn ss,0xc80000000000,0(%0,%1),0(%2),0\n" - " jz 4f\n" - "1:"ALR" %0,%3\n" - " "SLR" %1,%3\n" - " "SLR" %2,%3\n" - " j 0b\n" - "2: la %4,4095(%1)\n"/* %4 = ptr + 4095 */ - " nr %4,%3\n" /* %4 = (ptr + 4095) & -4096 */ - " "SLR" %4,%1\n" - " "CLR" %0,%4\n" /* copy crosses next page boundary? */ - " jnh 5f\n" - "3: .insn ss,0xc80000000000,0(%4,%1),0(%2),0\n" - " "SLR" %0,%4\n" - " j 5f\n" - "4:"SLR" %0,%0\n" - "5: \n" - EX_TABLE(0b,2b) EX_TABLE(3b,5b) - : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2) - : "d" (reg0) : "cc", "memory"); - return size; -} - -size_t copy_in_user_mvcos(size_t size, void __user *to, const void __user *from) -{ - register unsigned long reg0 asm("0") = 0x810081UL; - unsigned long tmp1, tmp2; - - tmp1 = -4096UL; - /* FIXME: copy with reduced length. */ - asm volatile( - "0: .insn ss,0xc80000000000,0(%0,%1),0(%2),0\n" - " jz 2f\n" - "1:"ALR" %0,%3\n" - " "SLR" %1,%3\n" - " "SLR" %2,%3\n" - " j 0b\n" - "2:"SLR" %0,%0\n" - "3: \n" - EX_TABLE(0b,3b) - : "+a" (size), "+a" (to), "+a" (from), "+a" (tmp1), "=a" (tmp2) - : "d" (reg0) : "cc", "memory"); - return size; -} - -size_t clear_user_mvcos(size_t size, void __user *to) -{ - register unsigned long reg0 asm("0") = 0x810000UL; - unsigned long tmp1, tmp2; - - tmp1 = -4096UL; - asm volatile( - "0: .insn ss,0xc80000000000,0(%0,%1),0(%4),0\n" - " jz 4f\n" - "1:"ALR" %0,%2\n" - " "SLR" %1,%2\n" - " j 0b\n" - "2: la %3,4095(%1)\n"/* %4 = to + 4095 */ - " nr %3,%2\n" /* %4 = (to + 4095) & -4096 */ - " "SLR" %3,%1\n" - " "CLR" %0,%3\n" /* copy crosses next page boundary? */ - " jnh 5f\n" - "3: .insn ss,0xc80000000000,0(%3,%1),0(%4),0\n" - " "SLR" %0,%3\n" - " j 5f\n" - "4:"SLR" %0,%0\n" - "5: \n" - EX_TABLE(0b,2b) EX_TABLE(3b,5b) - : "+a" (size), "+a" (to), "+a" (tmp1), "=a" (tmp2) - : "a" (empty_zero_page), "d" (reg0) : "cc", "memory"); - return size; -} - -extern size_t copy_from_user_std_small(size_t, const void __user *, void *); -extern size_t copy_to_user_std_small(size_t, void __user *, const void *); -extern size_t strnlen_user_std(size_t, const char __user *); -extern size_t strncpy_from_user_std(size_t, const char __user *, char *); -extern int futex_atomic_op(int, int __user *, int, int *); -extern int futex_atomic_cmpxchg(int __user *, int, int); - -struct uaccess_ops uaccess_mvcos = { - .copy_from_user = copy_from_user_mvcos, - .copy_from_user_small = copy_from_user_std_small, - .copy_to_user = copy_to_user_mvcos, - .copy_to_user_small = copy_to_user_std_small, - .copy_in_user = copy_in_user_mvcos, - .clear_user = clear_user_mvcos, - .strnlen_user = strnlen_user_std, - .strncpy_from_user = strncpy_from_user_std, - .futex_atomic_op = futex_atomic_op, - .futex_atomic_cmpxchg = futex_atomic_cmpxchg, -}; diff --git a/trunk/arch/s390/lib/uaccess_std.c b/trunk/arch/s390/lib/uaccess_std.c deleted file mode 100644 index 9a4d4a29ea79..000000000000 --- a/trunk/arch/s390/lib/uaccess_std.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * arch/s390/lib/uaccess_std.c - * - * Standard user space access functions based on mvcp/mvcs and doing - * interesting things in the secondary space mode. - * - * Copyright (C) IBM Corp. 2006 - * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), - * Gerald Schaefer (gerald.schaefer@de.ibm.com) - */ - -#include -#include -#include -#include - -#ifndef __s390x__ -#define AHI "ahi" -#define ALR "alr" -#define CLR "clr" -#define LHI "lhi" -#define SLR "slr" -#else -#define AHI "aghi" -#define ALR "algr" -#define CLR "clgr" -#define LHI "lghi" -#define SLR "slgr" -#endif - -size_t copy_from_user_std(size_t size, const void __user *ptr, void *x) -{ - unsigned long tmp1, tmp2; - - tmp1 = -256UL; - asm volatile( - "0: mvcp 0(%0,%2),0(%1),%3\n" - " jz 5f\n" - "1:"ALR" %0,%3\n" - " la %1,256(%1)\n" - " la %2,256(%2)\n" - "2: mvcp 0(%0,%2),0(%1),%3\n" - " jnz 1b\n" - " j 5f\n" - "3: la %4,255(%1)\n" /* %4 = ptr + 255 */ - " "LHI" %3,-4096\n" - " nr %4,%3\n" /* %4 = (ptr + 255) & -4096 */ - " "SLR" %4,%1\n" - " "CLR" %0,%4\n" /* copy crosses next page boundary? */ - " jnh 6f\n" - "4: mvcp 0(%4,%2),0(%1),%3\n" - " "SLR" %0,%4\n" - " j 6f\n" - "5:"SLR" %0,%0\n" - "6: \n" - EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b) - : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2) - : : "cc", "memory"); - return size; -} - -size_t copy_from_user_std_small(size_t size, const void __user *ptr, void *x) -{ - unsigned long tmp1, tmp2; - - tmp1 = 0UL; - asm volatile( - "0: mvcp 0(%0,%2),0(%1),%3\n" - " "SLR" %0,%0\n" - " j 3f\n" - "1: la %4,255(%1)\n" /* %4 = ptr + 255 */ - " "LHI" %3,-4096\n" - " nr %4,%3\n" /* %4 = (ptr + 255) & -4096 */ - " "SLR" %4,%1\n" - " "CLR" %0,%4\n" /* copy crosses next page boundary? */ - " jnh 3f\n" - "2: mvcp 0(%4,%2),0(%1),%3\n" - " "SLR" %0,%4\n" - "3:\n" - EX_TABLE(0b,1b) EX_TABLE(2b,3b) - : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2) - : : "cc", "memory"); - return size; -} - -size_t copy_to_user_std(size_t size, void __user *ptr, const void *x) -{ - unsigned long tmp1, tmp2; - - tmp1 = -256UL; - asm volatile( - "0: mvcs 0(%0,%1),0(%2),%3\n" - " jz 5f\n" - "1:"ALR" %0,%3\n" - " la %1,256(%1)\n" - " la %2,256(%2)\n" - "2: mvcs 0(%0,%1),0(%2),%3\n" - " jnz 1b\n" - " j 5f\n" - "3: la %4,255(%1)\n" /* %4 = ptr + 255 */ - " "LHI" %3,-4096\n" - " nr %4,%3\n" /* %4 = (ptr + 255) & -4096 */ - " "SLR" %4,%1\n" - " "CLR" %0,%4\n" /* copy crosses next page boundary? */ - " jnh 6f\n" - "4: mvcs 0(%4,%1),0(%2),%3\n" - " "SLR" %0,%4\n" - " j 6f\n" - "5:"SLR" %0,%0\n" - "6: \n" - EX_TABLE(0b,3b) EX_TABLE(2b,3b) EX_TABLE(4b,6b) - : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2) - : : "cc", "memory"); - return size; -} - -size_t copy_to_user_std_small(size_t size, void __user *ptr, const void *x) -{ - unsigned long tmp1, tmp2; - - tmp1 = 0UL; - asm volatile( - "0: mvcs 0(%0,%1),0(%2),%3\n" - " "SLR" %0,%0\n" - " j 3f\n" - "1: la %4,255(%1)\n" /* ptr + 255 */ - " "LHI" %3,-4096\n" - " nr %4,%3\n" /* (ptr + 255) & -4096UL */ - " "SLR" %4,%1\n" - " "CLR" %0,%4\n" /* copy crosses next page boundary? */ - " jnh 3f\n" - "2: mvcs 0(%4,%1),0(%2),%3\n" - " "SLR" %0,%4\n" - "3:\n" - EX_TABLE(0b,1b) EX_TABLE(2b,3b) - : "+a" (size), "+a" (ptr), "+a" (x), "+a" (tmp1), "=a" (tmp2) - : : "cc", "memory"); - return size; -} - -size_t copy_in_user_std(size_t size, void __user *to, const void __user *from) -{ - unsigned long tmp1; - - asm volatile( - " "AHI" %0,-1\n" - " jo 5f\n" - " sacf 256\n" - " bras %3,3f\n" - "0:"AHI" %0,257\n" - "1: mvc 0(1,%1),0(%2)\n" - " la %1,1(%1)\n" - " la %2,1(%2)\n" - " "AHI" %0,-1\n" - " jnz 1b\n" - " j 5f\n" - "2: mvc 0(256,%1),0(%2)\n" - " la %1,256(%1)\n" - " la %2,256(%2)\n" - "3:"AHI" %0,-256\n" - " jnm 2b\n" - "4: ex %0,1b-0b(%3)\n" - " sacf 0\n" - "5: "SLR" %0,%0\n" - "6:\n" - EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b) - : "+a" (size), "+a" (to), "+a" (from), "=a" (tmp1) - : : "cc", "memory"); - return size; -} - -size_t clear_user_std(size_t size, void __user *to) -{ - unsigned long tmp1, tmp2; - - asm volatile( - " "AHI" %0,-1\n" - " jo 5f\n" - " sacf 256\n" - " bras %3,3f\n" - " xc 0(1,%1),0(%1)\n" - "0:"AHI" %0,257\n" - " la %2,255(%1)\n" /* %2 = ptr + 255 */ - " srl %2,12\n" - " sll %2,12\n" /* %2 = (ptr + 255) & -4096 */ - " "SLR" %2,%1\n" - " "CLR" %0,%2\n" /* clear crosses next page boundary? */ - " jnh 5f\n" - " "AHI" %2,-1\n" - "1: ex %2,0(%3)\n" - " "AHI" %2,1\n" - " "SLR" %0,%2\n" - " j 5f\n" - "2: xc 0(256,%1),0(%1)\n" - " la %1,256(%1)\n" - "3:"AHI" %0,-256\n" - " jnm 2b\n" - "4: ex %0,0(%3)\n" - " sacf 0\n" - "5: "SLR" %0,%0\n" - "6:\n" - EX_TABLE(1b,6b) EX_TABLE(2b,0b) EX_TABLE(4b,0b) - : "+a" (size), "+a" (to), "=a" (tmp1), "=a" (tmp2) - : : "cc", "memory"); - return size; -} - -size_t strnlen_user_std(size_t size, const char __user *src) -{ - register unsigned long reg0 asm("0") = 0UL; - unsigned long tmp1, tmp2; - - asm volatile( - " la %2,0(%1)\n" - " la %3,0(%0,%1)\n" - " "SLR" %0,%0\n" - " sacf 256\n" - "0: srst %3,%2\n" - " jo 0b\n" - " la %0,1(%3)\n" /* strnlen_user results includes \0 */ - " "SLR" %0,%1\n" - "1: sacf 0\n" - EX_TABLE(0b,1b) - : "+a" (size), "+a" (src), "=a" (tmp1), "=a" (tmp2) - : "d" (reg0) : "cc", "memory"); - return size; -} - -size_t strncpy_from_user_std(size_t size, const char __user *src, char *dst) -{ - register unsigned long reg0 asm("0") = 0UL; - unsigned long tmp1, tmp2; - - asm volatile( - " la %3,0(%1)\n" - " la %4,0(%0,%1)\n" - " sacf 256\n" - "0: srst %4,%3\n" - " jo 0b\n" - " sacf 0\n" - " la %0,0(%4)\n" - " jh 1f\n" /* found \0 in string ? */ - " "AHI" %4,1\n" /* include \0 in copy */ - "1:"SLR" %0,%1\n" /* %0 = return length (without \0) */ - " "SLR" %4,%1\n" /* %4 = copy length (including \0) */ - "2: mvcp 0(%4,%2),0(%1),%5\n" - " jz 9f\n" - "3:"AHI" %4,-256\n" - " la %1,256(%1)\n" - " la %2,256(%2)\n" - "4: mvcp 0(%4,%2),0(%1),%5\n" - " jnz 3b\n" - " j 9f\n" - "7: sacf 0\n" - "8:"LHI" %0,%6\n" - "9:\n" - EX_TABLE(0b,7b) EX_TABLE(2b,8b) EX_TABLE(4b,8b) - : "+a" (size), "+a" (src), "+d" (dst), "=a" (tmp1), "=a" (tmp2) - : "d" (reg0), "K" (-EFAULT) : "cc", "memory"); - return size; -} - -#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg) \ - asm volatile( \ - " sacf 256\n" \ - "0: l %1,0(%6)\n" \ - "1:"insn \ - "2: cs %1,%2,0(%6)\n" \ - "3: jl 1b\n" \ - " lhi %0,0\n" \ - "4: sacf 0\n" \ - EX_TABLE(0b,4b) EX_TABLE(2b,4b) EX_TABLE(3b,4b) \ - : "=d" (ret), "=&d" (oldval), "=&d" (newval), \ - "=m" (*uaddr) \ - : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ - "m" (*uaddr) : "cc"); - -int futex_atomic_op(int op, int __user *uaddr, int oparg, int *old) -{ - int oldval = 0, newval, ret; - - inc_preempt_count(); - - switch (op) { - case FUTEX_OP_SET: - __futex_atomic_op("lr %2,%5\n", - ret, oldval, newval, uaddr, oparg); - break; - case FUTEX_OP_ADD: - __futex_atomic_op("lr %2,%1\nar %2,%5\n", - ret, oldval, newval, uaddr, oparg); - break; - case FUTEX_OP_OR: - __futex_atomic_op("lr %2,%1\nor %2,%5\n", - ret, oldval, newval, uaddr, oparg); - break; - case FUTEX_OP_ANDN: - __futex_atomic_op("lr %2,%1\nnr %2,%5\n", - ret, oldval, newval, uaddr, oparg); - break; - case FUTEX_OP_XOR: - __futex_atomic_op("lr %2,%1\nxr %2,%5\n", - ret, oldval, newval, uaddr, oparg); - break; - default: - ret = -ENOSYS; - } - dec_preempt_count(); - *old = oldval; - return ret; -} - -int futex_atomic_cmpxchg(int __user *uaddr, int oldval, int newval) -{ - int ret; - - asm volatile( - " sacf 256\n" - " cs %1,%4,0(%5)\n" - "0: lr %0,%1\n" - "1: sacf 0\n" - EX_TABLE(0b,1b) - : "=d" (ret), "+d" (oldval), "=m" (*uaddr) - : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr) - : "cc", "memory" ); - return ret; -} - -struct uaccess_ops uaccess_std = { - .copy_from_user = copy_from_user_std, - .copy_from_user_small = copy_from_user_std_small, - .copy_to_user = copy_to_user_std, - .copy_to_user_small = copy_to_user_std_small, - .copy_in_user = copy_in_user_std, - .clear_user = clear_user_std, - .strnlen_user = strnlen_user_std, - .strncpy_from_user = strncpy_from_user_std, - .futex_atomic_op = futex_atomic_op, - .futex_atomic_cmpxchg = futex_atomic_cmpxchg, -}; diff --git a/trunk/arch/s390/mm/cmm.c b/trunk/arch/s390/mm/cmm.c index 786a44dba5bf..ceea51cff03b 100644 --- a/trunk/arch/s390/mm/cmm.c +++ b/trunk/arch/s390/mm/cmm.c @@ -52,6 +52,22 @@ static struct timer_list cmm_timer; static void cmm_timer_fn(unsigned long); static void cmm_set_timer(void); +static long +cmm_strtoul(const char *cp, char **endp) +{ + unsigned int base = 10; + + if (*cp == '0') { + base = 8; + cp++; + if ((*cp == 'x' || *cp == 'X') && isxdigit(cp[1])) { + base = 16; + cp++; + } + } + return simple_strtoul(cp, endp, base); +} + static long cmm_alloc_pages(long pages, long *counter, struct cmm_page_array **list) { @@ -260,7 +276,7 @@ cmm_pages_handler(ctl_table *ctl, int write, struct file *filp, return -EFAULT; buf[sizeof(buf) - 1] = '\0'; cmm_skip_blanks(buf, &p); - pages = simple_strtoul(p, &p, 0); + pages = cmm_strtoul(p, &p); if (ctl == &cmm_table[0]) cmm_set_pages(pages); else @@ -301,9 +317,9 @@ cmm_timeout_handler(ctl_table *ctl, int write, struct file *filp, return -EFAULT; buf[sizeof(buf) - 1] = '\0'; cmm_skip_blanks(buf, &p); - pages = simple_strtoul(p, &p, 0); + pages = cmm_strtoul(p, &p); cmm_skip_blanks(p, &p); - seconds = simple_strtoul(p, &p, 0); + seconds = cmm_strtoul(p, &p); cmm_set_timeout(pages, seconds); } else { len = sprintf(buf, "%ld %ld\n", @@ -366,24 +382,24 @@ cmm_smsg_target(char *from, char *msg) if (strncmp(msg, "SHRINK", 6) == 0) { if (!cmm_skip_blanks(msg + 6, &msg)) return; - pages = simple_strtoul(msg, &msg, 0); + pages = cmm_strtoul(msg, &msg); cmm_skip_blanks(msg, &msg); if (*msg == '\0') cmm_set_pages(pages); } else if (strncmp(msg, "RELEASE", 7) == 0) { if (!cmm_skip_blanks(msg + 7, &msg)) return; - pages = simple_strtoul(msg, &msg, 0); + pages = cmm_strtoul(msg, &msg); cmm_skip_blanks(msg, &msg); if (*msg == '\0') cmm_add_timed_pages(pages); } else if (strncmp(msg, "REUSE", 5) == 0) { if (!cmm_skip_blanks(msg + 5, &msg)) return; - pages = simple_strtoul(msg, &msg, 0); + pages = cmm_strtoul(msg, &msg); if (!cmm_skip_blanks(msg, &msg)) return; - seconds = simple_strtoul(msg, &msg, 0); + seconds = cmm_strtoul(msg, &msg); cmm_skip_blanks(msg, &msg); if (*msg == '\0') cmm_set_timeout(pages, seconds); diff --git a/trunk/arch/s390/mm/fault.c b/trunk/arch/s390/mm/fault.c index 44f0cda7e72e..7cd82575813d 100644 --- a/trunk/arch/s390/mm/fault.c +++ b/trunk/arch/s390/mm/fault.c @@ -25,12 +25,10 @@ #include #include #include -#include #include #include #include -#include #ifndef CONFIG_64BIT #define __FAIL_ADDR_MASK 0x7ffff000 @@ -50,38 +48,6 @@ extern int sysctl_userprocess_debug; extern void die(const char *,struct pt_regs *,long); -#ifdef CONFIG_KPROBES -ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); -int register_page_fault_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_register(¬ify_page_fault_chain, nb); -} - -int unregister_page_fault_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(¬ify_page_fault_chain, nb); -} - -static inline int notify_page_fault(enum die_val val, const char *str, - struct pt_regs *regs, long err, int trap, int sig) -{ - struct die_args args = { - .regs = regs, - .str = str, - .err = err, - .trapnr = trap, - .signr = sig - }; - return atomic_notifier_call_chain(¬ify_page_fault_chain, val, &args); -} -#else -static inline int notify_page_fault(enum die_val val, const char *str, - struct pt_regs *regs, long err, int trap, int sig) -{ - return NOTIFY_DONE; -} -#endif - extern spinlock_t timerlist_lock; /* @@ -193,7 +159,7 @@ static void do_sigsegv(struct pt_regs *regs, unsigned long error_code, * 11 Page translation -> Not present (nullification) * 3b Region third trans. -> Not present (nullification) */ -static inline void __kprobes +static inline void do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) { struct task_struct *tsk; @@ -207,10 +173,6 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection) tsk = current; mm = tsk->mm; - if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14, - SIGSEGV) == NOTIFY_STOP) - return; - /* * Check for low-address protection. This needs to be treated * as a special case because the translation exception code diff --git a/trunk/arch/s390/mm/init.c b/trunk/arch/s390/mm/init.c index cfd9b8f7a523..eb6ebfef134a 100644 --- a/trunk/arch/s390/mm/init.c +++ b/trunk/arch/s390/mm/init.c @@ -108,23 +108,16 @@ void __init paging_init(void) unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE; static const int ssm_mask = 0x04000000L; unsigned long ro_start_pfn, ro_end_pfn; - unsigned long zones_size[MAX_NR_ZONES]; ro_start_pfn = PFN_DOWN((unsigned long)&__start_rodata); ro_end_pfn = PFN_UP((unsigned long)&__end_rodata); - memset(zones_size, 0, sizeof(zones_size)); - zones_size[ZONE_DMA] = max_low_pfn; - free_area_init_node(0, &contig_page_data, zones_size, - __pa(PAGE_OFFSET) >> PAGE_SHIFT, - zholes_size); - /* unmap whole virtual address space */ pg_dir = swapper_pg_dir; - for (i = 0; i < PTRS_PER_PGD; i++) - pmd_clear((pmd_t *) pg_dir++); + for (i=0;ipgd0 = (_PAGE_TABLE | __pa(pg_table)); + pg_dir->pgd1 = (_PAGE_TABLE | (__pa(pg_table)+1024)); + pg_dir->pgd2 = (_PAGE_TABLE | (__pa(pg_table)+2048)); + pg_dir->pgd3 = (_PAGE_TABLE | (__pa(pg_table)+3072)); pg_dir++; for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) { @@ -147,8 +143,8 @@ void __init paging_init(void) else pte = pfn_pte(pfn, PAGE_KERNEL); if (pfn >= max_low_pfn) - pte_val(pte) = _PAGE_TYPE_EMPTY; - set_pte(pg_table, pte); + pte_clear(&init_mm, 0, &pte); + set_pte(pg_table, pte); pfn++; } } @@ -163,6 +159,16 @@ void __init paging_init(void) : : "m" (pgdir_k), "m" (ssm_mask)); local_flush_tlb(); + + { + unsigned long zones_size[MAX_NR_ZONES]; + + memset(zones_size, 0, sizeof(zones_size)); + zones_size[ZONE_DMA] = max_low_pfn; + free_area_init_node(0, &contig_page_data, zones_size, + __pa(PAGE_OFFSET) >> PAGE_SHIFT, + zholes_size); + } return; } @@ -213,7 +219,7 @@ void __init paging_init(void) continue; } - pm_dir = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE * 4); + pm_dir = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE*4); pgd_populate(&init_mm, pg_dir, pm_dir); for (j = 0 ; j < PTRS_PER_PMD ; j++,pm_dir++) { @@ -222,7 +228,7 @@ void __init paging_init(void) continue; } - pt_dir = (pte_t *) alloc_bootmem_pages(PAGE_SIZE); + pt_dir = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); pmd_populate_kernel(&init_mm, pm_dir, pt_dir); for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) { @@ -230,8 +236,10 @@ void __init paging_init(void) pte = pfn_pte(pfn, __pgprot(_PAGE_RO)); else pte = pfn_pte(pfn, PAGE_KERNEL); - if (pfn >= max_low_pfn) - pte_val(pte) = _PAGE_TYPE_EMPTY; + if (pfn >= max_low_pfn) { + pte_clear(&init_mm, 0, &pte); + continue; + } set_pte(pt_dir, pte); pfn++; } diff --git a/trunk/arch/sh/kernel/cpu/sh4/sq.c b/trunk/arch/sh/kernel/cpu/sh4/sq.c index b09805f3ee23..781dbb11c038 100644 --- a/trunk/arch/sh/kernel/cpu/sh4/sq.c +++ b/trunk/arch/sh/kernel/cpu/sh4/sq.c @@ -421,22 +421,18 @@ static struct miscdevice sq_dev = { static int __init sq_api_init(void) { - int ret; printk(KERN_NOTICE "sq: Registering store queue API.\n"); +#ifdef CONFIG_PROC_FS create_proc_read_entry("sq_mapping", 0, 0, sq_mapping_read_proc, 0); +#endif - ret = misc_register(&sq_dev); - if (ret) - remove_proc_entry("sq_mapping", NULL); - - return ret; + return misc_register(&sq_dev); } static void __exit sq_api_exit(void) { misc_deregister(&sq_dev); - remove_proc_entry("sq_mapping", NULL); } module_init(sq_api_init); diff --git a/trunk/arch/sh64/Makefile b/trunk/arch/sh64/Makefile index ebf20043991c..8ca57ffa2b70 100644 --- a/trunk/arch/sh64/Makefile +++ b/trunk/arch/sh64/Makefile @@ -26,6 +26,7 @@ LDFLAGS += -EB -mshelf32_linux endif # No requirements for endianess support from AFLAGS, 'as' always run through gcc +AFLAGS += -m5 -isa=sh64 -traditional CFLAGS += $(cpu-y) LDFLAGS_vmlinux += --defsym phys_stext=_stext-$(CONFIG_CACHED_MEMORY_OFFSET) \ diff --git a/trunk/arch/sh64/kernel/process.c b/trunk/arch/sh64/kernel/process.c index db475b7833fb..dba8e14013b6 100644 --- a/trunk/arch/sh64/kernel/process.c +++ b/trunk/arch/sh64/kernel/process.c @@ -355,9 +355,6 @@ void machine_power_off(void) enter_deep_standby(); } -void (*pm_power_off)(void) = machine_power_off; -EXPORT_SYMBOL(pm_power_off); - void show_regs(struct pt_regs * regs) { unsigned long long ah, al, bh, bl, ch, cl; diff --git a/trunk/arch/sh64/mach-cayman/setup.c b/trunk/arch/sh64/mach-cayman/setup.c index 3ed87cd059d0..d84895dda3cd 100644 --- a/trunk/arch/sh64/mach-cayman/setup.c +++ b/trunk/arch/sh64/mach-cayman/setup.c @@ -112,10 +112,8 @@ struct resource io_resources[] = { }; struct resource kram_resources[] = { - /* These must be last in the array */ - { .name = "Kernel code", .start = 0, .end = 0 }, - /* These must be last in the array */ - { .name = "Kernel data", .start = 0, .end = 0 } + { "Kernel code", 0, 0 }, /* These must be last in the array */ + { "Kernel data", 0, 0 } /* These must be last in the array */ }; struct resource xram_resources[] = { diff --git a/trunk/arch/sh64/mm/ioremap.c b/trunk/arch/sh64/mm/ioremap.c index 80c56754f513..fb1866fa2c9d 100644 --- a/trunk/arch/sh64/mm/ioremap.c +++ b/trunk/arch/sh64/mm/ioremap.c @@ -449,9 +449,7 @@ ioremap_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, if (p + 32 >= e) /* Better than nothing */ break; if ((nm = r->name) == 0) nm = "???"; - p += sprintf(p, "%08lx-%08lx: %s\n", - (unsigned long)r->start, - (unsigned long)r->end, nm); + p += sprintf(p, "%08lx-%08lx: %s\n", r->start, r->end, nm); } return p-buf; diff --git a/trunk/arch/sparc/kernel/ebus.c b/trunk/arch/sparc/kernel/ebus.c index 75ac24d229b1..81c0cbd96ff0 100644 --- a/trunk/arch/sparc/kernel/ebus.c +++ b/trunk/arch/sparc/kernel/ebus.c @@ -277,7 +277,7 @@ void __init ebus_init(void) struct pci_dev *pdev; struct pcidev_cookie *cookie; struct device_node *dp; - struct resource *p; + unsigned long addr, *base; unsigned short pci_command; int len, reg, nreg; int num_ebus = 0; @@ -321,12 +321,13 @@ void __init ebus_init(void) } nreg = len / sizeof(struct linux_prom_pci_registers); - p = &ebus->self->resource[0]; + base = &ebus->self->resource[0].start; for (reg = 0; reg < nreg; reg++) { if (!(regs[reg].which_io & 0x03000000)) continue; - (p++)->start = regs[reg].phys_lo; + addr = regs[reg].phys_lo; + *base++ = addr; } ebus->ofdev.node = dp; diff --git a/trunk/arch/sparc/kernel/ioport.c b/trunk/arch/sparc/kernel/ioport.c index d33f8a07ccac..8654b446ac9e 100644 --- a/trunk/arch/sparc/kernel/ioport.c +++ b/trunk/arch/sparc/kernel/ioport.c @@ -508,7 +508,6 @@ void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *s void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) { -#ifndef CONFIG_SUN4 struct device_node *parent = dp->parent; if (sparc_cpu_model != sun4d && @@ -525,7 +524,6 @@ void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) iounit_init(dp->node, parent->node, sbus); } -#endif } void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) diff --git a/trunk/arch/sparc/kernel/setup.c b/trunk/arch/sparc/kernel/setup.c index 0251cab4708b..35488d6c7457 100644 --- a/trunk/arch/sparc/kernel/setup.c +++ b/trunk/arch/sparc/kernel/setup.c @@ -348,9 +348,9 @@ void __init setup_arch(char **cmdline_p) init_mm.context = (unsigned long) NO_CONTEXT; init_task.thread.kregs = &fake_swapper_regs; - paging_init(); - smp_setup_cpu_possible_map(); + + paging_init(); } static int __init set_preferred_console(void) diff --git a/trunk/arch/sparc/kernel/smp.c b/trunk/arch/sparc/kernel/smp.c index 276f22881d0f..e311ade1b490 100644 --- a/trunk/arch/sparc/kernel/smp.c +++ b/trunk/arch/sparc/kernel/smp.c @@ -34,6 +34,7 @@ #include #include +volatile int smp_processors_ready = 0; int smp_num_cpus = 1; volatile unsigned long cpu_callin_map[NR_CPUS] __initdata = {0,}; unsigned char boot_cpu_id = 0; diff --git a/trunk/arch/sparc/kernel/sun4d_smp.c b/trunk/arch/sparc/kernel/sun4d_smp.c index 3ff4edd32815..ba843f6a2832 100644 --- a/trunk/arch/sparc/kernel/sun4d_smp.c +++ b/trunk/arch/sparc/kernel/sun4d_smp.c @@ -42,7 +42,7 @@ extern ctxd_t *srmmu_ctx_table_phys; extern void calibrate_delay(void); -static volatile int smp_processors_ready = 0; +extern volatile int smp_processors_ready; static int smp_highest_cpu; extern volatile unsigned long cpu_callin_map[NR_CPUS]; extern cpuinfo_sparc cpu_data[NR_CPUS]; diff --git a/trunk/arch/sparc/kernel/sun4m_smp.c b/trunk/arch/sparc/kernel/sun4m_smp.c index 7d4a649138f6..3b32096134aa 100644 --- a/trunk/arch/sparc/kernel/sun4m_smp.c +++ b/trunk/arch/sparc/kernel/sun4m_smp.c @@ -39,6 +39,7 @@ extern ctxd_t *srmmu_ctx_table_phys; extern void calibrate_delay(void); +extern volatile int smp_processors_ready; extern volatile unsigned long cpu_callin_map[NR_CPUS]; extern unsigned char boot_cpu_id; @@ -216,6 +217,7 @@ void __init smp4m_smp_done(void) } /* Ok, they are spinning and ready to go. */ + smp_processors_ready = 1; } /* At each hardware IRQ, we get this called to forward IRQ reception diff --git a/trunk/arch/sparc/kernel/sys_sparc.c b/trunk/arch/sparc/kernel/sys_sparc.c index 896863fb208a..a41c8a5c2007 100644 --- a/trunk/arch/sparc/kernel/sys_sparc.c +++ b/trunk/arch/sparc/kernel/sys_sparc.c @@ -219,21 +219,6 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void __user return err; } -int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) -{ - if (ARCH_SUN4C_SUN4 && - (len > 0x20000000 || - ((flags & MAP_FIXED) && - addr < 0xe0000000 && addr + len > 0x20000000))) - return -EINVAL; - - /* See asm-sparc/uaccess.h */ - if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) - return -EINVAL; - - return 0; -} - /* Linux version of mmap */ static unsigned long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, @@ -248,13 +233,25 @@ static unsigned long do_mmap2(unsigned long addr, unsigned long len, goto out; } + retval = -EINVAL; len = PAGE_ALIGN(len); + if (ARCH_SUN4C_SUN4 && + (len > 0x20000000 || + ((flags & MAP_FIXED) && + addr < 0xe0000000 && addr + len > 0x20000000))) + goto out_putf; + + /* See asm-sparc/uaccess.h */ + if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) + goto out_putf; + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); down_write(¤t->mm->mmap_sem); retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); +out_putf: if (file) fput(file); out: @@ -470,21 +467,19 @@ asmlinkage int sys_getdomainname(char __user *name, int len) { int nlen, err; - if (len < 0) + if (len < 0 || len > __NEW_UTS_LEN) return -EINVAL; down_read(&uts_sem); nlen = strlen(system_utsname.domainname) + 1; - err = -EINVAL; - if (nlen > len) - goto out; + if (nlen < len) + len = nlen; err = -EFAULT; - if (!copy_to_user(name, system_utsname.domainname, nlen)) + if (!copy_to_user(name, system_utsname.domainname, len)) err = 0; -out: up_read(&uts_sem); return err; } diff --git a/trunk/arch/sparc/kernel/time.c b/trunk/arch/sparc/kernel/time.c index 845081b01267..04eb1eab6e3e 100644 --- a/trunk/arch/sparc/kernel/time.c +++ b/trunk/arch/sparc/kernel/time.c @@ -225,32 +225,6 @@ static __inline__ int has_low_battery(void) return (data1 == data2); /* Was the write blocked? */ } -static void __init mostek_set_system_time(void) -{ - unsigned int year, mon, day, hour, min, sec; - struct mostek48t02 *mregs; - - mregs = (struct mostek48t02 *)mstk48t02_regs; - if(!mregs) { - prom_printf("Something wrong, clock regs not mapped yet.\n"); - prom_halt(); - } - spin_lock_irq(&mostek_lock); - mregs->creg |= MSTK_CREG_READ; - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - mregs->creg &= ~MSTK_CREG_READ; - spin_unlock_irq(&mostek_lock); -} - /* Probe for the real time clock chip on Sun4 */ static __inline__ void sun4_clock_probe(void) { @@ -299,7 +273,6 @@ static __inline__ void sun4_clock_probe(void) #endif } -#ifndef CONFIG_SUN4 static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; @@ -334,8 +307,6 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) kick_start_clock(); - mostek_set_system_time(); - return 0; } @@ -354,37 +325,56 @@ static struct of_platform_driver clock_driver = { /* Probe for the mostek real time clock chip. */ -static int __init clock_init(void) +static void clock_init(void) { - return of_register_driver(&clock_driver, &of_bus_type); + of_register_driver(&clock_driver, &of_bus_type); } -/* Must be after subsys_initcall() so that busses are probed. Must - * be before device_initcall() because things like the RTC driver - * need to see the clock registers. - */ -fs_initcall(clock_init); -#endif /* !CONFIG_SUN4 */ - void __init sbus_time_init(void) { + unsigned int year, mon, day, hour, min, sec; + struct mostek48t02 *mregs; + +#ifdef CONFIG_SUN4 + int temp; + struct intersil *iregs; +#endif BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM); btfixup(); if (ARCH_SUN4) sun4_clock_probe(); + else + clock_init(); sparc_init_timers(timer_interrupt); #ifdef CONFIG_SUN4 if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) { - mostek_set_system_time(); +#endif + mregs = (struct mostek48t02 *)mstk48t02_regs; + if(!mregs) { + prom_printf("Something wrong, clock regs not mapped yet.\n"); + prom_halt(); + } + spin_lock_irq(&mostek_lock); + mregs->creg |= MSTK_CREG_READ; + sec = MSTK_REG_SEC(mregs); + min = MSTK_REG_MIN(mregs); + hour = MSTK_REG_HOUR(mregs); + day = MSTK_REG_DOM(mregs); + mon = MSTK_REG_MONTH(mregs); + year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); + mregs->creg &= ~MSTK_CREG_READ; + spin_unlock_irq(&mostek_lock); +#ifdef CONFIG_SUN4 } else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) { /* initialise the intersil on sun4 */ - unsigned int year, mon, day, hour, min, sec; - int temp; - struct intersil *iregs; iregs=intersil_clock; if(!iregs) { diff --git a/trunk/arch/sparc64/Kconfig b/trunk/arch/sparc64/Kconfig index 8d8ca716f7a7..8a36ba8868db 100644 --- a/trunk/arch/sparc64/Kconfig +++ b/trunk/arch/sparc64/Kconfig @@ -34,10 +34,6 @@ config ARCH_MAY_HAVE_PC_FDC bool default y -config AUDIT_ARCH - bool - default y - choice prompt "Kernel page size" default SPARC64_PAGE_SIZE_8KB diff --git a/trunk/arch/sparc64/defconfig b/trunk/arch/sparc64/defconfig index 51cf6027b701..43d9229fca07 100644 --- a/trunk/arch/sparc64/defconfig +++ b/trunk/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18 -# Sat Sep 23 18:32:19 2006 +# Linux kernel version: 2.6.18-rc2 +# Fri Jul 21 14:19:24 2006 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -9,7 +9,6 @@ CONFIG_64BIT=y CONFIG_MMU=y CONFIG_TIME_INTERPOLATION=y CONFIG_ARCH_MAY_HAVE_PC_FDC=y -CONFIG_AUDIT_ARCH=y CONFIG_SPARC64_PAGE_SIZE_8KB=y # CONFIG_SPARC64_PAGE_SIZE_64KB is not set # CONFIG_SPARC64_PAGE_SIZE_512KB is not set @@ -38,14 +37,14 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set +CONFIG_SYSCTL=y # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set CONFIG_RELAY=y CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set -CONFIG_UID16=y -CONFIG_SYSCTL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -54,12 +53,12 @@ CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y CONFIG_SLAB=y CONFIG_VM_EVENT_COUNTERS=y -CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -170,7 +169,6 @@ CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y CONFIG_XFRM_USER=m -# CONFIG_XFRM_SUB_POLICY is not set CONFIG_NET_KEY=m CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -216,15 +214,11 @@ CONFIG_IPV6_ROUTE_INFO=y CONFIG_INET6_AH=m CONFIG_INET6_ESP=m CONFIG_INET6_IPCOMP=m -# CONFIG_IPV6_MIP6 is not set CONFIG_INET6_XFRM_TUNNEL=m CONFIG_INET6_TUNNEL=m CONFIG_INET6_XFRM_MODE_TRANSPORT=m CONFIG_INET6_XFRM_MODE_TUNNEL=m -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set CONFIG_IPV6_TUNNEL=m -# CONFIG_IPV6_SUBTREES is not set -# CONFIG_IPV6_MULTIPLE_TABLES is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set @@ -239,7 +233,6 @@ CONFIG_IP_DCCP_ACKVEC=y # DCCP CCIDs Configuration (EXPERIMENTAL) # CONFIG_IP_DCCP_CCID2=m -# CONFIG_IP_DCCP_CCID2_DEBUG is not set CONFIG_IP_DCCP_CCID3=m CONFIG_IP_DCCP_TFRC_LIB=m @@ -266,6 +259,7 @@ CONFIG_VLAN_8021Q=m # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -1392,10 +1386,6 @@ CONFIG_KEYS=y # Cryptographic options # CONFIG_CRYPTO=y -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_MANAGER=m CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_MD4=y @@ -1405,12 +1395,9 @@ CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m CONFIG_CRYPTO_WP512=m CONFIG_CRYPTO_TGR192=m -CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_TWOFISH_COMMON=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m diff --git a/trunk/arch/sparc64/kernel/Makefile b/trunk/arch/sparc64/kernel/Makefile index e1eabebaed39..86c9fe3f3e4a 100644 --- a/trunk/arch/sparc64/kernel/Makefile +++ b/trunk/arch/sparc64/kernel/Makefile @@ -25,9 +25,6 @@ obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o obj-$(CONFIG_KPROBES) += kprobes.o -obj-$(CONFIG_AUDIT) += audit.o -obj-$(CONFIG_AUDIT)$(CONFIG_SPARC32_COMPAT) += compat_audit.o -obj-y += $(obj-yy) ifdef CONFIG_SUNOS_EMUL obj-y += sys_sunos32.o sunos_ioctl32.o diff --git a/trunk/arch/sparc64/kernel/audit.c b/trunk/arch/sparc64/kernel/audit.c deleted file mode 100644 index aef19cc27072..000000000000 --- a/trunk/arch/sparc64/kernel/audit.c +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include -#include - -static unsigned dir_class[] = { -#include -~0U -}; - -static unsigned read_class[] = { -#include -~0U -}; - -static unsigned write_class[] = { -#include -~0U -}; - -static unsigned chattr_class[] = { -#include -~0U -}; - -int audit_classify_syscall(int abi, unsigned syscall) -{ -#ifdef CONFIG_SPARC32_COMPAT - extern int sparc32_classify_syscall(unsigned); - if (abi == AUDIT_ARCH_SPARC) - return sparc32_classify_syscall(syscall); -#endif - switch(syscall) { - case __NR_open: - return 2; - case __NR_openat: - return 3; - case __NR_socketcall: - return 4; - case __NR_execve: - return 5; - default: - return 0; - } -} - -static int __init audit_classes_init(void) -{ -#ifdef CONFIG_SPARC32_COMPAT - extern __u32 sparc32_dir_class[]; - extern __u32 sparc32_write_class[]; - extern __u32 sparc32_read_class[]; - extern __u32 sparc32_chattr_class[]; - audit_register_class(AUDIT_CLASS_WRITE_32, sparc32_write_class); - audit_register_class(AUDIT_CLASS_READ_32, sparc32_read_class); - audit_register_class(AUDIT_CLASS_DIR_WRITE_32, sparc32_dir_class); - audit_register_class(AUDIT_CLASS_CHATTR_32, sparc32_chattr_class); -#endif - audit_register_class(AUDIT_CLASS_WRITE, write_class); - audit_register_class(AUDIT_CLASS_READ, read_class); - audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); - audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); - return 0; -} - -__initcall(audit_classes_init); diff --git a/trunk/arch/sparc64/kernel/compat_audit.c b/trunk/arch/sparc64/kernel/compat_audit.c deleted file mode 100644 index cca96c91b780..000000000000 --- a/trunk/arch/sparc64/kernel/compat_audit.c +++ /dev/null @@ -1,37 +0,0 @@ -#include - -unsigned sparc32_dir_class[] = { -#include -~0U -}; - -unsigned sparc32_chattr_class[] = { -#include -~0U -}; - -unsigned sparc32_write_class[] = { -#include -~0U -}; - -unsigned sparc32_read_class[] = { -#include -~0U -}; - -int sparc32_classify_syscall(unsigned syscall) -{ - switch(syscall) { - case __NR_open: - return 2; - case __NR_openat: - return 3; - case __NR_socketcall: - return 4; - case __NR_execve: - return 5; - default: - return 1; - } -} diff --git a/trunk/arch/sparc64/kernel/sys_sparc.c b/trunk/arch/sparc64/kernel/sys_sparc.c index c608c947e6c3..054d0abdb7ee 100644 --- a/trunk/arch/sparc64/kernel/sys_sparc.c +++ b/trunk/arch/sparc64/kernel/sys_sparc.c @@ -548,26 +548,6 @@ asmlinkage long sparc64_personality(unsigned long personality) return ret; } -int sparc64_mmap_check(unsigned long addr, unsigned long len, - unsigned long flags) -{ - if (test_thread_flag(TIF_32BIT)) { - if (len >= STACK_TOP32) - return -EINVAL; - - if ((flags & MAP_FIXED) && addr > STACK_TOP32 - len) - return -EINVAL; - } else { - if (len >= VA_EXCLUDE_START) - return -EINVAL; - - if ((flags & MAP_FIXED) && invalid_64bit_range(addr, len)) - return -EINVAL; - } - - return 0; -} - /* Linux version of mmap */ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, @@ -583,11 +563,27 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, } flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); len = PAGE_ALIGN(len); + retval = -EINVAL; + + if (test_thread_flag(TIF_32BIT)) { + if (len >= STACK_TOP32) + goto out_putf; + + if ((flags & MAP_FIXED) && addr > STACK_TOP32 - len) + goto out_putf; + } else { + if (len >= VA_EXCLUDE_START) + goto out_putf; + + if ((flags & MAP_FIXED) && invalid_64bit_range(addr, len)) + goto out_putf; + } down_write(¤t->mm->mmap_sem); retval = do_mmap(file, addr, len, prot, flags, off); up_write(¤t->mm->mmap_sem); +out_putf: if (file) fput(file); out: @@ -707,21 +703,19 @@ asmlinkage long sys_getdomainname(char __user *name, int len) { int nlen, err; - if (len < 0) + if (len < 0 || len > __NEW_UTS_LEN) return -EINVAL; down_read(&uts_sem); nlen = strlen(system_utsname.domainname) + 1; - err = -EINVAL; - if (nlen > len) - goto out; + if (nlen < len) + len = nlen; err = -EFAULT; - if (!copy_to_user(name, system_utsname.domainname, nlen)) + if (!copy_to_user(name, system_utsname.domainname, len)) err = 0; -out: up_read(&uts_sem); return err; } diff --git a/trunk/arch/sparc64/kernel/time.c b/trunk/arch/sparc64/kernel/time.c index b0b4feeec098..094d3e35be18 100644 --- a/trunk/arch/sparc64/kernel/time.c +++ b/trunk/arch/sparc64/kernel/time.c @@ -983,7 +983,7 @@ static struct time_interpolator sparc64_cpu_interpolator = { }; /* The quotient formula is taken from the IA64 port. */ -#define SPARC64_NSEC_PER_CYC_SHIFT 10UL +#define SPARC64_NSEC_PER_CYC_SHIFT 30UL void __init time_init(void) { unsigned long clock = sparc64_init_timers(); diff --git a/trunk/arch/sparc64/mm/generic.c b/trunk/arch/sparc64/mm/generic.c index af9d81db0b38..8cb06205d265 100644 --- a/trunk/arch/sparc64/mm/generic.c +++ b/trunk/arch/sparc64/mm/generic.c @@ -69,8 +69,6 @@ static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, } else offset += PAGE_SIZE; - if (pte_write(entry)) - entry = pte_mkdirty(entry); do { BUG_ON(!pte_none(*pte)); set_pte_at(mm, address, pte, entry); diff --git a/trunk/arch/um/kernel/dyn.lds.S b/trunk/arch/um/kernel/dyn.lds.S index 68ed24df5c8f..2517ecb8bf27 100644 --- a/trunk/arch/um/kernel/dyn.lds.S +++ b/trunk/arch/um/kernel/dyn.lds.S @@ -26,7 +26,6 @@ SECTIONS /* Read-only sections, merged into text segment: */ .hash : { *(.hash) } - .gnu.hash : { *(.gnu.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .gnu.version : { *(.gnu.version) } diff --git a/trunk/arch/v850/kernel/setup.c b/trunk/arch/v850/kernel/setup.c index 1bf672a25692..62bdb8d29fc0 100644 --- a/trunk/arch/v850/kernel/setup.c +++ b/trunk/arch/v850/kernel/setup.c @@ -1,8 +1,8 @@ /* * arch/v850/kernel/setup.c -- Arch-dependent initialization functions * - * Copyright (C) 2001,02,03,05,06 NEC Electronics Corporation - * Copyright (C) 2001,02,03,05,06 Miles Bader + * Copyright (C) 2001,02,03,05 NEC Electronics Corporation + * Copyright (C) 2001,02,03,05 Miles Bader * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this @@ -190,7 +190,7 @@ void free_initmem (void) for (addr = start; addr < end; addr += PAGE_SIZE) { struct page *page = virt_to_page (addr); ClearPageReserved (page); - init_page_count (page); + set_page_count (page, 1); __free_page (page); total_ram_pages++; } diff --git a/trunk/arch/v850/kernel/v850_ksyms.c b/trunk/arch/v850/kernel/v850_ksyms.c index 67bc48e57c60..c03ad6ed61cc 100644 --- a/trunk/arch/v850/kernel/v850_ksyms.c +++ b/trunk/arch/v850/kernel/v850_ksyms.c @@ -21,6 +21,9 @@ EXPORT_SYMBOL (trap_table); /* platform dependent support */ EXPORT_SYMBOL (kernel_thread); +EXPORT_SYMBOL (enable_irq); +EXPORT_SYMBOL (disable_irq); +EXPORT_SYMBOL (disable_irq_nosync); EXPORT_SYMBOL (__bug); /* Networking helper routines. */ @@ -30,9 +33,22 @@ EXPORT_SYMBOL (ip_compute_csum); EXPORT_SYMBOL (ip_fast_csum); /* string / mem functions */ +EXPORT_SYMBOL (strcpy); +EXPORT_SYMBOL (strncpy); +EXPORT_SYMBOL (strcat); +EXPORT_SYMBOL (strncat); +EXPORT_SYMBOL (strcmp); +EXPORT_SYMBOL (strncmp); +EXPORT_SYMBOL (strchr); +EXPORT_SYMBOL (strlen); +EXPORT_SYMBOL (strnlen); +EXPORT_SYMBOL (strrchr); +EXPORT_SYMBOL (strstr); EXPORT_SYMBOL (memset); EXPORT_SYMBOL (memcpy); EXPORT_SYMBOL (memmove); +EXPORT_SYMBOL (memcmp); +EXPORT_SYMBOL (memscan); /* semaphores */ EXPORT_SYMBOL (__down); diff --git a/trunk/arch/x86_64/Kconfig b/trunk/arch/x86_64/Kconfig index 6cd4878625f1..28df7d88ce2c 100644 --- a/trunk/arch/x86_64/Kconfig +++ b/trunk/arch/x86_64/Kconfig @@ -85,10 +85,6 @@ config DMI bool default y -config AUDIT_ARCH - bool - default y - source "init/Kconfig" diff --git a/trunk/arch/x86_64/crypto/Makefile b/trunk/arch/x86_64/crypto/Makefile index 15b538a8b7f7..426d20f4b72e 100644 --- a/trunk/arch/x86_64/crypto/Makefile +++ b/trunk/arch/x86_64/crypto/Makefile @@ -5,8 +5,5 @@ # obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o -obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o aes-x86_64-y := aes-x86_64-asm.o aes.o -twofish-x86_64-y := twofish-x86_64-asm.o twofish.o - diff --git a/trunk/arch/x86_64/crypto/aes.c b/trunk/arch/x86_64/crypto/aes.c index 5cdb13ea5cc2..68866fab37aa 100644 --- a/trunk/arch/x86_64/crypto/aes.c +++ b/trunk/arch/x86_64/crypto/aes.c @@ -228,14 +228,13 @@ static void __init gen_tabs(void) } static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) + unsigned int key_len, u32 *flags) { struct aes_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *key = (const __le32 *)in_key; - u32 *flags = &tfm->crt_flags; u32 i, j, t, u, v, w; - if (key_len % 8) { + if (key_len != 16 && key_len != 24 && key_len != 32) { *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } diff --git a/trunk/arch/x86_64/crypto/twofish-x86_64-asm.S b/trunk/arch/x86_64/crypto/twofish-x86_64-asm.S deleted file mode 100644 index 35974a586615..000000000000 --- a/trunk/arch/x86_64/crypto/twofish-x86_64-asm.S +++ /dev/null @@ -1,324 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2006 by Joachim Fritschi, * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ - -.file "twofish-x86_64-asm.S" -.text - -#include - -#define a_offset 0 -#define b_offset 4 -#define c_offset 8 -#define d_offset 12 - -/* Structure of the crypto context struct*/ - -#define s0 0 /* S0 Array 256 Words each */ -#define s1 1024 /* S1 Array */ -#define s2 2048 /* S2 Array */ -#define s3 3072 /* S3 Array */ -#define w 4096 /* 8 whitening keys (word) */ -#define k 4128 /* key 1-32 ( word ) */ - -/* define a few register aliases to allow macro substitution */ - -#define R0 %rax -#define R0D %eax -#define R0B %al -#define R0H %ah - -#define R1 %rbx -#define R1D %ebx -#define R1B %bl -#define R1H %bh - -#define R2 %rcx -#define R2D %ecx -#define R2B %cl -#define R2H %ch - -#define R3 %rdx -#define R3D %edx -#define R3B %dl -#define R3H %dh - - -/* performs input whitening */ -#define input_whitening(src,context,offset)\ - xor w+offset(context), src; - -/* performs input whitening */ -#define output_whitening(src,context,offset)\ - xor w+16+offset(context), src; - - -/* - * a input register containing a (rotated 16) - * b input register containing b - * c input register containing c - * d input register containing d (already rol $1) - * operations on a and b are interleaved to increase performance - */ -#define encrypt_round(a,b,c,d,round)\ - movzx b ## B, %edi;\ - mov s1(%r11,%rdi,4),%r8d;\ - movzx a ## B, %edi;\ - mov s2(%r11,%rdi,4),%r9d;\ - movzx b ## H, %edi;\ - ror $16, b ## D;\ - xor s2(%r11,%rdi,4),%r8d;\ - movzx a ## H, %edi;\ - ror $16, a ## D;\ - xor s3(%r11,%rdi,4),%r9d;\ - movzx b ## B, %edi;\ - xor s3(%r11,%rdi,4),%r8d;\ - movzx a ## B, %edi;\ - xor (%r11,%rdi,4), %r9d;\ - movzx b ## H, %edi;\ - ror $15, b ## D;\ - xor (%r11,%rdi,4), %r8d;\ - movzx a ## H, %edi;\ - xor s1(%r11,%rdi,4),%r9d;\ - add %r8d, %r9d;\ - add %r9d, %r8d;\ - add k+round(%r11), %r9d;\ - xor %r9d, c ## D;\ - rol $15, c ## D;\ - add k+4+round(%r11),%r8d;\ - xor %r8d, d ## D; - -/* - * a input register containing a(rotated 16) - * b input register containing b - * c input register containing c - * d input register containing d (already rol $1) - * operations on a and b are interleaved to increase performance - * during the round a and b are prepared for the output whitening - */ -#define encrypt_last_round(a,b,c,d,round)\ - mov b ## D, %r10d;\ - shl $32, %r10;\ - movzx b ## B, %edi;\ - mov s1(%r11,%rdi,4),%r8d;\ - movzx a ## B, %edi;\ - mov s2(%r11,%rdi,4),%r9d;\ - movzx b ## H, %edi;\ - ror $16, b ## D;\ - xor s2(%r11,%rdi,4),%r8d;\ - movzx a ## H, %edi;\ - ror $16, a ## D;\ - xor s3(%r11,%rdi,4),%r9d;\ - movzx b ## B, %edi;\ - xor s3(%r11,%rdi,4),%r8d;\ - movzx a ## B, %edi;\ - xor (%r11,%rdi,4), %r9d;\ - xor a, %r10;\ - movzx b ## H, %edi;\ - xor (%r11,%rdi,4), %r8d;\ - movzx a ## H, %edi;\ - xor s1(%r11,%rdi,4),%r9d;\ - add %r8d, %r9d;\ - add %r9d, %r8d;\ - add k+round(%r11), %r9d;\ - xor %r9d, c ## D;\ - ror $1, c ## D;\ - add k+4+round(%r11),%r8d;\ - xor %r8d, d ## D - -/* - * a input register containing a - * b input register containing b (rotated 16) - * c input register containing c (already rol $1) - * d input register containing d - * operations on a and b are interleaved to increase performance - */ -#define decrypt_round(a,b,c,d,round)\ - movzx a ## B, %edi;\ - mov (%r11,%rdi,4), %r9d;\ - movzx b ## B, %edi;\ - mov s3(%r11,%rdi,4),%r8d;\ - movzx a ## H, %edi;\ - ror $16, a ## D;\ - xor s1(%r11,%rdi,4),%r9d;\ - movzx b ## H, %edi;\ - ror $16, b ## D;\ - xor (%r11,%rdi,4), %r8d;\ - movzx a ## B, %edi;\ - xor s2(%r11,%rdi,4),%r9d;\ - movzx b ## B, %edi;\ - xor s1(%r11,%rdi,4),%r8d;\ - movzx a ## H, %edi;\ - ror $15, a ## D;\ - xor s3(%r11,%rdi,4),%r9d;\ - movzx b ## H, %edi;\ - xor s2(%r11,%rdi,4),%r8d;\ - add %r8d, %r9d;\ - add %r9d, %r8d;\ - add k+round(%r11), %r9d;\ - xor %r9d, c ## D;\ - add k+4+round(%r11),%r8d;\ - xor %r8d, d ## D;\ - rol $15, d ## D; - -/* - * a input register containing a - * b input register containing b - * c input register containing c (already rol $1) - * d input register containing d - * operations on a and b are interleaved to increase performance - * during the round a and b are prepared for the output whitening - */ -#define decrypt_last_round(a,b,c,d,round)\ - movzx a ## B, %edi;\ - mov (%r11,%rdi,4), %r9d;\ - movzx b ## B, %edi;\ - mov s3(%r11,%rdi,4),%r8d;\ - movzx b ## H, %edi;\ - ror $16, b ## D;\ - xor (%r11,%rdi,4), %r8d;\ - movzx a ## H, %edi;\ - mov b ## D, %r10d;\ - shl $32, %r10;\ - xor a, %r10;\ - ror $16, a ## D;\ - xor s1(%r11,%rdi,4),%r9d;\ - movzx b ## B, %edi;\ - xor s1(%r11,%rdi,4),%r8d;\ - movzx a ## B, %edi;\ - xor s2(%r11,%rdi,4),%r9d;\ - movzx b ## H, %edi;\ - xor s2(%r11,%rdi,4),%r8d;\ - movzx a ## H, %edi;\ - xor s3(%r11,%rdi,4),%r9d;\ - add %r8d, %r9d;\ - add %r9d, %r8d;\ - add k+round(%r11), %r9d;\ - xor %r9d, c ## D;\ - add k+4+round(%r11),%r8d;\ - xor %r8d, d ## D;\ - ror $1, d ## D; - -.align 8 -.global twofish_enc_blk -.global twofish_dec_blk - -twofish_enc_blk: - pushq R1 - - /* %rdi contains the crypto tfm adress */ - /* %rsi contains the output adress */ - /* %rdx contains the input adress */ - add $crypto_tfm_ctx_offset, %rdi /* set ctx adress */ - /* ctx adress is moved to free one non-rex register - as target for the 8bit high operations */ - mov %rdi, %r11 - - movq (R3), R1 - movq 8(R3), R3 - input_whitening(R1,%r11,a_offset) - input_whitening(R3,%r11,c_offset) - mov R1D, R0D - rol $16, R0D - shr $32, R1 - mov R3D, R2D - shr $32, R3 - rol $1, R3D - - encrypt_round(R0,R1,R2,R3,0); - encrypt_round(R2,R3,R0,R1,8); - encrypt_round(R0,R1,R2,R3,2*8); - encrypt_round(R2,R3,R0,R1,3*8); - encrypt_round(R0,R1,R2,R3,4*8); - encrypt_round(R2,R3,R0,R1,5*8); - encrypt_round(R0,R1,R2,R3,6*8); - encrypt_round(R2,R3,R0,R1,7*8); - encrypt_round(R0,R1,R2,R3,8*8); - encrypt_round(R2,R3,R0,R1,9*8); - encrypt_round(R0,R1,R2,R3,10*8); - encrypt_round(R2,R3,R0,R1,11*8); - encrypt_round(R0,R1,R2,R3,12*8); - encrypt_round(R2,R3,R0,R1,13*8); - encrypt_round(R0,R1,R2,R3,14*8); - encrypt_last_round(R2,R3,R0,R1,15*8); - - - output_whitening(%r10,%r11,a_offset) - movq %r10, (%rsi) - - shl $32, R1 - xor R0, R1 - - output_whitening(R1,%r11,c_offset) - movq R1, 8(%rsi) - - popq R1 - movq $1,%rax - ret - -twofish_dec_blk: - pushq R1 - - /* %rdi contains the crypto tfm adress */ - /* %rsi contains the output adress */ - /* %rdx contains the input adress */ - add $crypto_tfm_ctx_offset, %rdi /* set ctx adress */ - /* ctx adress is moved to free one non-rex register - as target for the 8bit high operations */ - mov %rdi, %r11 - - movq (R3), R1 - movq 8(R3), R3 - output_whitening(R1,%r11,a_offset) - output_whitening(R3,%r11,c_offset) - mov R1D, R0D - shr $32, R1 - rol $16, R1D - mov R3D, R2D - shr $32, R3 - rol $1, R2D - - decrypt_round(R0,R1,R2,R3,15*8); - decrypt_round(R2,R3,R0,R1,14*8); - decrypt_round(R0,R1,R2,R3,13*8); - decrypt_round(R2,R3,R0,R1,12*8); - decrypt_round(R0,R1,R2,R3,11*8); - decrypt_round(R2,R3,R0,R1,10*8); - decrypt_round(R0,R1,R2,R3,9*8); - decrypt_round(R2,R3,R0,R1,8*8); - decrypt_round(R0,R1,R2,R3,7*8); - decrypt_round(R2,R3,R0,R1,6*8); - decrypt_round(R0,R1,R2,R3,5*8); - decrypt_round(R2,R3,R0,R1,4*8); - decrypt_round(R0,R1,R2,R3,3*8); - decrypt_round(R2,R3,R0,R1,2*8); - decrypt_round(R0,R1,R2,R3,1*8); - decrypt_last_round(R2,R3,R0,R1,0); - - input_whitening(%r10,%r11,a_offset) - movq %r10, (%rsi) - - shl $32, R1 - xor R0, R1 - - input_whitening(R1,%r11,c_offset) - movq R1, 8(%rsi) - - popq R1 - movq $1,%rax - ret diff --git a/trunk/arch/x86_64/crypto/twofish.c b/trunk/arch/x86_64/crypto/twofish.c deleted file mode 100644 index 182d91d5cfb9..000000000000 --- a/trunk/arch/x86_64/crypto/twofish.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Glue Code for optimized x86_64 assembler version of TWOFISH - * - * Originally Twofish for GPG - * By Matthew Skala , July 26, 1998 - * 256-bit key length added March 20, 1999 - * Some modifications to reduce the text size by Werner Koch, April, 1998 - * Ported to the kerneli patch by Marc Mutz - * Ported to CryptoAPI by Colin Slater - * - * The original author has disclaimed all copyright interest in this - * code and thus put it in the public domain. The subsequent authors - * have put this under the GNU General Public License. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * This code is a "clean room" implementation, written from the paper - * _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey, - * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available - * through http://www.counterpane.com/twofish.html - * - * For background information on multiplication in finite fields, used for - * the matrix operations in the key schedule, see the book _Contemporary - * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the - * Third Edition. - */ - -#include -#include -#include -#include -#include -#include - -asmlinkage void twofish_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src); -asmlinkage void twofish_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src); - -static void twofish_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) -{ - twofish_enc_blk(tfm, dst, src); -} - -static void twofish_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) -{ - twofish_dec_blk(tfm, dst, src); -} - -static struct crypto_alg alg = { - .cra_name = "twofish", - .cra_driver_name = "twofish-x86_64", - .cra_priority = 200, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = TF_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct twofish_ctx), - .cra_alignmask = 3, - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(alg.cra_list), - .cra_u = { - .cipher = { - .cia_min_keysize = TF_MIN_KEY_SIZE, - .cia_max_keysize = TF_MAX_KEY_SIZE, - .cia_setkey = twofish_setkey, - .cia_encrypt = twofish_encrypt, - .cia_decrypt = twofish_decrypt - } - } -}; - -static int __init init(void) -{ - return crypto_register_alg(&alg); -} - -static void __exit fini(void) -{ - crypto_unregister_alg(&alg); -} - -module_init(init); -module_exit(fini); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION ("Twofish Cipher Algorithm, x86_64 asm optimized"); -MODULE_ALIAS("twofish"); diff --git a/trunk/arch/x86_64/defconfig b/trunk/arch/x86_64/defconfig index 5fb970715941..83d389b8ebd8 100644 --- a/trunk/arch/x86_64/defconfig +++ b/trunk/arch/x86_64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.18-rc4 -# Thu Aug 24 21:05:55 2006 +# Linux kernel version: 2.6.17-git22 +# Tue Jul 4 14:24:40 2006 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -37,7 +37,6 @@ CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_TASKSTATS is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y @@ -201,7 +200,7 @@ CONFIG_ACPI_THERMAL=y CONFIG_ACPI_NUMA=y # CONFIG_ACPI_ASUS is not set # CONFIG_ACPI_IBM is not set -# CONFIG_ACPI_TOSHIBA is not set +CONFIG_ACPI_TOSHIBA=y CONFIG_ACPI_BLACKLIST_YEAR=0 # CONFIG_ACPI_DEBUG is not set CONFIG_ACPI_EC=y @@ -216,7 +215,7 @@ CONFIG_ACPI_CONTAINER=y # CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_TABLE=y -CONFIG_CPU_FREQ_DEBUG=y +# CONFIG_CPU_FREQ_DEBUG is not set CONFIG_CPU_FREQ_STAT=y # CONFIG_CPU_FREQ_STAT_DETAILS is not set CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y @@ -414,7 +413,6 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -495,9 +493,8 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_CHR_DEV_SG=y +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set # CONFIG_CHR_DEV_SCH is not set # @@ -513,7 +510,7 @@ CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_SPI_ATTRS=y CONFIG_SCSI_FC_ATTRS=y # CONFIG_SCSI_ISCSI_ATTRS is not set -CONFIG_SCSI_SAS_ATTRS=y +# CONFIG_SCSI_SAS_ATTRS is not set # # SCSI low-level drivers @@ -539,7 +536,7 @@ CONFIG_MEGARAID_MAILBOX=y CONFIG_MEGARAID_SAS=y CONFIG_SCSI_SATA=y CONFIG_SCSI_SATA_AHCI=y -CONFIG_SCSI_SATA_SVW=y +# CONFIG_SCSI_SATA_SVW is not set CONFIG_SCSI_ATA_PIIX=y # CONFIG_SCSI_SATA_MV is not set CONFIG_SCSI_SATA_NV=y @@ -590,7 +587,7 @@ CONFIG_BLK_DEV_DM=y CONFIG_FUSION=y CONFIG_FUSION_SPI=y # CONFIG_FUSION_FC is not set -CONFIG_FUSION_SAS=y +# CONFIG_FUSION_SAS is not set CONFIG_FUSION_MAX_SGE=128 # CONFIG_FUSION_CTL is not set @@ -676,7 +673,7 @@ CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set -CONFIG_B44=y +# CONFIG_B44 is not set CONFIG_FORCEDETH=y # CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set @@ -713,7 +710,7 @@ CONFIG_E1000=y # CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y -CONFIG_BNX2=y +# CONFIG_BNX2 is not set # # Ethernet (10000 Mbit) @@ -843,7 +840,44 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Watchdog Cards # -# CONFIG_WATCHDOG is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=y +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_ALIM1535_WDT is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_IBMASR is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_I6300ESB_WDT is not set +# CONFIG_I8XX_TCO is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +# CONFIG_W83627HF_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_W83977F_WDT is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_SBC_EPX_C3_WATCHDOG is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_INTEL=y CONFIG_HW_RANDOM_AMD=y @@ -1020,7 +1054,6 @@ CONFIG_VGACON_SOFT_SCROLLBACK=y CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=256 CONFIG_VIDEO_SELECT=y CONFIG_DUMMY_CONSOLE=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound @@ -1162,7 +1195,7 @@ CONFIG_USB_MON=y # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set -# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set @@ -1266,7 +1299,7 @@ CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y # CONFIG_FUSE_FS is not set @@ -1340,6 +1373,7 @@ CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set +# CONFIG_CIFS_DEBUG2 is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set @@ -1459,5 +1493,4 @@ CONFIG_DEBUG_STACKOVERFLOW=y # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set -CONFIG_ZLIB_INFLATE=y CONFIG_PLIST=y diff --git a/trunk/arch/x86_64/ia32/Makefile b/trunk/arch/x86_64/ia32/Makefile index cdae36435e21..62bc5f56da9e 100644 --- a/trunk/arch/x86_64/ia32/Makefile +++ b/trunk/arch/x86_64/ia32/Makefile @@ -23,7 +23,6 @@ targets := $(foreach F,sysenter syscall,vsyscall-$F.o vsyscall-$F.so) # The DSO images are built using a special linker script quiet_cmd_syscall = SYSCALL $@ cmd_syscall = $(CC) -m32 -nostdlib -shared -s \ - $(call ld-option, -Wl$(comma)--hash-style=sysv) \ -Wl,-soname=linux-gate.so.1 -o $@ \ -Wl,-T,$(filter-out FORCE,$^) diff --git a/trunk/arch/x86_64/ia32/audit.c b/trunk/arch/x86_64/ia32/audit.c index 92d7d0c8d93f..ab94f2e58cdd 100644 --- a/trunk/arch/x86_64/ia32/audit.c +++ b/trunk/arch/x86_64/ia32/audit.c @@ -9,29 +9,3 @@ unsigned ia32_chattr_class[] = { #include ~0U }; - -unsigned ia32_write_class[] = { -#include -~0U -}; - -unsigned ia32_read_class[] = { -#include -~0U -}; - -int ia32_classify_syscall(unsigned syscall) -{ - switch(syscall) { - case __NR_open: - return 2; - case __NR_openat: - return 3; - case __NR_socketcall: - return 4; - case __NR_execve: - return 5; - default: - return 1; - } -} diff --git a/trunk/arch/x86_64/ia32/ia32_binfmt.c b/trunk/arch/x86_64/ia32/ia32_binfmt.c index 2fd5a67fd435..a9dc0f3b5b51 100644 --- a/trunk/arch/x86_64/ia32/ia32_binfmt.c +++ b/trunk/arch/x86_64/ia32/ia32_binfmt.c @@ -73,44 +73,39 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; * Dumping its extra ELF program headers includes all the other information * a debugger needs to easily find how the vsyscall DSO was being used. */ -#define ELF_CORE_EXTRA_PHDRS (find_vma(current->mm, VSYSCALL32_BASE) ? \ - (VSYSCALL32_EHDR->e_phnum) : 0) +#define ELF_CORE_EXTRA_PHDRS (VSYSCALL32_EHDR->e_phnum) #define ELF_CORE_WRITE_EXTRA_PHDRS \ do { \ - if (find_vma(current->mm, VSYSCALL32_BASE)) { \ - const struct elf32_phdr *const vsyscall_phdrs = \ - (const struct elf32_phdr *) (VSYSCALL32_BASE \ - + VSYSCALL32_EHDR->e_phoff);\ - int i; \ - Elf32_Off ofs = 0; \ - for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ - struct elf32_phdr phdr = vsyscall_phdrs[i]; \ - if (phdr.p_type == PT_LOAD) { \ - BUG_ON(ofs != 0); \ - ofs = phdr.p_offset = offset; \ - phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \ - phdr.p_filesz = phdr.p_memsz; \ - offset += phdr.p_filesz; \ - } \ - else \ - phdr.p_offset += ofs; \ - phdr.p_paddr = 0; /* match other core phdrs */ \ - DUMP_WRITE(&phdr, sizeof(phdr)); \ + const struct elf32_phdr *const vsyscall_phdrs = \ + (const struct elf32_phdr *) (VSYSCALL32_BASE \ + + VSYSCALL32_EHDR->e_phoff); \ + int i; \ + Elf32_Off ofs = 0; \ + for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ + struct elf32_phdr phdr = vsyscall_phdrs[i]; \ + if (phdr.p_type == PT_LOAD) { \ + BUG_ON(ofs != 0); \ + ofs = phdr.p_offset = offset; \ + phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \ + phdr.p_filesz = phdr.p_memsz; \ + offset += phdr.p_filesz; \ } \ + else \ + phdr.p_offset += ofs; \ + phdr.p_paddr = 0; /* match other core phdrs */ \ + DUMP_WRITE(&phdr, sizeof(phdr)); \ } \ } while (0) #define ELF_CORE_WRITE_EXTRA_DATA \ do { \ - if (find_vma(current->mm, VSYSCALL32_BASE)) { \ - const struct elf32_phdr *const vsyscall_phdrs = \ - (const struct elf32_phdr *) (VSYSCALL32_BASE \ - + VSYSCALL32_EHDR->e_phoff); \ - int i; \ - for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ - if (vsyscall_phdrs[i].p_type == PT_LOAD) \ - DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr,\ - PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \ - } \ + const struct elf32_phdr *const vsyscall_phdrs = \ + (const struct elf32_phdr *) (VSYSCALL32_BASE \ + + VSYSCALL32_EHDR->e_phoff); \ + int i; \ + for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ + if (vsyscall_phdrs[i].p_type == PT_LOAD) \ + DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr, \ + PAGE_ALIGN(vsyscall_phdrs[i].p_memsz)); \ } \ } while (0) diff --git a/trunk/arch/x86_64/ia32/ia32entry.S b/trunk/arch/x86_64/ia32/ia32entry.S index 5d4a7d125ed0..9b5bb413a6e9 100644 --- a/trunk/arch/x86_64/ia32/ia32entry.S +++ b/trunk/arch/x86_64/ia32/ia32entry.S @@ -103,7 +103,7 @@ ENTRY(ia32_sysenter_target) pushq %rax CFI_ADJUST_CFA_OFFSET 8 cld - SAVE_ARGS 0,0,0 + SAVE_ARGS 0,0,1 /* no need to do an access_ok check here because rbp has been 32bit zero extended */ 1: movl (%rbp),%r9d diff --git a/trunk/arch/x86_64/ia32/vsyscall.lds b/trunk/arch/x86_64/ia32/vsyscall.lds index 1dc86ff5bcb9..f2e75ed4c6c7 100644 --- a/trunk/arch/x86_64/ia32/vsyscall.lds +++ b/trunk/arch/x86_64/ia32/vsyscall.lds @@ -11,7 +11,6 @@ SECTIONS . = VSYSCALL_BASE + SIZEOF_HEADERS; .hash : { *(.hash) } :text - .gnu.hash : { *(.gnu.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .gnu.version : { *(.gnu.version) } diff --git a/trunk/arch/x86_64/kernel/audit.c b/trunk/arch/x86_64/kernel/audit.c index 21f33387bef3..a067aa468a85 100644 --- a/trunk/arch/x86_64/kernel/audit.c +++ b/trunk/arch/x86_64/kernel/audit.c @@ -8,54 +8,19 @@ static unsigned dir_class[] = { ~0U }; -static unsigned read_class[] = { -#include -~0U -}; - -static unsigned write_class[] = { -#include -~0U -}; - static unsigned chattr_class[] = { #include ~0U }; -int audit_classify_syscall(int abi, unsigned syscall) -{ -#ifdef CONFIG_IA32_EMULATION - extern int ia32_classify_syscall(unsigned); - if (abi == AUDIT_ARCH_I386) - return ia32_classify_syscall(syscall); -#endif - switch(syscall) { - case __NR_open: - return 2; - case __NR_openat: - return 3; - case __NR_execve: - return 5; - default: - return 0; - } -} - static int __init audit_classes_init(void) { #ifdef CONFIG_IA32_EMULATION extern __u32 ia32_dir_class[]; - extern __u32 ia32_write_class[]; - extern __u32 ia32_read_class[]; extern __u32 ia32_chattr_class[]; - audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class); - audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); #endif - audit_register_class(AUDIT_CLASS_WRITE, write_class); - audit_register_class(AUDIT_CLASS_READ, read_class); audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); return 0; diff --git a/trunk/arch/x86_64/kernel/e820.c b/trunk/arch/x86_64/kernel/e820.c index d6d7f731f6f0..e56c2adf57a4 100644 --- a/trunk/arch/x86_64/kernel/e820.c +++ b/trunk/arch/x86_64/kernel/e820.c @@ -71,11 +71,7 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size) #endif /* kernel code + 640k memory hole (later should not be needed, but be paranoid for now) */ - if (last >= 640*1024 && addr < 1024*1024) { - *addrp = 1024*1024; - return 1; - } - if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) { + if (last >= 640*1024 && addr < __pa_symbol(&_end)) { *addrp = __pa_symbol(&_end); return 1; } diff --git a/trunk/arch/x86_64/kernel/entry.S b/trunk/arch/x86_64/kernel/entry.S index aa8d8939abc1..d464dded68c0 100644 --- a/trunk/arch/x86_64/kernel/entry.S +++ b/trunk/arch/x86_64/kernel/entry.S @@ -513,7 +513,6 @@ END(stub_rt_sigreturn) swapgs 1: incl %gs:pda_irqcount # RED-PEN should check preempt count cmoveq %gs:pda_irqstackptr,%rsp - push %rbp # backlink for old unwinder /* * We entered an interrupt context - irqs are off: */ @@ -973,8 +972,6 @@ ENTRY(kernel_thread) ENDPROC(kernel_thread) child_rip: - pushq $0 # fake return address - CFI_STARTPROC /* * Here we are in the child and the registers are set as they were * at kernel_thread() invocation in the parent. @@ -985,7 +982,6 @@ child_rip: # exit xorl %edi, %edi call do_exit - CFI_ENDPROC ENDPROC(child_rip) /* @@ -1143,21 +1139,18 @@ ENTRY(machine_check) END(machine_check) #endif -/* Call softirq on interrupt stack. Interrupts are off. */ ENTRY(call_softirq) CFI_STARTPROC - push %rbp - CFI_ADJUST_CFA_OFFSET 8 - CFI_REL_OFFSET rbp,0 - mov %rsp,%rbp - CFI_DEF_CFA_REGISTER rbp + movq %gs:pda_irqstackptr,%rax + movq %rsp,%rdx + CFI_DEF_CFA_REGISTER rdx incl %gs:pda_irqcount - cmove %gs:pda_irqstackptr,%rsp - push %rbp # backlink for old unwinder + cmove %rax,%rsp + pushq %rdx + /*todo CFI_DEF_CFA_EXPRESSION ...*/ call __do_softirq - leaveq + popq %rsp CFI_DEF_CFA_REGISTER rsp - CFI_ADJUST_CFA_OFFSET -8 decl %gs:pda_irqcount ret CFI_ENDPROC diff --git a/trunk/arch/x86_64/kernel/head.S b/trunk/arch/x86_64/kernel/head.S index c9739ca81d06..6df05e6034fa 100644 --- a/trunk/arch/x86_64/kernel/head.S +++ b/trunk/arch/x86_64/kernel/head.S @@ -191,7 +191,6 @@ startup_64: * jump */ movq initial_code(%rip),%rax - pushq $0 # fake return address jmp *%rax /* SMP bootup changes these two */ diff --git a/trunk/arch/x86_64/kernel/init_task.c b/trunk/arch/x86_64/kernel/init_task.c index 3dc5854ba21e..ce31d904d601 100644 --- a/trunk/arch/x86_64/kernel/init_task.c +++ b/trunk/arch/x86_64/kernel/init_task.c @@ -46,9 +46,4 @@ EXPORT_SYMBOL(init_task); */ DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS; -/* Copies of the original ist values from the tss are only accessed during - * debugging, no special alignment required. - */ -DEFINE_PER_CPU(struct orig_ist, orig_ist); - #define ALIGN_TO_4K __attribute__((section(".data.init_task"))) diff --git a/trunk/arch/x86_64/kernel/machine_kexec.c b/trunk/arch/x86_64/kernel/machine_kexec.c index 106076b370fc..83fb24a02821 100644 --- a/trunk/arch/x86_64/kernel/machine_kexec.c +++ b/trunk/arch/x86_64/kernel/machine_kexec.c @@ -207,11 +207,14 @@ NORET_TYPE void machine_kexec(struct kimage *image) __flush_tlb(); - /* The segment registers are funny things, they have both a - * visible and an invisible part. Whenever the visible part is - * set to a specific selector, the invisible part is loaded - * with from a table in memory. At no other time is the - * descriptor table in memory accessed. + /* The segment registers are funny things, they are + * automatically loaded from a table, in memory wherever you + * set them to a specific selector, but this table is never + * accessed again unless you set the segment to a different selector. + * + * The more common model are caches where the behide + * the scenes work is done, but is also dropped at arbitrary + * times. * * I take advantage of this here by force loading the * segments, before I zap the gdt with an invalid value. diff --git a/trunk/arch/x86_64/kernel/mce.c b/trunk/arch/x86_64/kernel/mce.c index 4e017fb30fb3..88845674c661 100644 --- a/trunk/arch/x86_64/kernel/mce.c +++ b/trunk/arch/x86_64/kernel/mce.c @@ -615,7 +615,7 @@ static __cpuinit int mce_create_device(unsigned int cpu) } #ifdef CONFIG_HOTPLUG_CPU -static void mce_remove_device(unsigned int cpu) +static __cpuinit void mce_remove_device(unsigned int cpu) { int i; @@ -626,9 +626,10 @@ static void mce_remove_device(unsigned int cpu) sysdev_remove_file(&per_cpu(device_mce,cpu), &attr_check_interval); sysdev_unregister(&per_cpu(device_mce,cpu)); } +#endif /* Get notified when a cpu comes on/off. Be hotplug friendly. */ -static int +static __cpuinit int mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -637,17 +638,18 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) case CPU_ONLINE: mce_create_device(cpu); break; +#ifdef CONFIG_HOTPLUG_CPU case CPU_DEAD: mce_remove_device(cpu); break; +#endif } return NOTIFY_OK; } -static struct notifier_block mce_cpu_notifier = { +static struct notifier_block __cpuinitdata mce_cpu_notifier = { .notifier_call = mce_cpu_callback, }; -#endif static __init int mce_init_device(void) { @@ -662,7 +664,7 @@ static __init int mce_init_device(void) mce_create_device(i); } - register_hotcpu_notifier(&mce_cpu_notifier); + register_cpu_notifier(&mce_cpu_notifier); misc_register(&mce_log_device); return err; } diff --git a/trunk/arch/x86_64/kernel/mce_amd.c b/trunk/arch/x86_64/kernel/mce_amd.c index 883fe747f64c..db2acbf7ad28 100644 --- a/trunk/arch/x86_64/kernel/mce_amd.c +++ b/trunk/arch/x86_64/kernel/mce_amd.c @@ -558,7 +558,7 @@ static __cpuinit int threshold_create_device(unsigned int cpu) * of shared sysfs dir/files, and rest of the cores will be symlinked to it. */ -static void deallocate_threshold_block(unsigned int cpu, +static __cpuinit void deallocate_threshold_block(unsigned int cpu, unsigned int bank) { struct threshold_block *pos = NULL; @@ -578,7 +578,7 @@ static void deallocate_threshold_block(unsigned int cpu, per_cpu(threshold_banks, cpu)[bank]->blocks = NULL; } -static void threshold_remove_bank(unsigned int cpu, int bank) +static __cpuinit void threshold_remove_bank(unsigned int cpu, int bank) { int i = 0; struct threshold_bank *b; @@ -618,7 +618,7 @@ static void threshold_remove_bank(unsigned int cpu, int bank) per_cpu(threshold_banks, cpu)[bank] = NULL; } -static void threshold_remove_device(unsigned int cpu) +static __cpuinit void threshold_remove_device(unsigned int cpu) { unsigned int bank; @@ -629,8 +629,14 @@ static void threshold_remove_device(unsigned int cpu) } } +#else /* !CONFIG_HOTPLUG_CPU */ +static void threshold_remove_device(unsigned int cpu) +{ +} +#endif + /* get notified when a cpu comes on/off */ -static int threshold_cpu_callback(struct notifier_block *nfb, +static int __cpuinit threshold_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { /* cpu was unsigned int to begin with */ @@ -653,10 +659,9 @@ static int threshold_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block threshold_cpu_notifier = { +static struct notifier_block threshold_cpu_notifier __cpuinitdata = { .notifier_call = threshold_cpu_callback, }; -#endif /* CONFIG_HOTPLUG_CPU */ static __init int threshold_init_device(void) { @@ -668,7 +673,7 @@ static __init int threshold_init_device(void) if (err) return err; } - register_hotcpu_notifier(&threshold_cpu_notifier); + register_cpu_notifier(&threshold_cpu_notifier); return 0; } diff --git a/trunk/arch/x86_64/kernel/pci-calgary.c b/trunk/arch/x86_64/kernel/pci-calgary.c index 146924ba5df5..e71ed53b08fb 100644 --- a/trunk/arch/x86_64/kernel/pci-calgary.c +++ b/trunk/arch/x86_64/kernel/pci-calgary.c @@ -85,8 +85,7 @@ #define CSR_AGENT_MASK 0xffe0ffff #define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */ -#define MAX_NUM_CHASSIS 8 /* max number of chassis */ -#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2) /* max dev->bus->number */ +#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * 2) /* max dev->bus->number */ #define PHBS_PER_CALGARY 4 /* register offsets in Calgary's internal register space */ @@ -111,8 +110,7 @@ static const unsigned long phb_offsets[] = { 0xB000 /* PHB3 */ }; -static char bus_to_phb[MAX_PHB_BUS_NUM]; -void* tce_table_kva[MAX_PHB_BUS_NUM]; +void* tce_table_kva[MAX_NUM_OF_PHBS * MAX_NUMNODES]; unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED; static int translate_empty_slots __read_mostly = 0; static int calgary_detected __read_mostly = 0; @@ -121,7 +119,7 @@ static int calgary_detected __read_mostly = 0; * the bitmap of PHBs the user requested that we disable * translation on. */ -static DECLARE_BITMAP(translation_disabled, MAX_PHB_BUS_NUM); +static DECLARE_BITMAP(translation_disabled, MAX_NUMNODES * MAX_PHB_BUS_NUM); static void tce_cache_blast(struct iommu_table *tbl); @@ -454,7 +452,7 @@ static struct dma_mapping_ops calgary_dma_ops = { static inline int busno_to_phbid(unsigned char num) { - return bus_to_phb[num]; + return bus_to_phb(num) % PHBS_PER_CALGARY; } static inline unsigned long split_queue_offset(unsigned char num) @@ -814,7 +812,7 @@ static int __init calgary_init(void) int i, ret = -ENODEV; struct pci_dev *dev = NULL; - for (i = 0; i < MAX_PHB_BUS_NUM; i++) { + for (i = 0; i <= num_online_nodes() * MAX_NUM_OF_PHBS; i++) { dev = pci_get_device(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CALGARY, dev); @@ -824,7 +822,7 @@ static int __init calgary_init(void) calgary_init_one_nontraslated(dev); continue; } - if (!tce_table_kva[dev->bus->number] && !translate_empty_slots) { + if (!tce_table_kva[i] && !translate_empty_slots) { pci_dev_put(dev); continue; } @@ -844,7 +842,7 @@ static int __init calgary_init(void) pci_dev_put(dev); continue; } - if (!tce_table_kva[dev->bus->number] && !translate_empty_slots) + if (!tce_table_kva[i] && !translate_empty_slots) continue; calgary_disable_translation(dev); calgary_free_tar(dev); @@ -878,10 +876,9 @@ static inline int __init determine_tce_table_size(u64 ram) void __init detect_calgary(void) { u32 val; - int bus; + int bus, table_idx; void *tbl; - int calgary_found = 0; - int phb = -1; + int detected = 0; /* * if the user specified iommu=off or iommu=soft or we found @@ -892,46 +889,38 @@ void __init detect_calgary(void) specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE); - for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { - int dev; - - tce_table_kva[bus] = NULL; - bus_to_phb[bus] = -1; - + for (bus = 0, table_idx = 0; + bus <= num_online_nodes() * MAX_PHB_BUS_NUM; + bus++) { + BUG_ON(bus > MAX_NUMNODES * MAX_PHB_BUS_NUM); if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY) continue; - - /* - * There are 4 PHBs per Calgary chip. Set phb to which phb (0-3) - * it is connected to releative to the clagary chip. - */ - phb = (phb + 1) % PHBS_PER_CALGARY; - if (test_bit(bus, translation_disabled)) { printk(KERN_INFO "Calgary: translation is disabled for " "PHB 0x%x\n", bus); /* skip this phb, don't allocate a tbl for it */ + tce_table_kva[table_idx] = NULL; + table_idx++; continue; } /* - * Scan the slots of the PCI bus to see if there is a device present. - * The parent bus will be the zero-ith device, so start at 1. + * scan the first slot of the PCI bus to see if there + * are any devices present */ - for (dev = 1; dev < 8; dev++) { - val = read_pci_config(bus, dev, 0, 0); - if (val != 0xffffffff || translate_empty_slots) { - tbl = alloc_tce_table(); - if (!tbl) - goto cleanup; - tce_table_kva[bus] = tbl; - bus_to_phb[bus] = phb; - calgary_found = 1; - break; - } - } + val = read_pci_config(bus, 1, 0, 0); + if (val != 0xffffffff || translate_empty_slots) { + tbl = alloc_tce_table(); + if (!tbl) + goto cleanup; + detected = 1; + } else + tbl = NULL; + + tce_table_kva[table_idx] = tbl; + table_idx++; } - if (calgary_found) { + if (detected) { iommu_detected = 1; calgary_detected = 1; printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected. " @@ -940,9 +929,9 @@ void __init detect_calgary(void) return; cleanup: - for (--bus; bus >= 0; --bus) - if (tce_table_kva[bus]) - free_tce_table(tce_table_kva[bus]); + for (--table_idx; table_idx >= 0; --table_idx) + if (tce_table_kva[table_idx]) + free_tce_table(tce_table_kva[table_idx]); } int __init calgary_iommu_init(void) @@ -1013,7 +1002,7 @@ static int __init calgary_parse_options(char *p) if (p == endp) break; - if (bridge < MAX_PHB_BUS_NUM) { + if (bridge <= (num_online_nodes() * MAX_PHB_BUS_NUM)) { printk(KERN_INFO "Calgary: disabling " "translation for PHB 0x%x\n", bridge); set_bit(bridge, translation_disabled); diff --git a/trunk/arch/x86_64/kernel/pci-nommu.c b/trunk/arch/x86_64/kernel/pci-nommu.c index aad7609d8e92..c4c3cc36ac5b 100644 --- a/trunk/arch/x86_64/kernel/pci-nommu.c +++ b/trunk/arch/x86_64/kernel/pci-nommu.c @@ -92,7 +92,5 @@ void __init no_iommu_init(void) { if (dma_ops) return; - - force_iommu = 0; /* no HW IOMMU */ dma_ops = &nommu_dma_ops; } diff --git a/trunk/arch/x86_64/kernel/pci-swiotlb.c b/trunk/arch/x86_64/kernel/pci-swiotlb.c index 6a55f87ba97f..ebdb77fe2057 100644 --- a/trunk/arch/x86_64/kernel/pci-swiotlb.c +++ b/trunk/arch/x86_64/kernel/pci-swiotlb.c @@ -31,10 +31,9 @@ struct dma_mapping_ops swiotlb_dma_ops = { void pci_swiotlb_init(void) { /* don't initialize swiotlb if iommu=off (no_iommu=1) */ - if (!iommu_detected && !no_iommu && end_pfn > MAX_DMA32_PFN) + if (!iommu_detected && !no_iommu && + (end_pfn > MAX_DMA32_PFN || force_iommu)) swiotlb = 1; - if (swiotlb_force) - swiotlb = 1; if (swiotlb) { printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n"); swiotlb_init(); diff --git a/trunk/arch/x86_64/kernel/setup.c b/trunk/arch/x86_64/kernel/setup.c index 34afad704824..8a099ff1f8bc 100644 --- a/trunk/arch/x86_64/kernel/setup.c +++ b/trunk/arch/x86_64/kernel/setup.c @@ -521,6 +521,8 @@ static void discover_ebda(void) void __init setup_arch(char **cmdline_p) { + unsigned long kernel_end; + ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); screen_info = SCREEN_INFO; edid_info = EDID_INFO; @@ -594,8 +596,8 @@ void __init setup_arch(char **cmdline_p) (table_end - table_start) << PAGE_SHIFT); /* reserve kernel */ - reserve_bootmem_generic(__pa_symbol(&_text), - __pa_symbol(&_end) - __pa_symbol(&_text)); + kernel_end = round_up(__pa_symbol(&_end),PAGE_SIZE); + reserve_bootmem_generic(HIGH_MEMORY, kernel_end - HIGH_MEMORY); /* * reserve physical page 0 - it's a special BIOS page on many boxes, diff --git a/trunk/arch/x86_64/kernel/setup64.c b/trunk/arch/x86_64/kernel/setup64.c index 417de564456e..6fe58a634b5f 100644 --- a/trunk/arch/x86_64/kernel/setup64.c +++ b/trunk/arch/x86_64/kernel/setup64.c @@ -189,7 +189,6 @@ void __cpuinit cpu_init (void) { int cpu = stack_smp_processor_id(); struct tss_struct *t = &per_cpu(init_tss, cpu); - struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu); unsigned long v; char *estacks = NULL; struct task_struct *me; @@ -257,7 +256,7 @@ void __cpuinit cpu_init (void) estacks += EXCEPTION_STKSZ; break; } - orig_ist->ist[v] = t->ist[v] = (unsigned long)estacks; + t->ist[v] = (unsigned long)estacks; } t->io_bitmap_base = offsetof(struct tss_struct, io_bitmap); diff --git a/trunk/arch/x86_64/kernel/smp.c b/trunk/arch/x86_64/kernel/smp.c index 06af6ca60129..5a1c0a3bf872 100644 --- a/trunk/arch/x86_64/kernel/smp.c +++ b/trunk/arch/x86_64/kernel/smp.c @@ -203,7 +203,7 @@ int __cpuinit init_smp_flush(void) { int i; for_each_cpu_mask(i, cpu_possible_map) { - spin_lock_init(&per_cpu(flush_state, i).tlbstate_lock); + spin_lock_init(&per_cpu(flush_state.tlbstate_lock, i)); } return 0; } diff --git a/trunk/arch/x86_64/kernel/tce.c b/trunk/arch/x86_64/kernel/tce.c index 5530dda3f27a..d3a9e79e954c 100644 --- a/trunk/arch/x86_64/kernel/tce.c +++ b/trunk/arch/x86_64/kernel/tce.c @@ -96,6 +96,7 @@ static inline unsigned int table_size_to_number_of_entries(unsigned char size) static int tce_table_setparms(struct pci_dev *dev, struct iommu_table *tbl) { unsigned int bitmapsz; + unsigned int tce_table_index; unsigned long bmppages; int ret; @@ -104,7 +105,8 @@ static int tce_table_setparms(struct pci_dev *dev, struct iommu_table *tbl) /* set the tce table size - measured in entries */ tbl->it_size = table_size_to_number_of_entries(specified_table_size); - tbl->it_base = (unsigned long)tce_table_kva[dev->bus->number]; + tce_table_index = bus_to_phb(tbl->it_busno); + tbl->it_base = (unsigned long)tce_table_kva[tce_table_index]; if (!tbl->it_base) { printk(KERN_ERR "Calgary: iommu_table_setparms: " "no table allocated?!\n"); diff --git a/trunk/arch/x86_64/kernel/time.c b/trunk/arch/x86_64/kernel/time.c index 7a9b18224182..b9ff75992c16 100644 --- a/trunk/arch/x86_64/kernel/time.c +++ b/trunk/arch/x86_64/kernel/time.c @@ -28,7 +28,6 @@ #include #ifdef CONFIG_ACPI #include /* for PM timer frequency */ -#include #endif #include #include @@ -194,7 +193,7 @@ unsigned long profile_pc(struct pt_regs *regs) is just accounted to the spinlock function. Better would be to write these functions in assembler again and check exactly. */ - if (!user_mode(regs) && in_lock_functions(pc)) { + if (in_lock_functions(pc)) { char *v = *(char **)regs->rsp; if ((v >= _stext && v <= _etext) || (v >= _sinittext && v <= _einittext) || @@ -954,18 +953,11 @@ __cpuinit int unsynchronized_tsc(void) #ifdef CONFIG_SMP if (apic_is_clustered_box()) return 1; -#endif - /* Most intel systems have synchronized TSCs except for - multi node systems */ - if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { -#ifdef CONFIG_ACPI - /* But TSC doesn't tick in C3 so don't use it there */ - if (acpi_fadt.length > 0 && acpi_fadt.plvl3_lat < 100) - return 1; -#endif + /* Intel systems are normally all synchronized. Exceptions + are handled in the check above. */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) return 0; - } - +#endif /* Assume multi socket systems are not synchronized */ return num_present_cpus() > 1; } diff --git a/trunk/arch/x86_64/kernel/traps.c b/trunk/arch/x86_64/kernel/traps.c index b1249774d1e8..eb39a2775236 100644 --- a/trunk/arch/x86_64/kernel/traps.c +++ b/trunk/arch/x86_64/kernel/traps.c @@ -107,11 +107,7 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) } static int kstack_depth_to_print = 12; -#ifdef CONFIG_STACK_UNWIND static int call_trace = 1; -#else -#define call_trace (-1) -#endif #ifdef CONFIG_KALLSYMS # include @@ -178,7 +174,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, break; #endif default: - end = per_cpu(orig_ist, cpu).ist[k]; + end = per_cpu(init_tss, cpu).ist[k]; break; } /* @@ -258,6 +254,7 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s { const unsigned cpu = safe_smp_processor_id(); unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; + int i = 11; unsigned used = 0; printk("\nCall Trace:\n"); @@ -279,20 +276,11 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s unw_ret = show_trace_unwind(&info, NULL); } if (unw_ret > 0) { - if (call_trace == 1 && !arch_unw_user_mode(&info)) { - print_symbol("DWARF2 unwinder stuck at %s\n", - UNW_PC(&info)); - if ((long)UNW_SP(&info) < 0) { - printk("Leftover inexact backtrace:\n"); - stack = (unsigned long *)UNW_SP(&info); - } else - printk("Full inexact backtrace again:\n"); - } else if (call_trace >= 1) + if (call_trace > 0) return; - else - printk("Full inexact backtrace again:\n"); - } else - printk("Inexact backtrace:\n"); + printk("Legacy call trace:"); + i = 18; + } } /* @@ -533,7 +521,7 @@ void __kprobes oops_end(unsigned long flags) /* Nest count reaches zero, release the lock. */ spin_unlock_irqrestore(&die_lock, flags); if (panic_on_oops) - panic("Fatal exception"); + panic("Oops"); } void __kprobes __die(const char * str, struct pt_regs * regs, long err) @@ -1124,18 +1112,14 @@ static int __init kstack_setup(char *s) } __setup("kstack=", kstack_setup); -#ifdef CONFIG_STACK_UNWIND static int __init call_trace_setup(char *s) { if (strcmp(s, "old") == 0) call_trace = -1; else if (strcmp(s, "both") == 0) call_trace = 0; - else if (strcmp(s, "newfallback") == 0) - call_trace = 1; else if (strcmp(s, "new") == 0) - call_trace = 2; + call_trace = 1; return 1; } __setup("call_trace=", call_trace_setup); -#endif diff --git a/trunk/arch/x86_64/pci/k8-bus.c b/trunk/arch/x86_64/pci/k8-bus.c index 3acf60ded2a0..b50a7c7c47f8 100644 --- a/trunk/arch/x86_64/pci/k8-bus.c +++ b/trunk/arch/x86_64/pci/k8-bus.c @@ -2,6 +2,7 @@ #include #include #include +#include /* * This discovers the pcibus <-> node mapping on AMD K8. @@ -18,7 +19,6 @@ #define NR_LDT_BUS_NUMBER_REGISTERS 3 #define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF) #define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF) -#define PCI_DEVICE_ID_K8HTCONFIG 0x1100 /** * fill_mp_bus_to_cpumask() @@ -28,8 +28,7 @@ __init static int fill_mp_bus_to_cpumask(void) { - struct pci_dev *nb_dev = NULL; - int i, j; + int i, j, k; u32 ldtbus, nid; static int lbnr[3] = { LDT_BUS_NUMBER_REGISTER_0, @@ -37,8 +36,9 @@ fill_mp_bus_to_cpumask(void) LDT_BUS_NUMBER_REGISTER_2 }; - while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) { + cache_k8_northbridges(); + for (k = 0; k < num_k8_northbridges; k++) { + struct pci_dev *nb_dev = k8_northbridges[k]; pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid); for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) { diff --git a/trunk/arch/xtensa/kernel/ptrace.c b/trunk/arch/xtensa/kernel/ptrace.c index 9aea23cc0dc5..5064d9383963 100644 --- a/trunk/arch/xtensa/kernel/ptrace.c +++ b/trunk/arch/xtensa/kernel/ptrace.c @@ -212,7 +212,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) */ case PTRACE_KILL: ret = 0; - if (child->exit_state == EXIT_ZOMBIE) /* already dead */ + if (child->state == EXIT_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; child->ptrace &= ~PT_SINGLESTEP; diff --git a/trunk/arch/xtensa/kernel/traps.c b/trunk/arch/xtensa/kernel/traps.c index ce077d6bf3a0..27e409089a7b 100644 --- a/trunk/arch/xtensa/kernel/traps.c +++ b/trunk/arch/xtensa/kernel/traps.c @@ -487,9 +487,11 @@ void die(const char * str, struct pt_regs * regs, long err) if (in_interrupt()) panic("Fatal exception in interrupt"); - if (panic_on_oops) + if (panic_on_oops) { + printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); + ssleep(5); panic("Fatal exception"); - + } do_exit(err); } diff --git a/trunk/block/cfq-iosched.c b/trunk/block/cfq-iosched.c index 3a3aee08ec5f..aae3123bf3ee 100644 --- a/trunk/block/cfq-iosched.c +++ b/trunk/block/cfq-iosched.c @@ -1561,7 +1561,7 @@ cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc, /* ->key must be copied to avoid race with cfq_exit_queue() */ k = __cic->key; if (unlikely(!k)) { - cfq_drop_dead_cic(ioc, __cic); + cfq_drop_dead_cic(ioc, cic); goto restart; } diff --git a/trunk/block/elevator.c b/trunk/block/elevator.c index 9b72dc7c8a5c..bc7baeec0d10 100644 --- a/trunk/block/elevator.c +++ b/trunk/block/elevator.c @@ -765,8 +765,7 @@ void elv_unregister(struct elevator_type *e) read_lock(&tasklist_lock); do_each_thread(g, p) { task_lock(p); - if (p->io_context) - e->ops.trim(p->io_context); + e->ops.trim(p->io_context); task_unlock(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); diff --git a/trunk/block/ll_rw_blk.c b/trunk/block/ll_rw_blk.c index dcbd6ff1fa33..61d6b3c65b66 100644 --- a/trunk/block/ll_rw_blk.c +++ b/trunk/block/ll_rw_blk.c @@ -2734,18 +2734,6 @@ long blk_congestion_wait(int rw, long timeout) EXPORT_SYMBOL(blk_congestion_wait); -/** - * blk_congestion_end - wake up sleepers on a congestion queue - * @rw: READ or WRITE - */ -void blk_congestion_end(int rw) -{ - wait_queue_head_t *wqh = &congestion_wqh[rw]; - - if (waitqueue_active(wqh)) - wake_up(wqh); -} - /* * Has to be called with the request spinlock acquired */ @@ -3640,8 +3628,6 @@ struct io_context *current_io_context(gfp_t gfp_flags) ret->nr_batch_requests = 0; /* because this is 0 */ ret->aic = NULL; ret->cic_root.rb_node = NULL; - /* make sure set_task_ioprio() sees the settings above */ - smp_wmb(); tsk->io_context = ret; } diff --git a/trunk/crypto/Kconfig b/trunk/crypto/Kconfig index 1e2f39c21180..ba133d557045 100644 --- a/trunk/crypto/Kconfig +++ b/trunk/crypto/Kconfig @@ -9,71 +9,47 @@ config CRYPTO help This option provides the core Cryptographic API. -if CRYPTO - -config CRYPTO_ALGAPI - tristate - help - This option provides the API for cryptographic algorithms. - -config CRYPTO_BLKCIPHER - tristate - select CRYPTO_ALGAPI - -config CRYPTO_HASH - tristate - select CRYPTO_ALGAPI - -config CRYPTO_MANAGER - tristate "Cryptographic algorithm manager" - select CRYPTO_ALGAPI - default m - help - Create default cryptographic template instantiations such as - cbc(aes). - config CRYPTO_HMAC - tristate "HMAC support" - select CRYPTO_HASH + bool "HMAC support" + depends on CRYPTO help HMAC: Keyed-Hashing for Message Authentication (RFC2104). This is required for IPSec. config CRYPTO_NULL tristate "Null algorithms" - select CRYPTO_ALGAPI + depends on CRYPTO help These are 'Null' algorithms, used by IPsec, which do nothing. config CRYPTO_MD4 tristate "MD4 digest algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO help MD4 message digest algorithm (RFC1320). config CRYPTO_MD5 tristate "MD5 digest algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO help MD5 message digest algorithm (RFC1321). config CRYPTO_SHA1 tristate "SHA1 digest algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO help SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). config CRYPTO_SHA1_S390 tristate "SHA1 digest algorithm (s390)" - depends on S390 - select CRYPTO_ALGAPI + depends on CRYPTO && S390 help This is the s390 hardware accelerated implementation of the SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). config CRYPTO_SHA256 tristate "SHA256 digest algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO help SHA256 secure hash standard (DFIPS 180-2). @@ -82,8 +58,7 @@ config CRYPTO_SHA256 config CRYPTO_SHA256_S390 tristate "SHA256 digest algorithm (s390)" - depends on S390 - select CRYPTO_ALGAPI + depends on CRYPTO && S390 help This is the s390 hardware accelerated implementation of the SHA256 secure hash standard (DFIPS 180-2). @@ -93,7 +68,7 @@ config CRYPTO_SHA256_S390 config CRYPTO_SHA512 tristate "SHA384 and SHA512 digest algorithms" - select CRYPTO_ALGAPI + depends on CRYPTO help SHA512 secure hash standard (DFIPS 180-2). @@ -105,7 +80,7 @@ config CRYPTO_SHA512 config CRYPTO_WP512 tristate "Whirlpool digest algorithms" - select CRYPTO_ALGAPI + depends on CRYPTO help Whirlpool hash algorithm 512, 384 and 256-bit hashes @@ -117,7 +92,7 @@ config CRYPTO_WP512 config CRYPTO_TGR192 tristate "Tiger digest algorithms" - select CRYPTO_ALGAPI + depends on CRYPTO help Tiger hash algorithm 192, 160 and 128-bit hashes @@ -128,40 +103,21 @@ config CRYPTO_TGR192 See also: . -config CRYPTO_ECB - tristate "ECB support" - select CRYPTO_BLKCIPHER - default m - help - ECB: Electronic CodeBook mode - This is the simplest block cipher algorithm. It simply encrypts - the input block by block. - -config CRYPTO_CBC - tristate "CBC support" - select CRYPTO_BLKCIPHER - default m - help - CBC: Cipher Block Chaining mode - This block cipher algorithm is required for IPSec. - config CRYPTO_DES tristate "DES and Triple DES EDE cipher algorithms" - select CRYPTO_ALGAPI + depends on CRYPTO help DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). config CRYPTO_DES_S390 tristate "DES and Triple DES cipher algorithms (s390)" - depends on S390 - select CRYPTO_ALGAPI - select CRYPTO_BLKCIPHER + depends on CRYPTO && S390 help DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). config CRYPTO_BLOWFISH tristate "Blowfish cipher algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO help Blowfish cipher algorithm, by Bruce Schneier. @@ -174,8 +130,7 @@ config CRYPTO_BLOWFISH config CRYPTO_TWOFISH tristate "Twofish cipher algorithm" - select CRYPTO_ALGAPI - select CRYPTO_TWOFISH_COMMON + depends on CRYPTO help Twofish cipher algorithm. @@ -187,47 +142,9 @@ config CRYPTO_TWOFISH See also: -config CRYPTO_TWOFISH_COMMON - tristate - help - Common parts of the Twofish cipher algorithm shared by the - generic c and the assembler implementations. - -config CRYPTO_TWOFISH_586 - tristate "Twofish cipher algorithms (i586)" - depends on (X86 || UML_X86) && !64BIT - select CRYPTO_ALGAPI - select CRYPTO_TWOFISH_COMMON - help - Twofish cipher algorithm. - - Twofish was submitted as an AES (Advanced Encryption Standard) - candidate cipher by researchers at CounterPane Systems. It is a - 16 round block cipher supporting key sizes of 128, 192, and 256 - bits. - - See also: - - -config CRYPTO_TWOFISH_X86_64 - tristate "Twofish cipher algorithm (x86_64)" - depends on (X86 || UML_X86) && 64BIT - select CRYPTO_ALGAPI - select CRYPTO_TWOFISH_COMMON - help - Twofish cipher algorithm (x86_64). - - Twofish was submitted as an AES (Advanced Encryption Standard) - candidate cipher by researchers at CounterPane Systems. It is a - 16 round block cipher supporting key sizes of 128, 192, and 256 - bits. - - See also: - - config CRYPTO_SERPENT tristate "Serpent cipher algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO help Serpent cipher algorithm, by Anderson, Biham & Knudsen. @@ -240,7 +157,7 @@ config CRYPTO_SERPENT config CRYPTO_AES tristate "AES cipher algorithms" - select CRYPTO_ALGAPI + depends on CRYPTO help AES cipher algorithms (FIPS-197). AES uses the Rijndael algorithm. @@ -260,8 +177,7 @@ config CRYPTO_AES config CRYPTO_AES_586 tristate "AES cipher algorithms (i586)" - depends on (X86 || UML_X86) && !64BIT - select CRYPTO_ALGAPI + depends on CRYPTO && ((X86 || UML_X86) && !64BIT) help AES cipher algorithms (FIPS-197). AES uses the Rijndael algorithm. @@ -281,8 +197,7 @@ config CRYPTO_AES_586 config CRYPTO_AES_X86_64 tristate "AES cipher algorithms (x86_64)" - depends on (X86 || UML_X86) && 64BIT - select CRYPTO_ALGAPI + depends on CRYPTO && ((X86 || UML_X86) && 64BIT) help AES cipher algorithms (FIPS-197). AES uses the Rijndael algorithm. @@ -302,9 +217,7 @@ config CRYPTO_AES_X86_64 config CRYPTO_AES_S390 tristate "AES cipher algorithms (s390)" - depends on S390 - select CRYPTO_ALGAPI - select CRYPTO_BLKCIPHER + depends on CRYPTO && S390 help This is the s390 hardware accelerated implementation of the AES cipher algorithms (FIPS-197). AES uses the Rijndael @@ -324,21 +237,21 @@ config CRYPTO_AES_S390 config CRYPTO_CAST5 tristate "CAST5 (CAST-128) cipher algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO help The CAST5 encryption algorithm (synonymous with CAST-128) is described in RFC2144. config CRYPTO_CAST6 tristate "CAST6 (CAST-256) cipher algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO help The CAST6 encryption algorithm (synonymous with CAST-256) is described in RFC2612. config CRYPTO_TEA tristate "TEA, XTEA and XETA cipher algorithms" - select CRYPTO_ALGAPI + depends on CRYPTO help TEA cipher algorithm. @@ -355,7 +268,7 @@ config CRYPTO_TEA config CRYPTO_ARC4 tristate "ARC4 cipher algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO help ARC4 cipher algorithm. @@ -366,7 +279,7 @@ config CRYPTO_ARC4 config CRYPTO_KHAZAD tristate "Khazad cipher algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO help Khazad cipher algorithm. @@ -379,7 +292,7 @@ config CRYPTO_KHAZAD config CRYPTO_ANUBIS tristate "Anubis cipher algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO help Anubis cipher algorithm. @@ -394,7 +307,7 @@ config CRYPTO_ANUBIS config CRYPTO_DEFLATE tristate "Deflate compression algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO select ZLIB_INFLATE select ZLIB_DEFLATE help @@ -405,7 +318,7 @@ config CRYPTO_DEFLATE config CRYPTO_MICHAEL_MIC tristate "Michael MIC keyed digest algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO help Michael MIC is used for message integrity protection in TKIP (IEEE 802.11i). This algorithm is required for TKIP, but it @@ -414,7 +327,7 @@ config CRYPTO_MICHAEL_MIC config CRYPTO_CRC32C tristate "CRC32c CRC algorithm" - select CRYPTO_ALGAPI + depends on CRYPTO select LIBCRC32C help Castagnoli, et al Cyclic Redundancy-Check Algorithm. Used @@ -424,13 +337,10 @@ config CRYPTO_CRC32C config CRYPTO_TEST tristate "Testing module" - depends on m - select CRYPTO_ALGAPI + depends on CRYPTO && m help Quick & dirty crypto test module. source "drivers/crypto/Kconfig" - -endif # if CRYPTO - endmenu + diff --git a/trunk/crypto/Makefile b/trunk/crypto/Makefile index 72366208e291..d287b9e60c47 100644 --- a/trunk/crypto/Makefile +++ b/trunk/crypto/Makefile @@ -2,18 +2,11 @@ # Cryptographic API # -obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o +proc-crypto-$(CONFIG_PROC_FS) = proc.o -crypto_algapi-$(CONFIG_PROC_FS) += proc.o -crypto_algapi-objs := algapi.o $(crypto_algapi-y) -obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o +obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o \ + $(proc-crypto-y) -obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o - -crypto_hash-objs := hash.o -obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o - -obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o obj-$(CONFIG_CRYPTO_HMAC) += hmac.o obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o obj-$(CONFIG_CRYPTO_MD4) += md4.o @@ -23,12 +16,9 @@ obj-$(CONFIG_CRYPTO_SHA256) += sha256.o obj-$(CONFIG_CRYPTO_SHA512) += sha512.o obj-$(CONFIG_CRYPTO_WP512) += wp512.o obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o -obj-$(CONFIG_CRYPTO_ECB) += ecb.o -obj-$(CONFIG_CRYPTO_CBC) += cbc.o obj-$(CONFIG_CRYPTO_DES) += des.o obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o -obj-$(CONFIG_CRYPTO_TWOFISH_COMMON) += twofish_common.o obj-$(CONFIG_CRYPTO_SERPENT) += serpent.o obj-$(CONFIG_CRYPTO_AES) += aes.o obj-$(CONFIG_CRYPTO_CAST5) += cast5.o diff --git a/trunk/crypto/aes.c b/trunk/crypto/aes.c index e2440773878c..a038711831e7 100644 --- a/trunk/crypto/aes.c +++ b/trunk/crypto/aes.c @@ -249,14 +249,13 @@ gen_tabs (void) } static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) + unsigned int key_len, u32 *flags) { struct aes_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *key = (const __le32 *)in_key; - u32 *flags = &tfm->crt_flags; u32 i, t, u, v, w; - if (key_len % 8) { + if (key_len != 16 && key_len != 24 && key_len != 32) { *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } diff --git a/trunk/crypto/algapi.c b/trunk/crypto/algapi.c deleted file mode 100644 index c91530021e9c..000000000000 --- a/trunk/crypto/algapi.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Cryptographic API for algorithms (i.e., low-level API). - * - * Copyright (c) 2006 Herbert Xu - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "internal.h" - -static LIST_HEAD(crypto_template_list); - -void crypto_larval_error(const char *name, u32 type, u32 mask) -{ - struct crypto_alg *alg; - - down_read(&crypto_alg_sem); - alg = __crypto_alg_lookup(name, type, mask); - up_read(&crypto_alg_sem); - - if (alg) { - if (crypto_is_larval(alg)) { - struct crypto_larval *larval = (void *)alg; - complete(&larval->completion); - } - crypto_mod_put(alg); - } -} -EXPORT_SYMBOL_GPL(crypto_larval_error); - -static inline int crypto_set_driver_name(struct crypto_alg *alg) -{ - static const char suffix[] = "-generic"; - char *driver_name = alg->cra_driver_name; - int len; - - if (*driver_name) - return 0; - - len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); - if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME) - return -ENAMETOOLONG; - - memcpy(driver_name + len, suffix, sizeof(suffix)); - return 0; -} - -static int crypto_check_alg(struct crypto_alg *alg) -{ - if (alg->cra_alignmask & (alg->cra_alignmask + 1)) - return -EINVAL; - - if (alg->cra_alignmask & alg->cra_blocksize) - return -EINVAL; - - if (alg->cra_blocksize > PAGE_SIZE / 8) - return -EINVAL; - - if (alg->cra_priority < 0) - return -EINVAL; - - return crypto_set_driver_name(alg); -} - -static void crypto_destroy_instance(struct crypto_alg *alg) -{ - struct crypto_instance *inst = (void *)alg; - struct crypto_template *tmpl = inst->tmpl; - - tmpl->free(inst); - crypto_tmpl_put(tmpl); -} - -static void crypto_remove_spawns(struct list_head *spawns, - struct list_head *list) -{ - struct crypto_spawn *spawn, *n; - - list_for_each_entry_safe(spawn, n, spawns, list) { - struct crypto_instance *inst = spawn->inst; - struct crypto_template *tmpl = inst->tmpl; - - list_del_init(&spawn->list); - spawn->alg = NULL; - - if (crypto_is_dead(&inst->alg)) - continue; - - inst->alg.cra_flags |= CRYPTO_ALG_DEAD; - if (!tmpl || !crypto_tmpl_get(tmpl)) - continue; - - crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg); - list_move(&inst->alg.cra_list, list); - hlist_del(&inst->list); - inst->alg.cra_destroy = crypto_destroy_instance; - - if (!list_empty(&inst->alg.cra_users)) { - if (&n->list == spawns) - n = list_entry(inst->alg.cra_users.next, - typeof(*n), list); - __list_splice(&inst->alg.cra_users, spawns->prev); - } - } -} - -static int __crypto_register_alg(struct crypto_alg *alg, - struct list_head *list) -{ - struct crypto_alg *q; - int ret = -EAGAIN; - - if (crypto_is_dead(alg)) - goto out; - - INIT_LIST_HEAD(&alg->cra_users); - - ret = -EEXIST; - - atomic_set(&alg->cra_refcnt, 1); - list_for_each_entry(q, &crypto_alg_list, cra_list) { - if (q == alg) - goto out; - - if (crypto_is_moribund(q)) - continue; - - if (crypto_is_larval(q)) { - struct crypto_larval *larval = (void *)q; - - if (strcmp(alg->cra_name, q->cra_name) && - strcmp(alg->cra_driver_name, q->cra_name)) - continue; - - if (larval->adult) - continue; - if ((q->cra_flags ^ alg->cra_flags) & larval->mask) - continue; - if (!crypto_mod_get(alg)) - continue; - - larval->adult = alg; - complete(&larval->completion); - continue; - } - - if (strcmp(alg->cra_name, q->cra_name)) - continue; - - if (strcmp(alg->cra_driver_name, q->cra_driver_name) && - q->cra_priority > alg->cra_priority) - continue; - - crypto_remove_spawns(&q->cra_users, list); - } - - list_add(&alg->cra_list, &crypto_alg_list); - - crypto_notify(CRYPTO_MSG_ALG_REGISTER, alg); - ret = 0; - -out: - return ret; -} - -static void crypto_remove_final(struct list_head *list) -{ - struct crypto_alg *alg; - struct crypto_alg *n; - - list_for_each_entry_safe(alg, n, list, cra_list) { - list_del_init(&alg->cra_list); - crypto_alg_put(alg); - } -} - -int crypto_register_alg(struct crypto_alg *alg) -{ - LIST_HEAD(list); - int err; - - err = crypto_check_alg(alg); - if (err) - return err; - - down_write(&crypto_alg_sem); - err = __crypto_register_alg(alg, &list); - up_write(&crypto_alg_sem); - - crypto_remove_final(&list); - return err; -} -EXPORT_SYMBOL_GPL(crypto_register_alg); - -static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list) -{ - if (unlikely(list_empty(&alg->cra_list))) - return -ENOENT; - - alg->cra_flags |= CRYPTO_ALG_DEAD; - - crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg); - list_del_init(&alg->cra_list); - crypto_remove_spawns(&alg->cra_users, list); - - return 0; -} - -int crypto_unregister_alg(struct crypto_alg *alg) -{ - int ret; - LIST_HEAD(list); - - down_write(&crypto_alg_sem); - ret = crypto_remove_alg(alg, &list); - up_write(&crypto_alg_sem); - - if (ret) - return ret; - - BUG_ON(atomic_read(&alg->cra_refcnt) != 1); - if (alg->cra_destroy) - alg->cra_destroy(alg); - - crypto_remove_final(&list); - return 0; -} -EXPORT_SYMBOL_GPL(crypto_unregister_alg); - -int crypto_register_template(struct crypto_template *tmpl) -{ - struct crypto_template *q; - int err = -EEXIST; - - down_write(&crypto_alg_sem); - - list_for_each_entry(q, &crypto_template_list, list) { - if (q == tmpl) - goto out; - } - - list_add(&tmpl->list, &crypto_template_list); - crypto_notify(CRYPTO_MSG_TMPL_REGISTER, tmpl); - err = 0; -out: - up_write(&crypto_alg_sem); - return err; -} -EXPORT_SYMBOL_GPL(crypto_register_template); - -void crypto_unregister_template(struct crypto_template *tmpl) -{ - struct crypto_instance *inst; - struct hlist_node *p, *n; - struct hlist_head *list; - LIST_HEAD(users); - - down_write(&crypto_alg_sem); - - BUG_ON(list_empty(&tmpl->list)); - list_del_init(&tmpl->list); - - list = &tmpl->instances; - hlist_for_each_entry(inst, p, list, list) { - int err = crypto_remove_alg(&inst->alg, &users); - BUG_ON(err); - } - - crypto_notify(CRYPTO_MSG_TMPL_UNREGISTER, tmpl); - - up_write(&crypto_alg_sem); - - hlist_for_each_entry_safe(inst, p, n, list, list) { - BUG_ON(atomic_read(&inst->alg.cra_refcnt) != 1); - tmpl->free(inst); - } - crypto_remove_final(&users); -} -EXPORT_SYMBOL_GPL(crypto_unregister_template); - -static struct crypto_template *__crypto_lookup_template(const char *name) -{ - struct crypto_template *q, *tmpl = NULL; - - down_read(&crypto_alg_sem); - list_for_each_entry(q, &crypto_template_list, list) { - if (strcmp(q->name, name)) - continue; - if (unlikely(!crypto_tmpl_get(q))) - continue; - - tmpl = q; - break; - } - up_read(&crypto_alg_sem); - - return tmpl; -} - -struct crypto_template *crypto_lookup_template(const char *name) -{ - return try_then_request_module(__crypto_lookup_template(name), name); -} -EXPORT_SYMBOL_GPL(crypto_lookup_template); - -int crypto_register_instance(struct crypto_template *tmpl, - struct crypto_instance *inst) -{ - LIST_HEAD(list); - int err = -EINVAL; - - if (inst->alg.cra_destroy) - goto err; - - err = crypto_check_alg(&inst->alg); - if (err) - goto err; - - inst->alg.cra_module = tmpl->module; - - down_write(&crypto_alg_sem); - - err = __crypto_register_alg(&inst->alg, &list); - if (err) - goto unlock; - - hlist_add_head(&inst->list, &tmpl->instances); - inst->tmpl = tmpl; - -unlock: - up_write(&crypto_alg_sem); - - crypto_remove_final(&list); - -err: - return err; -} -EXPORT_SYMBOL_GPL(crypto_register_instance); - -int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, - struct crypto_instance *inst) -{ - int err = -EAGAIN; - - spawn->inst = inst; - - down_write(&crypto_alg_sem); - if (!crypto_is_moribund(alg)) { - list_add(&spawn->list, &alg->cra_users); - spawn->alg = alg; - err = 0; - } - up_write(&crypto_alg_sem); - - return err; -} -EXPORT_SYMBOL_GPL(crypto_init_spawn); - -void crypto_drop_spawn(struct crypto_spawn *spawn) -{ - down_write(&crypto_alg_sem); - list_del(&spawn->list); - up_write(&crypto_alg_sem); -} -EXPORT_SYMBOL_GPL(crypto_drop_spawn); - -struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn) -{ - struct crypto_alg *alg; - struct crypto_alg *alg2; - struct crypto_tfm *tfm; - - down_read(&crypto_alg_sem); - alg = spawn->alg; - alg2 = alg; - if (alg2) - alg2 = crypto_mod_get(alg2); - up_read(&crypto_alg_sem); - - if (!alg2) { - if (alg) - crypto_shoot_alg(alg); - return ERR_PTR(-EAGAIN); - } - - tfm = __crypto_alloc_tfm(alg, 0); - if (IS_ERR(tfm)) - crypto_mod_put(alg); - - return tfm; -} -EXPORT_SYMBOL_GPL(crypto_spawn_tfm); - -int crypto_register_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&crypto_chain, nb); -} -EXPORT_SYMBOL_GPL(crypto_register_notifier); - -int crypto_unregister_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&crypto_chain, nb); -} -EXPORT_SYMBOL_GPL(crypto_unregister_notifier); - -struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len, - u32 type, u32 mask) -{ - struct rtattr *rta = param; - struct crypto_attr_alg *alga; - - if (!RTA_OK(rta, len)) - return ERR_PTR(-EBADR); - if (rta->rta_type != CRYPTOA_ALG || RTA_PAYLOAD(rta) < sizeof(*alga)) - return ERR_PTR(-EINVAL); - - alga = RTA_DATA(rta); - alga->name[CRYPTO_MAX_ALG_NAME - 1] = 0; - - return crypto_alg_mod_lookup(alga->name, type, mask); -} -EXPORT_SYMBOL_GPL(crypto_get_attr_alg); - -struct crypto_instance *crypto_alloc_instance(const char *name, - struct crypto_alg *alg) -{ - struct crypto_instance *inst; - struct crypto_spawn *spawn; - int err; - - inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); - if (!inst) - return ERR_PTR(-ENOMEM); - - err = -ENAMETOOLONG; - if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", name, - alg->cra_name) >= CRYPTO_MAX_ALG_NAME) - goto err_free_inst; - - if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", - name, alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) - goto err_free_inst; - - spawn = crypto_instance_ctx(inst); - err = crypto_init_spawn(spawn, alg, inst); - - if (err) - goto err_free_inst; - - return inst; - -err_free_inst: - kfree(inst); - return ERR_PTR(err); -} -EXPORT_SYMBOL_GPL(crypto_alloc_instance); - -static int __init crypto_algapi_init(void) -{ - crypto_init_proc(); - return 0; -} - -static void __exit crypto_algapi_exit(void) -{ - crypto_exit_proc(); -} - -module_init(crypto_algapi_init); -module_exit(crypto_algapi_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Cryptographic algorithms API"); diff --git a/trunk/crypto/anubis.c b/trunk/crypto/anubis.c index 1c771f7f4dc5..7e2e1a29800e 100644 --- a/trunk/crypto/anubis.c +++ b/trunk/crypto/anubis.c @@ -461,11 +461,10 @@ static const u32 rc[] = { }; static int anubis_setkey(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) + unsigned int key_len, u32 *flags) { struct anubis_ctx *ctx = crypto_tfm_ctx(tfm); const __be32 *key = (const __be32 *)in_key; - u32 *flags = &tfm->crt_flags; int N, R, i, r; u32 kappa[ANUBIS_MAX_N]; u32 inter[ANUBIS_MAX_N]; diff --git a/trunk/crypto/api.c b/trunk/crypto/api.c index 2e84d4b54790..c11ec1fd4f18 100644 --- a/trunk/crypto/api.c +++ b/trunk/crypto/api.c @@ -15,202 +15,70 @@ * */ -#include +#include +#include +#include #include #include #include -#include -#include -#include +#include #include #include #include "internal.h" LIST_HEAD(crypto_alg_list); -EXPORT_SYMBOL_GPL(crypto_alg_list); DECLARE_RWSEM(crypto_alg_sem); -EXPORT_SYMBOL_GPL(crypto_alg_sem); -BLOCKING_NOTIFIER_HEAD(crypto_chain); -EXPORT_SYMBOL_GPL(crypto_chain); - -static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg) -{ - atomic_inc(&alg->cra_refcnt); - return alg; -} - -struct crypto_alg *crypto_mod_get(struct crypto_alg *alg) +static inline int crypto_alg_get(struct crypto_alg *alg) { - return try_module_get(alg->cra_module) ? crypto_alg_get(alg) : NULL; + return try_module_get(alg->cra_module); } -EXPORT_SYMBOL_GPL(crypto_mod_get); -void crypto_mod_put(struct crypto_alg *alg) +static inline void crypto_alg_put(struct crypto_alg *alg) { - crypto_alg_put(alg); module_put(alg->cra_module); } -EXPORT_SYMBOL_GPL(crypto_mod_put); -struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask) +static struct crypto_alg *crypto_alg_lookup(const char *name) { struct crypto_alg *q, *alg = NULL; - int best = -2; + int best = -1; + if (!name) + return NULL; + + down_read(&crypto_alg_sem); + list_for_each_entry(q, &crypto_alg_list, cra_list) { int exact, fuzzy; - if (crypto_is_moribund(q)) - continue; - - if ((q->cra_flags ^ type) & mask) - continue; - - if (crypto_is_larval(q) && - ((struct crypto_larval *)q)->mask != mask) - continue; - exact = !strcmp(q->cra_driver_name, name); fuzzy = !strcmp(q->cra_name, name); if (!exact && !(fuzzy && q->cra_priority > best)) continue; - if (unlikely(!crypto_mod_get(q))) + if (unlikely(!crypto_alg_get(q))) continue; best = q->cra_priority; if (alg) - crypto_mod_put(alg); + crypto_alg_put(alg); alg = q; if (exact) break; } - - return alg; -} -EXPORT_SYMBOL_GPL(__crypto_alg_lookup); - -static void crypto_larval_destroy(struct crypto_alg *alg) -{ - struct crypto_larval *larval = (void *)alg; - - BUG_ON(!crypto_is_larval(alg)); - if (larval->adult) - crypto_mod_put(larval->adult); - kfree(larval); -} - -static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type, - u32 mask) -{ - struct crypto_alg *alg; - struct crypto_larval *larval; - - larval = kzalloc(sizeof(*larval), GFP_KERNEL); - if (!larval) - return ERR_PTR(-ENOMEM); - - larval->mask = mask; - larval->alg.cra_flags = CRYPTO_ALG_LARVAL | type; - larval->alg.cra_priority = -1; - larval->alg.cra_destroy = crypto_larval_destroy; - - atomic_set(&larval->alg.cra_refcnt, 2); - strlcpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME); - init_completion(&larval->completion); - - down_write(&crypto_alg_sem); - alg = __crypto_alg_lookup(name, type, mask); - if (!alg) { - alg = &larval->alg; - list_add(&alg->cra_list, &crypto_alg_list); - } - up_write(&crypto_alg_sem); - - if (alg != &larval->alg) - kfree(larval); - - return alg; -} - -static void crypto_larval_kill(struct crypto_alg *alg) -{ - struct crypto_larval *larval = (void *)alg; - - down_write(&crypto_alg_sem); - list_del(&alg->cra_list); - up_write(&crypto_alg_sem); - complete(&larval->completion); - crypto_alg_put(alg); -} - -static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) -{ - struct crypto_larval *larval = (void *)alg; - - wait_for_completion_interruptible_timeout(&larval->completion, 60 * HZ); - alg = larval->adult; - if (alg) { - if (!crypto_mod_get(alg)) - alg = ERR_PTR(-EAGAIN); - } else - alg = ERR_PTR(-ENOENT); - crypto_mod_put(&larval->alg); - - return alg; -} - -static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type, - u32 mask) -{ - struct crypto_alg *alg; - - down_read(&crypto_alg_sem); - alg = __crypto_alg_lookup(name, type, mask); + up_read(&crypto_alg_sem); - return alg; } -struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask) +/* A far more intelligent version of this is planned. For now, just + * try an exact match on the name of the algorithm. */ +static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name) { - struct crypto_alg *alg; - struct crypto_alg *larval; - int ok; - - if (!name) - return ERR_PTR(-ENOENT); - - mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD); - type &= mask; - - alg = try_then_request_module(crypto_alg_lookup(name, type, mask), - name); - if (alg) - return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg; - - larval = crypto_larval_alloc(name, type, mask); - if (IS_ERR(larval) || !crypto_is_larval(larval)) - return larval; - - ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval); - if (ok == NOTIFY_DONE) { - request_module("cryptomgr"); - ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval); - } - - if (ok == NOTIFY_STOP) - alg = crypto_larval_wait(larval); - else { - crypto_mod_put(larval); - alg = ERR_PTR(-ENOENT); - } - crypto_larval_kill(larval); - return alg; + return try_then_request_module(crypto_alg_lookup(name), name); } -EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup); static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) { @@ -226,18 +94,17 @@ static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) case CRYPTO_ALG_TYPE_COMPRESS: return crypto_init_compress_flags(tfm, flags); + + default: + break; } - return 0; + BUG(); + return -EINVAL; } static int crypto_init_ops(struct crypto_tfm *tfm) { - const struct crypto_type *type = tfm->__crt_alg->cra_type; - - if (type) - return type->init(tfm); - switch (crypto_tfm_alg_type(tfm)) { case CRYPTO_ALG_TYPE_CIPHER: return crypto_init_cipher_ops(tfm); @@ -258,14 +125,6 @@ static int crypto_init_ops(struct crypto_tfm *tfm) static void crypto_exit_ops(struct crypto_tfm *tfm) { - const struct crypto_type *type = tfm->__crt_alg->cra_type; - - if (type) { - if (type->exit) - type->exit(tfm); - return; - } - switch (crypto_tfm_alg_type(tfm)) { case CRYPTO_ALG_TYPE_CIPHER: crypto_exit_cipher_ops(tfm); @@ -287,67 +146,53 @@ static void crypto_exit_ops(struct crypto_tfm *tfm) static unsigned int crypto_ctxsize(struct crypto_alg *alg, int flags) { - const struct crypto_type *type = alg->cra_type; unsigned int len; - len = alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1); - if (type) - return len + type->ctxsize(alg); - switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { default: BUG(); case CRYPTO_ALG_TYPE_CIPHER: - len += crypto_cipher_ctxsize(alg, flags); + len = crypto_cipher_ctxsize(alg, flags); break; case CRYPTO_ALG_TYPE_DIGEST: - len += crypto_digest_ctxsize(alg, flags); + len = crypto_digest_ctxsize(alg, flags); break; case CRYPTO_ALG_TYPE_COMPRESS: - len += crypto_compress_ctxsize(alg, flags); + len = crypto_compress_ctxsize(alg, flags); break; } - return len; -} - -void crypto_shoot_alg(struct crypto_alg *alg) -{ - down_write(&crypto_alg_sem); - alg->cra_flags |= CRYPTO_ALG_DYING; - up_write(&crypto_alg_sem); + return len + (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1)); } -EXPORT_SYMBOL_GPL(crypto_shoot_alg); -struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags) +struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) { struct crypto_tfm *tfm = NULL; + struct crypto_alg *alg; unsigned int tfm_size; - int err = -ENOMEM; + + alg = crypto_alg_mod_lookup(name); + if (alg == NULL) + goto out; tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, flags); tfm = kzalloc(tfm_size, GFP_KERNEL); if (tfm == NULL) - goto out; + goto out_put; tfm->__crt_alg = alg; - - err = crypto_init_flags(tfm, flags); - if (err) + + if (crypto_init_flags(tfm, flags)) goto out_free_tfm; - err = crypto_init_ops(tfm); - if (err) + if (crypto_init_ops(tfm)) goto out_free_tfm; - if (alg->cra_init && (err = alg->cra_init(tfm))) { - if (err == -EAGAIN) - crypto_shoot_alg(alg); + if (alg->cra_init && alg->cra_init(tfm)) goto cra_init_failed; - } goto out; @@ -355,97 +200,13 @@ struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags) crypto_exit_ops(tfm); out_free_tfm: kfree(tfm); - tfm = ERR_PTR(err); + tfm = NULL; +out_put: + crypto_alg_put(alg); out: return tfm; } -EXPORT_SYMBOL_GPL(__crypto_alloc_tfm); - -struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) -{ - struct crypto_tfm *tfm = NULL; - int err; - - do { - struct crypto_alg *alg; - - alg = crypto_alg_mod_lookup(name, 0, CRYPTO_ALG_ASYNC); - err = PTR_ERR(alg); - if (IS_ERR(alg)) - continue; - - tfm = __crypto_alloc_tfm(alg, flags); - err = 0; - if (IS_ERR(tfm)) { - crypto_mod_put(alg); - err = PTR_ERR(tfm); - tfm = NULL; - } - } while (err == -EAGAIN && !signal_pending(current)); - - return tfm; -} - -/* - * crypto_alloc_base - Locate algorithm and allocate transform - * @alg_name: Name of algorithm - * @type: Type of algorithm - * @mask: Mask for type comparison - * - * crypto_alloc_base() will first attempt to locate an already loaded - * algorithm. If that fails and the kernel supports dynamically loadable - * modules, it will then attempt to load a module of the same name or - * alias. If that fails it will send a query to any loaded crypto manager - * to construct an algorithm on the fly. A refcount is grabbed on the - * algorithm which is then associated with the new transform. - * - * The returned transform is of a non-determinate type. Most people - * should use one of the more specific allocation functions such as - * crypto_alloc_blkcipher. - * - * In case of error the return value is an error pointer. - */ -struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask) -{ - struct crypto_tfm *tfm; - int err; - - for (;;) { - struct crypto_alg *alg; - - alg = crypto_alg_mod_lookup(alg_name, type, mask); - err = PTR_ERR(alg); - tfm = ERR_PTR(err); - if (IS_ERR(alg)) - goto err; - - tfm = __crypto_alloc_tfm(alg, 0); - if (!IS_ERR(tfm)) - break; - - crypto_mod_put(alg); - err = PTR_ERR(tfm); -err: - if (err != -EAGAIN) - break; - if (signal_pending(current)) { - err = -EINTR; - break; - } - }; - - return tfm; -} -EXPORT_SYMBOL_GPL(crypto_alloc_base); - -/* - * crypto_free_tfm - Free crypto transform - * @tfm: Transform to free - * - * crypto_free_tfm() frees up the transform and any associated resources, - * then drops the refcount on the associated algorithm. - */ void crypto_free_tfm(struct crypto_tfm *tfm) { struct crypto_alg *alg; @@ -460,39 +221,108 @@ void crypto_free_tfm(struct crypto_tfm *tfm) if (alg->cra_exit) alg->cra_exit(tfm); crypto_exit_ops(tfm); - crypto_mod_put(alg); + crypto_alg_put(alg); memset(tfm, 0, size); kfree(tfm); } -int crypto_alg_available(const char *name, u32 flags) +static inline int crypto_set_driver_name(struct crypto_alg *alg) { - int ret = 0; - struct crypto_alg *alg = crypto_alg_mod_lookup(name, 0, - CRYPTO_ALG_ASYNC); + static const char suffix[] = "-generic"; + char *driver_name = alg->cra_driver_name; + int len; + + if (*driver_name) + return 0; + + len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); + if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME) + return -ENAMETOOLONG; + + memcpy(driver_name + len, suffix, sizeof(suffix)); + return 0; +} + +int crypto_register_alg(struct crypto_alg *alg) +{ + int ret; + struct crypto_alg *q; + + if (alg->cra_alignmask & (alg->cra_alignmask + 1)) + return -EINVAL; + + if (alg->cra_alignmask & alg->cra_blocksize) + return -EINVAL; + + if (alg->cra_blocksize > PAGE_SIZE / 8) + return -EINVAL; + + if (alg->cra_priority < 0) + return -EINVAL; - if (!IS_ERR(alg)) { - crypto_mod_put(alg); - ret = 1; + ret = crypto_set_driver_name(alg); + if (unlikely(ret)) + return ret; + + down_write(&crypto_alg_sem); + + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (q == alg) { + ret = -EEXIST; + goto out; + } } + list_add(&alg->cra_list, &crypto_alg_list); +out: + up_write(&crypto_alg_sem); return ret; } -EXPORT_SYMBOL_GPL(crypto_alloc_tfm); -EXPORT_SYMBOL_GPL(crypto_free_tfm); -EXPORT_SYMBOL_GPL(crypto_alg_available); +int crypto_unregister_alg(struct crypto_alg *alg) +{ + int ret = -ENOENT; + struct crypto_alg *q; + + BUG_ON(!alg->cra_module); + + down_write(&crypto_alg_sem); + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (alg == q) { + list_del(&alg->cra_list); + ret = 0; + goto out; + } + } +out: + up_write(&crypto_alg_sem); + return ret; +} -int crypto_has_alg(const char *name, u32 type, u32 mask) +int crypto_alg_available(const char *name, u32 flags) { int ret = 0; - struct crypto_alg *alg = crypto_alg_mod_lookup(name, type, mask); + struct crypto_alg *alg = crypto_alg_mod_lookup(name); - if (!IS_ERR(alg)) { - crypto_mod_put(alg); + if (alg) { + crypto_alg_put(alg); ret = 1; } return ret; } -EXPORT_SYMBOL_GPL(crypto_has_alg); + +static int __init init_crypto(void) +{ + printk(KERN_INFO "Initializing Cryptographic API\n"); + crypto_init_proc(); + return 0; +} + +__initcall(init_crypto); + +EXPORT_SYMBOL_GPL(crypto_register_alg); +EXPORT_SYMBOL_GPL(crypto_unregister_alg); +EXPORT_SYMBOL_GPL(crypto_alloc_tfm); +EXPORT_SYMBOL_GPL(crypto_free_tfm); +EXPORT_SYMBOL_GPL(crypto_alg_available); diff --git a/trunk/crypto/arc4.c b/trunk/crypto/arc4.c index 8be47e13a9e3..5edc6a65b987 100644 --- a/trunk/crypto/arc4.c +++ b/trunk/crypto/arc4.c @@ -25,7 +25,7 @@ struct arc4_ctx { }; static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) + unsigned int key_len, u32 *flags) { struct arc4_ctx *ctx = crypto_tfm_ctx(tfm); int i, j = 0, k = 0; diff --git a/trunk/crypto/blkcipher.c b/trunk/crypto/blkcipher.c deleted file mode 100644 index 034c939bf91a..000000000000 --- a/trunk/crypto/blkcipher.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Block chaining cipher operations. - * - * Generic encrypt/decrypt wrapper for ciphers, handles operations across - * multiple page boundaries by using temporary blocks. In user context, - * the kernel is given a chance to schedule us once per page. - * - * Copyright (c) 2006 Herbert Xu - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "internal.h" -#include "scatterwalk.h" - -enum { - BLKCIPHER_WALK_PHYS = 1 << 0, - BLKCIPHER_WALK_SLOW = 1 << 1, - BLKCIPHER_WALK_COPY = 1 << 2, - BLKCIPHER_WALK_DIFF = 1 << 3, -}; - -static int blkcipher_walk_next(struct blkcipher_desc *desc, - struct blkcipher_walk *walk); -static int blkcipher_walk_first(struct blkcipher_desc *desc, - struct blkcipher_walk *walk); - -static inline void blkcipher_map_src(struct blkcipher_walk *walk) -{ - walk->src.virt.addr = scatterwalk_map(&walk->in, 0); -} - -static inline void blkcipher_map_dst(struct blkcipher_walk *walk) -{ - walk->dst.virt.addr = scatterwalk_map(&walk->out, 1); -} - -static inline void blkcipher_unmap_src(struct blkcipher_walk *walk) -{ - scatterwalk_unmap(walk->src.virt.addr, 0); -} - -static inline void blkcipher_unmap_dst(struct blkcipher_walk *walk) -{ - scatterwalk_unmap(walk->dst.virt.addr, 1); -} - -static inline u8 *blkcipher_get_spot(u8 *start, unsigned int len) -{ - if (offset_in_page(start + len) < len) - return (u8 *)((unsigned long)(start + len) & PAGE_MASK); - return start; -} - -static inline unsigned int blkcipher_done_slow(struct crypto_blkcipher *tfm, - struct blkcipher_walk *walk, - unsigned int bsize) -{ - u8 *addr; - unsigned int alignmask = crypto_blkcipher_alignmask(tfm); - - addr = (u8 *)ALIGN((unsigned long)walk->buffer, alignmask + 1); - addr = blkcipher_get_spot(addr, bsize); - scatterwalk_copychunks(addr, &walk->out, bsize, 1); - return bsize; -} - -static inline unsigned int blkcipher_done_fast(struct blkcipher_walk *walk, - unsigned int n) -{ - n = walk->nbytes - n; - - if (walk->flags & BLKCIPHER_WALK_COPY) { - blkcipher_map_dst(walk); - memcpy(walk->dst.virt.addr, walk->page, n); - blkcipher_unmap_dst(walk); - } else if (!(walk->flags & BLKCIPHER_WALK_PHYS)) { - blkcipher_unmap_src(walk); - if (walk->flags & BLKCIPHER_WALK_DIFF) - blkcipher_unmap_dst(walk); - } - - scatterwalk_advance(&walk->in, n); - scatterwalk_advance(&walk->out, n); - - return n; -} - -int blkcipher_walk_done(struct blkcipher_desc *desc, - struct blkcipher_walk *walk, int err) -{ - struct crypto_blkcipher *tfm = desc->tfm; - unsigned int nbytes = 0; - - if (likely(err >= 0)) { - unsigned int bsize = crypto_blkcipher_blocksize(tfm); - unsigned int n; - - if (likely(!(walk->flags & BLKCIPHER_WALK_SLOW))) - n = blkcipher_done_fast(walk, err); - else - n = blkcipher_done_slow(tfm, walk, bsize); - - nbytes = walk->total - n; - err = 0; - } - - scatterwalk_done(&walk->in, 0, nbytes); - scatterwalk_done(&walk->out, 1, nbytes); - - walk->total = nbytes; - walk->nbytes = nbytes; - - if (nbytes) { - crypto_yield(desc->flags); - return blkcipher_walk_next(desc, walk); - } - - if (walk->iv != desc->info) - memcpy(desc->info, walk->iv, crypto_blkcipher_ivsize(tfm)); - if (walk->buffer != walk->page) - kfree(walk->buffer); - if (walk->page) - free_page((unsigned long)walk->page); - - return err; -} -EXPORT_SYMBOL_GPL(blkcipher_walk_done); - -static inline int blkcipher_next_slow(struct blkcipher_desc *desc, - struct blkcipher_walk *walk, - unsigned int bsize, - unsigned int alignmask) -{ - unsigned int n; - - if (walk->buffer) - goto ok; - - walk->buffer = walk->page; - if (walk->buffer) - goto ok; - - n = bsize * 2 + (alignmask & ~(crypto_tfm_ctx_alignment() - 1)); - walk->buffer = kmalloc(n, GFP_ATOMIC); - if (!walk->buffer) - return blkcipher_walk_done(desc, walk, -ENOMEM); - -ok: - walk->dst.virt.addr = (u8 *)ALIGN((unsigned long)walk->buffer, - alignmask + 1); - walk->dst.virt.addr = blkcipher_get_spot(walk->dst.virt.addr, bsize); - walk->src.virt.addr = blkcipher_get_spot(walk->dst.virt.addr + bsize, - bsize); - - scatterwalk_copychunks(walk->src.virt.addr, &walk->in, bsize, 0); - - walk->nbytes = bsize; - walk->flags |= BLKCIPHER_WALK_SLOW; - - return 0; -} - -static inline int blkcipher_next_copy(struct blkcipher_walk *walk) -{ - u8 *tmp = walk->page; - - blkcipher_map_src(walk); - memcpy(tmp, walk->src.virt.addr, walk->nbytes); - blkcipher_unmap_src(walk); - - walk->src.virt.addr = tmp; - walk->dst.virt.addr = tmp; - - return 0; -} - -static inline int blkcipher_next_fast(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - unsigned long diff; - - walk->src.phys.page = scatterwalk_page(&walk->in); - walk->src.phys.offset = offset_in_page(walk->in.offset); - walk->dst.phys.page = scatterwalk_page(&walk->out); - walk->dst.phys.offset = offset_in_page(walk->out.offset); - - if (walk->flags & BLKCIPHER_WALK_PHYS) - return 0; - - diff = walk->src.phys.offset - walk->dst.phys.offset; - diff |= walk->src.virt.page - walk->dst.virt.page; - - blkcipher_map_src(walk); - walk->dst.virt.addr = walk->src.virt.addr; - - if (diff) { - walk->flags |= BLKCIPHER_WALK_DIFF; - blkcipher_map_dst(walk); - } - - return 0; -} - -static int blkcipher_walk_next(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - struct crypto_blkcipher *tfm = desc->tfm; - unsigned int alignmask = crypto_blkcipher_alignmask(tfm); - unsigned int bsize = crypto_blkcipher_blocksize(tfm); - unsigned int n; - int err; - - n = walk->total; - if (unlikely(n < bsize)) { - desc->flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; - return blkcipher_walk_done(desc, walk, -EINVAL); - } - - walk->flags &= ~(BLKCIPHER_WALK_SLOW | BLKCIPHER_WALK_COPY | - BLKCIPHER_WALK_DIFF); - if (!scatterwalk_aligned(&walk->in, alignmask) || - !scatterwalk_aligned(&walk->out, alignmask)) { - walk->flags |= BLKCIPHER_WALK_COPY; - if (!walk->page) { - walk->page = (void *)__get_free_page(GFP_ATOMIC); - if (!walk->page) - n = 0; - } - } - - n = scatterwalk_clamp(&walk->in, n); - n = scatterwalk_clamp(&walk->out, n); - - if (unlikely(n < bsize)) { - err = blkcipher_next_slow(desc, walk, bsize, alignmask); - goto set_phys_lowmem; - } - - walk->nbytes = n; - if (walk->flags & BLKCIPHER_WALK_COPY) { - err = blkcipher_next_copy(walk); - goto set_phys_lowmem; - } - - return blkcipher_next_fast(desc, walk); - -set_phys_lowmem: - if (walk->flags & BLKCIPHER_WALK_PHYS) { - walk->src.phys.page = virt_to_page(walk->src.virt.addr); - walk->dst.phys.page = virt_to_page(walk->dst.virt.addr); - walk->src.phys.offset &= PAGE_SIZE - 1; - walk->dst.phys.offset &= PAGE_SIZE - 1; - } - return err; -} - -static inline int blkcipher_copy_iv(struct blkcipher_walk *walk, - struct crypto_blkcipher *tfm, - unsigned int alignmask) -{ - unsigned bs = crypto_blkcipher_blocksize(tfm); - unsigned int ivsize = crypto_blkcipher_ivsize(tfm); - unsigned int size = bs * 2 + ivsize + max(bs, ivsize) - (alignmask + 1); - u8 *iv; - - size += alignmask & ~(crypto_tfm_ctx_alignment() - 1); - walk->buffer = kmalloc(size, GFP_ATOMIC); - if (!walk->buffer) - return -ENOMEM; - - iv = (u8 *)ALIGN((unsigned long)walk->buffer, alignmask + 1); - iv = blkcipher_get_spot(iv, bs) + bs; - iv = blkcipher_get_spot(iv, bs) + bs; - iv = blkcipher_get_spot(iv, ivsize); - - walk->iv = memcpy(iv, walk->iv, ivsize); - return 0; -} - -int blkcipher_walk_virt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - walk->flags &= ~BLKCIPHER_WALK_PHYS; - return blkcipher_walk_first(desc, walk); -} -EXPORT_SYMBOL_GPL(blkcipher_walk_virt); - -int blkcipher_walk_phys(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - walk->flags |= BLKCIPHER_WALK_PHYS; - return blkcipher_walk_first(desc, walk); -} -EXPORT_SYMBOL_GPL(blkcipher_walk_phys); - -static int blkcipher_walk_first(struct blkcipher_desc *desc, - struct blkcipher_walk *walk) -{ - struct crypto_blkcipher *tfm = desc->tfm; - unsigned int alignmask = crypto_blkcipher_alignmask(tfm); - - walk->nbytes = walk->total; - if (unlikely(!walk->total)) - return 0; - - walk->buffer = NULL; - walk->iv = desc->info; - if (unlikely(((unsigned long)walk->iv & alignmask))) { - int err = blkcipher_copy_iv(walk, tfm, alignmask); - if (err) - return err; - } - - scatterwalk_start(&walk->in, walk->in.sg); - scatterwalk_start(&walk->out, walk->out.sg); - walk->page = NULL; - - return blkcipher_walk_next(desc, walk); -} - -static int setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) -{ - struct blkcipher_alg *cipher = &tfm->__crt_alg->cra_blkcipher; - - if (keylen < cipher->min_keysize || keylen > cipher->max_keysize) { - tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; - return -EINVAL; - } - - return cipher->setkey(tfm, key, keylen); -} - -static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg) -{ - struct blkcipher_alg *cipher = &alg->cra_blkcipher; - unsigned int len = alg->cra_ctxsize; - - if (cipher->ivsize) { - len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1); - len += cipher->ivsize; - } - - return len; -} - -static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm) -{ - struct blkcipher_tfm *crt = &tfm->crt_blkcipher; - struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher; - unsigned long align = crypto_tfm_alg_alignmask(tfm) + 1; - unsigned long addr; - - if (alg->ivsize > PAGE_SIZE / 8) - return -EINVAL; - - crt->setkey = setkey; - crt->encrypt = alg->encrypt; - crt->decrypt = alg->decrypt; - - addr = (unsigned long)crypto_tfm_ctx(tfm); - addr = ALIGN(addr, align); - addr += ALIGN(tfm->__crt_alg->cra_ctxsize, align); - crt->iv = (void *)addr; - - return 0; -} - -static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg) - __attribute_used__; -static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg) -{ - seq_printf(m, "type : blkcipher\n"); - seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); - seq_printf(m, "min keysize : %u\n", alg->cra_blkcipher.min_keysize); - seq_printf(m, "max keysize : %u\n", alg->cra_blkcipher.max_keysize); - seq_printf(m, "ivsize : %u\n", alg->cra_blkcipher.ivsize); -} - -const struct crypto_type crypto_blkcipher_type = { - .ctxsize = crypto_blkcipher_ctxsize, - .init = crypto_init_blkcipher_ops, -#ifdef CONFIG_PROC_FS - .show = crypto_blkcipher_show, -#endif -}; -EXPORT_SYMBOL_GPL(crypto_blkcipher_type); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Generic block chaining cipher type"); diff --git a/trunk/crypto/blowfish.c b/trunk/crypto/blowfish.c index 55238c4e37f0..490265f42b3b 100644 --- a/trunk/crypto/blowfish.c +++ b/trunk/crypto/blowfish.c @@ -399,7 +399,8 @@ static void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) /* * Calculates the blowfish S and P boxes for encryption and decryption. */ -static int bf_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) +static int bf_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int keylen, u32 *flags) { struct bf_ctx *ctx = crypto_tfm_ctx(tfm); u32 *P = ctx->p; diff --git a/trunk/crypto/cast5.c b/trunk/crypto/cast5.c index 13ea60abc19a..08eef58c1d3d 100644 --- a/trunk/crypto/cast5.c +++ b/trunk/crypto/cast5.c @@ -769,7 +769,8 @@ static void key_schedule(u32 * x, u32 * z, u32 * k) } -static int cast5_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned key_len) +static int cast5_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned key_len, u32 *flags) { struct cast5_ctx *c = crypto_tfm_ctx(tfm); int i; @@ -777,6 +778,11 @@ static int cast5_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned key_len) u32 z[4]; u32 k[16]; __be32 p_key[4]; + + if (key_len < 5 || key_len > 16) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } c->rr = key_len <= 10 ? 1 : 0; diff --git a/trunk/crypto/cast6.c b/trunk/crypto/cast6.c index 136ab6dfe8c5..08e33bfc3ad1 100644 --- a/trunk/crypto/cast6.c +++ b/trunk/crypto/cast6.c @@ -382,15 +382,14 @@ static inline void W(u32 *key, unsigned int i) { } static int cast6_setkey(struct crypto_tfm *tfm, const u8 *in_key, - unsigned key_len) + unsigned key_len, u32 *flags) { int i; u32 key[8]; __be32 p_key[8]; /* padded key */ struct cast6_ctx *c = crypto_tfm_ctx(tfm); - u32 *flags = &tfm->crt_flags; - if (key_len % 4 != 0) { + if (key_len < 16 || key_len > 32 || key_len % 4 != 0) { *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } diff --git a/trunk/crypto/cbc.c b/trunk/crypto/cbc.c deleted file mode 100644 index f5542b4db387..000000000000 --- a/trunk/crypto/cbc.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * CBC: Cipher Block Chaining mode - * - * Copyright (c) 2006 Herbert Xu - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -struct crypto_cbc_ctx { - struct crypto_cipher *child; - void (*xor)(u8 *dst, const u8 *src, unsigned int bs); -}; - -static int crypto_cbc_setkey(struct crypto_tfm *parent, const u8 *key, - unsigned int keylen) -{ - struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(parent); - struct crypto_cipher *child = ctx->child; - int err; - - crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); - crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) & - CRYPTO_TFM_REQ_MASK); - err = crypto_cipher_setkey(child, key, keylen); - crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) & - CRYPTO_TFM_RES_MASK); - return err; -} - -static int crypto_cbc_encrypt_segment(struct blkcipher_desc *desc, - struct blkcipher_walk *walk, - struct crypto_cipher *tfm, - void (*xor)(u8 *, const u8 *, - unsigned int)) -{ - void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = - crypto_cipher_alg(tfm)->cia_encrypt; - int bsize = crypto_cipher_blocksize(tfm); - unsigned int nbytes = walk->nbytes; - u8 *src = walk->src.virt.addr; - u8 *dst = walk->dst.virt.addr; - u8 *iv = walk->iv; - - do { - xor(iv, src, bsize); - fn(crypto_cipher_tfm(tfm), dst, iv); - memcpy(iv, dst, bsize); - - src += bsize; - dst += bsize; - } while ((nbytes -= bsize) >= bsize); - - return nbytes; -} - -static int crypto_cbc_encrypt_inplace(struct blkcipher_desc *desc, - struct blkcipher_walk *walk, - struct crypto_cipher *tfm, - void (*xor)(u8 *, const u8 *, - unsigned int)) -{ - void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = - crypto_cipher_alg(tfm)->cia_encrypt; - int bsize = crypto_cipher_blocksize(tfm); - unsigned int nbytes = walk->nbytes; - u8 *src = walk->src.virt.addr; - u8 *iv = walk->iv; - - do { - xor(src, iv, bsize); - fn(crypto_cipher_tfm(tfm), src, src); - iv = src; - - src += bsize; - } while ((nbytes -= bsize) >= bsize); - - memcpy(walk->iv, iv, bsize); - - return nbytes; -} - -static int crypto_cbc_encrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) -{ - struct blkcipher_walk walk; - struct crypto_blkcipher *tfm = desc->tfm; - struct crypto_cbc_ctx *ctx = crypto_blkcipher_ctx(tfm); - struct crypto_cipher *child = ctx->child; - void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); - - while ((nbytes = walk.nbytes)) { - if (walk.src.virt.addr == walk.dst.virt.addr) - nbytes = crypto_cbc_encrypt_inplace(desc, &walk, child, - xor); - else - nbytes = crypto_cbc_encrypt_segment(desc, &walk, child, - xor); - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - return err; -} - -static int crypto_cbc_decrypt_segment(struct blkcipher_desc *desc, - struct blkcipher_walk *walk, - struct crypto_cipher *tfm, - void (*xor)(u8 *, const u8 *, - unsigned int)) -{ - void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = - crypto_cipher_alg(tfm)->cia_decrypt; - int bsize = crypto_cipher_blocksize(tfm); - unsigned int nbytes = walk->nbytes; - u8 *src = walk->src.virt.addr; - u8 *dst = walk->dst.virt.addr; - u8 *iv = walk->iv; - - do { - fn(crypto_cipher_tfm(tfm), dst, src); - xor(dst, iv, bsize); - iv = src; - - src += bsize; - dst += bsize; - } while ((nbytes -= bsize) >= bsize); - - memcpy(walk->iv, iv, bsize); - - return nbytes; -} - -static int crypto_cbc_decrypt_inplace(struct blkcipher_desc *desc, - struct blkcipher_walk *walk, - struct crypto_cipher *tfm, - void (*xor)(u8 *, const u8 *, - unsigned int)) -{ - void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = - crypto_cipher_alg(tfm)->cia_decrypt; - int bsize = crypto_cipher_blocksize(tfm); - unsigned long alignmask = crypto_cipher_alignmask(tfm); - unsigned int nbytes = walk->nbytes; - u8 *src = walk->src.virt.addr; - u8 stack[bsize + alignmask]; - u8 *first_iv = (u8 *)ALIGN((unsigned long)stack, alignmask + 1); - - memcpy(first_iv, walk->iv, bsize); - - /* Start of the last block. */ - src += nbytes - nbytes % bsize - bsize; - memcpy(walk->iv, src, bsize); - - for (;;) { - fn(crypto_cipher_tfm(tfm), src, src); - if ((nbytes -= bsize) < bsize) - break; - xor(src, src - bsize, bsize); - src -= bsize; - } - - xor(src, first_iv, bsize); - - return nbytes; -} - -static int crypto_cbc_decrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) -{ - struct blkcipher_walk walk; - struct crypto_blkcipher *tfm = desc->tfm; - struct crypto_cbc_ctx *ctx = crypto_blkcipher_ctx(tfm); - struct crypto_cipher *child = ctx->child; - void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); - - while ((nbytes = walk.nbytes)) { - if (walk.src.virt.addr == walk.dst.virt.addr) - nbytes = crypto_cbc_decrypt_inplace(desc, &walk, child, - xor); - else - nbytes = crypto_cbc_decrypt_segment(desc, &walk, child, - xor); - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - return err; -} - -static void xor_byte(u8 *a, const u8 *b, unsigned int bs) -{ - do { - *a++ ^= *b++; - } while (--bs); -} - -static void xor_quad(u8 *dst, const u8 *src, unsigned int bs) -{ - u32 *a = (u32 *)dst; - u32 *b = (u32 *)src; - - do { - *a++ ^= *b++; - } while ((bs -= 4)); -} - -static void xor_64(u8 *a, const u8 *b, unsigned int bs) -{ - ((u32 *)a)[0] ^= ((u32 *)b)[0]; - ((u32 *)a)[1] ^= ((u32 *)b)[1]; -} - -static void xor_128(u8 *a, const u8 *b, unsigned int bs) -{ - ((u32 *)a)[0] ^= ((u32 *)b)[0]; - ((u32 *)a)[1] ^= ((u32 *)b)[1]; - ((u32 *)a)[2] ^= ((u32 *)b)[2]; - ((u32 *)a)[3] ^= ((u32 *)b)[3]; -} - -static int crypto_cbc_init_tfm(struct crypto_tfm *tfm) -{ - struct crypto_instance *inst = (void *)tfm->__crt_alg; - struct crypto_spawn *spawn = crypto_instance_ctx(inst); - struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(tfm); - - switch (crypto_tfm_alg_blocksize(tfm)) { - case 8: - ctx->xor = xor_64; - break; - - case 16: - ctx->xor = xor_128; - break; - - default: - if (crypto_tfm_alg_blocksize(tfm) % 4) - ctx->xor = xor_byte; - else - ctx->xor = xor_quad; - } - - tfm = crypto_spawn_tfm(spawn); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - ctx->child = crypto_cipher_cast(tfm); - return 0; -} - -static void crypto_cbc_exit_tfm(struct crypto_tfm *tfm) -{ - struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(tfm); - crypto_free_cipher(ctx->child); -} - -static struct crypto_instance *crypto_cbc_alloc(void *param, unsigned int len) -{ - struct crypto_instance *inst; - struct crypto_alg *alg; - - alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER, - CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC); - if (IS_ERR(alg)) - return ERR_PTR(PTR_ERR(alg)); - - inst = crypto_alloc_instance("cbc", alg); - if (IS_ERR(inst)) - goto out_put_alg; - - inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER; - inst->alg.cra_priority = alg->cra_priority; - inst->alg.cra_blocksize = alg->cra_blocksize; - inst->alg.cra_alignmask = alg->cra_alignmask; - inst->alg.cra_type = &crypto_blkcipher_type; - - if (!(alg->cra_blocksize % 4)) - inst->alg.cra_alignmask |= 3; - inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize; - inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize; - inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize; - - inst->alg.cra_ctxsize = sizeof(struct crypto_cbc_ctx); - - inst->alg.cra_init = crypto_cbc_init_tfm; - inst->alg.cra_exit = crypto_cbc_exit_tfm; - - inst->alg.cra_blkcipher.setkey = crypto_cbc_setkey; - inst->alg.cra_blkcipher.encrypt = crypto_cbc_encrypt; - inst->alg.cra_blkcipher.decrypt = crypto_cbc_decrypt; - -out_put_alg: - crypto_mod_put(alg); - return inst; -} - -static void crypto_cbc_free(struct crypto_instance *inst) -{ - crypto_drop_spawn(crypto_instance_ctx(inst)); - kfree(inst); -} - -static struct crypto_template crypto_cbc_tmpl = { - .name = "cbc", - .alloc = crypto_cbc_alloc, - .free = crypto_cbc_free, - .module = THIS_MODULE, -}; - -static int __init crypto_cbc_module_init(void) -{ - return crypto_register_template(&crypto_cbc_tmpl); -} - -static void __exit crypto_cbc_module_exit(void) -{ - crypto_unregister_template(&crypto_cbc_tmpl); -} - -module_init(crypto_cbc_module_init); -module_exit(crypto_cbc_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("CBC block cipher algorithm"); diff --git a/trunk/crypto/cipher.c b/trunk/crypto/cipher.c index 9e03701cfdcc..b899eb97abd7 100644 --- a/trunk/crypto/cipher.c +++ b/trunk/crypto/cipher.c @@ -23,28 +23,6 @@ #include "internal.h" #include "scatterwalk.h" -struct cipher_alg_compat { - unsigned int cia_min_keysize; - unsigned int cia_max_keysize; - int (*cia_setkey)(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen); - void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); - void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); - - unsigned int (*cia_encrypt_ecb)(const struct cipher_desc *desc, - u8 *dst, const u8 *src, - unsigned int nbytes); - unsigned int (*cia_decrypt_ecb)(const struct cipher_desc *desc, - u8 *dst, const u8 *src, - unsigned int nbytes); - unsigned int (*cia_encrypt_cbc)(const struct cipher_desc *desc, - u8 *dst, const u8 *src, - unsigned int nbytes); - unsigned int (*cia_decrypt_cbc)(const struct cipher_desc *desc, - u8 *dst, const u8 *src, - unsigned int nbytes); -}; - static inline void xor_64(u8 *a, const u8 *b) { ((u32 *)a)[0] ^= ((u32 *)b)[0]; @@ -67,10 +45,15 @@ static unsigned int crypt_slow(const struct cipher_desc *desc, u8 buffer[bsize * 2 + alignmask]; u8 *src = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); u8 *dst = src + bsize; + unsigned int n; + + n = scatterwalk_copychunks(src, in, bsize, 0); + scatterwalk_advance(in, n); - scatterwalk_copychunks(src, in, bsize, 0); desc->prfn(desc, dst, src, bsize); - scatterwalk_copychunks(dst, out, bsize, 1); + + n = scatterwalk_copychunks(dst, out, bsize, 1); + scatterwalk_advance(out, n); return bsize; } @@ -81,16 +64,12 @@ static inline unsigned int crypt_fast(const struct cipher_desc *desc, unsigned int nbytes, u8 *tmp) { u8 *src, *dst; - u8 *real_src, *real_dst; - - real_src = scatterwalk_map(in, 0); - real_dst = scatterwalk_map(out, 1); - src = real_src; - dst = scatterwalk_samebuf(in, out) ? src : real_dst; + src = in->data; + dst = scatterwalk_samebuf(in, out) ? src : out->data; if (tmp) { - memcpy(tmp, src, nbytes); + memcpy(tmp, in->data, nbytes); src = tmp; dst = tmp; } @@ -98,10 +77,7 @@ static inline unsigned int crypt_fast(const struct cipher_desc *desc, nbytes = desc->prfn(desc, dst, src, nbytes); if (tmp) - memcpy(real_dst, tmp, nbytes); - - scatterwalk_unmap(real_src, 0); - scatterwalk_unmap(real_dst, 1); + memcpy(out->data, tmp, nbytes); scatterwalk_advance(in, nbytes); scatterwalk_advance(out, nbytes); @@ -150,6 +126,9 @@ static int crypt(const struct cipher_desc *desc, tmp = (u8 *)buffer; } + scatterwalk_map(&walk_in, 0); + scatterwalk_map(&walk_out, 1); + n = scatterwalk_clamp(&walk_in, n); n = scatterwalk_clamp(&walk_out, n); @@ -166,7 +145,7 @@ static int crypt(const struct cipher_desc *desc, if (!nbytes) break; - crypto_yield(tfm->crt_flags); + crypto_yield(tfm); } if (buffer) @@ -285,12 +264,12 @@ static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; - tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) { tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } else - return cia->cia_setkey(tfm, key, keylen); + return cia->cia_setkey(tfm, key, keylen, + &tfm->crt_flags); } static int ecb_encrypt(struct crypto_tfm *tfm, @@ -298,7 +277,7 @@ static int ecb_encrypt(struct crypto_tfm *tfm, struct scatterlist *src, unsigned int nbytes) { struct cipher_desc desc; - struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher; + struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; desc.tfm = tfm; desc.crfn = cipher->cia_encrypt; @@ -313,7 +292,7 @@ static int ecb_decrypt(struct crypto_tfm *tfm, unsigned int nbytes) { struct cipher_desc desc; - struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher; + struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; desc.tfm = tfm; desc.crfn = cipher->cia_decrypt; @@ -328,7 +307,7 @@ static int cbc_encrypt(struct crypto_tfm *tfm, unsigned int nbytes) { struct cipher_desc desc; - struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher; + struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; desc.tfm = tfm; desc.crfn = cipher->cia_encrypt; @@ -344,7 +323,7 @@ static int cbc_encrypt_iv(struct crypto_tfm *tfm, unsigned int nbytes, u8 *iv) { struct cipher_desc desc; - struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher; + struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; desc.tfm = tfm; desc.crfn = cipher->cia_encrypt; @@ -360,7 +339,7 @@ static int cbc_decrypt(struct crypto_tfm *tfm, unsigned int nbytes) { struct cipher_desc desc; - struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher; + struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; desc.tfm = tfm; desc.crfn = cipher->cia_decrypt; @@ -376,7 +355,7 @@ static int cbc_decrypt_iv(struct crypto_tfm *tfm, unsigned int nbytes, u8 *iv) { struct cipher_desc desc; - struct cipher_alg_compat *cipher = (void *)&tfm->__crt_alg->cra_cipher; + struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; desc.tfm = tfm; desc.crfn = cipher->cia_decrypt; @@ -409,67 +388,17 @@ int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags) return 0; } -static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *, - const u8 *), - struct crypto_tfm *tfm, - u8 *dst, const u8 *src) -{ - unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); - unsigned int size = crypto_tfm_alg_blocksize(tfm); - u8 buffer[size + alignmask]; - u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); - - memcpy(tmp, src, size); - fn(tfm, tmp, tmp); - memcpy(dst, tmp, size); -} - -static void cipher_encrypt_unaligned(struct crypto_tfm *tfm, - u8 *dst, const u8 *src) -{ - unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); - struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; - - if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) { - cipher_crypt_unaligned(cipher->cia_encrypt, tfm, dst, src); - return; - } - - cipher->cia_encrypt(tfm, dst, src); -} - -static void cipher_decrypt_unaligned(struct crypto_tfm *tfm, - u8 *dst, const u8 *src) -{ - unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); - struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; - - if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) { - cipher_crypt_unaligned(cipher->cia_decrypt, tfm, dst, src); - return; - } - - cipher->cia_decrypt(tfm, dst, src); -} - int crypto_init_cipher_ops(struct crypto_tfm *tfm) { int ret = 0; struct cipher_tfm *ops = &tfm->crt_cipher; - struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher; ops->cit_setkey = setkey; - ops->cit_encrypt_one = crypto_tfm_alg_alignmask(tfm) ? - cipher_encrypt_unaligned : cipher->cia_encrypt; - ops->cit_decrypt_one = crypto_tfm_alg_alignmask(tfm) ? - cipher_decrypt_unaligned : cipher->cia_decrypt; switch (tfm->crt_cipher.cit_mode) { case CRYPTO_TFM_MODE_ECB: ops->cit_encrypt = ecb_encrypt; ops->cit_decrypt = ecb_decrypt; - ops->cit_encrypt_iv = nocrypt_iv; - ops->cit_decrypt_iv = nocrypt_iv; break; case CRYPTO_TFM_MODE_CBC: diff --git a/trunk/crypto/crc32c.c b/trunk/crypto/crc32c.c index 0fa744392a4c..f2660123aeb4 100644 --- a/trunk/crypto/crc32c.c +++ b/trunk/crypto/crc32c.c @@ -16,14 +16,14 @@ #include #include #include -#include +#include +#include #define CHKSUM_BLOCK_SIZE 32 #define CHKSUM_DIGEST_SIZE 4 struct chksum_ctx { u32 crc; - u32 key; }; /* @@ -35,7 +35,7 @@ static void chksum_init(struct crypto_tfm *tfm) { struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); - mctx->crc = mctx->key; + mctx->crc = ~(u32)0; /* common usage */ } /* @@ -44,15 +44,16 @@ static void chksum_init(struct crypto_tfm *tfm) * the seed. */ static int chksum_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) + unsigned int keylen, u32 *flags) { struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); if (keylen != sizeof(mctx->crc)) { - tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + if (flags) + *flags = CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } - mctx->key = le32_to_cpu(*(__le32 *)key); + mctx->crc = __cpu_to_le32(*(u32 *)key); return 0; } @@ -60,23 +61,19 @@ static void chksum_update(struct crypto_tfm *tfm, const u8 *data, unsigned int length) { struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); + u32 mcrc; - mctx->crc = crc32c(mctx->crc, data, length); + mcrc = crc32c(mctx->crc, data, (size_t)length); + + mctx->crc = mcrc; } static void chksum_final(struct crypto_tfm *tfm, u8 *out) { struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); + u32 mcrc = (mctx->crc ^ ~(u32)0); - *(__le32 *)out = ~cpu_to_le32(mctx->crc); -} - -static int crc32c_cra_init(struct crypto_tfm *tfm) -{ - struct chksum_ctx *mctx = crypto_tfm_ctx(tfm); - - mctx->key = ~0; - return 0; + *(u32 *)out = __le32_to_cpu(mcrc); } static struct crypto_alg alg = { @@ -86,7 +83,6 @@ static struct crypto_alg alg = { .cra_ctxsize = sizeof(struct chksum_ctx), .cra_module = THIS_MODULE, .cra_list = LIST_HEAD_INIT(alg.cra_list), - .cra_init = crc32c_cra_init, .cra_u = { .digest = { .dia_digestsize= CHKSUM_DIGEST_SIZE, diff --git a/trunk/crypto/crypto_null.c b/trunk/crypto/crypto_null.c index 24dbb5d8617e..a0d956b52949 100644 --- a/trunk/crypto/crypto_null.c +++ b/trunk/crypto/crypto_null.c @@ -48,7 +48,7 @@ static void null_final(struct crypto_tfm *tfm, u8 *out) { } static int null_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) + unsigned int keylen, u32 *flags) { return 0; } static void null_crypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) diff --git a/trunk/crypto/cryptomgr.c b/trunk/crypto/cryptomgr.c deleted file mode 100644 index 9b5b15601068..000000000000 --- a/trunk/crypto/cryptomgr.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Create default crypto algorithm instances. - * - * Copyright (c) 2006 Herbert Xu - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "internal.h" - -struct cryptomgr_param { - struct work_struct work; - - struct { - struct rtattr attr; - struct crypto_attr_alg data; - } alg; - - struct { - u32 type; - u32 mask; - char name[CRYPTO_MAX_ALG_NAME]; - } larval; - - char template[CRYPTO_MAX_ALG_NAME]; -}; - -static void cryptomgr_probe(void *data) -{ - struct cryptomgr_param *param = data; - struct crypto_template *tmpl; - struct crypto_instance *inst; - int err; - - tmpl = crypto_lookup_template(param->template); - if (!tmpl) - goto err; - - do { - inst = tmpl->alloc(¶m->alg, sizeof(param->alg)); - if (IS_ERR(inst)) - err = PTR_ERR(inst); - else if ((err = crypto_register_instance(tmpl, inst))) - tmpl->free(inst); - } while (err == -EAGAIN && !signal_pending(current)); - - crypto_tmpl_put(tmpl); - - if (err) - goto err; - -out: - kfree(param); - return; - -err: - crypto_larval_error(param->larval.name, param->larval.type, - param->larval.mask); - goto out; -} - -static int cryptomgr_schedule_probe(struct crypto_larval *larval) -{ - struct cryptomgr_param *param; - const char *name = larval->alg.cra_name; - const char *p; - unsigned int len; - - param = kmalloc(sizeof(*param), GFP_KERNEL); - if (!param) - goto err; - - for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++) - ; - - len = p - name; - if (!len || *p != '(') - goto err_free_param; - - memcpy(param->template, name, len); - param->template[len] = 0; - - name = p + 1; - for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++) - ; - - len = p - name; - if (!len || *p != ')' || p[1]) - goto err_free_param; - - param->alg.attr.rta_len = sizeof(param->alg); - param->alg.attr.rta_type = CRYPTOA_ALG; - memcpy(param->alg.data.name, name, len); - param->alg.data.name[len] = 0; - - memcpy(param->larval.name, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); - param->larval.type = larval->alg.cra_flags; - param->larval.mask = larval->mask; - - INIT_WORK(¶m->work, cryptomgr_probe, param); - schedule_work(¶m->work); - - return NOTIFY_STOP; - -err_free_param: - kfree(param); -err: - return NOTIFY_OK; -} - -static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, - void *data) -{ - switch (msg) { - case CRYPTO_MSG_ALG_REQUEST: - return cryptomgr_schedule_probe(data); - } - - return NOTIFY_DONE; -} - -static struct notifier_block cryptomgr_notifier = { - .notifier_call = cryptomgr_notify, -}; - -static int __init cryptomgr_init(void) -{ - return crypto_register_notifier(&cryptomgr_notifier); -} - -static void __exit cryptomgr_exit(void) -{ - int err = crypto_unregister_notifier(&cryptomgr_notifier); - BUG_ON(err); -} - -module_init(cryptomgr_init); -module_exit(cryptomgr_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Crypto Algorithm Manager"); diff --git a/trunk/crypto/des.c b/trunk/crypto/des.c index 1df3a714fa47..a9d3c235a6af 100644 --- a/trunk/crypto/des.c +++ b/trunk/crypto/des.c @@ -784,10 +784,9 @@ static void dkey(u32 *pe, const u8 *k) } static int des_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) + unsigned int keylen, u32 *flags) { struct des_ctx *dctx = crypto_tfm_ctx(tfm); - u32 *flags = &tfm->crt_flags; u32 tmp[DES_EXPKEY_WORDS]; int ret; @@ -865,12 +864,11 @@ static void des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) * */ static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) + unsigned int keylen, u32 *flags) { const u32 *K = (const u32 *)key; struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm); u32 *expkey = dctx->expkey; - u32 *flags = &tfm->crt_flags; if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) || !((K[2] ^ K[4]) | (K[3] ^ K[5])))) diff --git a/trunk/crypto/digest.c b/trunk/crypto/digest.c index 0155a94e4b15..603006a7bef2 100644 --- a/trunk/crypto/digest.c +++ b/trunk/crypto/digest.c @@ -11,89 +11,29 @@ * any later version. * */ - +#include #include #include #include -#include -#include - +#include #include "internal.h" -#include "scatterwalk.h" - -void crypto_digest_init(struct crypto_tfm *tfm) -{ - struct crypto_hash *hash = crypto_hash_cast(tfm); - struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags }; - - crypto_hash_init(&desc); -} -EXPORT_SYMBOL_GPL(crypto_digest_init); - -void crypto_digest_update(struct crypto_tfm *tfm, - struct scatterlist *sg, unsigned int nsg) -{ - struct crypto_hash *hash = crypto_hash_cast(tfm); - struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags }; - unsigned int nbytes = 0; - unsigned int i; - for (i = 0; i < nsg; i++) - nbytes += sg[i].length; - - crypto_hash_update(&desc, sg, nbytes); -} -EXPORT_SYMBOL_GPL(crypto_digest_update); - -void crypto_digest_final(struct crypto_tfm *tfm, u8 *out) +static void init(struct crypto_tfm *tfm) { - struct crypto_hash *hash = crypto_hash_cast(tfm); - struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags }; - - crypto_hash_final(&desc, out); -} -EXPORT_SYMBOL_GPL(crypto_digest_final); - -void crypto_digest_digest(struct crypto_tfm *tfm, - struct scatterlist *sg, unsigned int nsg, u8 *out) -{ - struct crypto_hash *hash = crypto_hash_cast(tfm); - struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags }; - unsigned int nbytes = 0; - unsigned int i; - - for (i = 0; i < nsg; i++) - nbytes += sg[i].length; - - crypto_hash_digest(&desc, sg, nbytes, out); -} -EXPORT_SYMBOL_GPL(crypto_digest_digest); - -static int init(struct hash_desc *desc) -{ - struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm); - tfm->__crt_alg->cra_digest.dia_init(tfm); - return 0; } -static int update(struct hash_desc *desc, - struct scatterlist *sg, unsigned int nbytes) +static void update(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg) { - struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm); + unsigned int i; unsigned int alignmask = crypto_tfm_alg_alignmask(tfm); - if (!nbytes) - return 0; - - for (;;) { - struct page *pg = sg->page; - unsigned int offset = sg->offset; - unsigned int l = sg->length; + for (i = 0; i < nsg; i++) { - if (unlikely(l > nbytes)) - l = nbytes; - nbytes -= l; + struct page *pg = sg[i].page; + unsigned int offset = sg[i].offset; + unsigned int l = sg[i].length; do { unsigned int bytes_from_page = min(l, ((unsigned int) @@ -115,60 +55,41 @@ static int update(struct hash_desc *desc, tfm->__crt_alg->cra_digest.dia_update(tfm, p, bytes_from_page); crypto_kunmap(src, 0); - crypto_yield(desc->flags); + crypto_yield(tfm); offset = 0; pg++; l -= bytes_from_page; } while (l > 0); - - if (!nbytes) - break; - sg = sg_next(sg); } - - return 0; } -static int final(struct hash_desc *desc, u8 *out) +static void final(struct crypto_tfm *tfm, u8 *out) { - struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm); unsigned long alignmask = crypto_tfm_alg_alignmask(tfm); - struct digest_alg *digest = &tfm->__crt_alg->cra_digest; - if (unlikely((unsigned long)out & alignmask)) { - unsigned long align = alignmask + 1; - unsigned long addr = (unsigned long)crypto_tfm_ctx(tfm); - u8 *dst = (u8 *)ALIGN(addr, align) + - ALIGN(tfm->__crt_alg->cra_ctxsize, align); - - digest->dia_final(tfm, dst); - memcpy(out, dst, digest->dia_digestsize); + unsigned int size = crypto_tfm_alg_digestsize(tfm); + u8 buffer[size + alignmask]; + u8 *dst = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); + tfm->__crt_alg->cra_digest.dia_final(tfm, dst); + memcpy(out, dst, size); } else - digest->dia_final(tfm, out); - - return 0; -} - -static int nosetkey(struct crypto_hash *tfm, const u8 *key, unsigned int keylen) -{ - crypto_hash_clear_flags(tfm, CRYPTO_TFM_RES_MASK); - return -ENOSYS; + tfm->__crt_alg->cra_digest.dia_final(tfm, out); } -static int setkey(struct crypto_hash *hash, const u8 *key, unsigned int keylen) +static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { - struct crypto_tfm *tfm = crypto_hash_tfm(hash); - - crypto_hash_clear_flags(hash, CRYPTO_TFM_RES_MASK); - return tfm->__crt_alg->cra_digest.dia_setkey(tfm, key, keylen); + u32 flags; + if (tfm->__crt_alg->cra_digest.dia_setkey == NULL) + return -ENOSYS; + return tfm->__crt_alg->cra_digest.dia_setkey(tfm, key, keylen, &flags); } -static int digest(struct hash_desc *desc, - struct scatterlist *sg, unsigned int nbytes, u8 *out) +static void digest(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg, u8 *out) { - init(desc); - update(desc, sg, nbytes); - return final(desc, out); + init(tfm); + update(tfm, sg, nsg); + final(tfm, out); } int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) @@ -178,22 +99,18 @@ int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) int crypto_init_digest_ops(struct crypto_tfm *tfm) { - struct hash_tfm *ops = &tfm->crt_hash; - struct digest_alg *dalg = &tfm->__crt_alg->cra_digest; - - if (dalg->dia_digestsize > crypto_tfm_alg_blocksize(tfm)) - return -EINVAL; + struct digest_tfm *ops = &tfm->crt_digest; - ops->init = init; - ops->update = update; - ops->final = final; - ops->digest = digest; - ops->setkey = dalg->dia_setkey ? setkey : nosetkey; - ops->digestsize = dalg->dia_digestsize; + ops->dit_init = init; + ops->dit_update = update; + ops->dit_final = final; + ops->dit_digest = digest; + ops->dit_setkey = setkey; - return 0; + return crypto_alloc_hmac_block(tfm); } void crypto_exit_digest_ops(struct crypto_tfm *tfm) { + crypto_free_hmac_block(tfm); } diff --git a/trunk/crypto/ecb.c b/trunk/crypto/ecb.c deleted file mode 100644 index f239aa9c4017..000000000000 --- a/trunk/crypto/ecb.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * ECB: Electronic CodeBook mode - * - * Copyright (c) 2006 Herbert Xu - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -struct crypto_ecb_ctx { - struct crypto_cipher *child; -}; - -static int crypto_ecb_setkey(struct crypto_tfm *parent, const u8 *key, - unsigned int keylen) -{ - struct crypto_ecb_ctx *ctx = crypto_tfm_ctx(parent); - struct crypto_cipher *child = ctx->child; - int err; - - crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); - crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) & - CRYPTO_TFM_REQ_MASK); - err = crypto_cipher_setkey(child, key, keylen); - crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) & - CRYPTO_TFM_RES_MASK); - return err; -} - -static int crypto_ecb_crypt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk, - struct crypto_cipher *tfm, - void (*fn)(struct crypto_tfm *, u8 *, const u8 *)) -{ - int bsize = crypto_cipher_blocksize(tfm); - unsigned int nbytes; - int err; - - err = blkcipher_walk_virt(desc, walk); - - while ((nbytes = walk->nbytes)) { - u8 *wsrc = walk->src.virt.addr; - u8 *wdst = walk->dst.virt.addr; - - do { - fn(crypto_cipher_tfm(tfm), wdst, wsrc); - - wsrc += bsize; - wdst += bsize; - } while ((nbytes -= bsize) >= bsize); - - err = blkcipher_walk_done(desc, walk, nbytes); - } - - return err; -} - -static int crypto_ecb_encrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) -{ - struct blkcipher_walk walk; - struct crypto_blkcipher *tfm = desc->tfm; - struct crypto_ecb_ctx *ctx = crypto_blkcipher_ctx(tfm); - struct crypto_cipher *child = ctx->child; - - blkcipher_walk_init(&walk, dst, src, nbytes); - return crypto_ecb_crypt(desc, &walk, child, - crypto_cipher_alg(child)->cia_encrypt); -} - -static int crypto_ecb_decrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) -{ - struct blkcipher_walk walk; - struct crypto_blkcipher *tfm = desc->tfm; - struct crypto_ecb_ctx *ctx = crypto_blkcipher_ctx(tfm); - struct crypto_cipher *child = ctx->child; - - blkcipher_walk_init(&walk, dst, src, nbytes); - return crypto_ecb_crypt(desc, &walk, child, - crypto_cipher_alg(child)->cia_decrypt); -} - -static int crypto_ecb_init_tfm(struct crypto_tfm *tfm) -{ - struct crypto_instance *inst = (void *)tfm->__crt_alg; - struct crypto_spawn *spawn = crypto_instance_ctx(inst); - struct crypto_ecb_ctx *ctx = crypto_tfm_ctx(tfm); - - tfm = crypto_spawn_tfm(spawn); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - ctx->child = crypto_cipher_cast(tfm); - return 0; -} - -static void crypto_ecb_exit_tfm(struct crypto_tfm *tfm) -{ - struct crypto_ecb_ctx *ctx = crypto_tfm_ctx(tfm); - crypto_free_cipher(ctx->child); -} - -static struct crypto_instance *crypto_ecb_alloc(void *param, unsigned int len) -{ - struct crypto_instance *inst; - struct crypto_alg *alg; - - alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_CIPHER, - CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC); - if (IS_ERR(alg)) - return ERR_PTR(PTR_ERR(alg)); - - inst = crypto_alloc_instance("ecb", alg); - if (IS_ERR(inst)) - goto out_put_alg; - - inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER; - inst->alg.cra_priority = alg->cra_priority; - inst->alg.cra_blocksize = alg->cra_blocksize; - inst->alg.cra_alignmask = alg->cra_alignmask; - inst->alg.cra_type = &crypto_blkcipher_type; - - inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize; - inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize; - - inst->alg.cra_ctxsize = sizeof(struct crypto_ecb_ctx); - - inst->alg.cra_init = crypto_ecb_init_tfm; - inst->alg.cra_exit = crypto_ecb_exit_tfm; - - inst->alg.cra_blkcipher.setkey = crypto_ecb_setkey; - inst->alg.cra_blkcipher.encrypt = crypto_ecb_encrypt; - inst->alg.cra_blkcipher.decrypt = crypto_ecb_decrypt; - -out_put_alg: - crypto_mod_put(alg); - return inst; -} - -static void crypto_ecb_free(struct crypto_instance *inst) -{ - crypto_drop_spawn(crypto_instance_ctx(inst)); - kfree(inst); -} - -static struct crypto_template crypto_ecb_tmpl = { - .name = "ecb", - .alloc = crypto_ecb_alloc, - .free = crypto_ecb_free, - .module = THIS_MODULE, -}; - -static int __init crypto_ecb_module_init(void) -{ - return crypto_register_template(&crypto_ecb_tmpl); -} - -static void __exit crypto_ecb_module_exit(void) -{ - crypto_unregister_template(&crypto_ecb_tmpl); -} - -module_init(crypto_ecb_module_init); -module_exit(crypto_ecb_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("ECB block cipher algorithm"); diff --git a/trunk/crypto/hash.c b/trunk/crypto/hash.c deleted file mode 100644 index cdec23d885fe..000000000000 --- a/trunk/crypto/hash.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Cryptographic Hash operations. - * - * Copyright (c) 2006 Herbert Xu - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - */ - -#include -#include -#include -#include - -#include "internal.h" - -static unsigned int crypto_hash_ctxsize(struct crypto_alg *alg) -{ - return alg->cra_ctxsize; -} - -static int crypto_init_hash_ops(struct crypto_tfm *tfm) -{ - struct hash_tfm *crt = &tfm->crt_hash; - struct hash_alg *alg = &tfm->__crt_alg->cra_hash; - - if (alg->digestsize > crypto_tfm_alg_blocksize(tfm)) - return -EINVAL; - - crt->init = alg->init; - crt->update = alg->update; - crt->final = alg->final; - crt->digest = alg->digest; - crt->setkey = alg->setkey; - crt->digestsize = alg->digestsize; - - return 0; -} - -static void crypto_hash_show(struct seq_file *m, struct crypto_alg *alg) - __attribute_used__; -static void crypto_hash_show(struct seq_file *m, struct crypto_alg *alg) -{ - seq_printf(m, "type : hash\n"); - seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); - seq_printf(m, "digestsize : %u\n", alg->cra_hash.digestsize); -} - -const struct crypto_type crypto_hash_type = { - .ctxsize = crypto_hash_ctxsize, - .init = crypto_init_hash_ops, -#ifdef CONFIG_PROC_FS - .show = crypto_hash_show, -#endif -}; -EXPORT_SYMBOL_GPL(crypto_hash_type); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Generic cryptographic hash type"); diff --git a/trunk/crypto/hmac.c b/trunk/crypto/hmac.c index b521bcd2b2c6..46120dee5ada 100644 --- a/trunk/crypto/hmac.c +++ b/trunk/crypto/hmac.c @@ -4,261 +4,121 @@ * HMAC: Keyed-Hashing for Message Authentication (RFC2104). * * Copyright (c) 2002 James Morris - * Copyright (c) 2006 Herbert Xu * * The HMAC implementation is derived from USAGI. * Copyright (c) 2002 Kazunori Miyazawa / USAGI * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) + * Software Foundation; either version 2 of the License, or (at your option) * any later version. * */ - -#include -#include -#include -#include -#include -#include +#include +#include +#include #include -#include - -struct hmac_ctx { - struct crypto_hash *child; -}; - -static inline void *align_ptr(void *p, unsigned int align) -{ - return (void *)ALIGN((unsigned long)p, align); -} - -static inline struct hmac_ctx *hmac_ctx(struct crypto_hash *tfm) -{ - return align_ptr(crypto_hash_ctx_aligned(tfm) + - crypto_hash_blocksize(tfm) * 2 + - crypto_hash_digestsize(tfm), sizeof(void *)); -} - -static int hmac_setkey(struct crypto_hash *parent, - const u8 *inkey, unsigned int keylen) -{ - int bs = crypto_hash_blocksize(parent); - int ds = crypto_hash_digestsize(parent); - char *ipad = crypto_hash_ctx_aligned(parent); - char *opad = ipad + bs; - char *digest = opad + bs; - struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *)); - struct crypto_hash *tfm = ctx->child; - unsigned int i; - - if (keylen > bs) { - struct hash_desc desc; - struct scatterlist tmp; - int err; - - desc.tfm = tfm; - desc.flags = crypto_hash_get_flags(parent); - desc.flags &= CRYPTO_TFM_REQ_MAY_SLEEP; - sg_set_buf(&tmp, inkey, keylen); - - err = crypto_hash_digest(&desc, &tmp, keylen, digest); - if (err) - return err; - - inkey = digest; - keylen = ds; - } - - memcpy(ipad, inkey, keylen); - memset(ipad + keylen, 0, bs - keylen); - memcpy(opad, ipad, bs); - - for (i = 0; i < bs; i++) { - ipad[i] ^= 0x36; - opad[i] ^= 0x5c; - } - - return 0; -} +#include +#include "internal.h" -static int hmac_init(struct hash_desc *pdesc) +static void hash_key(struct crypto_tfm *tfm, u8 *key, unsigned int keylen) { - struct crypto_hash *parent = pdesc->tfm; - int bs = crypto_hash_blocksize(parent); - int ds = crypto_hash_digestsize(parent); - char *ipad = crypto_hash_ctx_aligned(parent); - struct hmac_ctx *ctx = align_ptr(ipad + bs * 2 + ds, sizeof(void *)); - struct hash_desc desc; struct scatterlist tmp; - int err; - - desc.tfm = ctx->child; - desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; - sg_set_buf(&tmp, ipad, bs); - - err = crypto_hash_init(&desc); - if (unlikely(err)) - return err; - - return crypto_hash_update(&desc, &tmp, bs); + + sg_set_buf(&tmp, key, keylen); + crypto_digest_digest(tfm, &tmp, 1, key); } -static int hmac_update(struct hash_desc *pdesc, - struct scatterlist *sg, unsigned int nbytes) +int crypto_alloc_hmac_block(struct crypto_tfm *tfm) { - struct hmac_ctx *ctx = hmac_ctx(pdesc->tfm); - struct hash_desc desc; + int ret = 0; - desc.tfm = ctx->child; - desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; + BUG_ON(!crypto_tfm_alg_blocksize(tfm)); + + tfm->crt_digest.dit_hmac_block = kmalloc(crypto_tfm_alg_blocksize(tfm), + GFP_KERNEL); + if (tfm->crt_digest.dit_hmac_block == NULL) + ret = -ENOMEM; - return crypto_hash_update(&desc, sg, nbytes); + return ret; + } -static int hmac_final(struct hash_desc *pdesc, u8 *out) +void crypto_free_hmac_block(struct crypto_tfm *tfm) { - struct crypto_hash *parent = pdesc->tfm; - int bs = crypto_hash_blocksize(parent); - int ds = crypto_hash_digestsize(parent); - char *opad = crypto_hash_ctx_aligned(parent) + bs; - char *digest = opad + bs; - struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *)); - struct hash_desc desc; - struct scatterlist tmp; - int err; - - desc.tfm = ctx->child; - desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; - sg_set_buf(&tmp, opad, bs + ds); - - err = crypto_hash_final(&desc, digest); - if (unlikely(err)) - return err; - - return crypto_hash_digest(&desc, &tmp, bs + ds, out); -} - -static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg, - unsigned int nbytes, u8 *out) -{ - struct crypto_hash *parent = pdesc->tfm; - int bs = crypto_hash_blocksize(parent); - int ds = crypto_hash_digestsize(parent); - char *ipad = crypto_hash_ctx_aligned(parent); - char *opad = ipad + bs; - char *digest = opad + bs; - struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *)); - struct hash_desc desc; - struct scatterlist sg1[2]; - struct scatterlist sg2[1]; - int err; - - desc.tfm = ctx->child; - desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP; - - sg_set_buf(sg1, ipad, bs); - sg1[1].page = (void *)sg; - sg1[1].length = 0; - sg_set_buf(sg2, opad, bs + ds); - - err = crypto_hash_digest(&desc, sg1, nbytes + bs, digest); - if (unlikely(err)) - return err; - - return crypto_hash_digest(&desc, sg2, bs + ds, out); + kfree(tfm->crt_digest.dit_hmac_block); } -static int hmac_init_tfm(struct crypto_tfm *tfm) +void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen) { - struct crypto_instance *inst = (void *)tfm->__crt_alg; - struct crypto_spawn *spawn = crypto_instance_ctx(inst); - struct hmac_ctx *ctx = hmac_ctx(__crypto_hash_cast(tfm)); + unsigned int i; + struct scatterlist tmp; + char *ipad = tfm->crt_digest.dit_hmac_block; + + if (*keylen > crypto_tfm_alg_blocksize(tfm)) { + hash_key(tfm, key, *keylen); + *keylen = crypto_tfm_alg_digestsize(tfm); + } - tfm = crypto_spawn_tfm(spawn); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); + memset(ipad, 0, crypto_tfm_alg_blocksize(tfm)); + memcpy(ipad, key, *keylen); - ctx->child = crypto_hash_cast(tfm); - return 0; -} + for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) + ipad[i] ^= 0x36; -static void hmac_exit_tfm(struct crypto_tfm *tfm) -{ - struct hmac_ctx *ctx = hmac_ctx(__crypto_hash_cast(tfm)); - crypto_free_hash(ctx->child); + sg_set_buf(&tmp, ipad, crypto_tfm_alg_blocksize(tfm)); + + crypto_digest_init(tfm); + crypto_digest_update(tfm, &tmp, 1); } -static void hmac_free(struct crypto_instance *inst) +void crypto_hmac_update(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg) { - crypto_drop_spawn(crypto_instance_ctx(inst)); - kfree(inst); + crypto_digest_update(tfm, sg, nsg); } -static struct crypto_instance *hmac_alloc(void *param, unsigned int len) +void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, + unsigned int *keylen, u8 *out) { - struct crypto_instance *inst; - struct crypto_alg *alg; - - alg = crypto_get_attr_alg(param, len, CRYPTO_ALG_TYPE_HASH, - CRYPTO_ALG_TYPE_HASH_MASK | CRYPTO_ALG_ASYNC); - if (IS_ERR(alg)) - return ERR_PTR(PTR_ERR(alg)); - - inst = crypto_alloc_instance("hmac", alg); - if (IS_ERR(inst)) - goto out_put_alg; - - inst->alg.cra_flags = CRYPTO_ALG_TYPE_HASH; - inst->alg.cra_priority = alg->cra_priority; - inst->alg.cra_blocksize = alg->cra_blocksize; - inst->alg.cra_alignmask = alg->cra_alignmask; - inst->alg.cra_type = &crypto_hash_type; - - inst->alg.cra_hash.digestsize = - (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == - CRYPTO_ALG_TYPE_HASH ? alg->cra_hash.digestsize : - alg->cra_digest.dia_digestsize; - - inst->alg.cra_ctxsize = sizeof(struct hmac_ctx) + - ALIGN(inst->alg.cra_blocksize * 2 + - inst->alg.cra_hash.digestsize, - sizeof(void *)); - - inst->alg.cra_init = hmac_init_tfm; - inst->alg.cra_exit = hmac_exit_tfm; + unsigned int i; + struct scatterlist tmp; + char *opad = tfm->crt_digest.dit_hmac_block; + + if (*keylen > crypto_tfm_alg_blocksize(tfm)) { + hash_key(tfm, key, *keylen); + *keylen = crypto_tfm_alg_digestsize(tfm); + } - inst->alg.cra_hash.init = hmac_init; - inst->alg.cra_hash.update = hmac_update; - inst->alg.cra_hash.final = hmac_final; - inst->alg.cra_hash.digest = hmac_digest; - inst->alg.cra_hash.setkey = hmac_setkey; + crypto_digest_final(tfm, out); -out_put_alg: - crypto_mod_put(alg); - return inst; -} + memset(opad, 0, crypto_tfm_alg_blocksize(tfm)); + memcpy(opad, key, *keylen); + + for (i = 0; i < crypto_tfm_alg_blocksize(tfm); i++) + opad[i] ^= 0x5c; -static struct crypto_template hmac_tmpl = { - .name = "hmac", - .alloc = hmac_alloc, - .free = hmac_free, - .module = THIS_MODULE, -}; + sg_set_buf(&tmp, opad, crypto_tfm_alg_blocksize(tfm)); -static int __init hmac_module_init(void) -{ - return crypto_register_template(&hmac_tmpl); + crypto_digest_init(tfm); + crypto_digest_update(tfm, &tmp, 1); + + sg_set_buf(&tmp, out, crypto_tfm_alg_digestsize(tfm)); + + crypto_digest_update(tfm, &tmp, 1); + crypto_digest_final(tfm, out); } -static void __exit hmac_module_exit(void) +void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, + struct scatterlist *sg, unsigned int nsg, u8 *out) { - crypto_unregister_template(&hmac_tmpl); + crypto_hmac_init(tfm, key, keylen); + crypto_hmac_update(tfm, sg, nsg); + crypto_hmac_final(tfm, key, keylen, out); } -module_init(hmac_module_init); -module_exit(hmac_module_exit); +EXPORT_SYMBOL_GPL(crypto_hmac_init); +EXPORT_SYMBOL_GPL(crypto_hmac_update); +EXPORT_SYMBOL_GPL(crypto_hmac_final); +EXPORT_SYMBOL_GPL(crypto_hmac); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("HMAC hash algorithm"); diff --git a/trunk/crypto/internal.h b/trunk/crypto/internal.h index 2da6ad4f3593..959e602909a6 100644 --- a/trunk/crypto/internal.h +++ b/trunk/crypto/internal.h @@ -12,43 +12,19 @@ */ #ifndef _CRYPTO_INTERNAL_H #define _CRYPTO_INTERNAL_H - -#include -#include +#include #include #include #include #include #include -#include #include -#include #include #include #include -/* Crypto notification events. */ -enum { - CRYPTO_MSG_ALG_REQUEST, - CRYPTO_MSG_ALG_REGISTER, - CRYPTO_MSG_ALG_UNREGISTER, - CRYPTO_MSG_TMPL_REGISTER, - CRYPTO_MSG_TMPL_UNREGISTER, -}; - -struct crypto_instance; -struct crypto_template; - -struct crypto_larval { - struct crypto_alg alg; - struct crypto_alg *adult; - struct completion completion; - u32 mask; -}; - extern struct list_head crypto_alg_list; extern struct rw_semaphore crypto_alg_sem; -extern struct blocking_notifier_head crypto_chain; extern enum km_type crypto_km_types[]; @@ -67,33 +43,36 @@ static inline void crypto_kunmap(void *vaddr, int out) kunmap_atomic(vaddr, crypto_kmap_type(out)); } -static inline void crypto_yield(u32 flags) +static inline void crypto_yield(struct crypto_tfm *tfm) { - if (flags & CRYPTO_TFM_REQ_MAY_SLEEP) + if (tfm->crt_flags & CRYPTO_TFM_REQ_MAY_SLEEP) cond_resched(); } +#ifdef CONFIG_CRYPTO_HMAC +int crypto_alloc_hmac_block(struct crypto_tfm *tfm); +void crypto_free_hmac_block(struct crypto_tfm *tfm); +#else +static inline int crypto_alloc_hmac_block(struct crypto_tfm *tfm) +{ + return 0; +} + +static inline void crypto_free_hmac_block(struct crypto_tfm *tfm) +{ } +#endif + #ifdef CONFIG_PROC_FS void __init crypto_init_proc(void); -void __exit crypto_exit_proc(void); #else static inline void crypto_init_proc(void) { } -static inline void crypto_exit_proc(void) -{ } #endif static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg, int flags) { - unsigned int len = alg->cra_ctxsize; - - if (alg->cra_alignmask) { - len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1); - len += alg->cra_digest.dia_digestsize; - } - - return len; + return alg->cra_ctxsize; } static inline unsigned int crypto_cipher_ctxsize(struct crypto_alg *alg, @@ -117,10 +96,6 @@ static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg, return alg->cra_ctxsize; } -struct crypto_alg *crypto_mod_get(struct crypto_alg *alg); -struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask); -struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask); - int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags); int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags); int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags); @@ -133,52 +108,5 @@ void crypto_exit_digest_ops(struct crypto_tfm *tfm); void crypto_exit_cipher_ops(struct crypto_tfm *tfm); void crypto_exit_compress_ops(struct crypto_tfm *tfm); -void crypto_larval_error(const char *name, u32 type, u32 mask); - -void crypto_shoot_alg(struct crypto_alg *alg); -struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags); - -int crypto_register_instance(struct crypto_template *tmpl, - struct crypto_instance *inst); - -int crypto_register_notifier(struct notifier_block *nb); -int crypto_unregister_notifier(struct notifier_block *nb); - -static inline void crypto_alg_put(struct crypto_alg *alg) -{ - if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy) - alg->cra_destroy(alg); -} - -static inline int crypto_tmpl_get(struct crypto_template *tmpl) -{ - return try_module_get(tmpl->module); -} - -static inline void crypto_tmpl_put(struct crypto_template *tmpl) -{ - module_put(tmpl->module); -} - -static inline int crypto_is_larval(struct crypto_alg *alg) -{ - return alg->cra_flags & CRYPTO_ALG_LARVAL; -} - -static inline int crypto_is_dead(struct crypto_alg *alg) -{ - return alg->cra_flags & CRYPTO_ALG_DEAD; -} - -static inline int crypto_is_moribund(struct crypto_alg *alg) -{ - return alg->cra_flags & (CRYPTO_ALG_DEAD | CRYPTO_ALG_DYING); -} - -static inline int crypto_notify(unsigned long val, void *v) -{ - return blocking_notifier_call_chain(&crypto_chain, val, v); -} - #endif /* _CRYPTO_INTERNAL_H */ diff --git a/trunk/crypto/khazad.c b/trunk/crypto/khazad.c index 9fa24a2dd6ff..d4c9d3657b36 100644 --- a/trunk/crypto/khazad.c +++ b/trunk/crypto/khazad.c @@ -755,13 +755,19 @@ static const u64 c[KHAZAD_ROUNDS + 1] = { }; static int khazad_setkey(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) + unsigned int key_len, u32 *flags) { struct khazad_ctx *ctx = crypto_tfm_ctx(tfm); const __be32 *key = (const __be32 *)in_key; int r; const u64 *S = T7; u64 K2, K1; + + if (key_len != 16) + { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } /* key is supposed to be 32-bit aligned */ K2 = ((u64)be32_to_cpu(key[0]) << 32) | be32_to_cpu(key[1]); diff --git a/trunk/crypto/michael_mic.c b/trunk/crypto/michael_mic.c index 094397b48849..d061da21cfda 100644 --- a/trunk/crypto/michael_mic.c +++ b/trunk/crypto/michael_mic.c @@ -123,13 +123,14 @@ static void michael_final(struct crypto_tfm *tfm, u8 *out) static int michael_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) + unsigned int keylen, u32 *flags) { struct michael_mic_ctx *mctx = crypto_tfm_ctx(tfm); const __le32 *data = (const __le32 *)key; if (keylen != 8) { - tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + if (flags) + *flags = CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } diff --git a/trunk/crypto/proc.c b/trunk/crypto/proc.c index dabce0676f63..c0a5dd7ce2cc 100644 --- a/trunk/crypto/proc.c +++ b/trunk/crypto/proc.c @@ -12,8 +12,6 @@ * any later version. * */ - -#include #include #include #include @@ -56,7 +54,6 @@ static int c_show(struct seq_file *m, void *p) seq_printf(m, "driver : %s\n", alg->cra_driver_name); seq_printf(m, "module : %s\n", module_name(alg->cra_module)); seq_printf(m, "priority : %d\n", alg->cra_priority); - seq_printf(m, "refcnt : %d\n", atomic_read(&alg->cra_refcnt)); switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { case CRYPTO_ALG_TYPE_CIPHER: @@ -78,10 +75,7 @@ static int c_show(struct seq_file *m, void *p) seq_printf(m, "type : compression\n"); break; default: - if (alg->cra_type && alg->cra_type->show) - alg->cra_type->show(m, alg); - else - seq_printf(m, "type : unknown\n"); + seq_printf(m, "type : unknown\n"); break; } @@ -116,8 +110,3 @@ void __init crypto_init_proc(void) if (proc) proc->proc_fops = &proc_crypto_ops; } - -void __exit crypto_exit_proc(void) -{ - remove_proc_entry("crypto", NULL); -} diff --git a/trunk/crypto/scatterwalk.c b/trunk/crypto/scatterwalk.c index 35172d3f043b..2953e2cc56f0 100644 --- a/trunk/crypto/scatterwalk.c +++ b/trunk/crypto/scatterwalk.c @@ -15,11 +15,9 @@ */ #include #include -#include #include #include -#include - +#include #include "internal.h" #include "scatterwalk.h" @@ -29,77 +27,88 @@ enum km_type crypto_km_types[] = { KM_SOFTIRQ0, KM_SOFTIRQ1, }; -EXPORT_SYMBOL_GPL(crypto_km_types); -static inline void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) +static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) { - void *src = out ? buf : sgdata; - void *dst = out ? sgdata : buf; - - memcpy(dst, src, nbytes); + if (out) + memcpy(sgdata, buf, nbytes); + else + memcpy(buf, sgdata, nbytes); } void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg) { + unsigned int rest_of_page; + walk->sg = sg; + walk->page = sg->page; + walk->len_this_segment = sg->length; + BUG_ON(!sg->length); + rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1)); + walk->len_this_page = min(sg->length, rest_of_page); walk->offset = sg->offset; } -EXPORT_SYMBOL_GPL(scatterwalk_start); -void *scatterwalk_map(struct scatter_walk *walk, int out) +void scatterwalk_map(struct scatter_walk *walk, int out) +{ + walk->data = crypto_kmap(walk->page, out) + walk->offset; +} + +static inline void scatterwalk_unmap(struct scatter_walk *walk, int out) { - return crypto_kmap(scatterwalk_page(walk), out) + - offset_in_page(walk->offset); + /* walk->data may be pointing the first byte of the next page; + however, we know we transfered at least one byte. So, + walk->data - 1 will be a virtual address in the mapped page. */ + crypto_kunmap(walk->data - 1, out); } -EXPORT_SYMBOL_GPL(scatterwalk_map); static void scatterwalk_pagedone(struct scatter_walk *walk, int out, unsigned int more) { if (out) - flush_dcache_page(scatterwalk_page(walk)); + flush_dcache_page(walk->page); if (more) { - walk->offset += PAGE_SIZE - 1; - walk->offset &= PAGE_MASK; - if (walk->offset >= walk->sg->offset + walk->sg->length) + walk->len_this_segment -= walk->len_this_page; + + if (walk->len_this_segment) { + walk->page++; + walk->len_this_page = min(walk->len_this_segment, + (unsigned)PAGE_CACHE_SIZE); + walk->offset = 0; + } + else scatterwalk_start(walk, sg_next(walk->sg)); } } void scatterwalk_done(struct scatter_walk *walk, int out, int more) { - if (!offset_in_page(walk->offset) || !more) + scatterwalk_unmap(walk, out); + if (walk->len_this_page == 0 || !more) scatterwalk_pagedone(walk, out, more); } -EXPORT_SYMBOL_GPL(scatterwalk_done); -void scatterwalk_copychunks(void *buf, struct scatter_walk *walk, - size_t nbytes, int out) +/* + * Do not call this unless the total length of all of the fragments + * has been verified as multiple of the block size. + */ +int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, + size_t nbytes, int out) { - for (;;) { - unsigned int len_this_page = scatterwalk_pagelen(walk); - u8 *vaddr; - - if (len_this_page > nbytes) - len_this_page = nbytes; - - vaddr = scatterwalk_map(walk, out); - memcpy_dir(buf, vaddr, len_this_page, out); - scatterwalk_unmap(vaddr, out); - - if (nbytes == len_this_page) - break; - - buf += len_this_page; - nbytes -= len_this_page; + while (nbytes > walk->len_this_page) { + memcpy_dir(buf, walk->data, walk->len_this_page, out); + buf += walk->len_this_page; + nbytes -= walk->len_this_page; + scatterwalk_unmap(walk, out); scatterwalk_pagedone(walk, out, 1); + scatterwalk_map(walk, out); } - scatterwalk_advance(walk, nbytes); + memcpy_dir(buf, walk->data, nbytes, out); + return nbytes; } -EXPORT_SYMBOL_GPL(scatterwalk_copychunks); diff --git a/trunk/crypto/scatterwalk.h b/trunk/crypto/scatterwalk.h index f1592cc2d0f4..e79925c474a3 100644 --- a/trunk/crypto/scatterwalk.h +++ b/trunk/crypto/scatterwalk.h @@ -14,42 +14,45 @@ #ifndef _CRYPTO_SCATTERWALK_H #define _CRYPTO_SCATTERWALK_H - #include -#include +#include -#include "internal.h" +struct scatter_walk { + struct scatterlist *sg; + struct page *page; + void *data; + unsigned int len_this_page; + unsigned int len_this_segment; + unsigned int offset; +}; +/* Define sg_next is an inline routine now in case we want to change + scatterlist to a linked list later. */ static inline struct scatterlist *sg_next(struct scatterlist *sg) { - return (++sg)->length ? sg : (void *)sg->page; + return sg + 1; } -static inline unsigned long scatterwalk_samebuf(struct scatter_walk *walk_in, - struct scatter_walk *walk_out) +static inline int scatterwalk_samebuf(struct scatter_walk *walk_in, + struct scatter_walk *walk_out) { - return !(((walk_in->sg->page - walk_out->sg->page) << PAGE_SHIFT) + - (int)(walk_in->offset - walk_out->offset)); -} - -static inline unsigned int scatterwalk_pagelen(struct scatter_walk *walk) -{ - unsigned int len = walk->sg->offset + walk->sg->length - walk->offset; - unsigned int len_this_page = offset_in_page(~walk->offset) + 1; - return len_this_page > len ? len : len_this_page; + return walk_in->page == walk_out->page && + walk_in->offset == walk_out->offset; } static inline unsigned int scatterwalk_clamp(struct scatter_walk *walk, unsigned int nbytes) { - unsigned int len_this_page = scatterwalk_pagelen(walk); - return nbytes > len_this_page ? len_this_page : nbytes; + return nbytes > walk->len_this_page ? walk->len_this_page : nbytes; } static inline void scatterwalk_advance(struct scatter_walk *walk, unsigned int nbytes) { + walk->data += nbytes; walk->offset += nbytes; + walk->len_this_page -= nbytes; + walk->len_this_segment -= nbytes; } static inline unsigned int scatterwalk_aligned(struct scatter_walk *walk, @@ -58,20 +61,9 @@ static inline unsigned int scatterwalk_aligned(struct scatter_walk *walk, return !(walk->offset & alignmask); } -static inline struct page *scatterwalk_page(struct scatter_walk *walk) -{ - return walk->sg->page + (walk->offset >> PAGE_SHIFT); -} - -static inline void scatterwalk_unmap(void *vaddr, int out) -{ - crypto_kunmap(vaddr, out); -} - void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg); -void scatterwalk_copychunks(void *buf, struct scatter_walk *walk, - size_t nbytes, int out); -void *scatterwalk_map(struct scatter_walk *walk, int out); +int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out); +void scatterwalk_map(struct scatter_walk *walk, int out); void scatterwalk_done(struct scatter_walk *walk, int out, int more); #endif /* _CRYPTO_SCATTERWALK_H */ diff --git a/trunk/crypto/serpent.c b/trunk/crypto/serpent.c index 465d091cd3ec..de60cdddbf4a 100644 --- a/trunk/crypto/serpent.c +++ b/trunk/crypto/serpent.c @@ -216,7 +216,7 @@ struct serpent_ctx { static int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) + unsigned int keylen, u32 *flags) { struct serpent_ctx *ctx = crypto_tfm_ctx(tfm); u32 *k = ctx->expkey; @@ -224,6 +224,13 @@ static int serpent_setkey(struct crypto_tfm *tfm, const u8 *key, u32 r0,r1,r2,r3,r4; int i; + if ((keylen < SERPENT_MIN_KEY_SIZE) + || (keylen > SERPENT_MAX_KEY_SIZE)) + { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + /* Copy key, add padding */ for (i = 0; i < keylen; ++i) @@ -490,15 +497,21 @@ static struct crypto_alg serpent_alg = { }; static int tnepres_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) + unsigned int keylen, u32 *flags) { u8 rev_key[SERPENT_MAX_KEY_SIZE]; int i; + if ((keylen < SERPENT_MIN_KEY_SIZE) + || (keylen > SERPENT_MAX_KEY_SIZE)) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + for (i = 0; i < keylen; ++i) rev_key[keylen - i - 1] = key[i]; - return serpent_setkey(tfm, rev_key, keylen); + return serpent_setkey(tfm, rev_key, keylen, flags); } static void tnepres_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) diff --git a/trunk/crypto/sha1.c b/trunk/crypto/sha1.c index 1bba551e5b45..6c77b689f87e 100644 --- a/trunk/crypto/sha1.c +++ b/trunk/crypto/sha1.c @@ -109,7 +109,6 @@ static void sha1_final(struct crypto_tfm *tfm, u8 *out) static struct crypto_alg alg = { .cra_name = "sha1", - .cra_driver_name= "sha1-generic", .cra_flags = CRYPTO_ALG_TYPE_DIGEST, .cra_blocksize = SHA1_HMAC_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sha1_ctx), @@ -138,5 +137,3 @@ module_exit(fini); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); - -MODULE_ALIAS("sha1-generic"); diff --git a/trunk/crypto/sha256.c b/trunk/crypto/sha256.c index 716195bb54f2..bc71d85a7d02 100644 --- a/trunk/crypto/sha256.c +++ b/trunk/crypto/sha256.c @@ -309,7 +309,6 @@ static void sha256_final(struct crypto_tfm *tfm, u8 *out) static struct crypto_alg alg = { .cra_name = "sha256", - .cra_driver_name= "sha256-generic", .cra_flags = CRYPTO_ALG_TYPE_DIGEST, .cra_blocksize = SHA256_HMAC_BLOCK_SIZE, .cra_ctxsize = sizeof(struct sha256_ctx), @@ -338,5 +337,3 @@ module_exit(fini); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm"); - -MODULE_ALIAS("sha256-generic"); diff --git a/trunk/crypto/tcrypt.c b/trunk/crypto/tcrypt.c index 83307420d31c..e52f56c5bd5e 100644 --- a/trunk/crypto/tcrypt.c +++ b/trunk/crypto/tcrypt.c @@ -17,7 +17,6 @@ * */ -#include #include #include #include @@ -55,6 +54,8 @@ */ #define ENCRYPT 1 #define DECRYPT 0 +#define MODE_ECB 1 +#define MODE_CBC 0 static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 }; @@ -88,11 +89,9 @@ static void test_hash(char *algo, struct hash_testvec *template, unsigned int i, j, k, temp; struct scatterlist sg[8]; char result[64]; - struct crypto_hash *tfm; - struct hash_desc desc; + struct crypto_tfm *tfm; struct hash_testvec *hash_tv; unsigned int tsize; - int ret; printk("\ntesting %s\n", algo); @@ -106,42 +105,30 @@ static void test_hash(char *algo, struct hash_testvec *template, memcpy(tvmem, template, tsize); hash_tv = (void *)tvmem; - - tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) { - printk("failed to load transform for %s: %ld\n", algo, - PTR_ERR(tfm)); + tfm = crypto_alloc_tfm(algo, 0); + if (tfm == NULL) { + printk("failed to load transform for %s\n", algo); return; } - desc.tfm = tfm; - desc.flags = 0; - for (i = 0; i < tcount; i++) { printk("test %u:\n", i + 1); memset(result, 0, 64); sg_set_buf(&sg[0], hash_tv[i].plaintext, hash_tv[i].psize); - if (hash_tv[i].ksize) { - ret = crypto_hash_setkey(tfm, hash_tv[i].key, - hash_tv[i].ksize); - if (ret) { - printk("setkey() failed ret=%d\n", ret); - goto out; - } - } - - ret = crypto_hash_digest(&desc, sg, hash_tv[i].psize, result); - if (ret) { - printk("digest () failed ret=%d\n", ret); - goto out; + crypto_digest_init(tfm); + if (tfm->crt_u.digest.dit_setkey) { + crypto_digest_setkey(tfm, hash_tv[i].key, + hash_tv[i].ksize); } + crypto_digest_update(tfm, sg, 1); + crypto_digest_final(tfm, result); - hexdump(result, crypto_hash_digestsize(tfm)); + hexdump(result, crypto_tfm_alg_digestsize(tfm)); printk("%s\n", memcmp(result, hash_tv[i].digest, - crypto_hash_digestsize(tfm)) ? + crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); } @@ -167,56 +154,127 @@ static void test_hash(char *algo, struct hash_testvec *template, hash_tv[i].tap[k]); } - if (hash_tv[i].ksize) { - ret = crypto_hash_setkey(tfm, hash_tv[i].key, - hash_tv[i].ksize); + crypto_digest_digest(tfm, sg, hash_tv[i].np, result); - if (ret) { - printk("setkey() failed ret=%d\n", ret); - goto out; - } - } + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, hash_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? + "fail" : "pass"); + } + } - ret = crypto_hash_digest(&desc, sg, hash_tv[i].psize, - result); - if (ret) { - printk("digest () failed ret=%d\n", ret); - goto out; + crypto_free_tfm(tfm); +} + + +#ifdef CONFIG_CRYPTO_HMAC + +static void test_hmac(char *algo, struct hmac_testvec *template, + unsigned int tcount) +{ + unsigned int i, j, k, temp; + struct scatterlist sg[8]; + char result[64]; + struct crypto_tfm *tfm; + struct hmac_testvec *hmac_tv; + unsigned int tsize, klen; + + tfm = crypto_alloc_tfm(algo, 0); + if (tfm == NULL) { + printk("failed to load transform for %s\n", algo); + return; + } + + printk("\ntesting hmac_%s\n", algo); + + tsize = sizeof(struct hmac_testvec); + tsize *= tcount; + if (tsize > TVMEMSIZE) { + printk("template (%u) too big for tvmem (%u)\n", tsize, + TVMEMSIZE); + goto out; + } + + memcpy(tvmem, template, tsize); + hmac_tv = (void *)tvmem; + + for (i = 0; i < tcount; i++) { + printk("test %u:\n", i + 1); + memset(result, 0, sizeof (result)); + + klen = hmac_tv[i].ksize; + sg_set_buf(&sg[0], hmac_tv[i].plaintext, hmac_tv[i].psize); + + crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, 1, result); + + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", + memcmp(result, hmac_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : + "pass"); + } + + printk("\ntesting hmac_%s across pages\n", algo); + + memset(xbuf, 0, XBUFSIZE); + + j = 0; + for (i = 0; i < tcount; i++) { + if (hmac_tv[i].np) { + j++; + printk("test %u:\n",j); + memset(result, 0, 64); + + temp = 0; + klen = hmac_tv[i].ksize; + for (k = 0; k < hmac_tv[i].np; k++) { + memcpy(&xbuf[IDX[k]], + hmac_tv[i].plaintext + temp, + hmac_tv[i].tap[k]); + temp += hmac_tv[i].tap[k]; + sg_set_buf(&sg[k], &xbuf[IDX[k]], + hmac_tv[i].tap[k]); } - hexdump(result, crypto_hash_digestsize(tfm)); + crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, + hmac_tv[i].np, result); + hexdump(result, crypto_tfm_alg_digestsize(tfm)); + printk("%s\n", - memcmp(result, hash_tv[i].digest, - crypto_hash_digestsize(tfm)) ? + memcmp(result, hmac_tv[i].digest, + crypto_tfm_alg_digestsize(tfm)) ? "fail" : "pass"); } } - out: - crypto_free_hash(tfm); + crypto_free_tfm(tfm); } -static void test_cipher(char *algo, int enc, +#endif /* CONFIG_CRYPTO_HMAC */ + +static void test_cipher(char *algo, int mode, int enc, struct cipher_testvec *template, unsigned int tcount) { unsigned int ret, i, j, k, temp; unsigned int tsize; - unsigned int iv_len; - unsigned int len; char *q; - struct crypto_blkcipher *tfm; + struct crypto_tfm *tfm; char *key; struct cipher_testvec *cipher_tv; - struct blkcipher_desc desc; struct scatterlist sg[8]; - const char *e; + const char *e, *m; if (enc == ENCRYPT) e = "encryption"; else e = "decryption"; + if (mode == MODE_ECB) + m = "ECB"; + else + m = "CBC"; - printk("\ntesting %s %s\n", algo, e); + printk("\ntesting %s %s %s\n", algo, m, e); tsize = sizeof (struct cipher_testvec); tsize *= tcount; @@ -230,15 +288,15 @@ static void test_cipher(char *algo, int enc, memcpy(tvmem, template, tsize); cipher_tv = (void *)tvmem; - tfm = crypto_alloc_blkcipher(algo, 0, CRYPTO_ALG_ASYNC); + if (mode) + tfm = crypto_alloc_tfm(algo, 0); + else + tfm = crypto_alloc_tfm(algo, CRYPTO_TFM_MODE_CBC); - if (IS_ERR(tfm)) { - printk("failed to load transform for %s: %ld\n", algo, - PTR_ERR(tfm)); + if (tfm == NULL) { + printk("failed to load transform for %s %s\n", algo, m); return; } - desc.tfm = tfm; - desc.flags = 0; j = 0; for (i = 0; i < tcount; i++) { @@ -247,17 +305,14 @@ static void test_cipher(char *algo, int enc, printk("test %u (%d bit key):\n", j, cipher_tv[i].klen * 8); - crypto_blkcipher_clear_flags(tfm, ~0); + tfm->crt_flags = 0; if (cipher_tv[i].wk) - crypto_blkcipher_set_flags( - tfm, CRYPTO_TFM_REQ_WEAK_KEY); + tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY; key = cipher_tv[i].key; - ret = crypto_blkcipher_setkey(tfm, key, - cipher_tv[i].klen); + ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen); if (ret) { - printk("setkey() failed flags=%x\n", - crypto_blkcipher_get_flags(tfm)); + printk("setkey() failed flags=%x\n", tfm->crt_flags); if (!cipher_tv[i].fail) goto out; @@ -266,19 +321,19 @@ static void test_cipher(char *algo, int enc, sg_set_buf(&sg[0], cipher_tv[i].input, cipher_tv[i].ilen); - iv_len = crypto_blkcipher_ivsize(tfm); - if (iv_len) - crypto_blkcipher_set_iv(tfm, cipher_tv[i].iv, - iv_len); + if (!mode) { + crypto_cipher_set_iv(tfm, cipher_tv[i].iv, + crypto_tfm_alg_ivsize(tfm)); + } + + if (enc) + ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen); + else + ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen); - len = cipher_tv[i].ilen; - ret = enc ? - crypto_blkcipher_encrypt(&desc, sg, sg, len) : - crypto_blkcipher_decrypt(&desc, sg, sg, len); if (ret) { - printk("%s () failed flags=%x\n", e, - desc.flags); + printk("%s () failed flags=%x\n", e, tfm->crt_flags); goto out; } @@ -291,7 +346,7 @@ static void test_cipher(char *algo, int enc, } } - printk("\ntesting %s %s across pages (chunking)\n", algo, e); + printk("\ntesting %s %s %s across pages (chunking)\n", algo, m, e); memset(xbuf, 0, XBUFSIZE); j = 0; @@ -301,17 +356,14 @@ static void test_cipher(char *algo, int enc, printk("test %u (%d bit key):\n", j, cipher_tv[i].klen * 8); - crypto_blkcipher_clear_flags(tfm, ~0); + tfm->crt_flags = 0; if (cipher_tv[i].wk) - crypto_blkcipher_set_flags( - tfm, CRYPTO_TFM_REQ_WEAK_KEY); + tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY; key = cipher_tv[i].key; - ret = crypto_blkcipher_setkey(tfm, key, - cipher_tv[i].klen); + ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen); if (ret) { - printk("setkey() failed flags=%x\n", - crypto_blkcipher_get_flags(tfm)); + printk("setkey() failed flags=%x\n", tfm->crt_flags); if (!cipher_tv[i].fail) goto out; @@ -327,19 +379,18 @@ static void test_cipher(char *algo, int enc, cipher_tv[i].tap[k]); } - iv_len = crypto_blkcipher_ivsize(tfm); - if (iv_len) - crypto_blkcipher_set_iv(tfm, cipher_tv[i].iv, - iv_len); + if (!mode) { + crypto_cipher_set_iv(tfm, cipher_tv[i].iv, + crypto_tfm_alg_ivsize(tfm)); + } - len = cipher_tv[i].ilen; - ret = enc ? - crypto_blkcipher_encrypt(&desc, sg, sg, len) : - crypto_blkcipher_decrypt(&desc, sg, sg, len); + if (enc) + ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen); + else + ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen); if (ret) { - printk("%s () failed flags=%x\n", e, - desc.flags); + printk("%s () failed flags=%x\n", e, tfm->crt_flags); goto out; } @@ -358,10 +409,10 @@ static void test_cipher(char *algo, int enc, } out: - crypto_free_blkcipher(tfm); + crypto_free_tfm(tfm); } -static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, char *p, +static int test_cipher_jiffies(struct crypto_tfm *tfm, int enc, char *p, int blen, int sec) { struct scatterlist sg[1]; @@ -374,9 +425,9 @@ static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, char *p, for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { if (enc) - ret = crypto_blkcipher_encrypt(desc, sg, sg, blen); + ret = crypto_cipher_encrypt(tfm, sg, sg, blen); else - ret = crypto_blkcipher_decrypt(desc, sg, sg, blen); + ret = crypto_cipher_decrypt(tfm, sg, sg, blen); if (ret) return ret; @@ -387,7 +438,7 @@ static int test_cipher_jiffies(struct blkcipher_desc *desc, int enc, char *p, return 0; } -static int test_cipher_cycles(struct blkcipher_desc *desc, int enc, char *p, +static int test_cipher_cycles(struct crypto_tfm *tfm, int enc, char *p, int blen) { struct scatterlist sg[1]; @@ -403,9 +454,9 @@ static int test_cipher_cycles(struct blkcipher_desc *desc, int enc, char *p, /* Warm-up run. */ for (i = 0; i < 4; i++) { if (enc) - ret = crypto_blkcipher_encrypt(desc, sg, sg, blen); + ret = crypto_cipher_encrypt(tfm, sg, sg, blen); else - ret = crypto_blkcipher_decrypt(desc, sg, sg, blen); + ret = crypto_cipher_decrypt(tfm, sg, sg, blen); if (ret) goto out; @@ -417,9 +468,9 @@ static int test_cipher_cycles(struct blkcipher_desc *desc, int enc, char *p, start = get_cycles(); if (enc) - ret = crypto_blkcipher_encrypt(desc, sg, sg, blen); + ret = crypto_cipher_encrypt(tfm, sg, sg, blen); else - ret = crypto_blkcipher_decrypt(desc, sg, sg, blen); + ret = crypto_cipher_decrypt(tfm, sg, sg, blen); end = get_cycles(); if (ret) @@ -439,32 +490,35 @@ static int test_cipher_cycles(struct blkcipher_desc *desc, int enc, char *p, return ret; } -static void test_cipher_speed(char *algo, int enc, unsigned int sec, +static void test_cipher_speed(char *algo, int mode, int enc, unsigned int sec, struct cipher_testvec *template, unsigned int tcount, struct cipher_speed *speed) { unsigned int ret, i, j, iv_len; unsigned char *key, *p, iv[128]; - struct crypto_blkcipher *tfm; - struct blkcipher_desc desc; - const char *e; + struct crypto_tfm *tfm; + const char *e, *m; if (enc == ENCRYPT) e = "encryption"; else e = "decryption"; + if (mode == MODE_ECB) + m = "ECB"; + else + m = "CBC"; - printk("\ntesting speed of %s %s\n", algo, e); + printk("\ntesting speed of %s %s %s\n", algo, m, e); - tfm = crypto_alloc_blkcipher(algo, 0, CRYPTO_ALG_ASYNC); + if (mode) + tfm = crypto_alloc_tfm(algo, 0); + else + tfm = crypto_alloc_tfm(algo, CRYPTO_TFM_MODE_CBC); - if (IS_ERR(tfm)) { - printk("failed to load transform for %s: %ld\n", algo, - PTR_ERR(tfm)); + if (tfm == NULL) { + printk("failed to load transform for %s %s\n", algo, m); return; } - desc.tfm = tfm; - desc.flags = 0; for (i = 0; speed[i].klen != 0; i++) { if ((speed[i].blen + speed[i].klen) > TVMEMSIZE) { @@ -488,231 +542,125 @@ static void test_cipher_speed(char *algo, int enc, unsigned int sec, } p = (unsigned char *)tvmem + speed[i].klen; - ret = crypto_blkcipher_setkey(tfm, key, speed[i].klen); + ret = crypto_cipher_setkey(tfm, key, speed[i].klen); if (ret) { - printk("setkey() failed flags=%x\n", - crypto_blkcipher_get_flags(tfm)); + printk("setkey() failed flags=%x\n", tfm->crt_flags); goto out; } - iv_len = crypto_blkcipher_ivsize(tfm); - if (iv_len) { + if (!mode) { + iv_len = crypto_tfm_alg_ivsize(tfm); memset(&iv, 0xff, iv_len); - crypto_blkcipher_set_iv(tfm, iv, iv_len); + crypto_cipher_set_iv(tfm, iv, iv_len); } if (sec) - ret = test_cipher_jiffies(&desc, enc, p, speed[i].blen, + ret = test_cipher_jiffies(tfm, enc, p, speed[i].blen, sec); else - ret = test_cipher_cycles(&desc, enc, p, speed[i].blen); + ret = test_cipher_cycles(tfm, enc, p, speed[i].blen); if (ret) { - printk("%s() failed flags=%x\n", e, desc.flags); + printk("%s() failed flags=%x\n", e, tfm->crt_flags); break; } } out: - crypto_free_blkcipher(tfm); + crypto_free_tfm(tfm); } -static int test_hash_jiffies_digest(struct hash_desc *desc, char *p, int blen, - char *out, int sec) -{ - struct scatterlist sg[1]; - unsigned long start, end; - int bcount; - int ret; - - for (start = jiffies, end = start + sec * HZ, bcount = 0; - time_before(jiffies, end); bcount++) { - sg_set_buf(sg, p, blen); - ret = crypto_hash_digest(desc, sg, blen, out); - if (ret) - return ret; - } - - printk("%6u opers/sec, %9lu bytes/sec\n", - bcount / sec, ((long)bcount * blen) / sec); - - return 0; -} - -static int test_hash_jiffies(struct hash_desc *desc, char *p, int blen, - int plen, char *out, int sec) +static void test_digest_jiffies(struct crypto_tfm *tfm, char *p, int blen, + int plen, char *out, int sec) { struct scatterlist sg[1]; unsigned long start, end; int bcount, pcount; - int ret; - - if (plen == blen) - return test_hash_jiffies_digest(desc, p, blen, out, sec); for (start = jiffies, end = start + sec * HZ, bcount = 0; time_before(jiffies, end); bcount++) { - ret = crypto_hash_init(desc); - if (ret) - return ret; + crypto_digest_init(tfm); for (pcount = 0; pcount < blen; pcount += plen) { sg_set_buf(sg, p + pcount, plen); - ret = crypto_hash_update(desc, sg, plen); - if (ret) - return ret; + crypto_digest_update(tfm, sg, 1); } /* we assume there is enough space in 'out' for the result */ - ret = crypto_hash_final(desc, out); - if (ret) - return ret; + crypto_digest_final(tfm, out); } printk("%6u opers/sec, %9lu bytes/sec\n", bcount / sec, ((long)bcount * blen) / sec); - return 0; -} - -static int test_hash_cycles_digest(struct hash_desc *desc, char *p, int blen, - char *out) -{ - struct scatterlist sg[1]; - unsigned long cycles = 0; - int i; - int ret; - - local_bh_disable(); - local_irq_disable(); - - /* Warm-up run. */ - for (i = 0; i < 4; i++) { - sg_set_buf(sg, p, blen); - ret = crypto_hash_digest(desc, sg, blen, out); - if (ret) - goto out; - } - - /* The real thing. */ - for (i = 0; i < 8; i++) { - cycles_t start, end; - - start = get_cycles(); - - sg_set_buf(sg, p, blen); - ret = crypto_hash_digest(desc, sg, blen, out); - if (ret) - goto out; - - end = get_cycles(); - - cycles += end - start; - } - -out: - local_irq_enable(); - local_bh_enable(); - - if (ret) - return ret; - - printk("%6lu cycles/operation, %4lu cycles/byte\n", - cycles / 8, cycles / (8 * blen)); - - return 0; + return; } -static int test_hash_cycles(struct hash_desc *desc, char *p, int blen, - int plen, char *out) +static void test_digest_cycles(struct crypto_tfm *tfm, char *p, int blen, + int plen, char *out) { struct scatterlist sg[1]; unsigned long cycles = 0; int i, pcount; - int ret; - - if (plen == blen) - return test_hash_cycles_digest(desc, p, blen, out); local_bh_disable(); local_irq_disable(); /* Warm-up run. */ for (i = 0; i < 4; i++) { - ret = crypto_hash_init(desc); - if (ret) - goto out; + crypto_digest_init(tfm); for (pcount = 0; pcount < blen; pcount += plen) { sg_set_buf(sg, p + pcount, plen); - ret = crypto_hash_update(desc, sg, plen); - if (ret) - goto out; + crypto_digest_update(tfm, sg, 1); } - crypto_hash_final(desc, out); - if (ret) - goto out; + crypto_digest_final(tfm, out); } /* The real thing. */ for (i = 0; i < 8; i++) { cycles_t start, end; + crypto_digest_init(tfm); + start = get_cycles(); - ret = crypto_hash_init(desc); - if (ret) - goto out; for (pcount = 0; pcount < blen; pcount += plen) { sg_set_buf(sg, p + pcount, plen); - ret = crypto_hash_update(desc, sg, plen); - if (ret) - goto out; + crypto_digest_update(tfm, sg, 1); } - ret = crypto_hash_final(desc, out); - if (ret) - goto out; + crypto_digest_final(tfm, out); end = get_cycles(); cycles += end - start; } -out: local_irq_enable(); local_bh_enable(); - if (ret) - return ret; - printk("%6lu cycles/operation, %4lu cycles/byte\n", cycles / 8, cycles / (8 * blen)); - return 0; + return; } -static void test_hash_speed(char *algo, unsigned int sec, - struct hash_speed *speed) +static void test_digest_speed(char *algo, unsigned int sec, + struct digest_speed *speed) { - struct crypto_hash *tfm; - struct hash_desc desc; + struct crypto_tfm *tfm; char output[1024]; int i; - int ret; printk("\ntesting speed of %s\n", algo); - tfm = crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_tfm(algo, 0); - if (IS_ERR(tfm)) { - printk("failed to load transform for %s: %ld\n", algo, - PTR_ERR(tfm)); + if (tfm == NULL) { + printk("failed to load transform for %s\n", algo); return; } - desc.tfm = tfm; - desc.flags = 0; - - if (crypto_hash_digestsize(tfm) > sizeof(output)) { + if (crypto_tfm_alg_digestsize(tfm) > sizeof(output)) { printk("digestsize(%u) > outputbuffer(%zu)\n", - crypto_hash_digestsize(tfm), sizeof(output)); + crypto_tfm_alg_digestsize(tfm), sizeof(output)); goto out; } @@ -729,27 +677,20 @@ static void test_hash_speed(char *algo, unsigned int sec, memset(tvmem, 0xff, speed[i].blen); if (sec) - ret = test_hash_jiffies(&desc, tvmem, speed[i].blen, - speed[i].plen, output, sec); + test_digest_jiffies(tfm, tvmem, speed[i].blen, speed[i].plen, output, sec); else - ret = test_hash_cycles(&desc, tvmem, speed[i].blen, - speed[i].plen, output); - - if (ret) { - printk("hashing failed ret=%d\n", ret); - break; - } + test_digest_cycles(tfm, tvmem, speed[i].blen, speed[i].plen, output); } out: - crypto_free_hash(tfm); + crypto_free_tfm(tfm); } static void test_deflate(void) { unsigned int i; char result[COMP_BUF_SIZE]; - struct crypto_comp *tfm; + struct crypto_tfm *tfm; struct comp_testvec *tv; unsigned int tsize; @@ -821,7 +762,105 @@ static void test_deflate(void) ilen, dlen); } out: - crypto_free_comp(tfm); + crypto_free_tfm(tfm); +} + +static void test_crc32c(void) +{ +#define NUMVEC 6 +#define VECSIZE 40 + + int i, j, pass; + u32 crc; + u8 b, test_vec[NUMVEC][VECSIZE]; + static u32 vec_results[NUMVEC] = { + 0x0e2c157f, 0xe980ebf6, 0xde74bded, + 0xd579c862, 0xba979ad0, 0x2b29d913 + }; + static u32 tot_vec_results = 0x24c5d375; + + struct scatterlist sg[NUMVEC]; + struct crypto_tfm *tfm; + char *fmtdata = "testing crc32c initialized to %08x: %s\n"; +#define SEEDTESTVAL 0xedcba987 + u32 seed; + + printk("\ntesting crc32c\n"); + + tfm = crypto_alloc_tfm("crc32c", 0); + if (tfm == NULL) { + printk("failed to load transform for crc32c\n"); + return; + } + + crypto_digest_init(tfm); + crypto_digest_final(tfm, (u8*)&crc); + printk(fmtdata, crc, (crc == 0) ? "pass" : "ERROR"); + + /* + * stuff test_vec with known values, simple incrementing + * byte values. + */ + b = 0; + for (i = 0; i < NUMVEC; i++) { + for (j = 0; j < VECSIZE; j++) + test_vec[i][j] = ++b; + sg_set_buf(&sg[i], test_vec[i], VECSIZE); + } + + seed = SEEDTESTVAL; + (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32)); + crypto_digest_final(tfm, (u8*)&crc); + printk("testing crc32c setkey returns %08x : %s\n", crc, (crc == (SEEDTESTVAL ^ ~(u32)0)) ? + "pass" : "ERROR"); + + printk("testing crc32c using update/final:\n"); + + pass = 1; /* assume all is well */ + + for (i = 0; i < NUMVEC; i++) { + seed = ~(u32)0; + (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32)); + crypto_digest_update(tfm, &sg[i], 1); + crypto_digest_final(tfm, (u8*)&crc); + if (crc == vec_results[i]) { + printk(" %08x:OK", crc); + } else { + printk(" %08x:BAD, wanted %08x\n", crc, vec_results[i]); + pass = 0; + } + } + + printk("\ntesting crc32c using incremental accumulator:\n"); + crc = 0; + for (i = 0; i < NUMVEC; i++) { + seed = (crc ^ ~(u32)0); + (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32)); + crypto_digest_update(tfm, &sg[i], 1); + crypto_digest_final(tfm, (u8*)&crc); + } + if (crc == tot_vec_results) { + printk(" %08x:OK", crc); + } else { + printk(" %08x:BAD, wanted %08x\n", crc, tot_vec_results); + pass = 0; + } + + printk("\ntesting crc32c using digest:\n"); + seed = ~(u32)0; + (void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32)); + crypto_digest_digest(tfm, sg, NUMVEC, (u8*)&crc); + if (crc == tot_vec_results) { + printk(" %08x:OK", crc); + } else { + printk(" %08x:BAD, wanted %08x\n", crc, tot_vec_results); + pass = 0; + } + + printk("\n%s\n", pass ? "pass" : "ERROR"); + + crypto_free_tfm(tfm); + printk("crc32c test complete\n"); } static void test_available(void) @@ -830,8 +869,8 @@ static void test_available(void) while (*name) { printk("alg %s ", *name); - printk(crypto_has_alg(*name, 0, CRYPTO_ALG_ASYNC) ? - "found\n" : "not found\n"); + printk((crypto_alg_available(*name, 0)) ? + "found\n" : "not found\n"); name++; } } @@ -846,119 +885,79 @@ static void do_test(void) test_hash("sha1", sha1_tv_template, SHA1_TEST_VECTORS); //DES - test_cipher("ecb(des)", ENCRYPT, des_enc_tv_template, - DES_ENC_TEST_VECTORS); - test_cipher("ecb(des)", DECRYPT, des_dec_tv_template, - DES_DEC_TEST_VECTORS); - test_cipher("cbc(des)", ENCRYPT, des_cbc_enc_tv_template, - DES_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(des)", DECRYPT, des_cbc_dec_tv_template, - DES_CBC_DEC_TEST_VECTORS); + test_cipher ("des", MODE_ECB, ENCRYPT, des_enc_tv_template, DES_ENC_TEST_VECTORS); + test_cipher ("des", MODE_ECB, DECRYPT, des_dec_tv_template, DES_DEC_TEST_VECTORS); + test_cipher ("des", MODE_CBC, ENCRYPT, des_cbc_enc_tv_template, DES_CBC_ENC_TEST_VECTORS); + test_cipher ("des", MODE_CBC, DECRYPT, des_cbc_dec_tv_template, DES_CBC_DEC_TEST_VECTORS); //DES3_EDE - test_cipher("ecb(des3_ede)", ENCRYPT, des3_ede_enc_tv_template, - DES3_EDE_ENC_TEST_VECTORS); - test_cipher("ecb(des3_ede)", DECRYPT, des3_ede_dec_tv_template, - DES3_EDE_DEC_TEST_VECTORS); + test_cipher ("des3_ede", MODE_ECB, ENCRYPT, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS); + test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS); test_hash("md4", md4_tv_template, MD4_TEST_VECTORS); test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS); //BLOWFISH - test_cipher("ecb(blowfish)", ENCRYPT, bf_enc_tv_template, - BF_ENC_TEST_VECTORS); - test_cipher("ecb(blowfish)", DECRYPT, bf_dec_tv_template, - BF_DEC_TEST_VECTORS); - test_cipher("cbc(blowfish)", ENCRYPT, bf_cbc_enc_tv_template, - BF_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(blowfish)", DECRYPT, bf_cbc_dec_tv_template, - BF_CBC_DEC_TEST_VECTORS); + test_cipher ("blowfish", MODE_ECB, ENCRYPT, bf_enc_tv_template, BF_ENC_TEST_VECTORS); + test_cipher ("blowfish", MODE_ECB, DECRYPT, bf_dec_tv_template, BF_DEC_TEST_VECTORS); + test_cipher ("blowfish", MODE_CBC, ENCRYPT, bf_cbc_enc_tv_template, BF_CBC_ENC_TEST_VECTORS); + test_cipher ("blowfish", MODE_CBC, DECRYPT, bf_cbc_dec_tv_template, BF_CBC_DEC_TEST_VECTORS); //TWOFISH - test_cipher("ecb(twofish)", ENCRYPT, tf_enc_tv_template, - TF_ENC_TEST_VECTORS); - test_cipher("ecb(twofish)", DECRYPT, tf_dec_tv_template, - TF_DEC_TEST_VECTORS); - test_cipher("cbc(twofish)", ENCRYPT, tf_cbc_enc_tv_template, - TF_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(twofish)", DECRYPT, tf_cbc_dec_tv_template, - TF_CBC_DEC_TEST_VECTORS); + test_cipher ("twofish", MODE_ECB, ENCRYPT, tf_enc_tv_template, TF_ENC_TEST_VECTORS); + test_cipher ("twofish", MODE_ECB, DECRYPT, tf_dec_tv_template, TF_DEC_TEST_VECTORS); + test_cipher ("twofish", MODE_CBC, ENCRYPT, tf_cbc_enc_tv_template, TF_CBC_ENC_TEST_VECTORS); + test_cipher ("twofish", MODE_CBC, DECRYPT, tf_cbc_dec_tv_template, TF_CBC_DEC_TEST_VECTORS); //SERPENT - test_cipher("ecb(serpent)", ENCRYPT, serpent_enc_tv_template, - SERPENT_ENC_TEST_VECTORS); - test_cipher("ecb(serpent)", DECRYPT, serpent_dec_tv_template, - SERPENT_DEC_TEST_VECTORS); + test_cipher ("serpent", MODE_ECB, ENCRYPT, serpent_enc_tv_template, SERPENT_ENC_TEST_VECTORS); + test_cipher ("serpent", MODE_ECB, DECRYPT, serpent_dec_tv_template, SERPENT_DEC_TEST_VECTORS); //TNEPRES - test_cipher("ecb(tnepres)", ENCRYPT, tnepres_enc_tv_template, - TNEPRES_ENC_TEST_VECTORS); - test_cipher("ecb(tnepres)", DECRYPT, tnepres_dec_tv_template, - TNEPRES_DEC_TEST_VECTORS); + test_cipher ("tnepres", MODE_ECB, ENCRYPT, tnepres_enc_tv_template, TNEPRES_ENC_TEST_VECTORS); + test_cipher ("tnepres", MODE_ECB, DECRYPT, tnepres_dec_tv_template, TNEPRES_DEC_TEST_VECTORS); //AES - test_cipher("ecb(aes)", ENCRYPT, aes_enc_tv_template, - AES_ENC_TEST_VECTORS); - test_cipher("ecb(aes)", DECRYPT, aes_dec_tv_template, - AES_DEC_TEST_VECTORS); - test_cipher("cbc(aes)", ENCRYPT, aes_cbc_enc_tv_template, - AES_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(aes)", DECRYPT, aes_cbc_dec_tv_template, - AES_CBC_DEC_TEST_VECTORS); + test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS); + test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS); + test_cipher ("aes", MODE_CBC, ENCRYPT, aes_cbc_enc_tv_template, AES_CBC_ENC_TEST_VECTORS); + test_cipher ("aes", MODE_CBC, DECRYPT, aes_cbc_dec_tv_template, AES_CBC_DEC_TEST_VECTORS); //CAST5 - test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template, - CAST5_ENC_TEST_VECTORS); - test_cipher("ecb(cast5)", DECRYPT, cast5_dec_tv_template, - CAST5_DEC_TEST_VECTORS); + test_cipher ("cast5", MODE_ECB, ENCRYPT, cast5_enc_tv_template, CAST5_ENC_TEST_VECTORS); + test_cipher ("cast5", MODE_ECB, DECRYPT, cast5_dec_tv_template, CAST5_DEC_TEST_VECTORS); //CAST6 - test_cipher("ecb(cast6)", ENCRYPT, cast6_enc_tv_template, - CAST6_ENC_TEST_VECTORS); - test_cipher("ecb(cast6)", DECRYPT, cast6_dec_tv_template, - CAST6_DEC_TEST_VECTORS); + test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS); + test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS); //ARC4 - test_cipher("ecb(arc4)", ENCRYPT, arc4_enc_tv_template, - ARC4_ENC_TEST_VECTORS); - test_cipher("ecb(arc4)", DECRYPT, arc4_dec_tv_template, - ARC4_DEC_TEST_VECTORS); + test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS); + test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS); //TEA - test_cipher("ecb(tea)", ENCRYPT, tea_enc_tv_template, - TEA_ENC_TEST_VECTORS); - test_cipher("ecb(tea)", DECRYPT, tea_dec_tv_template, - TEA_DEC_TEST_VECTORS); + test_cipher ("tea", MODE_ECB, ENCRYPT, tea_enc_tv_template, TEA_ENC_TEST_VECTORS); + test_cipher ("tea", MODE_ECB, DECRYPT, tea_dec_tv_template, TEA_DEC_TEST_VECTORS); //XTEA - test_cipher("ecb(xtea)", ENCRYPT, xtea_enc_tv_template, - XTEA_ENC_TEST_VECTORS); - test_cipher("ecb(xtea)", DECRYPT, xtea_dec_tv_template, - XTEA_DEC_TEST_VECTORS); + test_cipher ("xtea", MODE_ECB, ENCRYPT, xtea_enc_tv_template, XTEA_ENC_TEST_VECTORS); + test_cipher ("xtea", MODE_ECB, DECRYPT, xtea_dec_tv_template, XTEA_DEC_TEST_VECTORS); //KHAZAD - test_cipher("ecb(khazad)", ENCRYPT, khazad_enc_tv_template, - KHAZAD_ENC_TEST_VECTORS); - test_cipher("ecb(khazad)", DECRYPT, khazad_dec_tv_template, - KHAZAD_DEC_TEST_VECTORS); + test_cipher ("khazad", MODE_ECB, ENCRYPT, khazad_enc_tv_template, KHAZAD_ENC_TEST_VECTORS); + test_cipher ("khazad", MODE_ECB, DECRYPT, khazad_dec_tv_template, KHAZAD_DEC_TEST_VECTORS); //ANUBIS - test_cipher("ecb(anubis)", ENCRYPT, anubis_enc_tv_template, - ANUBIS_ENC_TEST_VECTORS); - test_cipher("ecb(anubis)", DECRYPT, anubis_dec_tv_template, - ANUBIS_DEC_TEST_VECTORS); - test_cipher("cbc(anubis)", ENCRYPT, anubis_cbc_enc_tv_template, - ANUBIS_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(anubis)", DECRYPT, anubis_cbc_dec_tv_template, - ANUBIS_CBC_ENC_TEST_VECTORS); + test_cipher ("anubis", MODE_ECB, ENCRYPT, anubis_enc_tv_template, ANUBIS_ENC_TEST_VECTORS); + test_cipher ("anubis", MODE_ECB, DECRYPT, anubis_dec_tv_template, ANUBIS_DEC_TEST_VECTORS); + test_cipher ("anubis", MODE_CBC, ENCRYPT, anubis_cbc_enc_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS); + test_cipher ("anubis", MODE_CBC, DECRYPT, anubis_cbc_dec_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS); //XETA - test_cipher("ecb(xeta)", ENCRYPT, xeta_enc_tv_template, - XETA_ENC_TEST_VECTORS); - test_cipher("ecb(xeta)", DECRYPT, xeta_dec_tv_template, - XETA_DEC_TEST_VECTORS); + test_cipher ("xeta", MODE_ECB, ENCRYPT, xeta_enc_tv_template, XETA_ENC_TEST_VECTORS); + test_cipher ("xeta", MODE_ECB, DECRYPT, xeta_dec_tv_template, XETA_DEC_TEST_VECTORS); test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS); test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS); @@ -969,13 +968,12 @@ static void do_test(void) test_hash("tgr160", tgr160_tv_template, TGR160_TEST_VECTORS); test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS); test_deflate(); - test_hash("crc32c", crc32c_tv_template, CRC32C_TEST_VECTORS); - test_hash("hmac(md5)", hmac_md5_tv_template, - HMAC_MD5_TEST_VECTORS); - test_hash("hmac(sha1)", hmac_sha1_tv_template, - HMAC_SHA1_TEST_VECTORS); - test_hash("hmac(sha256)", hmac_sha256_tv_template, - HMAC_SHA256_TEST_VECTORS); + test_crc32c(); +#ifdef CONFIG_CRYPTO_HMAC + test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS); + test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS); + test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS); +#endif test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS); break; @@ -989,21 +987,15 @@ static void do_test(void) break; case 3: - test_cipher("ecb(des)", ENCRYPT, des_enc_tv_template, - DES_ENC_TEST_VECTORS); - test_cipher("ecb(des)", DECRYPT, des_dec_tv_template, - DES_DEC_TEST_VECTORS); - test_cipher("cbc(des)", ENCRYPT, des_cbc_enc_tv_template, - DES_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(des)", DECRYPT, des_cbc_dec_tv_template, - DES_CBC_DEC_TEST_VECTORS); + test_cipher ("des", MODE_ECB, ENCRYPT, des_enc_tv_template, DES_ENC_TEST_VECTORS); + test_cipher ("des", MODE_ECB, DECRYPT, des_dec_tv_template, DES_DEC_TEST_VECTORS); + test_cipher ("des", MODE_CBC, ENCRYPT, des_cbc_enc_tv_template, DES_CBC_ENC_TEST_VECTORS); + test_cipher ("des", MODE_CBC, DECRYPT, des_cbc_dec_tv_template, DES_CBC_DEC_TEST_VECTORS); break; case 4: - test_cipher("ecb(des3_ede)", ENCRYPT, des3_ede_enc_tv_template, - DES3_EDE_ENC_TEST_VECTORS); - test_cipher("ecb(des3_ede)", DECRYPT, des3_ede_dec_tv_template, - DES3_EDE_DEC_TEST_VECTORS); + test_cipher ("des3_ede", MODE_ECB, ENCRYPT, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS); + test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS); break; case 5: @@ -1015,43 +1007,29 @@ static void do_test(void) break; case 7: - test_cipher("ecb(blowfish)", ENCRYPT, bf_enc_tv_template, - BF_ENC_TEST_VECTORS); - test_cipher("ecb(blowfish)", DECRYPT, bf_dec_tv_template, - BF_DEC_TEST_VECTORS); - test_cipher("cbc(blowfish)", ENCRYPT, bf_cbc_enc_tv_template, - BF_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(blowfish)", DECRYPT, bf_cbc_dec_tv_template, - BF_CBC_DEC_TEST_VECTORS); + test_cipher ("blowfish", MODE_ECB, ENCRYPT, bf_enc_tv_template, BF_ENC_TEST_VECTORS); + test_cipher ("blowfish", MODE_ECB, DECRYPT, bf_dec_tv_template, BF_DEC_TEST_VECTORS); + test_cipher ("blowfish", MODE_CBC, ENCRYPT, bf_cbc_enc_tv_template, BF_CBC_ENC_TEST_VECTORS); + test_cipher ("blowfish", MODE_CBC, DECRYPT, bf_cbc_dec_tv_template, BF_CBC_DEC_TEST_VECTORS); break; case 8: - test_cipher("ecb(twofish)", ENCRYPT, tf_enc_tv_template, - TF_ENC_TEST_VECTORS); - test_cipher("ecb(twofish)", DECRYPT, tf_dec_tv_template, - TF_DEC_TEST_VECTORS); - test_cipher("cbc(twofish)", ENCRYPT, tf_cbc_enc_tv_template, - TF_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(twofish)", DECRYPT, tf_cbc_dec_tv_template, - TF_CBC_DEC_TEST_VECTORS); + test_cipher ("twofish", MODE_ECB, ENCRYPT, tf_enc_tv_template, TF_ENC_TEST_VECTORS); + test_cipher ("twofish", MODE_ECB, DECRYPT, tf_dec_tv_template, TF_DEC_TEST_VECTORS); + test_cipher ("twofish", MODE_CBC, ENCRYPT, tf_cbc_enc_tv_template, TF_CBC_ENC_TEST_VECTORS); + test_cipher ("twofish", MODE_CBC, DECRYPT, tf_cbc_dec_tv_template, TF_CBC_DEC_TEST_VECTORS); break; case 9: - test_cipher("ecb(serpent)", ENCRYPT, serpent_enc_tv_template, - SERPENT_ENC_TEST_VECTORS); - test_cipher("ecb(serpent)", DECRYPT, serpent_dec_tv_template, - SERPENT_DEC_TEST_VECTORS); + test_cipher ("serpent", MODE_ECB, ENCRYPT, serpent_enc_tv_template, SERPENT_ENC_TEST_VECTORS); + test_cipher ("serpent", MODE_ECB, DECRYPT, serpent_dec_tv_template, SERPENT_DEC_TEST_VECTORS); break; case 10: - test_cipher("ecb(aes)", ENCRYPT, aes_enc_tv_template, - AES_ENC_TEST_VECTORS); - test_cipher("ecb(aes)", DECRYPT, aes_dec_tv_template, - AES_DEC_TEST_VECTORS); - test_cipher("cbc(aes)", ENCRYPT, aes_cbc_enc_tv_template, - AES_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(aes)", DECRYPT, aes_cbc_dec_tv_template, - AES_CBC_DEC_TEST_VECTORS); + test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS); + test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS); + test_cipher ("aes", MODE_CBC, ENCRYPT, aes_cbc_enc_tv_template, AES_CBC_ENC_TEST_VECTORS); + test_cipher ("aes", MODE_CBC, DECRYPT, aes_cbc_dec_tv_template, AES_CBC_DEC_TEST_VECTORS); break; case 11: @@ -1067,24 +1045,18 @@ static void do_test(void) break; case 14: - test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template, - CAST5_ENC_TEST_VECTORS); - test_cipher("ecb(cast5)", DECRYPT, cast5_dec_tv_template, - CAST5_DEC_TEST_VECTORS); + test_cipher ("cast5", MODE_ECB, ENCRYPT, cast5_enc_tv_template, CAST5_ENC_TEST_VECTORS); + test_cipher ("cast5", MODE_ECB, DECRYPT, cast5_dec_tv_template, CAST5_DEC_TEST_VECTORS); break; case 15: - test_cipher("ecb(cast6)", ENCRYPT, cast6_enc_tv_template, - CAST6_ENC_TEST_VECTORS); - test_cipher("ecb(cast6)", DECRYPT, cast6_dec_tv_template, - CAST6_DEC_TEST_VECTORS); + test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS); + test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS); break; case 16: - test_cipher("ecb(arc4)", ENCRYPT, arc4_enc_tv_template, - ARC4_ENC_TEST_VECTORS); - test_cipher("ecb(arc4)", DECRYPT, arc4_dec_tv_template, - ARC4_DEC_TEST_VECTORS); + test_cipher ("arc4", MODE_ECB, ENCRYPT, arc4_enc_tv_template, ARC4_ENC_TEST_VECTORS); + test_cipher ("arc4", MODE_ECB, DECRYPT, arc4_dec_tv_template, ARC4_DEC_TEST_VECTORS); break; case 17: @@ -1092,28 +1064,22 @@ static void do_test(void) break; case 18: - test_hash("crc32c", crc32c_tv_template, CRC32C_TEST_VECTORS); + test_crc32c(); break; case 19: - test_cipher("ecb(tea)", ENCRYPT, tea_enc_tv_template, - TEA_ENC_TEST_VECTORS); - test_cipher("ecb(tea)", DECRYPT, tea_dec_tv_template, - TEA_DEC_TEST_VECTORS); + test_cipher ("tea", MODE_ECB, ENCRYPT, tea_enc_tv_template, TEA_ENC_TEST_VECTORS); + test_cipher ("tea", MODE_ECB, DECRYPT, tea_dec_tv_template, TEA_DEC_TEST_VECTORS); break; case 20: - test_cipher("ecb(xtea)", ENCRYPT, xtea_enc_tv_template, - XTEA_ENC_TEST_VECTORS); - test_cipher("ecb(xtea)", DECRYPT, xtea_dec_tv_template, - XTEA_DEC_TEST_VECTORS); + test_cipher ("xtea", MODE_ECB, ENCRYPT, xtea_enc_tv_template, XTEA_ENC_TEST_VECTORS); + test_cipher ("xtea", MODE_ECB, DECRYPT, xtea_dec_tv_template, XTEA_DEC_TEST_VECTORS); break; case 21: - test_cipher("ecb(khazad)", ENCRYPT, khazad_enc_tv_template, - KHAZAD_ENC_TEST_VECTORS); - test_cipher("ecb(khazad)", DECRYPT, khazad_dec_tv_template, - KHAZAD_DEC_TEST_VECTORS); + test_cipher ("khazad", MODE_ECB, ENCRYPT, khazad_enc_tv_template, KHAZAD_ENC_TEST_VECTORS); + test_cipher ("khazad", MODE_ECB, DECRYPT, khazad_dec_tv_template, KHAZAD_DEC_TEST_VECTORS); break; case 22: @@ -1129,21 +1095,15 @@ static void do_test(void) break; case 25: - test_cipher("ecb(tnepres)", ENCRYPT, tnepres_enc_tv_template, - TNEPRES_ENC_TEST_VECTORS); - test_cipher("ecb(tnepres)", DECRYPT, tnepres_dec_tv_template, - TNEPRES_DEC_TEST_VECTORS); + test_cipher ("tnepres", MODE_ECB, ENCRYPT, tnepres_enc_tv_template, TNEPRES_ENC_TEST_VECTORS); + test_cipher ("tnepres", MODE_ECB, DECRYPT, tnepres_dec_tv_template, TNEPRES_DEC_TEST_VECTORS); break; case 26: - test_cipher("ecb(anubis)", ENCRYPT, anubis_enc_tv_template, - ANUBIS_ENC_TEST_VECTORS); - test_cipher("ecb(anubis)", DECRYPT, anubis_dec_tv_template, - ANUBIS_DEC_TEST_VECTORS); - test_cipher("cbc(anubis)", ENCRYPT, anubis_cbc_enc_tv_template, - ANUBIS_CBC_ENC_TEST_VECTORS); - test_cipher("cbc(anubis)", DECRYPT, anubis_cbc_dec_tv_template, - ANUBIS_CBC_ENC_TEST_VECTORS); + test_cipher ("anubis", MODE_ECB, ENCRYPT, anubis_enc_tv_template, ANUBIS_ENC_TEST_VECTORS); + test_cipher ("anubis", MODE_ECB, DECRYPT, anubis_dec_tv_template, ANUBIS_DEC_TEST_VECTORS); + test_cipher ("anubis", MODE_CBC, ENCRYPT, anubis_cbc_enc_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS); + test_cipher ("anubis", MODE_CBC, DECRYPT, anubis_cbc_dec_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS); break; case 27: @@ -1160,88 +1120,85 @@ static void do_test(void) break; case 30: - test_cipher("ecb(xeta)", ENCRYPT, xeta_enc_tv_template, - XETA_ENC_TEST_VECTORS); - test_cipher("ecb(xeta)", DECRYPT, xeta_dec_tv_template, - XETA_DEC_TEST_VECTORS); + test_cipher ("xeta", MODE_ECB, ENCRYPT, xeta_enc_tv_template, XETA_ENC_TEST_VECTORS); + test_cipher ("xeta", MODE_ECB, DECRYPT, xeta_dec_tv_template, XETA_DEC_TEST_VECTORS); break; +#ifdef CONFIG_CRYPTO_HMAC case 100: - test_hash("hmac(md5)", hmac_md5_tv_template, - HMAC_MD5_TEST_VECTORS); + test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS); break; case 101: - test_hash("hmac(sha1)", hmac_sha1_tv_template, - HMAC_SHA1_TEST_VECTORS); + test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS); break; case 102: - test_hash("hmac(sha256)", hmac_sha256_tv_template, - HMAC_SHA256_TEST_VECTORS); + test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS); break; +#endif case 200: - test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0, + test_cipher_speed("aes", MODE_ECB, ENCRYPT, sec, NULL, 0, aes_speed_template); - test_cipher_speed("ecb(aes)", DECRYPT, sec, NULL, 0, + test_cipher_speed("aes", MODE_ECB, DECRYPT, sec, NULL, 0, aes_speed_template); - test_cipher_speed("cbc(aes)", ENCRYPT, sec, NULL, 0, + test_cipher_speed("aes", MODE_CBC, ENCRYPT, sec, NULL, 0, aes_speed_template); - test_cipher_speed("cbc(aes)", DECRYPT, sec, NULL, 0, + test_cipher_speed("aes", MODE_CBC, DECRYPT, sec, NULL, 0, aes_speed_template); break; case 201: - test_cipher_speed("ecb(des3_ede)", ENCRYPT, sec, + test_cipher_speed("des3_ede", MODE_ECB, ENCRYPT, sec, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS, des3_ede_speed_template); - test_cipher_speed("ecb(des3_ede)", DECRYPT, sec, + test_cipher_speed("des3_ede", MODE_ECB, DECRYPT, sec, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS, des3_ede_speed_template); - test_cipher_speed("cbc(des3_ede)", ENCRYPT, sec, + test_cipher_speed("des3_ede", MODE_CBC, ENCRYPT, sec, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS, des3_ede_speed_template); - test_cipher_speed("cbc(des3_ede)", DECRYPT, sec, + test_cipher_speed("des3_ede", MODE_CBC, DECRYPT, sec, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS, des3_ede_speed_template); break; case 202: - test_cipher_speed("ecb(twofish)", ENCRYPT, sec, NULL, 0, + test_cipher_speed("twofish", MODE_ECB, ENCRYPT, sec, NULL, 0, twofish_speed_template); - test_cipher_speed("ecb(twofish)", DECRYPT, sec, NULL, 0, + test_cipher_speed("twofish", MODE_ECB, DECRYPT, sec, NULL, 0, twofish_speed_template); - test_cipher_speed("cbc(twofish)", ENCRYPT, sec, NULL, 0, + test_cipher_speed("twofish", MODE_CBC, ENCRYPT, sec, NULL, 0, twofish_speed_template); - test_cipher_speed("cbc(twofish)", DECRYPT, sec, NULL, 0, + test_cipher_speed("twofish", MODE_CBC, DECRYPT, sec, NULL, 0, twofish_speed_template); break; case 203: - test_cipher_speed("ecb(blowfish)", ENCRYPT, sec, NULL, 0, + test_cipher_speed("blowfish", MODE_ECB, ENCRYPT, sec, NULL, 0, blowfish_speed_template); - test_cipher_speed("ecb(blowfish)", DECRYPT, sec, NULL, 0, + test_cipher_speed("blowfish", MODE_ECB, DECRYPT, sec, NULL, 0, blowfish_speed_template); - test_cipher_speed("cbc(blowfish)", ENCRYPT, sec, NULL, 0, + test_cipher_speed("blowfish", MODE_CBC, ENCRYPT, sec, NULL, 0, blowfish_speed_template); - test_cipher_speed("cbc(blowfish)", DECRYPT, sec, NULL, 0, + test_cipher_speed("blowfish", MODE_CBC, DECRYPT, sec, NULL, 0, blowfish_speed_template); break; case 204: - test_cipher_speed("ecb(des)", ENCRYPT, sec, NULL, 0, + test_cipher_speed("des", MODE_ECB, ENCRYPT, sec, NULL, 0, des_speed_template); - test_cipher_speed("ecb(des)", DECRYPT, sec, NULL, 0, + test_cipher_speed("des", MODE_ECB, DECRYPT, sec, NULL, 0, des_speed_template); - test_cipher_speed("cbc(des)", ENCRYPT, sec, NULL, 0, + test_cipher_speed("des", MODE_CBC, ENCRYPT, sec, NULL, 0, des_speed_template); - test_cipher_speed("cbc(des)", DECRYPT, sec, NULL, 0, + test_cipher_speed("des", MODE_CBC, DECRYPT, sec, NULL, 0, des_speed_template); break; @@ -1249,51 +1206,51 @@ static void do_test(void) /* fall through */ case 301: - test_hash_speed("md4", sec, generic_hash_speed_template); + test_digest_speed("md4", sec, generic_digest_speed_template); if (mode > 300 && mode < 400) break; case 302: - test_hash_speed("md5", sec, generic_hash_speed_template); + test_digest_speed("md5", sec, generic_digest_speed_template); if (mode > 300 && mode < 400) break; case 303: - test_hash_speed("sha1", sec, generic_hash_speed_template); + test_digest_speed("sha1", sec, generic_digest_speed_template); if (mode > 300 && mode < 400) break; case 304: - test_hash_speed("sha256", sec, generic_hash_speed_template); + test_digest_speed("sha256", sec, generic_digest_speed_template); if (mode > 300 && mode < 400) break; case 305: - test_hash_speed("sha384", sec, generic_hash_speed_template); + test_digest_speed("sha384", sec, generic_digest_speed_template); if (mode > 300 && mode < 400) break; case 306: - test_hash_speed("sha512", sec, generic_hash_speed_template); + test_digest_speed("sha512", sec, generic_digest_speed_template); if (mode > 300 && mode < 400) break; case 307: - test_hash_speed("wp256", sec, generic_hash_speed_template); + test_digest_speed("wp256", sec, generic_digest_speed_template); if (mode > 300 && mode < 400) break; case 308: - test_hash_speed("wp384", sec, generic_hash_speed_template); + test_digest_speed("wp384", sec, generic_digest_speed_template); if (mode > 300 && mode < 400) break; case 309: - test_hash_speed("wp512", sec, generic_hash_speed_template); + test_digest_speed("wp512", sec, generic_digest_speed_template); if (mode > 300 && mode < 400) break; case 310: - test_hash_speed("tgr128", sec, generic_hash_speed_template); + test_digest_speed("tgr128", sec, generic_digest_speed_template); if (mode > 300 && mode < 400) break; case 311: - test_hash_speed("tgr160", sec, generic_hash_speed_template); + test_digest_speed("tgr160", sec, generic_digest_speed_template); if (mode > 300 && mode < 400) break; case 312: - test_hash_speed("tgr192", sec, generic_hash_speed_template); + test_digest_speed("tgr192", sec, generic_digest_speed_template); if (mode > 300 && mode < 400) break; case 399: diff --git a/trunk/crypto/tcrypt.h b/trunk/crypto/tcrypt.h index a40c4411729e..1fac5602f633 100644 --- a/trunk/crypto/tcrypt.h +++ b/trunk/crypto/tcrypt.h @@ -28,7 +28,7 @@ struct hash_testvec { /* only used with keyed hash algorithms */ char key[128] __attribute__ ((__aligned__(4))); - char plaintext[240]; + char plaintext[128]; char digest[MAX_DIGEST_SIZE]; unsigned char tap[MAX_TAP]; unsigned char psize; @@ -36,6 +36,16 @@ struct hash_testvec { unsigned char ksize; }; +struct hmac_testvec { + char key[128]; + char plaintext[128]; + char digest[MAX_DIGEST_SIZE]; + unsigned char tap[MAX_TAP]; + unsigned char ksize; + unsigned char psize; + unsigned char np; +}; + struct cipher_testvec { char key[MAX_KEYLEN] __attribute__ ((__aligned__(4))); char iv[MAX_IVLEN]; @@ -55,7 +65,7 @@ struct cipher_speed { unsigned int blen; }; -struct hash_speed { +struct digest_speed { unsigned int blen; /* buffer length */ unsigned int plen; /* per-update length */ }; @@ -687,13 +697,14 @@ static struct hash_testvec tgr128_tv_template[] = { }, }; +#ifdef CONFIG_CRYPTO_HMAC /* * HMAC-MD5 test vectors from RFC2202 * (These need to be fixed to not use strlen). */ #define HMAC_MD5_TEST_VECTORS 7 -static struct hash_testvec hmac_md5_tv_template[] = +static struct hmac_testvec hmac_md5_tv_template[] = { { .key = { [0 ... 15] = 0x0b }, @@ -757,7 +768,7 @@ static struct hash_testvec hmac_md5_tv_template[] = */ #define HMAC_SHA1_TEST_VECTORS 7 -static struct hash_testvec hmac_sha1_tv_template[] = { +static struct hmac_testvec hmac_sha1_tv_template[] = { { .key = { [0 ... 19] = 0x0b }, .ksize = 20, @@ -822,7 +833,7 @@ static struct hash_testvec hmac_sha1_tv_template[] = { */ #define HMAC_SHA256_TEST_VECTORS 10 -static struct hash_testvec hmac_sha256_tv_template[] = { +static struct hmac_testvec hmac_sha256_tv_template[] = { { .key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, @@ -933,6 +944,8 @@ static struct hash_testvec hmac_sha256_tv_template[] = { }, }; +#endif /* CONFIG_CRYPTO_HMAC */ + /* * DES test vectors. */ @@ -2883,183 +2896,6 @@ static struct hash_testvec michael_mic_tv_template[] = { } }; -/* - * CRC32C test vectors - */ -#define CRC32C_TEST_VECTORS 14 - -static struct hash_testvec crc32c_tv_template[] = { - { - .psize = 0, - .digest = { 0x00, 0x00, 0x00, 0x00 } - }, - { - .key = { 0x87, 0xa9, 0xcb, 0xed }, - .ksize = 4, - .psize = 0, - .digest = { 0x78, 0x56, 0x34, 0x12 }, - }, - { - .key = { 0xff, 0xff, 0xff, 0xff }, - .ksize = 4, - .plaintext = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28 }, - .psize = 40, - .digest = { 0x7f, 0x15, 0x2c, 0x0e } - }, - { - .key = { 0xff, 0xff, 0xff, 0xff }, - .ksize = 4, - .plaintext = { 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, - 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50 }, - .psize = 40, - .digest = { 0xf6, 0xeb, 0x80, 0xe9 } - }, - { - .key = { 0xff, 0xff, 0xff, 0xff }, - .ksize = 4, - .plaintext = { 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, - 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78 }, - .psize = 40, - .digest = { 0xed, 0xbd, 0x74, 0xde } - }, - { - .key = { 0xff, 0xff, 0xff, 0xff }, - .ksize = 4, - .plaintext = { 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, - 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, - 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0 }, - .psize = 40, - .digest = { 0x62, 0xc8, 0x79, 0xd5 } - }, - { - .key = { 0xff, 0xff, 0xff, 0xff }, - .ksize = 4, - .plaintext = { 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, - 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, - 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, - 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, - 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8 }, - .psize = 40, - .digest = { 0xd0, 0x9a, 0x97, 0xba } - }, - { - .key = { 0xff, 0xff, 0xff, 0xff }, - .ksize = 4, - .plaintext = { 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, - 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, - 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, - 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, - 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0 }, - .psize = 40, - .digest = { 0x13, 0xd9, 0x29, 0x2b } - }, - { - .key = { 0x80, 0xea, 0xd3, 0xf1 }, - .ksize = 4, - .plaintext = { 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, - 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50 }, - .psize = 40, - .digest = { 0x0c, 0xb5, 0xe2, 0xa2 } - }, - { - .key = { 0xf3, 0x4a, 0x1d, 0x5d }, - .ksize = 4, - .plaintext = { 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, - 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78 }, - .psize = 40, - .digest = { 0xd1, 0x7f, 0xfb, 0xa6 } - }, - { - .key = { 0x2e, 0x80, 0x04, 0x59 }, - .ksize = 4, - .plaintext = { 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, - 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, - 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0 }, - .psize = 40, - .digest = { 0x59, 0x33, 0xe6, 0x7a } - }, - { - .key = { 0xa6, 0xcc, 0x19, 0x85 }, - .ksize = 4, - .plaintext = { 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, - 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, - 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, - 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, - 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8 }, - .psize = 40, - .digest = { 0xbe, 0x03, 0x01, 0xd2 } - }, - { - .key = { 0x41, 0xfc, 0xfe, 0x2d }, - .ksize = 4, - .plaintext = { 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, - 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, - 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, - 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, - 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0 }, - .psize = 40, - .digest = { 0x75, 0xd3, 0xc5, 0x24 } - }, - { - .key = { 0xff, 0xff, 0xff, 0xff }, - .ksize = 4, - .plaintext = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, - 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, - 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, - 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, - 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, - 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, - 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, - 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, - 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, - 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, - 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, - 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, - 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, - 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, - 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, - 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, - 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, - 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0 }, - .psize = 240, - .digest = { 0x75, 0xd3, 0xc5, 0x24 }, - .np = 2, - .tap = { 31, 209 } - }, -}; - /* * Cipher speed tests */ @@ -3147,7 +2983,7 @@ static struct cipher_speed des_speed_template[] = { /* * Digest speed tests */ -static struct hash_speed generic_hash_speed_template[] = { +static struct digest_speed generic_digest_speed_template[] = { { .blen = 16, .plen = 16, }, { .blen = 64, .plen = 16, }, { .blen = 64, .plen = 64, }, diff --git a/trunk/crypto/tea.c b/trunk/crypto/tea.c index 1c54e26fa529..5367adc82fc9 100644 --- a/trunk/crypto/tea.c +++ b/trunk/crypto/tea.c @@ -46,10 +46,16 @@ struct xtea_ctx { }; static int tea_setkey(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) + unsigned int key_len, u32 *flags) { struct tea_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *key = (const __le32 *)in_key; + + if (key_len != 16) + { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } ctx->KEY[0] = le32_to_cpu(key[0]); ctx->KEY[1] = le32_to_cpu(key[1]); @@ -119,10 +125,16 @@ static void tea_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) } static int xtea_setkey(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) + unsigned int key_len, u32 *flags) { struct xtea_ctx *ctx = crypto_tfm_ctx(tfm); const __le32 *key = (const __le32 *)in_key; + + if (key_len != 16) + { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } ctx->KEY[0] = le32_to_cpu(key[0]); ctx->KEY[1] = le32_to_cpu(key[1]); diff --git a/trunk/crypto/twofish.c b/trunk/crypto/twofish.c index 4979a2be48a9..ec2488242e2d 100644 --- a/trunk/crypto/twofish.c +++ b/trunk/crypto/twofish.c @@ -39,7 +39,6 @@ */ #include -#include #include #include #include @@ -47,6 +46,534 @@ #include #include + +/* The large precomputed tables for the Twofish cipher (twofish.c) + * Taken from the same source as twofish.c + * Marc Mutz + */ + +/* These two tables are the q0 and q1 permutations, exactly as described in + * the Twofish paper. */ + +static const u8 q0[256] = { + 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, + 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, + 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, + 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, + 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, + 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, + 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, + 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, + 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, + 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, + 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, + 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, + 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, + 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, + 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, + 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, + 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, + 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, + 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, + 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, + 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, + 0x4A, 0x5E, 0xC1, 0xE0 +}; + +static const u8 q1[256] = { + 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, + 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, + 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, + 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, + 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, + 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, + 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, + 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, + 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, + 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, + 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, + 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, + 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, + 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, + 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, + 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, + 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, + 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, + 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, + 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, + 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, + 0x55, 0x09, 0xBE, 0x91 +}; + +/* These MDS tables are actually tables of MDS composed with q0 and q1, + * because it is only ever used that way and we can save some time by + * precomputing. Of course the main saving comes from precomputing the + * GF(2^8) multiplication involved in the MDS matrix multiply; by looking + * things up in these tables we reduce the matrix multiply to four lookups + * and three XORs. Semi-formally, the definition of these tables is: + * mds[0][i] = MDS (q1[i] 0 0 0)^T mds[1][i] = MDS (0 q0[i] 0 0)^T + * mds[2][i] = MDS (0 0 q1[i] 0)^T mds[3][i] = MDS (0 0 0 q0[i])^T + * where ^T means "transpose", the matrix multiply is performed in GF(2^8) + * represented as GF(2)[x]/v(x) where v(x)=x^8+x^6+x^5+x^3+1 as described + * by Schneier et al, and I'm casually glossing over the byte/word + * conversion issues. */ + +static const u32 mds[4][256] = { + {0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, + 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, + 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, + 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, + 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, + 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, + 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1, + 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, + 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, + 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, + 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0, + 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, + 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, + 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, + 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3, + 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, + 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, + 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, + 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C, + 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, + 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, + 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, + 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72, + 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, + 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, + 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, + 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39, + 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, + 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, + 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, + 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5, + 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, + 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, + 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, + 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E, + 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, + 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, + 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, + 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2, + 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, + 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, + 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, + 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91}, + + {0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, + 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, + 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, + 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, + 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, + 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, + 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A, + 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, + 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, + 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, + 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9, + 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, + 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, + 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, + 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414, + 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, + 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, + 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, + 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5, + 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, + 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, + 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, + 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202, + 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, + 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, + 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, + 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808, + 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, + 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, + 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, + 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505, + 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, + 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, + 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, + 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF, + 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, + 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, + 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, + 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6, + 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, + 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, + 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, + 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8}, + + {0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, + 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, + 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, + 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, + 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, + 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, + 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB, + 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, + 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, + 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, + 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C, + 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, + 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, + 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, + 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035, + 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, + 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, + 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, + 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F, + 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, + 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, + 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, + 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA, + 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, + 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, + 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, + 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D, + 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, + 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, + 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, + 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086, + 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, + 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, + 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, + 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691, + 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, + 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, + 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, + 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E, + 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, + 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, + 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, + 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF}, + + {0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, + 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, + 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, + 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, + 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, + 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, + 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3, + 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, + 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, + 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, + 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF, + 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, + 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, + 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, + 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA, + 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, + 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, + 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, + 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D, + 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, + 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, + 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, + 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B, + 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, + 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, + 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, + 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE, + 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, + 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, + 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, + 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E, + 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, + 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, + 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, + 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718, + 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, + 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, + 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, + 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882, + 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, + 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, + 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, + 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8} +}; + +/* The exp_to_poly and poly_to_exp tables are used to perform efficient + * operations in GF(2^8) represented as GF(2)[x]/w(x) where + * w(x)=x^8+x^6+x^3+x^2+1. We care about doing that because it's part of the + * definition of the RS matrix in the key schedule. Elements of that field + * are polynomials of degree not greater than 7 and all coefficients 0 or 1, + * which can be represented naturally by bytes (just substitute x=2). In that + * form, GF(2^8) addition is the same as bitwise XOR, but GF(2^8) + * multiplication is inefficient without hardware support. To multiply + * faster, I make use of the fact x is a generator for the nonzero elements, + * so that every element p of GF(2)[x]/w(x) is either 0 or equal to (x)^n for + * some n in 0..254. Note that that caret is exponentiation in GF(2^8), + * *not* polynomial notation. So if I want to compute pq where p and q are + * in GF(2^8), I can just say: + * 1. if p=0 or q=0 then pq=0 + * 2. otherwise, find m and n such that p=x^m and q=x^n + * 3. pq=(x^m)(x^n)=x^(m+n), so add m and n and find pq + * The translations in steps 2 and 3 are looked up in the tables + * poly_to_exp (for step 2) and exp_to_poly (for step 3). To see this + * in action, look at the CALC_S macro. As additional wrinkles, note that + * one of my operands is always a constant, so the poly_to_exp lookup on it + * is done in advance; I included the original values in the comments so + * readers can have some chance of recognizing that this *is* the RS matrix + * from the Twofish paper. I've only included the table entries I actually + * need; I never do a lookup on a variable input of zero and the biggest + * exponents I'll ever see are 254 (variable) and 237 (constant), so they'll + * never sum to more than 491. I'm repeating part of the exp_to_poly table + * so that I don't have to do mod-255 reduction in the exponent arithmetic. + * Since I know my constant operands are never zero, I only have to worry + * about zero values in the variable operand, and I do it with a simple + * conditional branch. I know conditionals are expensive, but I couldn't + * see a non-horrible way of avoiding them, and I did manage to group the + * statements so that each if covers four group multiplications. */ + +static const u8 poly_to_exp[255] = { + 0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19, + 0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A, + 0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C, + 0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B, + 0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47, + 0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D, + 0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8, + 0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C, + 0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83, + 0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48, + 0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26, + 0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E, + 0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3, + 0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9, + 0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A, + 0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D, + 0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75, + 0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84, + 0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64, + 0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49, + 0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF, + 0x85, 0xC8, 0xA1 +}; + +static const u8 exp_to_poly[492] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, + 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, + 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, + 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, + 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, + 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, + 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, + 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, + 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, + 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, + 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, + 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, + 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, + 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, + 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, + 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, + 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, + 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, + 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB, + 0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1, + 0x8F, 0x53, 0xA6, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, + 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, + 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, + 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, + 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, + 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, + 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, + 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, + 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, + 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, + 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, + 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, + 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, + 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, + 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, + 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, + 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, + 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, + 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, + 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB +}; + + +/* The table constants are indices of + * S-box entries, preprocessed through q0 and q1. */ +static const u8 calc_sb_tbl[512] = { + 0xA9, 0x75, 0x67, 0xF3, 0xB3, 0xC6, 0xE8, 0xF4, + 0x04, 0xDB, 0xFD, 0x7B, 0xA3, 0xFB, 0x76, 0xC8, + 0x9A, 0x4A, 0x92, 0xD3, 0x80, 0xE6, 0x78, 0x6B, + 0xE4, 0x45, 0xDD, 0x7D, 0xD1, 0xE8, 0x38, 0x4B, + 0x0D, 0xD6, 0xC6, 0x32, 0x35, 0xD8, 0x98, 0xFD, + 0x18, 0x37, 0xF7, 0x71, 0xEC, 0xF1, 0x6C, 0xE1, + 0x43, 0x30, 0x75, 0x0F, 0x37, 0xF8, 0x26, 0x1B, + 0xFA, 0x87, 0x13, 0xFA, 0x94, 0x06, 0x48, 0x3F, + 0xF2, 0x5E, 0xD0, 0xBA, 0x8B, 0xAE, 0x30, 0x5B, + 0x84, 0x8A, 0x54, 0x00, 0xDF, 0xBC, 0x23, 0x9D, + 0x19, 0x6D, 0x5B, 0xC1, 0x3D, 0xB1, 0x59, 0x0E, + 0xF3, 0x80, 0xAE, 0x5D, 0xA2, 0xD2, 0x82, 0xD5, + 0x63, 0xA0, 0x01, 0x84, 0x83, 0x07, 0x2E, 0x14, + 0xD9, 0xB5, 0x51, 0x90, 0x9B, 0x2C, 0x7C, 0xA3, + 0xA6, 0xB2, 0xEB, 0x73, 0xA5, 0x4C, 0xBE, 0x54, + 0x16, 0x92, 0x0C, 0x74, 0xE3, 0x36, 0x61, 0x51, + 0xC0, 0x38, 0x8C, 0xB0, 0x3A, 0xBD, 0xF5, 0x5A, + 0x73, 0xFC, 0x2C, 0x60, 0x25, 0x62, 0x0B, 0x96, + 0xBB, 0x6C, 0x4E, 0x42, 0x89, 0xF7, 0x6B, 0x10, + 0x53, 0x7C, 0x6A, 0x28, 0xB4, 0x27, 0xF1, 0x8C, + 0xE1, 0x13, 0xE6, 0x95, 0xBD, 0x9C, 0x45, 0xC7, + 0xE2, 0x24, 0xF4, 0x46, 0xB6, 0x3B, 0x66, 0x70, + 0xCC, 0xCA, 0x95, 0xE3, 0x03, 0x85, 0x56, 0xCB, + 0xD4, 0x11, 0x1C, 0xD0, 0x1E, 0x93, 0xD7, 0xB8, + 0xFB, 0xA6, 0xC3, 0x83, 0x8E, 0x20, 0xB5, 0xFF, + 0xE9, 0x9F, 0xCF, 0x77, 0xBF, 0xC3, 0xBA, 0xCC, + 0xEA, 0x03, 0x77, 0x6F, 0x39, 0x08, 0xAF, 0xBF, + 0x33, 0x40, 0xC9, 0xE7, 0x62, 0x2B, 0x71, 0xE2, + 0x81, 0x79, 0x79, 0x0C, 0x09, 0xAA, 0xAD, 0x82, + 0x24, 0x41, 0xCD, 0x3A, 0xF9, 0xEA, 0xD8, 0xB9, + 0xE5, 0xE4, 0xC5, 0x9A, 0xB9, 0xA4, 0x4D, 0x97, + 0x44, 0x7E, 0x08, 0xDA, 0x86, 0x7A, 0xE7, 0x17, + 0xA1, 0x66, 0x1D, 0x94, 0xAA, 0xA1, 0xED, 0x1D, + 0x06, 0x3D, 0x70, 0xF0, 0xB2, 0xDE, 0xD2, 0xB3, + 0x41, 0x0B, 0x7B, 0x72, 0xA0, 0xA7, 0x11, 0x1C, + 0x31, 0xEF, 0xC2, 0xD1, 0x27, 0x53, 0x90, 0x3E, + 0x20, 0x8F, 0xF6, 0x33, 0x60, 0x26, 0xFF, 0x5F, + 0x96, 0xEC, 0x5C, 0x76, 0xB1, 0x2A, 0xAB, 0x49, + 0x9E, 0x81, 0x9C, 0x88, 0x52, 0xEE, 0x1B, 0x21, + 0x5F, 0xC4, 0x93, 0x1A, 0x0A, 0xEB, 0xEF, 0xD9, + 0x91, 0xC5, 0x85, 0x39, 0x49, 0x99, 0xEE, 0xCD, + 0x2D, 0xAD, 0x4F, 0x31, 0x8F, 0x8B, 0x3B, 0x01, + 0x47, 0x18, 0x87, 0x23, 0x6D, 0xDD, 0x46, 0x1F, + 0xD6, 0x4E, 0x3E, 0x2D, 0x69, 0xF9, 0x64, 0x48, + 0x2A, 0x4F, 0xCE, 0xF2, 0xCB, 0x65, 0x2F, 0x8E, + 0xFC, 0x78, 0x97, 0x5C, 0x05, 0x58, 0x7A, 0x19, + 0xAC, 0x8D, 0x7F, 0xE5, 0xD5, 0x98, 0x1A, 0x57, + 0x4B, 0x67, 0x0E, 0x7F, 0xA7, 0x05, 0x5A, 0x64, + 0x28, 0xAF, 0x14, 0x63, 0x3F, 0xB6, 0x29, 0xFE, + 0x88, 0xF5, 0x3C, 0xB7, 0x4C, 0x3C, 0x02, 0xA5, + 0xB8, 0xCE, 0xDA, 0xE9, 0xB0, 0x68, 0x17, 0x44, + 0x55, 0xE0, 0x1F, 0x4D, 0x8A, 0x43, 0x7D, 0x69, + 0x57, 0x29, 0xC7, 0x2E, 0x8D, 0xAC, 0x74, 0x15, + 0xB7, 0x59, 0xC4, 0xA8, 0x9F, 0x0A, 0x72, 0x9E, + 0x7E, 0x6E, 0x15, 0x47, 0x22, 0xDF, 0x12, 0x34, + 0x58, 0x35, 0x07, 0x6A, 0x99, 0xCF, 0x34, 0xDC, + 0x6E, 0x22, 0x50, 0xC9, 0xDE, 0xC0, 0x68, 0x9B, + 0x65, 0x89, 0xBC, 0xD4, 0xDB, 0xED, 0xF8, 0xAB, + 0xC8, 0x12, 0xA8, 0xA2, 0x2B, 0x0D, 0x40, 0x52, + 0xDC, 0xBB, 0xFE, 0x02, 0x32, 0x2F, 0xA4, 0xA9, + 0xCA, 0xD7, 0x10, 0x61, 0x21, 0x1E, 0xF0, 0xB4, + 0xD3, 0x50, 0x5D, 0x04, 0x0F, 0xF6, 0x00, 0xC2, + 0x6F, 0x16, 0x9D, 0x25, 0x36, 0x86, 0x42, 0x56, + 0x4A, 0x55, 0x5E, 0x09, 0xC1, 0xBE, 0xE0, 0x91 +}; + +/* Macro to perform one column of the RS matrix multiplication. The + * parameters a, b, c, and d are the four bytes of output; i is the index + * of the key bytes, and w, x, y, and z, are the column of constants from + * the RS matrix, preprocessed through the poly_to_exp table. */ + +#define CALC_S(a, b, c, d, i, w, x, y, z) \ + if (key[i]) { \ + tmp = poly_to_exp[key[i] - 1]; \ + (a) ^= exp_to_poly[tmp + (w)]; \ + (b) ^= exp_to_poly[tmp + (x)]; \ + (c) ^= exp_to_poly[tmp + (y)]; \ + (d) ^= exp_to_poly[tmp + (z)]; \ + } + +/* Macros to calculate the key-dependent S-boxes for a 128-bit key using + * the S vector from CALC_S. CALC_SB_2 computes a single entry in all + * four S-boxes, where i is the index of the entry to compute, and a and b + * are the index numbers preprocessed through the q0 and q1 tables + * respectively. */ + +#define CALC_SB_2(i, a, b) \ + ctx->s[0][i] = mds[0][q0[(a) ^ sa] ^ se]; \ + ctx->s[1][i] = mds[1][q0[(b) ^ sb] ^ sf]; \ + ctx->s[2][i] = mds[2][q1[(a) ^ sc] ^ sg]; \ + ctx->s[3][i] = mds[3][q1[(b) ^ sd] ^ sh] + +/* Macro exactly like CALC_SB_2, but for 192-bit keys. */ + +#define CALC_SB192_2(i, a, b) \ + ctx->s[0][i] = mds[0][q0[q0[(b) ^ sa] ^ se] ^ si]; \ + ctx->s[1][i] = mds[1][q0[q1[(b) ^ sb] ^ sf] ^ sj]; \ + ctx->s[2][i] = mds[2][q1[q0[(a) ^ sc] ^ sg] ^ sk]; \ + ctx->s[3][i] = mds[3][q1[q1[(a) ^ sd] ^ sh] ^ sl]; + +/* Macro exactly like CALC_SB_2, but for 256-bit keys. */ + +#define CALC_SB256_2(i, a, b) \ + ctx->s[0][i] = mds[0][q0[q0[q1[(b) ^ sa] ^ se] ^ si] ^ sm]; \ + ctx->s[1][i] = mds[1][q0[q1[q1[(a) ^ sb] ^ sf] ^ sj] ^ sn]; \ + ctx->s[2][i] = mds[2][q1[q0[q0[(a) ^ sc] ^ sg] ^ sk] ^ so]; \ + ctx->s[3][i] = mds[3][q1[q1[q0[(b) ^ sd] ^ sh] ^ sl] ^ sp]; + +/* Macros to calculate the whitening and round subkeys. CALC_K_2 computes the + * last two stages of the h() function for a given index (either 2i or 2i+1). + * a, b, c, and d are the four bytes going into the last two stages. For + * 128-bit keys, this is the entire h() function and a and c are the index + * preprocessed through q0 and q1 respectively; for longer keys they are the + * output of previous stages. j is the index of the first key byte to use. + * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2 + * twice, doing the Pseudo-Hadamard Transform, and doing the necessary + * rotations. Its parameters are: a, the array to write the results into, + * j, the index of the first output entry, k and l, the preprocessed indices + * for index 2i, and m and n, the preprocessed indices for index 2i+1. + * CALC_K192_2 expands CALC_K_2 to handle 192-bit keys, by doing an + * additional lookup-and-XOR stage. The parameters a, b, c and d are the + * four bytes going into the last three stages. For 192-bit keys, c = d + * are the index preprocessed through q0, and a = b are the index + * preprocessed through q1; j is the index of the first key byte to use. + * CALC_K192 is identical to CALC_K but for using the CALC_K192_2 macro + * instead of CALC_K_2. + * CALC_K256_2 expands CALC_K192_2 to handle 256-bit keys, by doing an + * additional lookup-and-XOR stage. The parameters a and b are the index + * preprocessed through q0 and q1 respectively; j is the index of the first + * key byte to use. CALC_K256 is identical to CALC_K but for using the + * CALC_K256_2 macro instead of CALC_K_2. */ + +#define CALC_K_2(a, b, c, d, j) \ + mds[0][q0[a ^ key[(j) + 8]] ^ key[j]] \ + ^ mds[1][q0[b ^ key[(j) + 9]] ^ key[(j) + 1]] \ + ^ mds[2][q1[c ^ key[(j) + 10]] ^ key[(j) + 2]] \ + ^ mds[3][q1[d ^ key[(j) + 11]] ^ key[(j) + 3]] + +#define CALC_K(a, j, k, l, m, n) \ + x = CALC_K_2 (k, l, k, l, 0); \ + y = CALC_K_2 (m, n, m, n, 4); \ + y = rol32(y, 8); \ + x += y; y += x; ctx->a[j] = x; \ + ctx->a[(j) + 1] = rol32(y, 9) + +#define CALC_K192_2(a, b, c, d, j) \ + CALC_K_2 (q0[a ^ key[(j) + 16]], \ + q1[b ^ key[(j) + 17]], \ + q0[c ^ key[(j) + 18]], \ + q1[d ^ key[(j) + 19]], j) + +#define CALC_K192(a, j, k, l, m, n) \ + x = CALC_K192_2 (l, l, k, k, 0); \ + y = CALC_K192_2 (n, n, m, m, 4); \ + y = rol32(y, 8); \ + x += y; y += x; ctx->a[j] = x; \ + ctx->a[(j) + 1] = rol32(y, 9) + +#define CALC_K256_2(a, b, j) \ + CALC_K192_2 (q1[b ^ key[(j) + 24]], \ + q1[a ^ key[(j) + 25]], \ + q0[a ^ key[(j) + 26]], \ + q0[b ^ key[(j) + 27]], j) + +#define CALC_K256(a, j, k, l, m, n) \ + x = CALC_K256_2 (k, l, 0); \ + y = CALC_K256_2 (m, n, 4); \ + y = rol32(y, 8); \ + x += y; y += x; ctx->a[j] = x; \ + ctx->a[(j) + 1] = rol32(y, 9) + + /* Macros to compute the g() function in the encryption and decryption * rounds. G1 is the straight g() function; G2 includes the 8-bit * rotation for the high 32-bit word. */ @@ -103,7 +630,176 @@ x ^= ctx->w[m]; \ dst[n] = cpu_to_le32(x) +#define TF_MIN_KEY_SIZE 16 +#define TF_MAX_KEY_SIZE 32 +#define TF_BLOCK_SIZE 16 + +/* Structure for an expanded Twofish key. s contains the key-dependent + * S-boxes composed with the MDS matrix; w contains the eight "whitening" + * subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note + * that k[i] corresponds to what the Twofish paper calls K[i+8]. */ +struct twofish_ctx { + u32 s[4][256], w[8], k[32]; +}; + +/* Perform the key setup. */ +static int twofish_setkey(struct crypto_tfm *tfm, const u8 *key, + unsigned int key_len, u32 *flags) +{ + + struct twofish_ctx *ctx = crypto_tfm_ctx(tfm); + int i, j, k; + + /* Temporaries for CALC_K. */ + u32 x, y; + + /* The S vector used to key the S-boxes, split up into individual bytes. + * 128-bit keys use only sa through sh; 256-bit use all of them. */ + u8 sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0, sg = 0, sh = 0; + u8 si = 0, sj = 0, sk = 0, sl = 0, sm = 0, sn = 0, so = 0, sp = 0; + + /* Temporary for CALC_S. */ + u8 tmp; + + /* Check key length. */ + if (key_len != 16 && key_len != 24 && key_len != 32) + { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; /* unsupported key length */ + } + + /* Compute the first two words of the S vector. The magic numbers are + * the entries of the RS matrix, preprocessed through poly_to_exp. The + * numbers in the comments are the original (polynomial form) matrix + * entries. */ + CALC_S (sa, sb, sc, sd, 0, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (sa, sb, sc, sd, 1, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (sa, sb, sc, sd, 2, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (sa, sb, sc, sd, 3, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (sa, sb, sc, sd, 4, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (sa, sb, sc, sd, 5, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (sa, sb, sc, sd, 6, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (sa, sb, sc, sd, 7, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + CALC_S (se, sf, sg, sh, 8, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (se, sf, sg, sh, 9, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (se, sf, sg, sh, 10, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (se, sf, sg, sh, 11, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (se, sf, sg, sh, 12, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (se, sf, sg, sh, 13, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (se, sf, sg, sh, 14, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (se, sf, sg, sh, 15, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + + if (key_len == 24 || key_len == 32) { /* 192- or 256-bit key */ + /* Calculate the third word of the S vector */ + CALC_S (si, sj, sk, sl, 16, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (si, sj, sk, sl, 17, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (si, sj, sk, sl, 18, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (si, sj, sk, sl, 19, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (si, sj, sk, sl, 20, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (si, sj, sk, sl, 21, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (si, sj, sk, sl, 22, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (si, sj, sk, sl, 23, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + } + + if (key_len == 32) { /* 256-bit key */ + /* Calculate the fourth word of the S vector */ + CALC_S (sm, sn, so, sp, 24, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ + CALC_S (sm, sn, so, sp, 25, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ + CALC_S (sm, sn, so, sp, 26, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ + CALC_S (sm, sn, so, sp, 27, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ + CALC_S (sm, sn, so, sp, 28, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ + CALC_S (sm, sn, so, sp, 29, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ + CALC_S (sm, sn, so, sp, 30, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ + CALC_S (sm, sn, so, sp, 31, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ + + /* Compute the S-boxes. */ + for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { + CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); + } + + /* Calculate whitening and round subkeys. The constants are + * indices of subkeys, preprocessed through q0 and q1. */ + CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3); + CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); + CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); + CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); + CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); + CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B); + CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); + CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); + CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); + CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD); + CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71); + CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); + CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F); + CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B); + CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA); + CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F); + CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); + CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); + CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00); + CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); + } else if (key_len == 24) { /* 192-bit key */ + /* Compute the S-boxes. */ + for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { + CALC_SB192_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); + } + + /* Calculate whitening and round subkeys. The constants are + * indices of subkeys, preprocessed through q0 and q1. */ + CALC_K192 (w, 0, 0xA9, 0x75, 0x67, 0xF3); + CALC_K192 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); + CALC_K192 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); + CALC_K192 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); + CALC_K192 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); + CALC_K192 (k, 2, 0x80, 0xE6, 0x78, 0x6B); + CALC_K192 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); + CALC_K192 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); + CALC_K192 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); + CALC_K192 (k, 10, 0x35, 0xD8, 0x98, 0xFD); + CALC_K192 (k, 12, 0x18, 0x37, 0xF7, 0x71); + CALC_K192 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); + CALC_K192 (k, 16, 0x43, 0x30, 0x75, 0x0F); + CALC_K192 (k, 18, 0x37, 0xF8, 0x26, 0x1B); + CALC_K192 (k, 20, 0xFA, 0x87, 0x13, 0xFA); + CALC_K192 (k, 22, 0x94, 0x06, 0x48, 0x3F); + CALC_K192 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); + CALC_K192 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); + CALC_K192 (k, 28, 0x84, 0x8A, 0x54, 0x00); + CALC_K192 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); + } else { /* 128-bit key */ + /* Compute the S-boxes. */ + for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { + CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); + } + + /* Calculate whitening and round subkeys. The constants are + * indices of subkeys, preprocessed through q0 and q1. */ + CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3); + CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); + CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B); + CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8); + CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3); + CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B); + CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D); + CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B); + CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32); + CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD); + CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71); + CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); + CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F); + CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B); + CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA); + CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F); + CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); + CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B); + CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00); + CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D); + } + + return 0; +} /* Encrypt one block. in and out may be the same. */ static void twofish_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) @@ -181,8 +877,6 @@ static void twofish_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) static struct crypto_alg alg = { .cra_name = "twofish", - .cra_driver_name = "twofish-generic", - .cra_priority = 100, .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = TF_BLOCK_SIZE, .cra_ctxsize = sizeof(struct twofish_ctx), diff --git a/trunk/crypto/twofish_common.c b/trunk/crypto/twofish_common.c deleted file mode 100644 index b4b9c0c3f4ae..000000000000 --- a/trunk/crypto/twofish_common.c +++ /dev/null @@ -1,744 +0,0 @@ -/* - * Common Twofish algorithm parts shared between the c and assembler - * implementations - * - * Originally Twofish for GPG - * By Matthew Skala , July 26, 1998 - * 256-bit key length added March 20, 1999 - * Some modifications to reduce the text size by Werner Koch, April, 1998 - * Ported to the kerneli patch by Marc Mutz - * Ported to CryptoAPI by Colin Slater - * - * The original author has disclaimed all copyright interest in this - * code and thus put it in the public domain. The subsequent authors - * have put this under the GNU General Public License. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * This code is a "clean room" implementation, written from the paper - * _Twofish: A 128-Bit Block Cipher_ by Bruce Schneier, John Kelsey, - * Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson, available - * through http://www.counterpane.com/twofish.html - * - * For background information on multiplication in finite fields, used for - * the matrix operations in the key schedule, see the book _Contemporary - * Abstract Algebra_ by Joseph A. Gallian, especially chapter 22 in the - * Third Edition. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - - -/* The large precomputed tables for the Twofish cipher (twofish.c) - * Taken from the same source as twofish.c - * Marc Mutz - */ - -/* These two tables are the q0 and q1 permutations, exactly as described in - * the Twofish paper. */ - -static const u8 q0[256] = { - 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, - 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, - 0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48, 0xF2, 0xD0, 0x8B, 0x30, - 0x84, 0x54, 0xDF, 0x23, 0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82, - 0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C, 0xA6, 0xEB, 0xA5, 0xBE, - 0x16, 0x0C, 0xE3, 0x61, 0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B, - 0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1, 0xE1, 0xE6, 0xBD, 0x45, - 0xE2, 0xF4, 0xB6, 0x66, 0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7, - 0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA, 0xEA, 0x77, 0x39, 0xAF, - 0x33, 0xC9, 0x62, 0x71, 0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8, - 0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7, 0xA1, 0x1D, 0xAA, 0xED, - 0x06, 0x70, 0xB2, 0xD2, 0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90, - 0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB, 0x9E, 0x9C, 0x52, 0x1B, - 0x5F, 0x93, 0x0A, 0xEF, 0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B, - 0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64, 0x2A, 0xCE, 0xCB, 0x2F, - 0xFC, 0x97, 0x05, 0x7A, 0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A, - 0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02, 0xB8, 0xDA, 0xB0, 0x17, - 0x55, 0x1F, 0x8A, 0x7D, 0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72, - 0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34, 0x6E, 0x50, 0xDE, 0x68, - 0x65, 0xBC, 0xDB, 0xF8, 0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4, - 0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00, 0x6F, 0x9D, 0x36, 0x42, - 0x4A, 0x5E, 0xC1, 0xE0 -}; - -static const u8 q1[256] = { - 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, - 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, - 0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F, 0x5E, 0xBA, 0xAE, 0x5B, - 0x8A, 0x00, 0xBC, 0x9D, 0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5, - 0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3, 0xB2, 0x73, 0x4C, 0x54, - 0x92, 0x74, 0x36, 0x51, 0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96, - 0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C, 0x13, 0x95, 0x9C, 0xC7, - 0x24, 0x46, 0x3B, 0x70, 0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8, - 0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC, 0x03, 0x6F, 0x08, 0xBF, - 0x40, 0xE7, 0x2B, 0xE2, 0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9, - 0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17, 0x66, 0x94, 0xA1, 0x1D, - 0x3D, 0xF0, 0xDE, 0xB3, 0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E, - 0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49, 0x81, 0x88, 0xEE, 0x21, - 0xC4, 0x1A, 0xEB, 0xD9, 0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01, - 0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48, 0x4F, 0xF2, 0x65, 0x8E, - 0x78, 0x5C, 0x58, 0x19, 0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64, - 0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5, 0xCE, 0xE9, 0x68, 0x44, - 0xE0, 0x4D, 0x43, 0x69, 0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E, - 0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC, 0x22, 0xC9, 0xC0, 0x9B, - 0x89, 0xD4, 0xED, 0xAB, 0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9, - 0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2, 0x16, 0x25, 0x86, 0x56, - 0x55, 0x09, 0xBE, 0x91 -}; - -/* These MDS tables are actually tables of MDS composed with q0 and q1, - * because it is only ever used that way and we can save some time by - * precomputing. Of course the main saving comes from precomputing the - * GF(2^8) multiplication involved in the MDS matrix multiply; by looking - * things up in these tables we reduce the matrix multiply to four lookups - * and three XORs. Semi-formally, the definition of these tables is: - * mds[0][i] = MDS (q1[i] 0 0 0)^T mds[1][i] = MDS (0 q0[i] 0 0)^T - * mds[2][i] = MDS (0 0 q1[i] 0)^T mds[3][i] = MDS (0 0 0 q0[i])^T - * where ^T means "transpose", the matrix multiply is performed in GF(2^8) - * represented as GF(2)[x]/v(x) where v(x)=x^8+x^6+x^5+x^3+1 as described - * by Schneier et al, and I'm casually glossing over the byte/word - * conversion issues. */ - -static const u32 mds[4][256] = { - { - 0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, - 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, - 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, - 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, - 0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, - 0xB0B0B306, 0x7575DE3F, 0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, - 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D, 0xAEAE2C6D, 0x7F7FABC1, - 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5, - 0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, - 0x3131272C, 0x808065A3, 0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, - 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51, 0x2A2A3638, 0xC4C49CB0, - 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796, - 0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, - 0x6767C027, 0xE9E9AF8C, 0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, - 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70, 0x29294CCA, 0xF0F035E3, - 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8, - 0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, - 0xC8C81DC3, 0x9999FFCC, 0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, - 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2, 0xB5B53D79, 0x09090F0C, - 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9, - 0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, - 0xEDEDD07A, 0x4343FC17, 0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, - 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3, 0x5656E70B, 0xE3E3DA72, - 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E, - 0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, - 0x8181942A, 0x91910149, 0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, - 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9, 0x7878AEC5, 0xC5C56D39, - 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01, - 0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, - 0x55559DF9, 0x7E7E5A48, 0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, - 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519, 0x0606F48D, 0x404086E5, - 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64, - 0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, - 0x2D2D333C, 0x3030D6A5, 0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, - 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969, 0xD9D97929, 0x8686912E, - 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E, - 0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, - 0xC1C112CF, 0x8585EBDC, 0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, - 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB, 0xABABA212, 0x6F6F3EA2, - 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9, - 0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, - 0x04047FF6, 0x272746C2, 0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, - 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91}, - - { - 0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, - 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, - 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, - 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, - 0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, - 0x94B1FBFB, 0x485A7E7E, 0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, - 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060, 0x1945FDFD, 0x5BA33A3A, - 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757, - 0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, - 0x9B53AAAA, 0x7C635D5D, 0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, - 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7, 0xC0F09090, 0x8CAFE9E9, - 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656, - 0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, - 0xB499C3C3, 0xF1975B5B, 0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, - 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8, 0xCCFF9999, 0x95EA1414, - 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3, - 0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, - 0xBF7E9595, 0xBA207D7D, 0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, - 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB, 0x81FB0F0F, 0x793DB5B5, - 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282, - 0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, - 0x86135050, 0xE730F7F7, 0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, - 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B, 0x410B9F9F, 0x7B8B0202, - 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC, - 0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, - 0xB1C72B2B, 0xAB6F8E8E, 0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, - 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9, 0x91EF1313, 0x85FE0808, - 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272, - 0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, - 0x6929A9A9, 0x647D4F4F, 0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, - 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED, 0xAC87D1D1, 0x7F8E0505, - 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5, - 0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, - 0x4C5F7979, 0x02B6B7B7, 0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, - 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2, 0x57AC3333, 0xC718CFCF, - 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3, - 0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, - 0x99E51D1D, 0x34392323, 0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, - 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA, 0xC8FA9E9E, 0xA882D6D6, - 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF, - 0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, - 0x0FE25151, 0x00000000, 0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, - 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8}, - - { - 0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, - 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, - 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, - 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, - 0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, - 0xB006B0B3, 0x753F75DE, 0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, - 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0, 0xAE6DAE2C, 0x7FC17FAB, - 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA, - 0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, - 0x312C3127, 0x80A38065, 0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, - 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F, 0x2A382A36, 0xC4B0C49C, - 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07, - 0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, - 0x672767C0, 0xE98CE9AF, 0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, - 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C, 0x29CA294C, 0xF0E3F035, - 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96, - 0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, - 0xC8C3C81D, 0x99CC99FF, 0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, - 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E, 0xB579B53D, 0x090C090F, - 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD, - 0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, - 0xED7AEDD0, 0x431743FC, 0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, - 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71, 0x560B56E7, 0xE372E3DA, - 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85, - 0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, - 0x812A8194, 0x91499101, 0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, - 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5, 0x78C578AE, 0xC539C56D, - 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B, - 0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, - 0x55F9559D, 0x7E487E5A, 0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, - 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45, 0x068D06F4, 0x40E54086, - 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D, - 0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, - 0x2D3C2D33, 0x30A530D6, 0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, - 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929, 0xD929D979, 0x862E8691, - 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D, - 0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, - 0xC1CFC112, 0x85DC85EB, 0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, - 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F, 0xAB12ABA2, 0x6FA26F3E, - 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9, - 0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, - 0x04F6047F, 0x27C22746, 0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, - 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF}, - - { - 0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, - 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, - 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, - 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, - 0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, - 0xB1FB94B1, 0x5A7E485A, 0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, - 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5, 0x45FD1945, 0xA33A5BA3, - 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216, - 0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, - 0x53AA9B53, 0x635D7C63, 0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, - 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123, 0xF090C0F0, 0xAFE98CAF, - 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7, - 0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, - 0x99C3B499, 0x975BF197, 0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, - 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB, 0xFF99CCFF, 0xEA1495EA, - 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C, - 0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, - 0x7E95BF7E, 0x207DBA20, 0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, - 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137, 0xFB0F81FB, 0x3DB5793D, - 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE, - 0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, - 0x13508613, 0x30F7E730, 0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, - 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252, 0x0B9F410B, 0x8B027B8B, - 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4, - 0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, - 0xC72BB1C7, 0x6F8EAB6F, 0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, - 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A, 0xEF1391EF, 0xFE0885FE, - 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB, - 0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, - 0x29A96929, 0x7D4F647D, 0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, - 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0, 0x87D1AC87, 0x8E057F8E, - 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8, - 0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, - 0x5F794C5F, 0xB6B702B6, 0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, - 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38, 0xAC3357AC, 0x18CFC718, - 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA, - 0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, - 0xE51D99E5, 0x39233439, 0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, - 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6, 0xFA9EC8FA, 0x82D6A882, - 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D, - 0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, - 0xE2510FE2, 0x00000000, 0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, - 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8} -}; - -/* The exp_to_poly and poly_to_exp tables are used to perform efficient - * operations in GF(2^8) represented as GF(2)[x]/w(x) where - * w(x)=x^8+x^6+x^3+x^2+1. We care about doing that because it's part of the - * definition of the RS matrix in the key schedule. Elements of that field - * are polynomials of degree not greater than 7 and all coefficients 0 or 1, - * which can be represented naturally by bytes (just substitute x=2). In that - * form, GF(2^8) addition is the same as bitwise XOR, but GF(2^8) - * multiplication is inefficient without hardware support. To multiply - * faster, I make use of the fact x is a generator for the nonzero elements, - * so that every element p of GF(2)[x]/w(x) is either 0 or equal to (x)^n for - * some n in 0..254. Note that that caret is exponentiation in GF(2^8), - * *not* polynomial notation. So if I want to compute pq where p and q are - * in GF(2^8), I can just say: - * 1. if p=0 or q=0 then pq=0 - * 2. otherwise, find m and n such that p=x^m and q=x^n - * 3. pq=(x^m)(x^n)=x^(m+n), so add m and n and find pq - * The translations in steps 2 and 3 are looked up in the tables - * poly_to_exp (for step 2) and exp_to_poly (for step 3). To see this - * in action, look at the CALC_S macro. As additional wrinkles, note that - * one of my operands is always a constant, so the poly_to_exp lookup on it - * is done in advance; I included the original values in the comments so - * readers can have some chance of recognizing that this *is* the RS matrix - * from the Twofish paper. I've only included the table entries I actually - * need; I never do a lookup on a variable input of zero and the biggest - * exponents I'll ever see are 254 (variable) and 237 (constant), so they'll - * never sum to more than 491. I'm repeating part of the exp_to_poly table - * so that I don't have to do mod-255 reduction in the exponent arithmetic. - * Since I know my constant operands are never zero, I only have to worry - * about zero values in the variable operand, and I do it with a simple - * conditional branch. I know conditionals are expensive, but I couldn't - * see a non-horrible way of avoiding them, and I did manage to group the - * statements so that each if covers four group multiplications. */ - -static const u8 poly_to_exp[255] = { - 0x00, 0x01, 0x17, 0x02, 0x2E, 0x18, 0x53, 0x03, 0x6A, 0x2F, 0x93, 0x19, - 0x34, 0x54, 0x45, 0x04, 0x5C, 0x6B, 0xB6, 0x30, 0xA6, 0x94, 0x4B, 0x1A, - 0x8C, 0x35, 0x81, 0x55, 0xAA, 0x46, 0x0D, 0x05, 0x24, 0x5D, 0x87, 0x6C, - 0x9B, 0xB7, 0xC1, 0x31, 0x2B, 0xA7, 0xA3, 0x95, 0x98, 0x4C, 0xCA, 0x1B, - 0xE6, 0x8D, 0x73, 0x36, 0xCD, 0x82, 0x12, 0x56, 0x62, 0xAB, 0xF0, 0x47, - 0x4F, 0x0E, 0xBD, 0x06, 0xD4, 0x25, 0xD2, 0x5E, 0x27, 0x88, 0x66, 0x6D, - 0xD6, 0x9C, 0x79, 0xB8, 0x08, 0xC2, 0xDF, 0x32, 0x68, 0x2C, 0xFD, 0xA8, - 0x8A, 0xA4, 0x5A, 0x96, 0x29, 0x99, 0x22, 0x4D, 0x60, 0xCB, 0xE4, 0x1C, - 0x7B, 0xE7, 0x3B, 0x8E, 0x9E, 0x74, 0xF4, 0x37, 0xD8, 0xCE, 0xF9, 0x83, - 0x6F, 0x13, 0xB2, 0x57, 0xE1, 0x63, 0xDC, 0xAC, 0xC4, 0xF1, 0xAF, 0x48, - 0x0A, 0x50, 0x42, 0x0F, 0xBA, 0xBE, 0xC7, 0x07, 0xDE, 0xD5, 0x78, 0x26, - 0x65, 0xD3, 0xD1, 0x5F, 0xE3, 0x28, 0x21, 0x89, 0x59, 0x67, 0xFC, 0x6E, - 0xB1, 0xD7, 0xF8, 0x9D, 0xF3, 0x7A, 0x3A, 0xB9, 0xC6, 0x09, 0x41, 0xC3, - 0xAE, 0xE0, 0xDB, 0x33, 0x44, 0x69, 0x92, 0x2D, 0x52, 0xFE, 0x16, 0xA9, - 0x0C, 0x8B, 0x80, 0xA5, 0x4A, 0x5B, 0xB5, 0x97, 0xC9, 0x2A, 0xA2, 0x9A, - 0xC0, 0x23, 0x86, 0x4E, 0xBC, 0x61, 0xEF, 0xCC, 0x11, 0xE5, 0x72, 0x1D, - 0x3D, 0x7C, 0xEB, 0xE8, 0xE9, 0x3C, 0xEA, 0x8F, 0x7D, 0x9F, 0xEC, 0x75, - 0x1E, 0xF5, 0x3E, 0x38, 0xF6, 0xD9, 0x3F, 0xCF, 0x76, 0xFA, 0x1F, 0x84, - 0xA0, 0x70, 0xED, 0x14, 0x90, 0xB3, 0x7E, 0x58, 0xFB, 0xE2, 0x20, 0x64, - 0xD0, 0xDD, 0x77, 0xAD, 0xDA, 0xC5, 0x40, 0xF2, 0x39, 0xB0, 0xF7, 0x49, - 0xB4, 0x0B, 0x7F, 0x51, 0x15, 0x43, 0x91, 0x10, 0x71, 0xBB, 0xEE, 0xBF, - 0x85, 0xC8, 0xA1 -}; - -static const u8 exp_to_poly[492] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, 0x9A, 0x79, 0xF2, - 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, 0xF5, 0xA7, 0x03, - 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, 0x8B, 0x5B, 0xB6, - 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, 0xA4, 0x05, 0x0A, - 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xED, 0x97, 0x63, - 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, 0x0F, 0x1E, 0x3C, - 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, 0xF4, 0xA5, 0x07, - 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, 0x22, 0x44, 0x88, - 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, 0xA2, 0x09, 0x12, - 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, 0xCC, 0xD5, 0xE7, - 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, 0x1B, 0x36, 0x6C, - 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, 0x32, 0x64, 0xC8, - 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, 0x5A, 0xB4, 0x25, - 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, 0xAC, 0x15, 0x2A, - 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, 0x91, 0x6F, 0xDE, - 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, 0x3F, 0x7E, 0xFC, - 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, 0xB1, 0x2F, 0x5E, - 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, 0x82, 0x49, 0x92, - 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, 0x71, 0xE2, 0x89, - 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB, 0xDB, 0xFB, 0xBB, - 0x3B, 0x76, 0xEC, 0x95, 0x67, 0xCE, 0xD1, 0xEF, 0x93, 0x6B, 0xD6, 0xE1, - 0x8F, 0x53, 0xA6, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x4D, - 0x9A, 0x79, 0xF2, 0xA9, 0x1F, 0x3E, 0x7C, 0xF8, 0xBD, 0x37, 0x6E, 0xDC, - 0xF5, 0xA7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xCD, 0xD7, 0xE3, - 0x8B, 0x5B, 0xB6, 0x21, 0x42, 0x84, 0x45, 0x8A, 0x59, 0xB2, 0x29, 0x52, - 0xA4, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x0D, 0x1A, 0x34, 0x68, 0xD0, - 0xED, 0x97, 0x63, 0xC6, 0xC1, 0xCF, 0xD3, 0xEB, 0x9B, 0x7B, 0xF6, 0xA1, - 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xAD, 0x17, 0x2E, 0x5C, 0xB8, 0x3D, 0x7A, - 0xF4, 0xA5, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0x8D, 0x57, 0xAE, 0x11, - 0x22, 0x44, 0x88, 0x5D, 0xBA, 0x39, 0x72, 0xE4, 0x85, 0x47, 0x8E, 0x51, - 0xA2, 0x09, 0x12, 0x24, 0x48, 0x90, 0x6D, 0xDA, 0xF9, 0xBF, 0x33, 0x66, - 0xCC, 0xD5, 0xE7, 0x83, 0x4B, 0x96, 0x61, 0xC2, 0xC9, 0xDF, 0xF3, 0xAB, - 0x1B, 0x36, 0x6C, 0xD8, 0xFD, 0xB7, 0x23, 0x46, 0x8C, 0x55, 0xAA, 0x19, - 0x32, 0x64, 0xC8, 0xDD, 0xF7, 0xA3, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x2D, - 0x5A, 0xB4, 0x25, 0x4A, 0x94, 0x65, 0xCA, 0xD9, 0xFF, 0xB3, 0x2B, 0x56, - 0xAC, 0x15, 0x2A, 0x54, 0xA8, 0x1D, 0x3A, 0x74, 0xE8, 0x9D, 0x77, 0xEE, - 0x91, 0x6F, 0xDE, 0xF1, 0xAF, 0x13, 0x26, 0x4C, 0x98, 0x7D, 0xFA, 0xB9, - 0x3F, 0x7E, 0xFC, 0xB5, 0x27, 0x4E, 0x9C, 0x75, 0xEA, 0x99, 0x7F, 0xFE, - 0xB1, 0x2F, 0x5E, 0xBC, 0x35, 0x6A, 0xD4, 0xE5, 0x87, 0x43, 0x86, 0x41, - 0x82, 0x49, 0x92, 0x69, 0xD2, 0xE9, 0x9F, 0x73, 0xE6, 0x81, 0x4F, 0x9E, - 0x71, 0xE2, 0x89, 0x5F, 0xBE, 0x31, 0x62, 0xC4, 0xC5, 0xC7, 0xC3, 0xCB -}; - - -/* The table constants are indices of - * S-box entries, preprocessed through q0 and q1. */ -static const u8 calc_sb_tbl[512] = { - 0xA9, 0x75, 0x67, 0xF3, 0xB3, 0xC6, 0xE8, 0xF4, - 0x04, 0xDB, 0xFD, 0x7B, 0xA3, 0xFB, 0x76, 0xC8, - 0x9A, 0x4A, 0x92, 0xD3, 0x80, 0xE6, 0x78, 0x6B, - 0xE4, 0x45, 0xDD, 0x7D, 0xD1, 0xE8, 0x38, 0x4B, - 0x0D, 0xD6, 0xC6, 0x32, 0x35, 0xD8, 0x98, 0xFD, - 0x18, 0x37, 0xF7, 0x71, 0xEC, 0xF1, 0x6C, 0xE1, - 0x43, 0x30, 0x75, 0x0F, 0x37, 0xF8, 0x26, 0x1B, - 0xFA, 0x87, 0x13, 0xFA, 0x94, 0x06, 0x48, 0x3F, - 0xF2, 0x5E, 0xD0, 0xBA, 0x8B, 0xAE, 0x30, 0x5B, - 0x84, 0x8A, 0x54, 0x00, 0xDF, 0xBC, 0x23, 0x9D, - 0x19, 0x6D, 0x5B, 0xC1, 0x3D, 0xB1, 0x59, 0x0E, - 0xF3, 0x80, 0xAE, 0x5D, 0xA2, 0xD2, 0x82, 0xD5, - 0x63, 0xA0, 0x01, 0x84, 0x83, 0x07, 0x2E, 0x14, - 0xD9, 0xB5, 0x51, 0x90, 0x9B, 0x2C, 0x7C, 0xA3, - 0xA6, 0xB2, 0xEB, 0x73, 0xA5, 0x4C, 0xBE, 0x54, - 0x16, 0x92, 0x0C, 0x74, 0xE3, 0x36, 0x61, 0x51, - 0xC0, 0x38, 0x8C, 0xB0, 0x3A, 0xBD, 0xF5, 0x5A, - 0x73, 0xFC, 0x2C, 0x60, 0x25, 0x62, 0x0B, 0x96, - 0xBB, 0x6C, 0x4E, 0x42, 0x89, 0xF7, 0x6B, 0x10, - 0x53, 0x7C, 0x6A, 0x28, 0xB4, 0x27, 0xF1, 0x8C, - 0xE1, 0x13, 0xE6, 0x95, 0xBD, 0x9C, 0x45, 0xC7, - 0xE2, 0x24, 0xF4, 0x46, 0xB6, 0x3B, 0x66, 0x70, - 0xCC, 0xCA, 0x95, 0xE3, 0x03, 0x85, 0x56, 0xCB, - 0xD4, 0x11, 0x1C, 0xD0, 0x1E, 0x93, 0xD7, 0xB8, - 0xFB, 0xA6, 0xC3, 0x83, 0x8E, 0x20, 0xB5, 0xFF, - 0xE9, 0x9F, 0xCF, 0x77, 0xBF, 0xC3, 0xBA, 0xCC, - 0xEA, 0x03, 0x77, 0x6F, 0x39, 0x08, 0xAF, 0xBF, - 0x33, 0x40, 0xC9, 0xE7, 0x62, 0x2B, 0x71, 0xE2, - 0x81, 0x79, 0x79, 0x0C, 0x09, 0xAA, 0xAD, 0x82, - 0x24, 0x41, 0xCD, 0x3A, 0xF9, 0xEA, 0xD8, 0xB9, - 0xE5, 0xE4, 0xC5, 0x9A, 0xB9, 0xA4, 0x4D, 0x97, - 0x44, 0x7E, 0x08, 0xDA, 0x86, 0x7A, 0xE7, 0x17, - 0xA1, 0x66, 0x1D, 0x94, 0xAA, 0xA1, 0xED, 0x1D, - 0x06, 0x3D, 0x70, 0xF0, 0xB2, 0xDE, 0xD2, 0xB3, - 0x41, 0x0B, 0x7B, 0x72, 0xA0, 0xA7, 0x11, 0x1C, - 0x31, 0xEF, 0xC2, 0xD1, 0x27, 0x53, 0x90, 0x3E, - 0x20, 0x8F, 0xF6, 0x33, 0x60, 0x26, 0xFF, 0x5F, - 0x96, 0xEC, 0x5C, 0x76, 0xB1, 0x2A, 0xAB, 0x49, - 0x9E, 0x81, 0x9C, 0x88, 0x52, 0xEE, 0x1B, 0x21, - 0x5F, 0xC4, 0x93, 0x1A, 0x0A, 0xEB, 0xEF, 0xD9, - 0x91, 0xC5, 0x85, 0x39, 0x49, 0x99, 0xEE, 0xCD, - 0x2D, 0xAD, 0x4F, 0x31, 0x8F, 0x8B, 0x3B, 0x01, - 0x47, 0x18, 0x87, 0x23, 0x6D, 0xDD, 0x46, 0x1F, - 0xD6, 0x4E, 0x3E, 0x2D, 0x69, 0xF9, 0x64, 0x48, - 0x2A, 0x4F, 0xCE, 0xF2, 0xCB, 0x65, 0x2F, 0x8E, - 0xFC, 0x78, 0x97, 0x5C, 0x05, 0x58, 0x7A, 0x19, - 0xAC, 0x8D, 0x7F, 0xE5, 0xD5, 0x98, 0x1A, 0x57, - 0x4B, 0x67, 0x0E, 0x7F, 0xA7, 0x05, 0x5A, 0x64, - 0x28, 0xAF, 0x14, 0x63, 0x3F, 0xB6, 0x29, 0xFE, - 0x88, 0xF5, 0x3C, 0xB7, 0x4C, 0x3C, 0x02, 0xA5, - 0xB8, 0xCE, 0xDA, 0xE9, 0xB0, 0x68, 0x17, 0x44, - 0x55, 0xE0, 0x1F, 0x4D, 0x8A, 0x43, 0x7D, 0x69, - 0x57, 0x29, 0xC7, 0x2E, 0x8D, 0xAC, 0x74, 0x15, - 0xB7, 0x59, 0xC4, 0xA8, 0x9F, 0x0A, 0x72, 0x9E, - 0x7E, 0x6E, 0x15, 0x47, 0x22, 0xDF, 0x12, 0x34, - 0x58, 0x35, 0x07, 0x6A, 0x99, 0xCF, 0x34, 0xDC, - 0x6E, 0x22, 0x50, 0xC9, 0xDE, 0xC0, 0x68, 0x9B, - 0x65, 0x89, 0xBC, 0xD4, 0xDB, 0xED, 0xF8, 0xAB, - 0xC8, 0x12, 0xA8, 0xA2, 0x2B, 0x0D, 0x40, 0x52, - 0xDC, 0xBB, 0xFE, 0x02, 0x32, 0x2F, 0xA4, 0xA9, - 0xCA, 0xD7, 0x10, 0x61, 0x21, 0x1E, 0xF0, 0xB4, - 0xD3, 0x50, 0x5D, 0x04, 0x0F, 0xF6, 0x00, 0xC2, - 0x6F, 0x16, 0x9D, 0x25, 0x36, 0x86, 0x42, 0x56, - 0x4A, 0x55, 0x5E, 0x09, 0xC1, 0xBE, 0xE0, 0x91 -}; - -/* Macro to perform one column of the RS matrix multiplication. The - * parameters a, b, c, and d are the four bytes of output; i is the index - * of the key bytes, and w, x, y, and z, are the column of constants from - * the RS matrix, preprocessed through the poly_to_exp table. */ - -#define CALC_S(a, b, c, d, i, w, x, y, z) \ - if (key[i]) { \ - tmp = poly_to_exp[key[i] - 1]; \ - (a) ^= exp_to_poly[tmp + (w)]; \ - (b) ^= exp_to_poly[tmp + (x)]; \ - (c) ^= exp_to_poly[tmp + (y)]; \ - (d) ^= exp_to_poly[tmp + (z)]; \ - } - -/* Macros to calculate the key-dependent S-boxes for a 128-bit key using - * the S vector from CALC_S. CALC_SB_2 computes a single entry in all - * four S-boxes, where i is the index of the entry to compute, and a and b - * are the index numbers preprocessed through the q0 and q1 tables - * respectively. */ - -#define CALC_SB_2(i, a, b) \ - ctx->s[0][i] = mds[0][q0[(a) ^ sa] ^ se]; \ - ctx->s[1][i] = mds[1][q0[(b) ^ sb] ^ sf]; \ - ctx->s[2][i] = mds[2][q1[(a) ^ sc] ^ sg]; \ - ctx->s[3][i] = mds[3][q1[(b) ^ sd] ^ sh] - -/* Macro exactly like CALC_SB_2, but for 192-bit keys. */ - -#define CALC_SB192_2(i, a, b) \ - ctx->s[0][i] = mds[0][q0[q0[(b) ^ sa] ^ se] ^ si]; \ - ctx->s[1][i] = mds[1][q0[q1[(b) ^ sb] ^ sf] ^ sj]; \ - ctx->s[2][i] = mds[2][q1[q0[(a) ^ sc] ^ sg] ^ sk]; \ - ctx->s[3][i] = mds[3][q1[q1[(a) ^ sd] ^ sh] ^ sl]; - -/* Macro exactly like CALC_SB_2, but for 256-bit keys. */ - -#define CALC_SB256_2(i, a, b) \ - ctx->s[0][i] = mds[0][q0[q0[q1[(b) ^ sa] ^ se] ^ si] ^ sm]; \ - ctx->s[1][i] = mds[1][q0[q1[q1[(a) ^ sb] ^ sf] ^ sj] ^ sn]; \ - ctx->s[2][i] = mds[2][q1[q0[q0[(a) ^ sc] ^ sg] ^ sk] ^ so]; \ - ctx->s[3][i] = mds[3][q1[q1[q0[(b) ^ sd] ^ sh] ^ sl] ^ sp]; - -/* Macros to calculate the whitening and round subkeys. CALC_K_2 computes the - * last two stages of the h() function for a given index (either 2i or 2i+1). - * a, b, c, and d are the four bytes going into the last two stages. For - * 128-bit keys, this is the entire h() function and a and c are the index - * preprocessed through q0 and q1 respectively; for longer keys they are the - * output of previous stages. j is the index of the first key byte to use. - * CALC_K computes a pair of subkeys for 128-bit Twofish, by calling CALC_K_2 - * twice, doing the Pseudo-Hadamard Transform, and doing the necessary - * rotations. Its parameters are: a, the array to write the results into, - * j, the index of the first output entry, k and l, the preprocessed indices - * for index 2i, and m and n, the preprocessed indices for index 2i+1. - * CALC_K192_2 expands CALC_K_2 to handle 192-bit keys, by doing an - * additional lookup-and-XOR stage. The parameters a, b, c and d are the - * four bytes going into the last three stages. For 192-bit keys, c = d - * are the index preprocessed through q0, and a = b are the index - * preprocessed through q1; j is the index of the first key byte to use. - * CALC_K192 is identical to CALC_K but for using the CALC_K192_2 macro - * instead of CALC_K_2. - * CALC_K256_2 expands CALC_K192_2 to handle 256-bit keys, by doing an - * additional lookup-and-XOR stage. The parameters a and b are the index - * preprocessed through q0 and q1 respectively; j is the index of the first - * key byte to use. CALC_K256 is identical to CALC_K but for using the - * CALC_K256_2 macro instead of CALC_K_2. */ - -#define CALC_K_2(a, b, c, d, j) \ - mds[0][q0[a ^ key[(j) + 8]] ^ key[j]] \ - ^ mds[1][q0[b ^ key[(j) + 9]] ^ key[(j) + 1]] \ - ^ mds[2][q1[c ^ key[(j) + 10]] ^ key[(j) + 2]] \ - ^ mds[3][q1[d ^ key[(j) + 11]] ^ key[(j) + 3]] - -#define CALC_K(a, j, k, l, m, n) \ - x = CALC_K_2 (k, l, k, l, 0); \ - y = CALC_K_2 (m, n, m, n, 4); \ - y = rol32(y, 8); \ - x += y; y += x; ctx->a[j] = x; \ - ctx->a[(j) + 1] = rol32(y, 9) - -#define CALC_K192_2(a, b, c, d, j) \ - CALC_K_2 (q0[a ^ key[(j) + 16]], \ - q1[b ^ key[(j) + 17]], \ - q0[c ^ key[(j) + 18]], \ - q1[d ^ key[(j) + 19]], j) - -#define CALC_K192(a, j, k, l, m, n) \ - x = CALC_K192_2 (l, l, k, k, 0); \ - y = CALC_K192_2 (n, n, m, m, 4); \ - y = rol32(y, 8); \ - x += y; y += x; ctx->a[j] = x; \ - ctx->a[(j) + 1] = rol32(y, 9) - -#define CALC_K256_2(a, b, j) \ - CALC_K192_2 (q1[b ^ key[(j) + 24]], \ - q1[a ^ key[(j) + 25]], \ - q0[a ^ key[(j) + 26]], \ - q0[b ^ key[(j) + 27]], j) - -#define CALC_K256(a, j, k, l, m, n) \ - x = CALC_K256_2 (k, l, 0); \ - y = CALC_K256_2 (m, n, 4); \ - y = rol32(y, 8); \ - x += y; y += x; ctx->a[j] = x; \ - ctx->a[(j) + 1] = rol32(y, 9) - -/* Perform the key setup. */ -int twofish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len) -{ - - struct twofish_ctx *ctx = crypto_tfm_ctx(tfm); - u32 *flags = &tfm->crt_flags; - - int i, j, k; - - /* Temporaries for CALC_K. */ - u32 x, y; - - /* The S vector used to key the S-boxes, split up into individual bytes. - * 128-bit keys use only sa through sh; 256-bit use all of them. */ - u8 sa = 0, sb = 0, sc = 0, sd = 0, se = 0, sf = 0, sg = 0, sh = 0; - u8 si = 0, sj = 0, sk = 0, sl = 0, sm = 0, sn = 0, so = 0, sp = 0; - - /* Temporary for CALC_S. */ - u8 tmp; - - /* Check key length. */ - if (key_len % 8) - { - *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; - return -EINVAL; /* unsupported key length */ - } - - /* Compute the first two words of the S vector. The magic numbers are - * the entries of the RS matrix, preprocessed through poly_to_exp. The - * numbers in the comments are the original (polynomial form) matrix - * entries. */ - CALC_S (sa, sb, sc, sd, 0, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ - CALC_S (sa, sb, sc, sd, 1, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ - CALC_S (sa, sb, sc, sd, 2, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ - CALC_S (sa, sb, sc, sd, 3, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ - CALC_S (sa, sb, sc, sd, 4, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ - CALC_S (sa, sb, sc, sd, 5, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ - CALC_S (sa, sb, sc, sd, 6, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ - CALC_S (sa, sb, sc, sd, 7, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ - CALC_S (se, sf, sg, sh, 8, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ - CALC_S (se, sf, sg, sh, 9, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ - CALC_S (se, sf, sg, sh, 10, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ - CALC_S (se, sf, sg, sh, 11, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ - CALC_S (se, sf, sg, sh, 12, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ - CALC_S (se, sf, sg, sh, 13, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ - CALC_S (se, sf, sg, sh, 14, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ - CALC_S (se, sf, sg, sh, 15, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ - - if (key_len == 24 || key_len == 32) { /* 192- or 256-bit key */ - /* Calculate the third word of the S vector */ - CALC_S (si, sj, sk, sl, 16, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ - CALC_S (si, sj, sk, sl, 17, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ - CALC_S (si, sj, sk, sl, 18, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ - CALC_S (si, sj, sk, sl, 19, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ - CALC_S (si, sj, sk, sl, 20, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ - CALC_S (si, sj, sk, sl, 21, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ - CALC_S (si, sj, sk, sl, 22, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ - CALC_S (si, sj, sk, sl, 23, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ - } - - if (key_len == 32) { /* 256-bit key */ - /* Calculate the fourth word of the S vector */ - CALC_S (sm, sn, so, sp, 24, 0x00, 0x2D, 0x01, 0x2D); /* 01 A4 02 A4 */ - CALC_S (sm, sn, so, sp, 25, 0x2D, 0xA4, 0x44, 0x8A); /* A4 56 A1 55 */ - CALC_S (sm, sn, so, sp, 26, 0x8A, 0xD5, 0xBF, 0xD1); /* 55 82 FC 87 */ - CALC_S (sm, sn, so, sp, 27, 0xD1, 0x7F, 0x3D, 0x99); /* 87 F3 C1 5A */ - CALC_S (sm, sn, so, sp, 28, 0x99, 0x46, 0x66, 0x96); /* 5A 1E 47 58 */ - CALC_S (sm, sn, so, sp, 29, 0x96, 0x3C, 0x5B, 0xED); /* 58 C6 AE DB */ - CALC_S (sm, sn, so, sp, 30, 0xED, 0x37, 0x4F, 0xE0); /* DB 68 3D 9E */ - CALC_S (sm, sn, so, sp, 31, 0xE0, 0xD0, 0x8C, 0x17); /* 9E E5 19 03 */ - - /* Compute the S-boxes. */ - for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { - CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); - } - - /* Calculate whitening and round subkeys. The constants are - * indices of subkeys, preprocessed through q0 and q1. */ - CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3); - CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); - CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); - CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); - CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); - CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B); - CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); - CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); - CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); - CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD); - CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71); - CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); - CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F); - CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B); - CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA); - CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F); - CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); - CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); - CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00); - CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); - } else if (key_len == 24) { /* 192-bit key */ - /* Compute the S-boxes. */ - for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { - CALC_SB192_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); - } - - /* Calculate whitening and round subkeys. The constants are - * indices of subkeys, preprocessed through q0 and q1. */ - CALC_K192 (w, 0, 0xA9, 0x75, 0x67, 0xF3); - CALC_K192 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); - CALC_K192 (w, 4, 0x04, 0xDB, 0xFD, 0x7B); - CALC_K192 (w, 6, 0xA3, 0xFB, 0x76, 0xC8); - CALC_K192 (k, 0, 0x9A, 0x4A, 0x92, 0xD3); - CALC_K192 (k, 2, 0x80, 0xE6, 0x78, 0x6B); - CALC_K192 (k, 4, 0xE4, 0x45, 0xDD, 0x7D); - CALC_K192 (k, 6, 0xD1, 0xE8, 0x38, 0x4B); - CALC_K192 (k, 8, 0x0D, 0xD6, 0xC6, 0x32); - CALC_K192 (k, 10, 0x35, 0xD8, 0x98, 0xFD); - CALC_K192 (k, 12, 0x18, 0x37, 0xF7, 0x71); - CALC_K192 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); - CALC_K192 (k, 16, 0x43, 0x30, 0x75, 0x0F); - CALC_K192 (k, 18, 0x37, 0xF8, 0x26, 0x1B); - CALC_K192 (k, 20, 0xFA, 0x87, 0x13, 0xFA); - CALC_K192 (k, 22, 0x94, 0x06, 0x48, 0x3F); - CALC_K192 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); - CALC_K192 (k, 26, 0x8B, 0xAE, 0x30, 0x5B); - CALC_K192 (k, 28, 0x84, 0x8A, 0x54, 0x00); - CALC_K192 (k, 30, 0xDF, 0xBC, 0x23, 0x9D); - } else { /* 128-bit key */ - /* Compute the S-boxes. */ - for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) { - CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] ); - } - - /* Calculate whitening and round subkeys. The constants are - * indices of subkeys, preprocessed through q0 and q1. */ - CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3); - CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4); - CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B); - CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8); - CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3); - CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B); - CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D); - CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B); - CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32); - CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD); - CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71); - CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1); - CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F); - CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B); - CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA); - CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F); - CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA); - CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B); - CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00); - CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D); - } - - return 0; -} - -EXPORT_SYMBOL_GPL(twofish_setkey); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Twofish cipher common functions"); diff --git a/trunk/drivers/acpi/ac.c b/trunk/drivers/acpi/ac.c index 11abc7bf777e..96309b9660da 100644 --- a/trunk/drivers/acpi/ac.c +++ b/trunk/drivers/acpi/ac.c @@ -285,8 +285,6 @@ static int __init acpi_ac_init(void) { int result; - if (acpi_disabled) - return -ENODEV; acpi_ac_dir = acpi_lock_ac_dir(); if (!acpi_ac_dir) diff --git a/trunk/drivers/acpi/acpi_memhotplug.c b/trunk/drivers/acpi/acpi_memhotplug.c index 1dda370f402b..81e970adeab3 100644 --- a/trunk/drivers/acpi/acpi_memhotplug.c +++ b/trunk/drivers/acpi/acpi_memhotplug.c @@ -129,15 +129,11 @@ acpi_memory_get_device_resources(struct acpi_memory_device *mem_device) struct acpi_memory_info *info, *n; - if (!list_empty(&mem_device->res_list)) - return 0; - status = acpi_walk_resources(mem_device->device->handle, METHOD_NAME__CRS, acpi_memory_get_resource, mem_device); if (ACPI_FAILURE(status)) { list_for_each_entry_safe(info, n, &mem_device->res_list, list) kfree(info); - INIT_LIST_HEAD(&mem_device->res_list); return -EINVAL; } @@ -234,10 +230,17 @@ static int acpi_memory_enable_device(struct acpi_memory_device *mem_device) * (i.e. memory-hot-remove function) */ list_for_each_entry(info, &mem_device->res_list, list) { - if (info->enabled) { /* just sanity check...*/ + u64 start_pfn, end_pfn; + + start_pfn = info->start_addr >> PAGE_SHIFT; + end_pfn = (info->start_addr + info->length - 1) >> PAGE_SHIFT; + + if (pfn_valid(start_pfn) || pfn_valid(end_pfn)) { + /* already enabled. try next area */ num_enabled++; continue; } + result = add_memory(node, info->start_addr, info->length); if (result) continue; @@ -484,8 +487,10 @@ acpi_memory_register_notify_handler(acpi_handle handle, status = is_memory_device(handle); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)){ + ACPI_EXCEPTION((AE_INFO, status, "handle is no memory device")); return AE_OK; /* continue */ + } status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, acpi_memory_device_notify, NULL); @@ -501,8 +506,10 @@ acpi_memory_deregister_notify_handler(acpi_handle handle, status = is_memory_device(handle); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)){ + ACPI_EXCEPTION((AE_INFO, status, "handle is no memory device")); return AE_OK; /* continue */ + } status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, diff --git a/trunk/drivers/acpi/battery.c b/trunk/drivers/acpi/battery.c index 9810e2a55d0a..6e5221707d97 100644 --- a/trunk/drivers/acpi/battery.c +++ b/trunk/drivers/acpi/battery.c @@ -757,9 +757,6 @@ static int __init acpi_battery_init(void) { int result; - if (acpi_disabled) - return -ENODEV; - acpi_battery_dir = acpi_lock_battery_dir(); if (!acpi_battery_dir) return -ENODEV; diff --git a/trunk/drivers/acpi/bus.c b/trunk/drivers/acpi/bus.c index 279c4bac92e5..b2977695e120 100644 --- a/trunk/drivers/acpi/bus.c +++ b/trunk/drivers/acpi/bus.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -69,8 +68,7 @@ int acpi_bus_get_device(acpi_handle handle, struct acpi_device **device) status = acpi_get_data(handle, acpi_bus_data_handler, (void **)device); if (ACPI_FAILURE(status) || !*device) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", - handle)); + ACPI_EXCEPTION((AE_INFO, status, "No context for object [%p]", handle)); return -ENODEV; } @@ -194,7 +192,7 @@ int acpi_bus_set_power(acpi_handle handle, int state) /* Make sure this is a valid target state */ if (!device->flags.power_manageable) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable\n", + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device `[%s]' is not power manageable", device->kobj.name)); return -ENODEV; } @@ -740,10 +738,7 @@ static int __init acpi_init(void) return -ENODEV; } - result = firmware_register(&acpi_subsys); - if (result < 0) - printk(KERN_WARNING "%s: firmware_register error: %d\n", - __FUNCTION__, result); + firmware_register(&acpi_subsys); result = acpi_bus_init(); diff --git a/trunk/drivers/acpi/dock.c b/trunk/drivers/acpi/dock.c index 578b99b71d9c..1c0a39d8b04e 100644 --- a/trunk/drivers/acpi/dock.c +++ b/trunk/drivers/acpi/dock.c @@ -58,8 +58,8 @@ struct dock_dependent_device { }; #define DOCK_DOCKING 0x00000001 -#define DOCK_EVENT 3 -#define UNDOCK_EVENT 2 +#define DOCK_EVENT KOBJ_DOCK +#define UNDOCK_EVENT KOBJ_UNDOCK static struct dock_station *dock_station; @@ -322,10 +322,11 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) static void dock_event(struct dock_station *ds, u32 event, int num) { - /* - * we don't do events until someone tells me that - * they would like to have them. - */ + struct acpi_device *device; + + device = dock_create_acpi_device(ds->handle); + if (device) + kobject_uevent(&device->kobj, num); } /** diff --git a/trunk/drivers/acpi/hotkey.c b/trunk/drivers/acpi/hotkey.c index 1ba2db671865..32c9d88fd196 100644 --- a/trunk/drivers/acpi/hotkey.c +++ b/trunk/drivers/acpi/hotkey.c @@ -91,14 +91,6 @@ enum { HK_EVENT_ENTERRING_S5, }; -enum conf_entry_enum { - bus_handle = 0, - bus_method = 1, - action_handle = 2, - method = 3, - LAST_CONF_ENTRY -}; - /* procdir we use */ static struct proc_dir_entry *hotkey_proc_dir; static struct proc_dir_entry *hotkey_config; @@ -252,15 +244,19 @@ static int hotkey_info_open_fs(struct inode *inode, struct file *file) static char *format_result(union acpi_object *object) { - char *buf; + char *buf = NULL; + + buf = (char *)kmalloc(RESULT_STR_LEN, GFP_KERNEL); + if (buf) + memset(buf, 0, RESULT_STR_LEN); + else + goto do_fail; - buf = kzalloc(RESULT_STR_LEN, GFP_KERNEL); - if (!buf) - return NULL; /* Now, just support integer type */ if (object->type == ACPI_TYPE_INTEGER) sprintf(buf, "%d\n", (u32) object->integer.value); - return buf; + do_fail: + return (buf); } static int hotkey_polling_seq_show(struct seq_file *seq, void *offset) @@ -490,102 +486,98 @@ static void free_hotkey_device(union acpi_hotkey *key) static void free_hotkey_buffer(union acpi_hotkey *key) { - /* key would never be null, action method could be */ kfree(key->event_hotkey.action_method); } static void free_poll_hotkey_buffer(union acpi_hotkey *key) { - /* key would never be null, others could be*/ kfree(key->poll_hotkey.action_method); kfree(key->poll_hotkey.poll_method); kfree(key->poll_hotkey.poll_result); } static int -init_hotkey_device(union acpi_hotkey *key, char **config_entry, - int std_num, int external_num) +init_hotkey_device(union acpi_hotkey *key, char *bus_str, char *action_str, + char *method, int std_num, int external_num) { acpi_handle tmp_handle; acpi_status status = AE_OK; + if (std_num < 0 || IS_POLL(std_num) || !key) goto do_fail; - if (!config_entry[bus_handle] || !config_entry[action_handle] - || !config_entry[method]) + if (!bus_str || !action_str || !method) goto do_fail; key->link.hotkey_type = ACPI_HOTKEY_EVENT; key->link.hotkey_standard_num = std_num; key->event_hotkey.flag = 0; - key->event_hotkey.action_method = config_entry[method]; + key->event_hotkey.action_method = method; - status = acpi_get_handle(NULL, config_entry[bus_handle], - &(key->event_hotkey.bus_handle)); + status = + acpi_get_handle(NULL, bus_str, &(key->event_hotkey.bus_handle)); if (ACPI_FAILURE(status)) - goto do_fail_zero; + goto do_fail; key->event_hotkey.external_hotkey_num = external_num; - status = acpi_get_handle(NULL, config_entry[action_handle], + status = + acpi_get_handle(NULL, action_str, &(key->event_hotkey.action_handle)); if (ACPI_FAILURE(status)) - goto do_fail_zero; + goto do_fail; status = acpi_get_handle(key->event_hotkey.action_handle, - config_entry[method], &tmp_handle); + method, &tmp_handle); if (ACPI_FAILURE(status)) - goto do_fail_zero; + goto do_fail; return AE_OK; -do_fail_zero: - key->event_hotkey.action_method = NULL; -do_fail: + do_fail: return -ENODEV; } static int -init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry, - int std_num) +init_poll_hotkey_device(union acpi_hotkey *key, + char *poll_str, + char *poll_method, + char *action_str, char *action_method, int std_num) { acpi_status status = AE_OK; acpi_handle tmp_handle; + if (std_num < 0 || IS_EVENT(std_num) || !key) goto do_fail; - if (!config_entry[bus_handle] ||!config_entry[bus_method] || - !config_entry[action_handle] || !config_entry[method]) + + if (!poll_str || !poll_method || !action_str || !action_method) goto do_fail; key->link.hotkey_type = ACPI_HOTKEY_POLLING; key->link.hotkey_standard_num = std_num; key->poll_hotkey.flag = 0; - key->poll_hotkey.poll_method = config_entry[bus_method]; - key->poll_hotkey.action_method = config_entry[method]; + key->poll_hotkey.poll_method = poll_method; + key->poll_hotkey.action_method = action_method; - status = acpi_get_handle(NULL, config_entry[bus_handle], - &(key->poll_hotkey.poll_handle)); + status = + acpi_get_handle(NULL, poll_str, &(key->poll_hotkey.poll_handle)); if (ACPI_FAILURE(status)) - goto do_fail_zero; + goto do_fail; status = acpi_get_handle(key->poll_hotkey.poll_handle, - config_entry[bus_method], &tmp_handle); + poll_method, &tmp_handle); if (ACPI_FAILURE(status)) - goto do_fail_zero; + goto do_fail; status = - acpi_get_handle(NULL, config_entry[action_handle], + acpi_get_handle(NULL, action_str, &(key->poll_hotkey.action_handle)); if (ACPI_FAILURE(status)) - goto do_fail_zero; + goto do_fail; status = acpi_get_handle(key->poll_hotkey.action_handle, - config_entry[method], &tmp_handle); + action_method, &tmp_handle); if (ACPI_FAILURE(status)) - goto do_fail_zero; + goto do_fail; key->poll_hotkey.poll_result = (union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL); if (!key->poll_hotkey.poll_result) - goto do_fail_zero; + goto do_fail; return AE_OK; - -do_fail_zero: - key->poll_hotkey.poll_method = NULL; - key->poll_hotkey.action_method = NULL; -do_fail: + do_fail: return -ENODEV; } @@ -660,18 +652,17 @@ static int hotkey_poll_config_seq_show(struct seq_file *seq, void *offset) } static int -get_parms(char *config_record, int *cmd, char **config_entry, - int *internal_event_num, int *external_event_num) +get_parms(char *config_record, + int *cmd, + char **bus_handle, + char **bus_method, + char **action_handle, + char **method, int *internal_event_num, int *external_event_num) { -/* the format of *config_record = - * "1:\d+:*" : "cmd:internal_event_num" - * "\d+:\w+:\w+:\w+:\w+:\d+:\d+" : - * "cmd:bus_handle:bus_method:action_handle:method:internal_event_num:external_event_num" - */ char *tmp, *tmp1, count; - int i; sscanf(config_record, "%d", cmd); + if (*cmd == 1) { if (sscanf(config_record, "%d:%d", cmd, internal_event_num) != 2) @@ -683,27 +674,59 @@ get_parms(char *config_record, int *cmd, char **config_entry, if (!tmp) goto do_fail; tmp++; - for (i = 0; i < LAST_CONF_ENTRY; i++) { - tmp1 = strchr(tmp, ':'); - if (!tmp1) { - goto do_fail; - } - count = tmp1 - tmp; - config_entry[i] = kzalloc(count + 1, GFP_KERNEL); - if (!config_entry[i]) - goto handle_failure; - strncpy(config_entry[i], tmp, count); - tmp = tmp1 + 1; - } - if (sscanf(tmp, "%d:%d", internal_event_num, external_event_num) <= 0) - goto handle_failure; - if (!IS_OTHERS(*internal_event_num)) { - return 6; - } -handle_failure: - while (i-- > 0) - kfree(config_entry[i]); -do_fail: + tmp1 = strchr(tmp, ':'); + if (!tmp1) + goto do_fail; + + count = tmp1 - tmp; + *bus_handle = (char *)kmalloc(count + 1, GFP_KERNEL); + if (!*bus_handle) + goto do_fail; + strncpy(*bus_handle, tmp, count); + *(*bus_handle + count) = 0; + + tmp = tmp1; + tmp++; + tmp1 = strchr(tmp, ':'); + if (!tmp1) + goto do_fail; + count = tmp1 - tmp; + *bus_method = (char *)kmalloc(count + 1, GFP_KERNEL); + if (!*bus_method) + goto do_fail; + strncpy(*bus_method, tmp, count); + *(*bus_method + count) = 0; + + tmp = tmp1; + tmp++; + tmp1 = strchr(tmp, ':'); + if (!tmp1) + goto do_fail; + count = tmp1 - tmp; + *action_handle = (char *)kmalloc(count + 1, GFP_KERNEL); + if (!*action_handle) + goto do_fail; + strncpy(*action_handle, tmp, count); + *(*action_handle + count) = 0; + + tmp = tmp1; + tmp++; + tmp1 = strchr(tmp, ':'); + if (!tmp1) + goto do_fail; + count = tmp1 - tmp; + *method = (char *)kmalloc(count + 1, GFP_KERNEL); + if (!*method) + goto do_fail; + strncpy(*method, tmp, count); + *(*method + count) = 0; + + if (sscanf(tmp1 + 1, "%d:%d", internal_event_num, external_event_num) <= + 0) + goto do_fail; + + return 6; + do_fail: return -1; } @@ -713,34 +736,50 @@ static ssize_t hotkey_write_config(struct file *file, size_t count, loff_t * data) { char *config_record = NULL; - char *config_entry[LAST_CONF_ENTRY]; + char *bus_handle = NULL; + char *bus_method = NULL; + char *action_handle = NULL; + char *method = NULL; int cmd, internal_event_num, external_event_num; int ret = 0; - union acpi_hotkey *key = kzalloc(sizeof(union acpi_hotkey), GFP_KERNEL); + union acpi_hotkey *key = NULL; - if (!key) - return -ENOMEM; - config_record = kzalloc(count + 1, GFP_KERNEL); - if (!config_record) { - kfree(key); + config_record = (char *)kmalloc(count + 1, GFP_KERNEL); + if (!config_record) return -ENOMEM; - } if (copy_from_user(config_record, buffer, count)) { kfree(config_record); - kfree(key); printk(KERN_ERR PREFIX "Invalid data\n"); return -EINVAL; } - ret = get_parms(config_record, &cmd, config_entry, - &internal_event_num, &external_event_num); + config_record[count] = 0; + + ret = get_parms(config_record, + &cmd, + &bus_handle, + &bus_method, + &action_handle, + &method, &internal_event_num, &external_event_num); + kfree(config_record); + if (IS_OTHERS(internal_event_num)) + goto do_fail; if (ret != 6) { + do_fail: + kfree(bus_handle); + kfree(bus_method); + kfree(action_handle); + kfree(method); printk(KERN_ERR PREFIX "Invalid data format ret=%d\n", ret); return -EINVAL; } + key = kmalloc(sizeof(union acpi_hotkey), GFP_KERNEL); + if (!key) + goto do_fail; + memset(key, 0, sizeof(union acpi_hotkey)); if (cmd == 1) { union acpi_hotkey *tmp = NULL; tmp = get_hotkey_by_event(&global_hotkey_list, @@ -752,19 +791,34 @@ static ssize_t hotkey_write_config(struct file *file, goto cont_cmd; } if (IS_EVENT(internal_event_num)) { - if (init_hotkey_device(key, config_entry, - internal_event_num, external_event_num)) - goto init_hotkey_fail; - } else { - if (init_poll_hotkey_device(key, config_entry, - internal_event_num)) - goto init_poll_hotkey_fail; + kfree(bus_method); + ret = init_hotkey_device(key, bus_handle, action_handle, method, + internal_event_num, + external_event_num); + } else + ret = init_poll_hotkey_device(key, bus_handle, bus_method, + action_handle, method, + internal_event_num); + if (ret) { + kfree(bus_handle); + kfree(action_handle); + if (IS_EVENT(internal_event_num)) + free_hotkey_buffer(key); + else + free_poll_hotkey_buffer(key); + kfree(key); + printk(KERN_ERR PREFIX "Invalid hotkey\n"); + return -EINVAL; } -cont_cmd: + + cont_cmd: + kfree(bus_handle); + kfree(action_handle); + switch (cmd) { case 0: - if (get_hotkey_by_event(&global_hotkey_list, - key->link.hotkey_standard_num)) + if (get_hotkey_by_event + (&global_hotkey_list, key->link.hotkey_standard_num)) goto fail_out; else hotkey_add(key); @@ -773,7 +827,6 @@ static ssize_t hotkey_write_config(struct file *file, hotkey_remove(key); break; case 2: - /* key is kfree()ed if matched*/ if (hotkey_update(key)) goto fail_out; break; @@ -782,22 +835,11 @@ static ssize_t hotkey_write_config(struct file *file, break; } return count; - -init_poll_hotkey_fail: /* failed init_poll_hotkey_device */ - kfree(config_entry[bus_method]); - config_entry[bus_method] = NULL; -init_hotkey_fail: /* failed init_hotkey_device */ - kfree(config_entry[method]); -fail_out: - kfree(config_entry[bus_handle]); - kfree(config_entry[action_handle]); - /* No double free since elements =NULL for error cases */ - if (IS_EVENT(internal_event_num)) { - if (config_entry[bus_method]) - kfree(config_entry[bus_method]); - free_hotkey_buffer(key); /* frees [method] */ - } else - free_poll_hotkey_buffer(key); /* frees [bus_method]+[method] */ + fail_out: + if (IS_EVENT(internal_event_num)) + free_hotkey_buffer(key); + else + free_poll_hotkey_buffer(key); kfree(key); printk(KERN_ERR PREFIX "invalid key\n"); return -EINVAL; @@ -881,9 +923,10 @@ static ssize_t hotkey_execute_aml_method(struct file *file, union acpi_hotkey *key; - arg = kzalloc(count + 1, GFP_KERNEL); + arg = (char *)kmalloc(count + 1, GFP_KERNEL); if (!arg) return -ENOMEM; + arg[count] = 0; if (copy_from_user(arg, buffer, count)) { kfree(arg); diff --git a/trunk/drivers/acpi/i2c_ec.c b/trunk/drivers/acpi/i2c_ec.c index 6809c283ec58..84239d51dc0c 100644 --- a/trunk/drivers/acpi/i2c_ec.c +++ b/trunk/drivers/acpi/i2c_ec.c @@ -330,7 +330,7 @@ static int acpi_ec_hc_add(struct acpi_device *device) status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n")); - kfree(ec_hc); + kfree(ec_hc->smbus); kfree(smbus); return -EIO; } diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index 507f051d1cef..b7d1514cd199 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -746,16 +746,6 @@ acpi_status acpi_os_wait_semaphore(acpi_handle handle, u32 units, u16 timeout) ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout)); - /* - * This can be called during resume with interrupts off. - * Like boot-time, we should be single threaded and will - * always get the lock if we try -- timeout or not. - * If this doesn't succeed, then we will oops courtesy of - * might_sleep() in down(). - */ - if (!down_trylock(sem)) - return AE_OK; - switch (timeout) { /* * No Wait: diff --git a/trunk/drivers/acpi/sbs.c b/trunk/drivers/acpi/sbs.c index 62bef0b3b614..db7b350a5035 100644 --- a/trunk/drivers/acpi/sbs.c +++ b/trunk/drivers/acpi/sbs.c @@ -1714,9 +1714,6 @@ static int __init acpi_sbs_init(void) { int result = 0; - if (acpi_disabled) - return -ENODEV; - init_MUTEX(&sbs_sem); if (capacity_mode != DEF_CAPACITY_UNIT diff --git a/trunk/drivers/acpi/scan.c b/trunk/drivers/acpi/scan.c index 698a1540e303..5fcb50c7b778 100644 --- a/trunk/drivers/acpi/scan.c +++ b/trunk/drivers/acpi/scan.c @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -114,8 +113,6 @@ static struct kset acpi_namespace_kset = { static void acpi_device_register(struct acpi_device *device, struct acpi_device *parent) { - int err; - /* * Linkage * ------- @@ -141,10 +138,7 @@ static void acpi_device_register(struct acpi_device *device, device->kobj.parent = &parent->kobj; device->kobj.ktype = &ktype_acpi_ns; device->kobj.kset = &acpi_namespace_kset; - err = kobject_register(&device->kobj); - if (err < 0) - printk(KERN_WARNING "%s: kobject_register error: %d\n", - __FUNCTION__, err); + kobject_register(&device->kobj); create_sysfs_device_files(device); } @@ -1456,9 +1450,7 @@ static int __init acpi_scan_init(void) if (acpi_disabled) return 0; - result = kset_register(&acpi_namespace_kset); - if (result < 0) - printk(KERN_ERR PREFIX "kset_register error: %d\n", result); + kset_register(&acpi_namespace_kset); result = bus_register(&acpi_bus_type); if (result) { diff --git a/trunk/drivers/acpi/utils.c b/trunk/drivers/acpi/utils.c index d0d84c43a9d4..f48227f4c8c9 100644 --- a/trunk/drivers/acpi/utils.c +++ b/trunk/drivers/acpi/utils.c @@ -262,7 +262,7 @@ acpi_evaluate_integer(acpi_handle handle, if (!data) return AE_BAD_PARAMETER; - element = kmalloc(sizeof(union acpi_object), irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL); + element = kmalloc(sizeof(union acpi_object), GFP_KERNEL); if (!element) return AE_NO_MEMORY; diff --git a/trunk/drivers/atm/he.c b/trunk/drivers/atm/he.c index 41e052fecd7f..d369130f4235 100644 --- a/trunk/drivers/atm/he.c +++ b/trunk/drivers/atm/he.c @@ -1912,7 +1912,7 @@ he_service_rbrq(struct he_dev *he_dev, int group) skb->tail = skb->data + skb->len; #ifdef USE_CHECKSUM_HW if (vcc->vpi == 0 && vcc->vci >= ATM_NOT_RSV_VCI) { - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_HW; skb->csum = TCP_CKSUM(skb->data, he_vcc->pdu_len); } @@ -1928,9 +1928,7 @@ he_service_rbrq(struct he_dev *he_dev, int group) #ifdef notdef ATM_SKB(skb)->vcc = vcc; #endif - spin_unlock(&he_dev->global_lock); vcc->push(vcc, skb); - spin_lock(&he_dev->global_lock); atomic_inc(&vcc->stats->rx); @@ -2284,8 +2282,6 @@ __enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid) TPDRQ_MASK(he_readl(he_dev, TPDRQ_B_H))); if (new_tail == he_dev->tpdrq_head) { - int slot; - hprintk("tpdrq full (cid 0x%x)\n", cid); /* * FIXME @@ -2293,13 +2289,6 @@ __enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid) * after service_tbrq, service the backlog * for now, we just drop the pdu */ - for (slot = 0; slot < TPD_MAXIOV; ++slot) { - if (tpd->iovec[slot].addr) - pci_unmap_single(he_dev->pci_dev, - tpd->iovec[slot].addr, - tpd->iovec[slot].len & TPD_LEN_MASK, - PCI_DMA_TODEVICE); - } if (tpd->skb) { if (tpd->vcc->pop) tpd->vcc->pop(tpd->vcc, tpd->skb); diff --git a/trunk/drivers/base/hypervisor.c b/trunk/drivers/base/hypervisor.c index 7080b413ddc9..0c85e9d6a448 100644 --- a/trunk/drivers/base/hypervisor.c +++ b/trunk/drivers/base/hypervisor.c @@ -1,9 +1,8 @@ /* * hypervisor.c - /sys/hypervisor subsystem. * - * Copyright (C) IBM Corp. 2006 - * * This file is released under the GPLv2 + * */ #include diff --git a/trunk/drivers/base/node.c b/trunk/drivers/base/node.c index e9b0957f15d1..d7de1753e094 100644 --- a/trunk/drivers/base/node.c +++ b/trunk/drivers/base/node.c @@ -64,7 +64,7 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) "Node %d Mapped: %8lu kB\n" "Node %d AnonPages: %8lu kB\n" "Node %d PageTables: %8lu kB\n" - "Node %d NFS_Unstable: %8lu kB\n" + "Node %d NFS Unstable: %8lu kB\n" "Node %d Bounce: %8lu kB\n" "Node %d Slab: %8lu kB\n", nid, K(i.totalram), diff --git a/trunk/drivers/base/topology.c b/trunk/drivers/base/topology.c index 3ef9d514b916..c2d621632383 100644 --- a/trunk/drivers/base/topology.c +++ b/trunk/drivers/base/topology.c @@ -139,7 +139,7 @@ static int __cpuinit topology_sysfs_init(void) (void *)(long)i); } - register_hotcpu_notifier(&topology_cpu_notifier); + register_cpu_notifier(&topology_cpu_notifier); return 0; } diff --git a/trunk/drivers/block/cciss.c b/trunk/drivers/block/cciss.c index 2cd3391ff878..7b0eca703a67 100644 --- a/trunk/drivers/block/cciss.c +++ b/trunk/drivers/block/cciss.c @@ -48,14 +48,14 @@ #include #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "HP CISS Driver (v 3.6.10)" -#define DRIVER_VERSION CCISS_DRIVER_VERSION(3,6,10) +#define DRIVER_NAME "HP CISS Driver (v 2.6.10)" +#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,10) /* Embedded module documentation macros - see modules.h */ MODULE_AUTHOR("Hewlett-Packard Company"); -MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 3.6.10"); +MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.10"); MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" - " SA6i P600 P800 P400 P400i E200 E200i E500"); + " SA6i P600 P800 P400 P400i E200 E200i"); MODULE_LICENSE("GPL"); #include "cciss_cmd.h" @@ -82,7 +82,6 @@ static const struct pci_device_id cciss_pci_device_id[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3213}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3214}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215}, - {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3233}, {0,} }; @@ -111,7 +110,6 @@ static struct board_type products[] = { {0x3213103C, "Smart Array E200i", &SA5_access}, {0x3214103C, "Smart Array E200i", &SA5_access}, {0x3215103C, "Smart Array E200i", &SA5_access}, - {0x3233103C, "Smart Array E500", &SA5_access}, }; /* How long to wait (in milliseconds) for board to go into simple mode */ diff --git a/trunk/drivers/block/cryptoloop.c b/trunk/drivers/block/cryptoloop.c index 40535036e893..3d4261c39f16 100644 --- a/trunk/drivers/block/cryptoloop.c +++ b/trunk/drivers/block/cryptoloop.c @@ -40,13 +40,11 @@ static int cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) { int err = -EINVAL; - int cipher_len; - int mode_len; char cms[LO_NAME_SIZE]; /* cipher-mode string */ char *cipher; char *mode; char *cmsp = cms; /* c-m string pointer */ - struct crypto_blkcipher *tfm; + struct crypto_tfm *tfm = NULL; /* encryption breaks for non sector aligned offsets */ @@ -55,39 +53,20 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) strncpy(cms, info->lo_crypt_name, LO_NAME_SIZE); cms[LO_NAME_SIZE - 1] = 0; - - cipher = cmsp; - cipher_len = strcspn(cmsp, "-"); - - mode = cmsp + cipher_len; - mode_len = 0; - if (*mode) { - mode++; - mode_len = strcspn(mode, "-"); - } - - if (!mode_len) { - mode = "cbc"; - mode_len = 3; - } - - if (cipher_len + mode_len + 3 > LO_NAME_SIZE) + cipher = strsep(&cmsp, "-"); + mode = strsep(&cmsp, "-"); + + if (mode == NULL || strcmp(mode, "cbc") == 0) + tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC | + CRYPTO_TFM_REQ_MAY_SLEEP); + else if (strcmp(mode, "ecb") == 0) + tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB | + CRYPTO_TFM_REQ_MAY_SLEEP); + if (tfm == NULL) return -EINVAL; - memmove(cms, mode, mode_len); - cmsp = cms + mode_len; - *cmsp++ = '('; - memcpy(cmsp, info->lo_crypt_name, cipher_len); - cmsp += cipher_len; - *cmsp++ = ')'; - *cmsp = 0; - - tfm = crypto_alloc_blkcipher(cms, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - err = crypto_blkcipher_setkey(tfm, info->lo_encrypt_key, - info->lo_encrypt_key_size); + err = tfm->crt_u.cipher.cit_setkey(tfm, info->lo_encrypt_key, + info->lo_encrypt_key_size); if (err != 0) goto out_free_tfm; @@ -96,49 +75,99 @@ cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info) return 0; out_free_tfm: - crypto_free_blkcipher(tfm); + crypto_free_tfm(tfm); out: return err; } -typedef int (*encdec_cbc_t)(struct blkcipher_desc *desc, +typedef int (*encdec_ecb_t)(struct crypto_tfm *tfm, struct scatterlist *sg_out, struct scatterlist *sg_in, unsigned int nsg); + static int -cryptoloop_transfer(struct loop_device *lo, int cmd, - struct page *raw_page, unsigned raw_off, - struct page *loop_page, unsigned loop_off, - int size, sector_t IV) +cryptoloop_transfer_ecb(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t IV) +{ + struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; + struct scatterlist sg_out = { NULL, }; + struct scatterlist sg_in = { NULL, }; + + encdec_ecb_t encdecfunc; + struct page *in_page, *out_page; + unsigned in_offs, out_offs; + + if (cmd == READ) { + in_page = raw_page; + in_offs = raw_off; + out_page = loop_page; + out_offs = loop_off; + encdecfunc = tfm->crt_u.cipher.cit_decrypt; + } else { + in_page = loop_page; + in_offs = loop_off; + out_page = raw_page; + out_offs = raw_off; + encdecfunc = tfm->crt_u.cipher.cit_encrypt; + } + + while (size > 0) { + const int sz = min(size, LOOP_IV_SECTOR_SIZE); + + sg_in.page = in_page; + sg_in.offset = in_offs; + sg_in.length = sz; + + sg_out.page = out_page; + sg_out.offset = out_offs; + sg_out.length = sz; + + encdecfunc(tfm, &sg_out, &sg_in, sz); + + size -= sz; + in_offs += sz; + out_offs += sz; + } + + return 0; +} + +typedef int (*encdec_cbc_t)(struct crypto_tfm *tfm, + struct scatterlist *sg_out, + struct scatterlist *sg_in, + unsigned int nsg, u8 *iv); + +static int +cryptoloop_transfer_cbc(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t IV) { - struct crypto_blkcipher *tfm = lo->key_data; - struct blkcipher_desc desc = { - .tfm = tfm, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP, - }; + struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; struct scatterlist sg_out = { NULL, }; struct scatterlist sg_in = { NULL, }; encdec_cbc_t encdecfunc; struct page *in_page, *out_page; unsigned in_offs, out_offs; - int err; if (cmd == READ) { in_page = raw_page; in_offs = raw_off; out_page = loop_page; out_offs = loop_off; - encdecfunc = crypto_blkcipher_crt(tfm)->decrypt; + encdecfunc = tfm->crt_u.cipher.cit_decrypt_iv; } else { in_page = loop_page; in_offs = loop_off; out_page = raw_page; out_offs = raw_off; - encdecfunc = crypto_blkcipher_crt(tfm)->encrypt; + encdecfunc = tfm->crt_u.cipher.cit_encrypt_iv; } while (size > 0) { @@ -154,10 +183,7 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, sg_out.offset = out_offs; sg_out.length = sz; - desc.info = iv; - err = encdecfunc(&desc, &sg_out, &sg_in, sz); - if (err) - return err; + encdecfunc(tfm, &sg_out, &sg_in, sz, (u8 *)iv); IV++; size -= sz; @@ -168,6 +194,32 @@ cryptoloop_transfer(struct loop_device *lo, int cmd, return 0; } +static int +cryptoloop_transfer(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t IV) +{ + struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; + if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB) + { + lo->transfer = cryptoloop_transfer_ecb; + return cryptoloop_transfer_ecb(lo, cmd, raw_page, raw_off, + loop_page, loop_off, size, IV); + } + if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_CBC) + { + lo->transfer = cryptoloop_transfer_cbc; + return cryptoloop_transfer_cbc(lo, cmd, raw_page, raw_off, + loop_page, loop_off, size, IV); + } + + /* This is not supposed to happen */ + + printk( KERN_ERR "cryptoloop: unsupported cipher mode in cryptoloop_transfer!\n"); + return -EINVAL; +} + static int cryptoloop_ioctl(struct loop_device *lo, int cmd, unsigned long arg) { @@ -177,9 +229,9 @@ cryptoloop_ioctl(struct loop_device *lo, int cmd, unsigned long arg) static int cryptoloop_release(struct loop_device *lo) { - struct crypto_blkcipher *tfm = lo->key_data; + struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; if (tfm != NULL) { - crypto_free_blkcipher(tfm); + crypto_free_tfm(tfm); lo->key_data = NULL; return 0; } diff --git a/trunk/drivers/block/floppy.c b/trunk/drivers/block/floppy.c index ad1d7065a1b2..5109fa37c662 100644 --- a/trunk/drivers/block/floppy.c +++ b/trunk/drivers/block/floppy.c @@ -4177,11 +4177,6 @@ static int __init floppy_init(void) int i, unit, drive; int err, dr; -#if defined(CONFIG_PPC_MERGE) - if (check_legacy_ioport(FDC1)) - return -ENODEV; -#endif - raw_cmd = NULL; for (dr = 0; dr < N_DRIVE; dr++) { @@ -4239,6 +4234,13 @@ static int __init floppy_init(void) } use_virtual_dma = can_use_virtual_dma & 1; +#if defined(CONFIG_PPC_MERGE) + if (check_legacy_ioport(FDC1)) { + del_timer(&fd_timeout); + err = -ENODEV; + goto out_unreg_region; + } +#endif fdc_state[0].address = FDC1; if (fdc_state[0].address == -1) { del_timer(&fd_timeout); diff --git a/trunk/drivers/block/nbd.c b/trunk/drivers/block/nbd.c index bdbade9a5cf5..0a1b1ea36ddc 100644 --- a/trunk/drivers/block/nbd.c +++ b/trunk/drivers/block/nbd.c @@ -300,15 +300,6 @@ static struct request *nbd_read_stat(struct nbd_device *lo) lo->disk->disk_name, result); goto harderror; } - - if (ntohl(reply.magic) != NBD_REPLY_MAGIC) { - printk(KERN_ERR "%s: Wrong magic (0x%lx)\n", - lo->disk->disk_name, - (unsigned long)ntohl(reply.magic)); - result = -EPROTO; - goto harderror; - } - req = nbd_find_request(lo, reply.handle); if (unlikely(IS_ERR(req))) { result = PTR_ERR(req); @@ -321,6 +312,13 @@ static struct request *nbd_read_stat(struct nbd_device *lo) goto harderror; } + if (ntohl(reply.magic) != NBD_REPLY_MAGIC) { + printk(KERN_ERR "%s: Wrong magic (0x%lx)\n", + lo->disk->disk_name, + (unsigned long)ntohl(reply.magic)); + result = -EPROTO; + goto harderror; + } if (ntohl(reply.error)) { printk(KERN_ERR "%s: Other side returned error (%d)\n", lo->disk->disk_name, ntohl(reply.error)); @@ -341,8 +339,7 @@ static struct request *nbd_read_stat(struct nbd_device *lo) printk(KERN_ERR "%s: Receive data failed (result %d)\n", lo->disk->disk_name, result); - req->errors++; - return req; + goto harderror; } dprintk(DBG_RX, "%s: request %p: got %d bytes data\n", lo->disk->disk_name, req, bvec->bv_len); diff --git a/trunk/drivers/block/pktcdvd.c b/trunk/drivers/block/pktcdvd.c index 451b996bba91..bde2c64b6346 100644 --- a/trunk/drivers/block/pktcdvd.c +++ b/trunk/drivers/block/pktcdvd.c @@ -2577,19 +2577,19 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm case PKT_CTRL_CMD_SETUP: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + mutex_lock(&ctl_mutex); ret = pkt_setup_dev(&ctrl_cmd); mutex_unlock(&ctl_mutex); break; case PKT_CTRL_CMD_TEARDOWN: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + mutex_lock(&ctl_mutex); ret = pkt_remove_dev(&ctrl_cmd); mutex_unlock(&ctl_mutex); break; case PKT_CTRL_CMD_STATUS: - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + mutex_lock(&ctl_mutex); pkt_get_status(&ctrl_cmd); mutex_unlock(&ctl_mutex); break; diff --git a/trunk/drivers/cdrom/gscd.c b/trunk/drivers/cdrom/gscd.c index fa7082489765..b6ee50a2916d 100644 --- a/trunk/drivers/cdrom/gscd.c +++ b/trunk/drivers/cdrom/gscd.c @@ -266,7 +266,7 @@ static void __do_gscd_request(unsigned long dummy) goto out; if (req->cmd != READ) { - printk("GSCD: bad cmd %u\n", rq_data_dir(req)); + printk("GSCD: bad cmd %lu\n", rq_data_dir(req)); end_request(req, 0); goto repeat; } diff --git a/trunk/drivers/char/Kconfig b/trunk/drivers/char/Kconfig index 52ea94b891f5..c40e487d9f5c 100644 --- a/trunk/drivers/char/Kconfig +++ b/trunk/drivers/char/Kconfig @@ -495,21 +495,6 @@ config LEGACY_PTY_COUNT When not in use, each legacy PTY occupies 12 bytes on 32-bit architectures and 24 bytes on 64-bit architectures. -config BRIQ_PANEL - tristate 'Total Impact briQ front panel driver' - depends on PPC_CHRP - ---help--- - The briQ is a small footprint CHRP computer with a frontpanel VFD, a - tristate led and two switches. It is the size of a CDROM drive. - - If you have such one and want anything showing on the VFD then you - must answer Y here. - - To compile this driver as a module, choose M here: the - module will be called briq_panel. - - It's safe to say N here. - config PRINTER tristate "Parallel printer support" depends on PARPORT @@ -611,13 +596,6 @@ config HVC_CONSOLE console. This driver allows each pSeries partition to have a console which is accessed via the HMC. -config HVC_ISERIES - bool "iSeries Hypervisor Virtual Console support" - depends on PPC_ISERIES && !VIOCONS - select HVC_DRIVER - help - iSeries machines support a hypervisor virtual console. - config HVC_RTAS bool "IBM RTAS Console support" depends on PPC_RTAS diff --git a/trunk/drivers/char/Makefile b/trunk/drivers/char/Makefile index 8c6dfc621520..6e0f4469d8bb 100644 --- a/trunk/drivers/char/Makefile +++ b/trunk/drivers/char/Makefile @@ -42,7 +42,6 @@ obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/ generic_serial.o obj-$(CONFIG_HVC_CONSOLE) += hvc_vio.o hvsi.o -obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o obj-$(CONFIG_HVC_DRIVER) += hvc_console.o obj-$(CONFIG_RAW_DRIVER) += raw.o @@ -52,7 +51,6 @@ obj-$(CONFIG_VIOCONS) += viocons.o obj-$(CONFIG_VIOTAPE) += viotape.o obj-$(CONFIG_HVCS) += hvcs.o obj-$(CONFIG_SGI_MBCS) += mbcs.o -obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o obj-$(CONFIG_PRINTER) += lp.o obj-$(CONFIG_TIPAR) += tipar.o diff --git a/trunk/drivers/char/agp/agp.h b/trunk/drivers/char/agp/agp.h index 8b3317fd46c9..3c623b67ea1c 100644 --- a/trunk/drivers/char/agp/agp.h +++ b/trunk/drivers/char/agp/agp.h @@ -117,7 +117,7 @@ struct agp_bridge_driver { }; struct agp_bridge_data { - const struct agp_version *version; + struct agp_version *version; struct agp_bridge_driver *driver; struct vm_operations_struct *vm_ops; void *previous_size; diff --git a/trunk/drivers/char/agp/backend.c b/trunk/drivers/char/agp/backend.c index d59e037ddd12..509adc403250 100644 --- a/trunk/drivers/char/agp/backend.c +++ b/trunk/drivers/char/agp/backend.c @@ -44,7 +44,7 @@ * past 0.99 at all due to some boolean logic error. */ #define AGPGART_VERSION_MAJOR 0 #define AGPGART_VERSION_MINOR 101 -static const struct agp_version agp_current_version = +static struct agp_version agp_current_version = { .major = AGPGART_VERSION_MAJOR, .minor = AGPGART_VERSION_MINOR, diff --git a/trunk/drivers/char/agp/efficeon-agp.c b/trunk/drivers/char/agp/efficeon-agp.c index 30f730ff81c1..b788b0a3bbf3 100644 --- a/trunk/drivers/char/agp/efficeon-agp.c +++ b/trunk/drivers/char/agp/efficeon-agp.c @@ -337,6 +337,13 @@ static struct agp_bridge_driver efficeon_driver = { .agp_destroy_page = agp_generic_destroy_page, }; + +static int agp_efficeon_resume(struct pci_dev *pdev) +{ + printk(KERN_DEBUG PFX "agp_efficeon_resume()\n"); + return efficeon_configure(); +} + static int __devinit agp_efficeon_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -407,18 +414,11 @@ static void __devexit agp_efficeon_remove(struct pci_dev *pdev) agp_put_bridge(bridge); } -#ifdef CONFIG_PM static int agp_efficeon_suspend(struct pci_dev *dev, pm_message_t state) { return 0; } -static int agp_efficeon_resume(struct pci_dev *pdev) -{ - printk(KERN_DEBUG PFX "agp_efficeon_resume()\n"); - return efficeon_configure(); -} -#endif static struct pci_device_id agp_efficeon_pci_table[] = { { @@ -439,10 +439,8 @@ static struct pci_driver agp_efficeon_pci_driver = { .id_table = agp_efficeon_pci_table, .probe = agp_efficeon_probe, .remove = agp_efficeon_remove, -#ifdef CONFIG_PM .suspend = agp_efficeon_suspend, .resume = agp_efficeon_resume, -#endif }; static int __init agp_efficeon_init(void) diff --git a/trunk/drivers/char/agp/frontend.c b/trunk/drivers/char/agp/frontend.c index 0f2ed2aa2d81..d9c5a9142ad1 100644 --- a/trunk/drivers/char/agp/frontend.c +++ b/trunk/drivers/char/agp/frontend.c @@ -151,12 +151,35 @@ static void agp_add_seg_to_client(struct agp_client *client, client->segments = seg; } +/* Originally taken from linux/mm/mmap.c from the array + * protection_map. + * The original really should be exported to modules, or + * some routine which does the conversion for you + */ + +static const pgprot_t my_protect_map[16] = +{ + __P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111, + __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111 +}; + static pgprot_t agp_convert_mmap_flags(int prot) { +#define _trans(x,bit1,bit2) \ +((bit1==bit2)?(x&bit1):(x&bit1)?bit2:0) + unsigned long prot_bits; + pgprot_t temp; + + prot_bits = _trans(prot, PROT_READ, VM_READ) | + _trans(prot, PROT_WRITE, VM_WRITE) | + _trans(prot, PROT_EXEC, VM_EXEC); + + prot_bits |= VM_SHARED; - prot_bits = calc_vm_prot_bits(prot) | VM_SHARED; - return vm_get_page_prot(prot_bits); + temp = my_protect_map[prot_bits & 0x0000000f]; + + return temp; } static int agp_create_segment(struct agp_client *client, struct agp_region *region) diff --git a/trunk/drivers/char/agp/generic.c b/trunk/drivers/char/agp/generic.c index 0dcdb363923f..cc5ea347a8a7 100644 --- a/trunk/drivers/char/agp/generic.c +++ b/trunk/drivers/char/agp/generic.c @@ -568,34 +568,25 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); goto done; - } else if (*requested_mode & AGPSTAT3_4X) { - *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); - *bridge_agpstat |= AGPSTAT3_4X; - goto done; - } else { /* - * If we didn't specify an AGP mode, we see if both - * the graphics card, and the bridge can do x8, and use if so. - * If not, we fall back to x4 mode. + * If we didn't specify AGPx8, we can only do x4. + * If the hardware can't do x4, we're up shit creek, and never + * should have got this far. */ - if ((*bridge_agpstat & AGPSTAT3_8X) && (*vga_agpstat & AGPSTAT3_8X)) { - printk(KERN_INFO PFX "No AGP mode specified. Setting to highest mode supported by bridge & card (x8).\n"); - *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); - *vga_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); - } else { - printk(KERN_INFO PFX "Fell back to AGPx4 mode because"); - if (!(*bridge_agpstat & AGPSTAT3_8X)) { - printk("bridge couldn't do x8. bridge_agpstat:%x (orig=%x)\n", *bridge_agpstat, origbridge); - *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); - *bridge_agpstat |= AGPSTAT3_4X; - } - if (!(*vga_agpstat & AGPSTAT3_8X)) { - printk("graphics card couldn't do x8. vga_agpstat:%x (orig=%x)\n", *vga_agpstat, origvga); - *vga_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); - *vga_agpstat |= AGPSTAT3_4X; - } + *bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD); + if ((*bridge_agpstat & AGPSTAT3_4X) && (*vga_agpstat & AGPSTAT3_4X)) + *bridge_agpstat |= AGPSTAT3_4X; + else { + printk(KERN_INFO PFX "Badness. Don't know which AGP mode to set. " + "[bridge_agpstat:%x vga_agpstat:%x fell back to:- bridge_agpstat:%x vga_agpstat:%x]\n", + origbridge, origvga, *bridge_agpstat, *vga_agpstat); + if (!(*bridge_agpstat & AGPSTAT3_4X)) + printk(KERN_INFO PFX "Bridge couldn't do AGP x4.\n"); + if (!(*vga_agpstat & AGPSTAT3_4X)) + printk(KERN_INFO PFX "Graphic card couldn't do AGP x4.\n"); + return; } } diff --git a/trunk/drivers/char/agp/intel-agp.c b/trunk/drivers/char/agp/intel-agp.c index d1ede7db5a12..61ac3809f997 100644 --- a/trunk/drivers/char/agp/intel-agp.c +++ b/trunk/drivers/char/agp/intel-agp.c @@ -2,6 +2,14 @@ * Intel AGPGART routines. */ +/* + * Intel(R) 855GM/852GM and 865G support added by David Dawes + * . + * + * Intel(R) 915G/915GM support added by Alan Hourihane + * . + */ + #include #include #include @@ -9,21 +17,6 @@ #include #include "agp.h" -#define PCI_DEVICE_ID_INTEL_82946GZ_HB 0x2970 -#define PCI_DEVICE_ID_INTEL_82946GZ_IG 0x2972 -#define PCI_DEVICE_ID_INTEL_82965G_1_HB 0x2980 -#define PCI_DEVICE_ID_INTEL_82965G_1_IG 0x2982 -#define PCI_DEVICE_ID_INTEL_82965Q_HB 0x2990 -#define PCI_DEVICE_ID_INTEL_82965Q_IG 0x2992 -#define PCI_DEVICE_ID_INTEL_82965G_HB 0x29A0 -#define PCI_DEVICE_ID_INTEL_82965G_IG 0x29A2 - -#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB) - - /* Intel 815 register */ #define INTEL_815_APCONT 0x51 #define INTEL_815_ATTBASE_MASK ~0x1FFFFFFF @@ -47,8 +40,6 @@ #define I915_GMCH_GMS_STOLEN_48M (0x6 << 4) #define I915_GMCH_GMS_STOLEN_64M (0x7 << 4) -/* Intel 965G registers */ -#define I965_MSAC 0x62 /* Intel 7505 registers */ #define INTEL_I7505_APSIZE 0x74 @@ -363,7 +354,6 @@ static struct aper_size_info_fixed intel_i830_sizes[] = /* The 64M mode still requires a 128k gatt */ {64, 16384, 5}, {256, 65536, 6}, - {512, 131072, 7}, }; static struct _intel_i830_private { @@ -387,11 +377,7 @@ static void intel_i830_init_gtt_entries(void) /* We obtain the size of the GTT, which is also stored (for some * reason) at the top of stolen memory. Then we add 4KB to that * for the video BIOS popup, which is also stored in there. */ - - if (IS_I965) - size = 512 + 4; - else - size = agp_bridge->driver->fetch_size() + 4; + size = agp_bridge->driver->fetch_size() + 4; if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { @@ -437,7 +423,7 @@ static void intel_i830_init_gtt_entries(void) if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965 ) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB) gtt_entries = MB(48) - KB(size); else gtt_entries = 0; @@ -447,7 +433,7 @@ static void intel_i830_init_gtt_entries(void) if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB) gtt_entries = MB(64) - KB(size); else gtt_entries = 0; @@ -805,77 +791,6 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) return 0; } -static int intel_i965_fetch_size(void) -{ - struct aper_size_info_fixed *values; - u32 offset = 0; - u8 temp; - -#define I965_512MB_ADDRESS_MASK (3<<1) - - values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); - - pci_read_config_byte(intel_i830_private.i830_dev, I965_MSAC, &temp); - temp &= I965_512MB_ADDRESS_MASK; - switch (temp) { - case 0x00: - offset = 0; /* 128MB */ - break; - case 0x06: - offset = 3; /* 512MB */ - break; - default: - case 0x02: - offset = 2; /* 256MB */ - break; - } - - agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset); - - return values[offset].size; -} - -/* The intel i965 automatically initializes the agp aperture during POST. -+ * Use the memory already set aside for in the GTT. -+ */ -static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) -{ - int page_order; - struct aper_size_info_fixed *size; - int num_entries; - u32 temp; - - size = agp_bridge->current_size; - page_order = size->page_order; - num_entries = size->num_entries; - agp_bridge->gatt_table_real = NULL; - - pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp); - - temp &= 0xfff00000; - intel_i830_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024); - - if (!intel_i830_private.gtt) - return -ENOMEM; - - - intel_i830_private.registers = ioremap(temp,128 * 4096); - if (!intel_i830_private.registers) - return -ENOMEM; - - temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000; - global_cache_flush(); /* FIXME: ? */ - - /* we have to call this as early as possible after the MMIO base address is known */ - intel_i830_init_gtt_entries(); - - agp_bridge->gatt_table = NULL; - - agp_bridge->gatt_bus_addr = temp; - - return 0; -} - static int intel_fetch_size(void) { @@ -1392,7 +1307,7 @@ static struct agp_bridge_driver intel_830_driver = { .owner = THIS_MODULE, .aperture_sizes = intel_i830_sizes, .size_type = FIXED_APER_SIZE, - .num_aperture_sizes = 4, + .num_aperture_sizes = 3, .needs_scratch_page = TRUE, .configure = intel_i830_configure, .fetch_size = intel_i830_fetch_size, @@ -1554,7 +1469,7 @@ static struct agp_bridge_driver intel_915_driver = { .owner = THIS_MODULE, .aperture_sizes = intel_i830_sizes, .size_type = FIXED_APER_SIZE, - .num_aperture_sizes = 4, + .num_aperture_sizes = 3, .needs_scratch_page = TRUE, .configure = intel_i915_configure, .fetch_size = intel_i915_fetch_size, @@ -1574,29 +1489,6 @@ static struct agp_bridge_driver intel_915_driver = { .agp_destroy_page = agp_generic_destroy_page, }; -static struct agp_bridge_driver intel_i965_driver = { - .owner = THIS_MODULE, - .aperture_sizes = intel_i830_sizes, - .size_type = FIXED_APER_SIZE, - .num_aperture_sizes = 4, - .needs_scratch_page = TRUE, - .configure = intel_i915_configure, - .fetch_size = intel_i965_fetch_size, - .cleanup = intel_i915_cleanup, - .tlb_flush = intel_i810_tlbflush, - .mask_memory = intel_i810_mask_memory, - .masks = intel_i810_masks, - .agp_enable = intel_i810_agp_enable, - .cache_flush = global_cache_flush, - .create_gatt_table = intel_i965_create_gatt_table, - .free_gatt_table = intel_i830_free_gatt_table, - .insert_memory = intel_i915_insert_entries, - .remove_memory = intel_i915_remove_entries, - .alloc_by_type = intel_i830_alloc_by_type, - .free_by_type = intel_i810_free_by_type, - .agp_alloc_page = agp_generic_alloc_page, - .agp_destroy_page = agp_generic_destroy_page, -}; static struct agp_bridge_driver intel_7505_driver = { .owner = THIS_MODULE, @@ -1792,35 +1684,6 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, bridge->driver = &intel_845_driver; name = "945GM"; break; - case PCI_DEVICE_ID_INTEL_82946GZ_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82946GZ_IG)) - bridge->driver = &intel_i965_driver; - else - bridge->driver = &intel_845_driver; - name = "946GZ"; - break; - case PCI_DEVICE_ID_INTEL_82965G_1_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82965G_1_IG)) - bridge->driver = &intel_i965_driver; - else - bridge->driver = &intel_845_driver; - name = "965G"; - break; - case PCI_DEVICE_ID_INTEL_82965Q_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82965Q_IG)) - bridge->driver = &intel_i965_driver; - else - bridge->driver = &intel_845_driver; - name = "965Q"; - break; - case PCI_DEVICE_ID_INTEL_82965G_HB: - if (find_i830(PCI_DEVICE_ID_INTEL_82965G_IG)) - bridge->driver = &intel_i965_driver; - else - bridge->driver = &intel_845_driver; - name = "965G"; - break; - case PCI_DEVICE_ID_INTEL_7505_0: bridge->driver = &intel_7505_driver; name = "E7505"; @@ -1903,7 +1766,6 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev) agp_put_bridge(bridge); } -#ifdef CONFIG_PM static int agp_intel_resume(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); @@ -1924,12 +1786,9 @@ static int agp_intel_resume(struct pci_dev *pdev) intel_i830_configure(); else if (bridge->driver == &intel_810_driver) intel_i810_configure(); - else if (bridge->driver == &intel_i965_driver) - intel_i915_configure(); return 0; } -#endif static struct pci_device_id agp_intel_pci_table[] = { #define ID(x) \ @@ -1966,10 +1825,6 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_82915GM_HB), ID(PCI_DEVICE_ID_INTEL_82945G_HB), ID(PCI_DEVICE_ID_INTEL_82945GM_HB), - ID(PCI_DEVICE_ID_INTEL_82946GZ_HB), - ID(PCI_DEVICE_ID_INTEL_82965G_1_HB), - ID(PCI_DEVICE_ID_INTEL_82965Q_HB), - ID(PCI_DEVICE_ID_INTEL_82965G_HB), { } }; @@ -1980,9 +1835,7 @@ static struct pci_driver agp_intel_pci_driver = { .id_table = agp_intel_pci_table, .probe = agp_intel_probe, .remove = __devexit_p(agp_intel_remove), -#ifdef CONFIG_PM .resume = agp_intel_resume, -#endif }; static int __init agp_intel_init(void) diff --git a/trunk/drivers/char/agp/uninorth-agp.c b/trunk/drivers/char/agp/uninorth-agp.c index 91b71e750ee1..1de1b12043bf 100644 --- a/trunk/drivers/char/agp/uninorth-agp.c +++ b/trunk/drivers/char/agp/uninorth-agp.c @@ -601,8 +601,8 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev, uninorth_node = of_find_node_by_name(NULL, "u3"); } if (uninorth_node) { - const int *revprop = get_property(uninorth_node, - "device-rev", NULL); + int *revprop = (int *) + get_property(uninorth_node, "device-rev", NULL); if (revprop != NULL) uninorth_rev = *revprop & 0x3f; of_node_put(uninorth_node); diff --git a/trunk/drivers/char/agp/via-agp.c b/trunk/drivers/char/agp/via-agp.c index c149ac9ce9a7..b8ec25d17478 100644 --- a/trunk/drivers/char/agp/via-agp.c +++ b/trunk/drivers/char/agp/via-agp.c @@ -9,7 +9,7 @@ #include #include "agp.h" -static const struct pci_device_id agp_via_pci_table[]; +static struct pci_device_id agp_via_pci_table[]; #define VIA_GARTCTRL 0x80 #define VIA_APSIZE 0x84 @@ -485,7 +485,7 @@ static int agp_via_resume(struct pci_dev *pdev) #endif /* CONFIG_PM */ /* must be the same order as name table above */ -static const struct pci_device_id agp_via_pci_table[] = { +static struct pci_device_id agp_via_pci_table[] = { #define ID(x) \ { \ .class = (PCI_CLASS_BRIDGE_HOST << 8), \ diff --git a/trunk/drivers/char/briq_panel.c b/trunk/drivers/char/briq_panel.c deleted file mode 100644 index b8c22255f6ad..000000000000 --- a/trunk/drivers/char/briq_panel.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Drivers for the Total Impact PPC based computer "BRIQ" - * by Dr. Karsten Jeppesen - * - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define BRIQ_PANEL_MINOR 156 -#define BRIQ_PANEL_VFD_IOPORT 0x0390 -#define BRIQ_PANEL_LED_IOPORT 0x0398 -#define BRIQ_PANEL_VER "1.1 (04/20/2002)" -#define BRIQ_PANEL_MSG0 "Loading Linux" - -static int vfd_is_open; -static unsigned char vfd[40]; -static int vfd_cursor; -static unsigned char ledpb, led; - -static void update_vfd(void) -{ - int i; - - /* cursor home */ - outb(0x02, BRIQ_PANEL_VFD_IOPORT); - for (i=0; i<20; i++) - outb(vfd[i], BRIQ_PANEL_VFD_IOPORT + 1); - - /* cursor to next line */ - outb(0xc0, BRIQ_PANEL_VFD_IOPORT); - for (i=20; i<40; i++) - outb(vfd[i], BRIQ_PANEL_VFD_IOPORT + 1); - -} - -static void set_led(char state) -{ - if (state == 'R') - led = 0x01; - else if (state == 'G') - led = 0x02; - else if (state == 'Y') - led = 0x03; - else if (state == 'X') - led = 0x00; - outb(led, BRIQ_PANEL_LED_IOPORT); -} - -static int briq_panel_open(struct inode *ino, struct file *filep) -{ - /* enforce single access */ - if (vfd_is_open) - return -EBUSY; - vfd_is_open = 1; - - return 0; -} - -static int briq_panel_release(struct inode *ino, struct file *filep) -{ - if (!vfd_is_open) - return -ENODEV; - - vfd_is_open = 0; - - return 0; -} - -static ssize_t briq_panel_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - unsigned short c; - unsigned char cp; - -#if 0 /* Can't seek (pread) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; -#endif - - if (!vfd_is_open) - return -ENODEV; - - c = (inb(BRIQ_PANEL_LED_IOPORT) & 0x000c) | (ledpb & 0x0003); - set_led(' '); - /* upper button released */ - if ((!(ledpb & 0x0004)) && (c & 0x0004)) { - cp = ' '; - ledpb = c; - if (copy_to_user(buf, &cp, 1)) - return -EFAULT; - return 1; - } - /* lower button released */ - else if ((!(ledpb & 0x0008)) && (c & 0x0008)) { - cp = '\r'; - ledpb = c; - if (copy_to_user(buf, &cp, 1)) - return -EFAULT; - return 1; - } else { - ledpb = c; - return 0; - } -} - -static void scroll_vfd( void ) -{ - int i; - - for (i=0; i<20; i++) { - vfd[i] = vfd[i+20]; - vfd[i+20] = ' '; - } - vfd_cursor = 20; -} - -static ssize_t briq_panel_write(struct file *file, const char __user *buf, size_t len, - loff_t *ppos) -{ - size_t indx = len; - int i, esc = 0; - -#if 0 /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; -#endif - - if (!vfd_is_open) - return -EBUSY; - - for (;;) { - char c; - if (!indx) - break; - if (get_user(c, buf)) - return -EFAULT; - if (esc) { - set_led(c); - esc = 0; - } else if (c == 27) { - esc = 1; - } else if (c == 12) { - /* do a form feed */ - for (i=0; i<40; i++) - vfd[i] = ' '; - vfd_cursor = 0; - } else if (c == 10) { - if (vfd_cursor < 20) - vfd_cursor = 20; - else if (vfd_cursor < 40) - vfd_cursor = 40; - else if (vfd_cursor < 60) - vfd_cursor = 60; - if (vfd_cursor > 59) - scroll_vfd(); - } else { - /* just a character */ - if (vfd_cursor > 39) - scroll_vfd(); - vfd[vfd_cursor++] = c; - } - indx--; - buf++; - } - update_vfd(); - - return len; -} - -static struct file_operations briq_panel_fops = { - .owner = THIS_MODULE, - .read = briq_panel_read, - .write = briq_panel_write, - .open = briq_panel_open, - .release = briq_panel_release, -}; - -static struct miscdevice briq_panel_miscdev = { - BRIQ_PANEL_MINOR, - "briq_panel", - &briq_panel_fops -}; - -static int __init briq_panel_init(void) -{ - struct device_node *root = find_path_device("/"); - const char *machine; - int i; - - machine = get_property(root, "model", NULL); - if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) - return -ENODEV; - - printk(KERN_INFO - "briq_panel: v%s Dr. Karsten Jeppesen (kj@totalimpact.com)\n", - BRIQ_PANEL_VER); - - if (!request_region(BRIQ_PANEL_VFD_IOPORT, 4, "BRIQ Front Panel")) - return -EBUSY; - - if (!request_region(BRIQ_PANEL_LED_IOPORT, 2, "BRIQ Front Panel")) { - release_region(BRIQ_PANEL_VFD_IOPORT, 4); - return -EBUSY; - } - ledpb = inb(BRIQ_PANEL_LED_IOPORT) & 0x000c; - - if (misc_register(&briq_panel_miscdev) < 0) { - release_region(BRIQ_PANEL_VFD_IOPORT, 4); - release_region(BRIQ_PANEL_LED_IOPORT, 2); - return -EBUSY; - } - - outb(0x38, BRIQ_PANEL_VFD_IOPORT); /* Function set */ - outb(0x01, BRIQ_PANEL_VFD_IOPORT); /* Clear display */ - outb(0x0c, BRIQ_PANEL_VFD_IOPORT); /* Display on */ - outb(0x06, BRIQ_PANEL_VFD_IOPORT); /* Entry normal */ - for (i=0; i<40; i++) - vfd[i]=' '; -#ifndef MODULE - vfd[0] = 'L'; - vfd[1] = 'o'; - vfd[2] = 'a'; - vfd[3] = 'd'; - vfd[4] = 'i'; - vfd[5] = 'n'; - vfd[6] = 'g'; - vfd[7] = ' '; - vfd[8] = '.'; - vfd[9] = '.'; - vfd[10] = '.'; -#endif /* !MODULE */ - - update_vfd(); - - return 0; -} - -static void __exit briq_panel_exit(void) -{ - misc_deregister(&briq_panel_miscdev); - release_region(BRIQ_PANEL_VFD_IOPORT, 4); - release_region(BRIQ_PANEL_LED_IOPORT, 2); -} - -module_init(briq_panel_init); -module_exit(briq_panel_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Karsten Jeppesen "); -MODULE_DESCRIPTION("Driver for the Total Impact briQ front panel"); diff --git a/trunk/drivers/char/drm/radeon_state.c b/trunk/drivers/char/drm/radeon_state.c index 39a7f685e3fd..5bb2234a9094 100644 --- a/trunk/drivers/char/drm/radeon_state.c +++ b/trunk/drivers/char/drm/radeon_state.c @@ -175,14 +175,6 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * } break; - case R200_EMIT_VAP_CTL:{ - RING_LOCALS; - BEGIN_RING(2); - OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); - ADVANCE_RING(); - } - break; - case RADEON_EMIT_RB3D_COLORPITCH: case RADEON_EMIT_RE_LINE_PATTERN: case RADEON_EMIT_SE_LINE_WIDTH: @@ -210,6 +202,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * case R200_EMIT_TCL_LIGHT_MODEL_CTL_0: case R200_EMIT_TFACTOR_0: case R200_EMIT_VTX_FMT_0: + case R200_EMIT_VAP_CTL: case R200_EMIT_MATRIX_SELECT_0: case R200_EMIT_TEX_PROC_CTL_2: case R200_EMIT_TCL_UCP_VERT_BLEND_CTL: diff --git a/trunk/drivers/char/hvc_console.c b/trunk/drivers/char/hvc_console.c index a76d2c40dd5e..ca2f538e549e 100644 --- a/trunk/drivers/char/hvc_console.c +++ b/trunk/drivers/char/hvc_console.c @@ -80,8 +80,7 @@ struct hvc_struct { struct tty_struct *tty; unsigned int count; int do_wakeup; - char *outbuf; - int outbuf_size; + char outbuf[N_OUTBUF] __ALIGNED__; int n_outbuf; uint32_t vtermno; struct hv_ops *ops; @@ -320,8 +319,10 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) struct kobject *kobjp; /* Auto increments kobject reference if found. */ - if (!(hp = hvc_get_by_index(tty->index))) + if (!(hp = hvc_get_by_index(tty->index))) { + printk(KERN_WARNING "hvc_console: tty open failed, no vty associated with tty.\n"); return -ENODEV; + } spin_lock_irqsave(&hp->lock, flags); /* Check and then increment for fast path open. */ @@ -504,7 +505,7 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count if (hp->n_outbuf > 0) hvc_push(hp); - while (count > 0 && (rsize = hp->outbuf_size - hp->n_outbuf) > 0) { + while (count > 0 && (rsize = N_OUTBUF - hp->n_outbuf) > 0) { if (rsize > count) rsize = count; memcpy(hp->outbuf + hp->n_outbuf, buf, rsize); @@ -537,7 +538,7 @@ static int hvc_write_room(struct tty_struct *tty) if (!hp) return -1; - return hp->outbuf_size - hp->n_outbuf; + return N_OUTBUF - hp->n_outbuf; } static int hvc_chars_in_buffer(struct tty_struct *tty) @@ -667,7 +668,6 @@ int khvcd(void *unused) do { poll_mask = 0; hvc_kicked = 0; - try_to_freeze(); wmb(); if (cpus_empty(cpus_in_xmon)) { spin_lock(&hvc_structs_lock); @@ -728,13 +728,12 @@ static struct kobj_type hvc_kobj_type = { }; struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, - struct hv_ops *ops, int outbuf_size) + struct hv_ops *ops) { struct hvc_struct *hp; int i; - hp = kmalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size, - GFP_KERNEL); + hp = kmalloc(sizeof(*hp), GFP_KERNEL); if (!hp) return ERR_PTR(-ENOMEM); @@ -743,8 +742,6 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, hp->vtermno = vtermno; hp->irq = irq; hp->ops = ops; - hp->outbuf_size = outbuf_size; - hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; kobject_init(&hp->kobj); hp->kobj.ktype = &hvc_kobj_type; diff --git a/trunk/drivers/char/hvc_console.h b/trunk/drivers/char/hvc_console.h index 8c59818050e6..96b7401319c1 100644 --- a/trunk/drivers/char/hvc_console.h +++ b/trunk/drivers/char/hvc_console.h @@ -56,7 +56,7 @@ extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); /* register a vterm for hvc tty operation (module_init or hotplug add) */ extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq, - struct hv_ops *ops, int outbuf_size); + struct hv_ops *ops); /* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */ extern int __devexit hvc_remove(struct hvc_struct *hp); diff --git a/trunk/drivers/char/hvc_iseries.c b/trunk/drivers/char/hvc_iseries.c deleted file mode 100644 index 4747729459c7..000000000000 --- a/trunk/drivers/char/hvc_iseries.c +++ /dev/null @@ -1,594 +0,0 @@ -/* - * iSeries vio driver interface to hvc_console.c - * - * This code is based heavily on hvc_vio.c and viocons.c - * - * Copyright (C) 2006 Stephen Rothwell, IBM Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "hvc_console.h" - -#define VTTY_PORTS 10 - -static DEFINE_SPINLOCK(consolelock); -static DEFINE_SPINLOCK(consoleloglock); - -static const char hvc_driver_name[] = "hvc_console"; - -#define IN_BUF_SIZE 200 - -/* - * Our port information. - */ -static struct port_info { - HvLpIndex lp; - u64 seq; /* sequence number of last HV send */ - u64 ack; /* last ack from HV */ - struct hvc_struct *hp; - int in_start; - int in_end; - unsigned char in_buf[IN_BUF_SIZE]; -} port_info[VTTY_PORTS] = { - [ 0 ... VTTY_PORTS - 1 ] = { - .lp = HvLpIndexInvalid - } -}; - -#define viochar_is_console(pi) ((pi) == &port_info[0]) - -static struct vio_device_id hvc_driver_table[] __devinitdata = { - {"serial", "IBM,iSeries-vty"}, - { "", "" } -}; -MODULE_DEVICE_TABLE(vio, hvc_driver_table); - -static void hvlog(char *fmt, ...) -{ - int i; - unsigned long flags; - va_list args; - static char buf[256]; - - spin_lock_irqsave(&consoleloglock, flags); - va_start(args, fmt); - i = vscnprintf(buf, sizeof(buf) - 1, fmt, args); - va_end(args); - buf[i++] = '\r'; - HvCall_writeLogBuffer(buf, i); - spin_unlock_irqrestore(&consoleloglock, flags); -} - -/* - * Initialize the common fields in a charLpEvent - */ -static void init_data_event(struct viocharlpevent *viochar, HvLpIndex lp) -{ - struct HvLpEvent *hev = &viochar->event; - - memset(viochar, 0, sizeof(struct viocharlpevent)); - - hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DEFERRED_ACK | - HV_LP_EVENT_INT; - hev->xType = HvLpEvent_Type_VirtualIo; - hev->xSubtype = viomajorsubtype_chario | viochardata; - hev->xSourceLp = HvLpConfig_getLpIndex(); - hev->xTargetLp = lp; - hev->xSizeMinus1 = sizeof(struct viocharlpevent); - hev->xSourceInstanceId = viopath_sourceinst(lp); - hev->xTargetInstanceId = viopath_targetinst(lp); -} - -static int get_chars(uint32_t vtermno, char *buf, int count) -{ - struct port_info *pi; - int n = 0; - unsigned long flags; - - if (vtermno >= VTTY_PORTS) - return -EINVAL; - if (count == 0) - return 0; - - pi = &port_info[vtermno]; - spin_lock_irqsave(&consolelock, flags); - - if (pi->in_end == 0) - goto done; - - n = pi->in_end - pi->in_start; - if (n > count) - n = count; - memcpy(buf, &pi->in_buf[pi->in_start], n); - pi->in_start += n; - if (pi->in_start == pi->in_end) { - pi->in_start = 0; - pi->in_end = 0; - } -done: - spin_unlock_irqrestore(&consolelock, flags); - return n; -} - -static int put_chars(uint32_t vtermno, const char *buf, int count) -{ - struct viocharlpevent *viochar; - struct port_info *pi; - HvLpEvent_Rc hvrc; - unsigned long flags; - int sent = 0; - - if (vtermno >= VTTY_PORTS) - return -EINVAL; - - pi = &port_info[vtermno]; - - spin_lock_irqsave(&consolelock, flags); - - if (viochar_is_console(pi) && !viopath_isactive(pi->lp)) { - spin_lock_irqsave(&consoleloglock, flags); - HvCall_writeLogBuffer(buf, count); - spin_unlock_irqrestore(&consoleloglock, flags); - sent = count; - goto done; - } - - viochar = vio_get_event_buffer(viomajorsubtype_chario); - if (viochar == NULL) { - hvlog("\n\rviocons: Can't get viochar buffer."); - goto done; - } - - while ((count > 0) && ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) { - int len; - - len = (count > VIOCHAR_MAX_DATA) ? VIOCHAR_MAX_DATA : count; - - if (viochar_is_console(pi)) { - spin_lock_irqsave(&consoleloglock, flags); - HvCall_writeLogBuffer(buf, len); - spin_unlock_irqrestore(&consoleloglock, flags); - } - - init_data_event(viochar, pi->lp); - - viochar->len = len; - viochar->event.xCorrelationToken = pi->seq++; - viochar->event.xSizeMinus1 = - offsetof(struct viocharlpevent, data) + len; - - memcpy(viochar->data, buf, len); - - hvrc = HvCallEvent_signalLpEvent(&viochar->event); - if (hvrc) - hvlog("\n\rerror sending event! return code %d\n\r", - (int)hvrc); - sent += len; - count -= len; - buf += len; - } - - vio_free_event_buffer(viomajorsubtype_chario, viochar); -done: - spin_unlock_irqrestore(&consolelock, flags); - return sent; -} - -static struct hv_ops hvc_get_put_ops = { - .get_chars = get_chars, - .put_chars = put_chars, -}; - -static int __devinit hvc_vio_probe(struct vio_dev *vdev, - const struct vio_device_id *id) -{ - struct hvc_struct *hp; - struct port_info *pi; - - /* probed with invalid parameters. */ - if (!vdev || !id) - return -EPERM; - - if (vdev->unit_address >= VTTY_PORTS) - return -ENODEV; - - pi = &port_info[vdev->unit_address]; - - hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops, - VIOCHAR_MAX_DATA); - if (IS_ERR(hp)) - return PTR_ERR(hp); - pi->hp = hp; - dev_set_drvdata(&vdev->dev, pi); - - return 0; -} - -static int __devexit hvc_vio_remove(struct vio_dev *vdev) -{ - struct port_info *pi = dev_get_drvdata(&vdev->dev); - struct hvc_struct *hp = pi->hp; - - return hvc_remove(hp); -} - -static struct vio_driver hvc_vio_driver = { - .id_table = hvc_driver_table, - .probe = hvc_vio_probe, - .remove = hvc_vio_remove, - .driver = { - .name = hvc_driver_name, - .owner = THIS_MODULE, - } -}; - -static void hvc_open_event(struct HvLpEvent *event) -{ - unsigned long flags; - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - u8 port = cevent->virtual_device; - struct port_info *pi; - int reject = 0; - - if (hvlpevent_is_ack(event)) { - if (port >= VTTY_PORTS) - return; - - spin_lock_irqsave(&consolelock, flags); - - pi = &port_info[port]; - if (event->xRc == HvLpEvent_Rc_Good) { - pi->seq = pi->ack = 0; - /* - * This line allows connections from the primary - * partition but once one is connected from the - * primary partition nothing short of a reboot - * of linux will allow access from the hosting - * partition again without a required iSeries fix. - */ - pi->lp = event->xTargetLp; - } - - spin_unlock_irqrestore(&consolelock, flags); - if (event->xRc != HvLpEvent_Rc_Good) - printk(KERN_WARNING - "hvc: handle_open_event: event->xRc == (%d).\n", - event->xRc); - - if (event->xCorrelationToken != 0) { - atomic_t *aptr= (atomic_t *)event->xCorrelationToken; - atomic_set(aptr, 1); - } else - printk(KERN_WARNING - "hvc: weird...got open ack without atomic\n"); - return; - } - - /* This had better require an ack, otherwise complain */ - if (!hvlpevent_need_ack(event)) { - printk(KERN_WARNING "hvc: viocharopen without ack bit!\n"); - return; - } - - spin_lock_irqsave(&consolelock, flags); - - /* Make sure this is a good virtual tty */ - if (port >= VTTY_PORTS) { - event->xRc = HvLpEvent_Rc_SubtypeError; - cevent->subtype_result_code = viorc_openRejected; - /* - * Flag state here since we can't printk while holding - * the consolelock spinlock. - */ - reject = 1; - } else { - pi = &port_info[port]; - if ((pi->lp != HvLpIndexInvalid) && - (pi->lp != event->xSourceLp)) { - /* - * If this is tty is already connected to a different - * partition, fail. - */ - event->xRc = HvLpEvent_Rc_SubtypeError; - cevent->subtype_result_code = viorc_openRejected; - reject = 2; - } else { - pi->lp = event->xSourceLp; - event->xRc = HvLpEvent_Rc_Good; - cevent->subtype_result_code = viorc_good; - pi->seq = pi->ack = 0; - } - } - - spin_unlock_irqrestore(&consolelock, flags); - - if (reject == 1) - printk(KERN_WARNING "hvc: open rejected: bad virtual tty.\n"); - else if (reject == 2) - printk(KERN_WARNING "hvc: open rejected: console in exclusive " - "use by another partition.\n"); - - /* Return the acknowledgement */ - HvCallEvent_ackLpEvent(event); -} - -/* - * Handle a close charLpEvent. This should ONLY be an Interrupt because the - * virtual console should never actually issue a close event to the hypervisor - * because the virtual console never goes away. A close event coming from the - * hypervisor simply means that there are no client consoles connected to the - * virtual console. - */ -static void hvc_close_event(struct HvLpEvent *event) -{ - unsigned long flags; - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - u8 port = cevent->virtual_device; - - if (!hvlpevent_is_int(event)) { - printk(KERN_WARNING - "hvc: got unexpected close acknowlegement\n"); - return; - } - - if (port >= VTTY_PORTS) { - printk(KERN_WARNING - "hvc: close message from invalid virtual device.\n"); - return; - } - - /* For closes, just mark the console partition invalid */ - spin_lock_irqsave(&consolelock, flags); - - if (port_info[port].lp == event->xSourceLp) - port_info[port].lp = HvLpIndexInvalid; - - spin_unlock_irqrestore(&consolelock, flags); -} - -static void hvc_data_event(struct HvLpEvent *event) -{ - unsigned long flags; - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - struct port_info *pi; - int n; - u8 port = cevent->virtual_device; - - if (port >= VTTY_PORTS) { - printk(KERN_WARNING "hvc: data on invalid virtual device %d\n", - port); - return; - } - if (cevent->len == 0) - return; - - /* - * Change 05/01/2003 - Ryan Arnold: If a partition other than - * the current exclusive partition tries to send us data - * events then just drop them on the floor because we don't - * want his stinking data. He isn't authorized to receive - * data because he wasn't the first one to get the console, - * therefore he shouldn't be allowed to send data either. - * This will work without an iSeries fix. - */ - pi = &port_info[port]; - if (pi->lp != event->xSourceLp) - return; - - spin_lock_irqsave(&consolelock, flags); - - n = IN_BUF_SIZE - pi->in_end; - if (n > cevent->len) - n = cevent->len; - if (n > 0) { - memcpy(&pi->in_buf[pi->in_end], cevent->data, n); - pi->in_end += n; - } - spin_unlock_irqrestore(&consolelock, flags); - if (n == 0) - printk(KERN_WARNING "hvc: input buffer overflow\n"); -} - -static void hvc_ack_event(struct HvLpEvent *event) -{ - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - unsigned long flags; - u8 port = cevent->virtual_device; - - if (port >= VTTY_PORTS) { - printk(KERN_WARNING "hvc: data on invalid virtual device\n"); - return; - } - - spin_lock_irqsave(&consolelock, flags); - port_info[port].ack = event->xCorrelationToken; - spin_unlock_irqrestore(&consolelock, flags); -} - -static void hvc_config_event(struct HvLpEvent *event) -{ - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - - if (cevent->data[0] == 0x01) - printk(KERN_INFO "hvc: window resized to %d: %d: %d: %d\n", - cevent->data[1], cevent->data[2], - cevent->data[3], cevent->data[4]); - else - printk(KERN_WARNING "hvc: unknown config event\n"); -} - -static void hvc_handle_event(struct HvLpEvent *event) -{ - int charminor; - - if (event == NULL) - return; - - charminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK; - switch (charminor) { - case viocharopen: - hvc_open_event(event); - break; - case viocharclose: - hvc_close_event(event); - break; - case viochardata: - hvc_data_event(event); - break; - case viocharack: - hvc_ack_event(event); - break; - case viocharconfig: - hvc_config_event(event); - break; - default: - if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) { - event->xRc = HvLpEvent_Rc_InvalidSubtype; - HvCallEvent_ackLpEvent(event); - } - } -} - -static int send_open(HvLpIndex remoteLp, void *sem) -{ - return HvCallEvent_signalLpEventFast(remoteLp, - HvLpEvent_Type_VirtualIo, - viomajorsubtype_chario | viocharopen, - HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, - viopath_sourceinst(remoteLp), - viopath_targetinst(remoteLp), - (u64)(unsigned long)sem, VIOVERSION << 16, - 0, 0, 0, 0); -} - -static int hvc_vio_init(void) -{ - atomic_t wait_flag; - int rc; - - /* +2 for fudge */ - rc = viopath_open(HvLpConfig_getPrimaryLpIndex(), - viomajorsubtype_chario, VIOCHAR_WINDOW + 2); - if (rc) - printk(KERN_WARNING "hvc: error opening to primary %d\n", rc); - - if (viopath_hostLp == HvLpIndexInvalid) - vio_set_hostlp(); - - /* - * And if the primary is not the same as the hosting LP, open to the - * hosting lp - */ - if ((viopath_hostLp != HvLpIndexInvalid) && - (viopath_hostLp != HvLpConfig_getPrimaryLpIndex())) { - printk(KERN_INFO "hvc: open path to hosting (%d)\n", - viopath_hostLp); - rc = viopath_open(viopath_hostLp, viomajorsubtype_chario, - VIOCHAR_WINDOW + 2); /* +2 for fudge */ - if (rc) - printk(KERN_WARNING - "error opening to partition %d: %d\n", - viopath_hostLp, rc); - } - - if (vio_setHandler(viomajorsubtype_chario, hvc_handle_event) < 0) - printk(KERN_WARNING - "hvc: error seting handler for console events!\n"); - - /* - * First, try to open the console to the hosting lp. - * Wait on a semaphore for the response. - */ - atomic_set(&wait_flag, 0); - if ((viopath_isactive(viopath_hostLp)) && - (send_open(viopath_hostLp, &wait_flag) == 0)) { - printk(KERN_INFO "hvc: hosting partition %d\n", viopath_hostLp); - while (atomic_read(&wait_flag) == 0) - mb(); - atomic_set(&wait_flag, 0); - } - - /* - * If we don't have an active console, try the primary - */ - if ((!viopath_isactive(port_info[0].lp)) && - (viopath_isactive(HvLpConfig_getPrimaryLpIndex())) && - (send_open(HvLpConfig_getPrimaryLpIndex(), &wait_flag) == 0)) { - printk(KERN_INFO "hvc: opening console to primary partition\n"); - while (atomic_read(&wait_flag) == 0) - mb(); - } - - /* Register as a vio device to receive callbacks */ - rc = vio_register_driver(&hvc_vio_driver); - - return rc; -} -module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */ - -static void hvc_vio_exit(void) -{ - vio_unregister_driver(&hvc_vio_driver); -} -module_exit(hvc_vio_exit); - -/* the device tree order defines our numbering */ -static int hvc_find_vtys(void) -{ - struct device_node *vty; - int num_found = 0; - - for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL; - vty = of_find_node_by_name(vty, "vty")) { - uint32_t *vtermno; - - /* We have statically defined space for only a certain number - * of console adapters. - */ - if ((num_found >= MAX_NR_HVC_CONSOLES) || - (num_found >= VTTY_PORTS)) - break; - - vtermno = (uint32_t *)get_property(vty, "reg", NULL); - if (!vtermno) - continue; - - if (!device_is_compatible(vty, "IBM,iSeries-vty")) - continue; - - if (num_found == 0) - add_preferred_console("hvc", 0, NULL); - hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops); - ++num_found; - } - - return num_found; -} -console_initcall(hvc_find_vtys); diff --git a/trunk/drivers/char/hvc_rtas.c b/trunk/drivers/char/hvc_rtas.c index 4b97eaf18602..57106e02fd2e 100644 --- a/trunk/drivers/char/hvc_rtas.c +++ b/trunk/drivers/char/hvc_rtas.c @@ -94,7 +94,7 @@ static int hvc_rtas_init(void) /* Allocate an hvc_struct for the console device we instantiated * earlier. Save off hp so that we can return it on exit */ - hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops, 16); + hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops); if (IS_ERR(hp)) return PTR_ERR(hp); diff --git a/trunk/drivers/char/hvc_vio.c b/trunk/drivers/char/hvc_vio.c index cc95941148fb..9add81ceb440 100644 --- a/trunk/drivers/char/hvc_vio.c +++ b/trunk/drivers/char/hvc_vio.c @@ -90,8 +90,7 @@ static int __devinit hvc_vio_probe(struct vio_dev *vdev, if (!vdev || !id) return -EPERM; - hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops, - MAX_VIO_PUT_CHARS); + hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops); if (IS_ERR(hp)) return PTR_ERR(hp); dev_set_drvdata(&vdev->dev, hp); @@ -141,7 +140,7 @@ static int hvc_find_vtys(void) for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL; vty = of_find_node_by_name(vty, "vty")) { - const uint32_t *vtermno; + uint32_t *vtermno; /* We have statically defined space for only a certain number * of console adapters. @@ -149,7 +148,7 @@ static int hvc_find_vtys(void) if (num_found >= MAX_NR_HVC_CONSOLES) break; - vtermno = get_property(vty, "reg", NULL); + vtermno = (uint32_t *)get_property(vty, "reg", NULL); if (!vtermno) continue; diff --git a/trunk/drivers/char/hvsi.c b/trunk/drivers/char/hvsi.c index a89a95fb5e40..41db8060e8f7 100644 --- a/trunk/drivers/char/hvsi.c +++ b/trunk/drivers/char/hvsi.c @@ -311,8 +311,7 @@ static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet, /* CD went away; no more connection */ pr_debug("hvsi%i: CD dropped\n", hp->index); hp->mctrl &= TIOCM_CD; - /* If userland hasn't done an open(2) yet, hp->tty is NULL. */ - if (hp->tty && !(hp->tty->flags & CLOCAL)) + if (!(hp->tty->flags & CLOCAL)) *to_hangup = hp->tty; } break; @@ -987,7 +986,10 @@ static void hvsi_write_worker(void *arg) start_j = 0; #endif /* DEBUG */ wake_up_all(&hp->emptyq); - tty_wakeup(hp->tty); + if (test_bit(TTY_DO_WRITE_WAKEUP, &hp->tty->flags) + && hp->tty->ldisc.write_wakeup) + hp->tty->ldisc.write_wakeup(hp->tty); + wake_up_interruptible(&hp->tty->write_wait); } out: @@ -1274,10 +1276,11 @@ static int __init hvsi_console_init(void) vty != NULL; vty = of_find_compatible_node(vty, "serial", "hvterm-protocol")) { struct hvsi_struct *hp; - const uint32_t *vtermno, *irq; + uint32_t *vtermno; + uint32_t *irq; - vtermno = get_property(vty, "reg", NULL); - irq = get_property(vty, "interrupts", NULL); + vtermno = (uint32_t *)get_property(vty, "reg", NULL); + irq = (uint32_t *)get_property(vty, "interrupts", NULL); if (!vtermno || !irq) continue; diff --git a/trunk/drivers/char/hw_random/geode-rng.c b/trunk/drivers/char/hw_random/geode-rng.c index d37ced0d132b..be61f22ee7bb 100644 --- a/trunk/drivers/char/hw_random/geode-rng.c +++ b/trunk/drivers/char/hw_random/geode-rng.c @@ -107,14 +107,10 @@ static int __init mod_init(void) if (err) { printk(KERN_ERR PFX "RNG registering failed (%d)\n", err); - goto err_unmap; + goto out; } out: return err; - -err_unmap: - iounmap(mem); - goto out; } static void __exit mod_exit(void) diff --git a/trunk/drivers/char/hw_random/intel-rng.c b/trunk/drivers/char/hw_random/intel-rng.c index ccd7e7102234..6594bd5645f4 100644 --- a/trunk/drivers/char/hw_random/intel-rng.c +++ b/trunk/drivers/char/hw_random/intel-rng.c @@ -164,7 +164,7 @@ static int __init mod_init(void) if (err) { printk(KERN_ERR PFX "RNG registering failed (%d)\n", err); - goto err_unmap; + goto out; } out: return err; diff --git a/trunk/drivers/char/hw_random/omap-rng.c b/trunk/drivers/char/hw_random/omap-rng.c index a01d796d1eeb..819516b35a79 100644 --- a/trunk/drivers/char/hw_random/omap-rng.c +++ b/trunk/drivers/char/hw_random/omap-rng.c @@ -25,12 +25,12 @@ #include #include #include -#include #include -#include +#include #include #include +#include #define RNG_OUT_REG 0x00 /* Output register */ #define RNG_STAT_REG 0x04 /* Status register @@ -52,7 +52,7 @@ static void __iomem *rng_base; static struct clk *rng_ick; -static struct platform_device *rng_dev; +static struct device *rng_dev; static u32 omap_rng_read_reg(int reg) { @@ -83,8 +83,9 @@ static struct hwrng omap_rng_ops = { .data_read = omap_rng_data_read, }; -static int __init omap_rng_probe(struct platform_device *pdev) +static int __init omap_rng_probe(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); struct resource *res, *mem; int ret; @@ -94,14 +95,16 @@ static int __init omap_rng_probe(struct platform_device *pdev) */ BUG_ON(rng_dev); - if (cpu_is_omap24xx()) { + if (cpu_is_omap24xx()) { rng_ick = clk_get(NULL, "rng_ick"); if (IS_ERR(rng_ick)) { - dev_err(&pdev->dev, "Could not get rng_ick\n"); + dev_err(dev, "Could not get rng_ick\n"); ret = PTR_ERR(rng_ick); return ret; - } else - clk_enable(rng_ick); + } + else { + clk_use(rng_ick); + } } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -114,7 +117,7 @@ static int __init omap_rng_probe(struct platform_device *pdev) if (mem == NULL) return -EBUSY; - dev_set_drvdata(&pdev->dev, mem); + dev_set_drvdata(dev, mem); rng_base = (u32 __iomem *)io_p2v(res->start); ret = hwrng_register(&omap_rng_ops); @@ -124,25 +127,25 @@ static int __init omap_rng_probe(struct platform_device *pdev) return ret; } - dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n", + dev_info(dev, "OMAP Random Number Generator ver. %02x\n", omap_rng_read_reg(RNG_REV_REG)); omap_rng_write_reg(RNG_MASK_REG, 0x1); - rng_dev = pdev; + rng_dev = dev; return 0; } -static int __exit omap_rng_remove(struct platform_device *pdev) +static int __exit omap_rng_remove(struct device *dev) { - struct resource *mem = dev_get_drvdata(&pdev->dev); + struct resource *mem = dev_get_drvdata(dev); hwrng_unregister(&omap_rng_ops); omap_rng_write_reg(RNG_MASK_REG, 0x0); if (cpu_is_omap24xx()) { - clk_disable(rng_ick); + clk_unuse(rng_ick); clk_put(rng_ick); } @@ -154,16 +157,18 @@ static int __exit omap_rng_remove(struct platform_device *pdev) #ifdef CONFIG_PM -static int omap_rng_suspend(struct platform_device *pdev, pm_message_t message) +static int omap_rng_suspend(struct device *dev, pm_message_t message, u32 level) { omap_rng_write_reg(RNG_MASK_REG, 0x0); + return 0; } -static int omap_rng_resume(struct platform_device *pdev) +static int omap_rng_resume(struct device *dev, pm_message_t message, u32 level) { omap_rng_write_reg(RNG_MASK_REG, 0x1); - return 0; + + return 1; } #else @@ -174,11 +179,9 @@ static int omap_rng_resume(struct platform_device *pdev) #endif -static struct platform_driver omap_rng_driver = { - .driver = { - .name = "omap_rng", - .owner = THIS_MODULE, - }, +static struct device_driver omap_rng_driver = { + .name = "omap_rng", + .bus = &platform_bus_type, .probe = omap_rng_probe, .remove = __exit_p(omap_rng_remove), .suspend = omap_rng_suspend, @@ -190,12 +193,12 @@ static int __init omap_rng_init(void) if (!cpu_is_omap16xx() && !cpu_is_omap24xx()) return -ENODEV; - return platform_driver_register(&omap_rng_driver); + return driver_register(&omap_rng_driver); } static void __exit omap_rng_exit(void) { - platform_driver_unregister(&omap_rng_driver); + driver_unregister(&omap_rng_driver); } module_init(omap_rng_init); diff --git a/trunk/drivers/char/ipmi/ipmi_msghandler.c b/trunk/drivers/char/ipmi/ipmi_msghandler.c index 843d34c8627c..0aa5d608fe6f 100644 --- a/trunk/drivers/char/ipmi/ipmi_msghandler.c +++ b/trunk/drivers/char/ipmi/ipmi_msghandler.c @@ -3428,7 +3428,6 @@ struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) rv = kmalloc(sizeof(struct ipmi_recv_msg), GFP_ATOMIC); if (rv) { - rv->user = NULL; rv->done = free_recv_msg; atomic_inc(&recv_msg_inuse_count); } diff --git a/trunk/drivers/char/ipmi/ipmi_si_intf.c b/trunk/drivers/char/ipmi/ipmi_si_intf.c index abca98beac14..f57eba0bf253 100644 --- a/trunk/drivers/char/ipmi/ipmi_si_intf.c +++ b/trunk/drivers/char/ipmi/ipmi_si_intf.c @@ -402,10 +402,10 @@ static void handle_flags(struct smi_info *smi_info) smi_info->curr_msg->data, smi_info->curr_msg->data_size); smi_info->si_state = SI_GETTING_EVENTS; - } else if (smi_info->msg_flags & OEM_DATA_AVAIL && - smi_info->oem_data_avail_handler) { - if (smi_info->oem_data_avail_handler(smi_info)) - goto retry; + } else if (smi_info->msg_flags & OEM_DATA_AVAIL) { + if (smi_info->oem_data_avail_handler) + if (smi_info->oem_data_avail_handler(smi_info)) + goto retry; } else { smi_info->si_state = SI_NORMAL; } @@ -2481,7 +2481,6 @@ static __devinit int init_ipmi_si(void) #ifdef CONFIG_PCI pci_unregister_driver(&ipmi_pci_driver); #endif - driver_unregister(&ipmi_driver); printk("ipmi_si: Unable to find any System Interface(s)\n"); return -ENODEV; } else { diff --git a/trunk/drivers/char/istallion.c b/trunk/drivers/char/istallion.c index 8c09997cc3d6..84dfc4278139 100644 --- a/trunk/drivers/char/istallion.c +++ b/trunk/drivers/char/istallion.c @@ -3488,7 +3488,7 @@ static int stli_initecp(stlibrd_t *brdp) */ EBRDENABLE(brdp); sigsp = (cdkecpsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR); - memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t)); + memcpy(&sig, sigsp, sizeof(cdkecpsig_t)); EBRDDISABLE(brdp); if (sig.magic != cpu_to_le32(ECP_MAGIC)) diff --git a/trunk/drivers/char/keyboard.c b/trunk/drivers/char/keyboard.c index 3e90aac37510..056ebe84b81d 100644 --- a/trunk/drivers/char/keyboard.c +++ b/trunk/drivers/char/keyboard.c @@ -107,6 +107,7 @@ const int NR_TYPES = ARRAY_SIZE(max_vals); struct kbd_struct kbd_table[MAX_NR_CONSOLES]; static struct kbd_struct *kbd = kbd_table; +static struct kbd_struct kbd0; int spawnpid, spawnsig; @@ -222,13 +223,13 @@ static void kd_nosound(unsigned long ignored) { struct list_head *node; - list_for_each(node, &kbd_handler.h_list) { + list_for_each(node,&kbd_handler.h_list) { struct input_handle *handle = to_handle_h(node); if (test_bit(EV_SND, handle->dev->evbit)) { if (test_bit(SND_TONE, handle->dev->sndbit)) - input_inject_event(handle, EV_SND, SND_TONE, 0); + input_event(handle->dev, EV_SND, SND_TONE, 0); if (test_bit(SND_BELL, handle->dev->sndbit)) - input_inject_event(handle, EV_SND, SND_BELL, 0); + input_event(handle->dev, EV_SND, SND_BELL, 0); } } } @@ -246,11 +247,11 @@ void kd_mksound(unsigned int hz, unsigned int ticks) struct input_handle *handle = to_handle_h(node); if (test_bit(EV_SND, handle->dev->evbit)) { if (test_bit(SND_TONE, handle->dev->sndbit)) { - input_inject_event(handle, EV_SND, SND_TONE, hz); + input_event(handle->dev, EV_SND, SND_TONE, hz); break; } if (test_bit(SND_BELL, handle->dev->sndbit)) { - input_inject_event(handle, EV_SND, SND_BELL, 1); + input_event(handle->dev, EV_SND, SND_BELL, 1); break; } } @@ -271,15 +272,15 @@ int kbd_rate(struct kbd_repeat *rep) unsigned int d = 0; unsigned int p = 0; - list_for_each(node, &kbd_handler.h_list) { + list_for_each(node,&kbd_handler.h_list) { struct input_handle *handle = to_handle_h(node); struct input_dev *dev = handle->dev; if (test_bit(EV_REP, dev->evbit)) { if (rep->delay > 0) - input_inject_event(handle, EV_REP, REP_DELAY, rep->delay); + input_event(dev, EV_REP, REP_DELAY, rep->delay); if (rep->period > 0) - input_inject_event(handle, EV_REP, REP_PERIOD, rep->period); + input_event(dev, EV_REP, REP_PERIOD, rep->period); d = dev->rep[REP_DELAY]; p = dev->rep[REP_PERIOD]; } @@ -987,7 +988,7 @@ static inline unsigned char getleds(void) * interrupt routines for this thing allows us to easily mask * this when we don't want any of the above to happen. * This allows for easy and efficient race-condition prevention - * for kbd_start => input_inject_event(dev, EV_LED, ...) => ... + * for kbd_refresh_leds => input_event(dev, EV_LED, ...) => ... */ static void kbd_bh(unsigned long dummy) @@ -997,11 +998,11 @@ static void kbd_bh(unsigned long dummy) if (leds != ledstate) { list_for_each(node, &kbd_handler.h_list) { - struct input_handle *handle = to_handle_h(node); - input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); - input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02)); - input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04)); - input_inject_event(handle, EV_SYN, SYN_REPORT, 0); + struct input_handle * handle = to_handle_h(node); + input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01)); + input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02)); + input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04)); + input_sync(handle->dev); } } @@ -1010,6 +1011,23 @@ static void kbd_bh(unsigned long dummy) DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); +/* + * This allows a newly plugged keyboard to pick the LED state. + */ +static void kbd_refresh_leds(struct input_handle *handle) +{ + unsigned char leds = ledstate; + + tasklet_disable(&keyboard_tasklet); + if (leds != 0xff) { + input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01)); + input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02)); + input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04)); + input_sync(handle->dev); + } + tasklet_enable(&keyboard_tasklet); +} + #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\ defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\ defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\ @@ -1025,7 +1043,7 @@ static const unsigned short x86_keycodes[256] = 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92, - 284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339, + 284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339, 367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349, 360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355, 103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361, @@ -1047,55 +1065,38 @@ extern void sun_do_break(void); static int emulate_raw(struct vc_data *vc, unsigned int keycode, unsigned char up_flag) { - int code; + if (keycode > 255 || !x86_keycodes[keycode]) + return -1; switch (keycode) { case KEY_PAUSE: put_queue(vc, 0xe1); put_queue(vc, 0x1d | up_flag); put_queue(vc, 0x45 | up_flag); - break; - + return 0; case KEY_HANGEUL: if (!up_flag) put_queue(vc, 0xf2); - break; - + return 0; case KEY_HANJA: if (!up_flag) put_queue(vc, 0xf1); - break; - - case KEY_SYSRQ: - /* - * Real AT keyboards (that's what we're trying - * to emulate here emit 0xe0 0x2a 0xe0 0x37 when - * pressing PrtSc/SysRq alone, but simply 0x54 - * when pressing Alt+PrtSc/SysRq. - */ - if (sysrq_alt) { - put_queue(vc, 0x54 | up_flag); - } else { - put_queue(vc, 0xe0); - put_queue(vc, 0x2a | up_flag); - put_queue(vc, 0xe0); - put_queue(vc, 0x37 | up_flag); - } - break; + return 0; + } - default: - if (keycode > 255) - return -1; + if (keycode == KEY_SYSRQ && sysrq_alt) { + put_queue(vc, 0x54 | up_flag); + return 0; + } - code = x86_keycodes[keycode]; - if (!code) - return -1; + if (x86_keycodes[keycode] & 0x100) + put_queue(vc, 0xe0); - if (code & 0x100) - put_queue(vc, 0xe0); - put_queue(vc, (code & 0x7f) | up_flag); + put_queue(vc, (x86_keycodes[keycode] & 0x7f) | up_flag); - break; + if (keycode == KEY_SYSRQ) { + put_queue(vc, 0xe0); + put_queue(vc, 0x37 | up_flag); } return 0; @@ -1297,15 +1298,16 @@ static struct input_handle *kbd_connect(struct input_handler *handler, if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit)) return NULL; - handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); - if (!handle) + if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) return NULL; + memset(handle, 0, sizeof(struct input_handle)); handle->dev = dev; handle->handler = handler; handle->name = "kbd"; input_open_device(handle); + kbd_refresh_leds(handle); return handle; } @@ -1316,24 +1318,6 @@ static void kbd_disconnect(struct input_handle *handle) kfree(handle); } -/* - * Start keyboard handler on the new keyboard by refreshing LED state to - * match the rest of the system. - */ -static void kbd_start(struct input_handle *handle) -{ - unsigned char leds = ledstate; - - tasklet_disable(&keyboard_tasklet); - if (leds != 0xff) { - input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); - input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02)); - input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04)); - input_inject_event(handle, EV_SYN, SYN_REPORT, 0); - } - tasklet_enable(&keyboard_tasklet); -} - static struct input_device_id kbd_ids[] = { { .flags = INPUT_DEVICE_ID_MATCH_EVBIT, @@ -1354,7 +1338,6 @@ static struct input_handler kbd_handler = { .event = kbd_event, .connect = kbd_connect, .disconnect = kbd_disconnect, - .start = kbd_start, .name = "kbd", .id_table = kbd_ids, }; @@ -1363,15 +1346,15 @@ int __init kbd_init(void) { int i; - for (i = 0; i < MAX_NR_CONSOLES; i++) { - kbd_table[i].ledflagstate = KBD_DEFLEDS; - kbd_table[i].default_ledflagstate = KBD_DEFLEDS; - kbd_table[i].ledmode = LED_SHOW_FLAGS; - kbd_table[i].lockstate = KBD_DEFLOCK; - kbd_table[i].slockstate = 0; - kbd_table[i].modeflags = KBD_DEFMODE; - kbd_table[i].kbdmode = VC_XLATE; - } + kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS; + kbd0.ledmode = LED_SHOW_FLAGS; + kbd0.lockstate = KBD_DEFLOCK; + kbd0.slockstate = 0; + kbd0.modeflags = KBD_DEFMODE; + kbd0.kbdmode = VC_XLATE; + + for (i = 0 ; i < MAX_NR_CONSOLES ; i++) + kbd_table[i] = kbd0; input_register_handler(&kbd_handler); diff --git a/trunk/drivers/char/moxa.c b/trunk/drivers/char/moxa.c index a369dd6877d8..4ea7bd5f4f56 100644 --- a/trunk/drivers/char/moxa.c +++ b/trunk/drivers/char/moxa.c @@ -142,7 +142,6 @@ typedef struct _moxa_board_conf { static moxa_board_conf moxa_boards[MAX_BOARDS]; static void __iomem *moxaBaseAddr[MAX_BOARDS]; -static int loadstat[MAX_BOARDS]; struct moxa_str { int type; @@ -1689,8 +1688,6 @@ int MoxaDriverPoll(void) if (moxaCard == 0) return (-1); for (card = 0; card < MAX_BOARDS; card++) { - if (loadstat[card] == 0) - continue; if ((ports = moxa_boards[card].numPorts) == 0) continue; if (readb(moxaIntPend[card]) == 0xff) { @@ -2906,7 +2903,6 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) } break; } - loadstat[cardno] = 1; return (0); } @@ -2924,7 +2920,7 @@ static int moxaloadc218(int cardno, void __iomem *baseAddr, int len) len1 = len >> 1; ptr = (ushort *) moxaBuff; for (i = 0; i < len1; i++) - usum += le16_to_cpu(*(ptr + i)); + usum += *(ptr + i); retry = 0; do { len1 = len >> 1; @@ -2996,7 +2992,7 @@ static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPor wlen = len >> 1; uptr = (ushort *) moxaBuff; for (i = 0; i < wlen; i++) - usum += le16_to_cpu(uptr[i]); + usum += uptr[i]; retry = 0; j = 0; do { diff --git a/trunk/drivers/char/pc8736x_gpio.c b/trunk/drivers/char/pc8736x_gpio.c index 84e5a68635f1..645eb81cb5a9 100644 --- a/trunk/drivers/char/pc8736x_gpio.c +++ b/trunk/drivers/char/pc8736x_gpio.c @@ -221,6 +221,7 @@ static struct nsc_gpio_ops pc8736x_gpio_ops = { .gpio_change = pc8736x_gpio_change, .gpio_current = pc8736x_gpio_current }; +EXPORT_SYMBOL(pc8736x_gpio_ops); static int pc8736x_gpio_open(struct inode *inode, struct file *file) { diff --git a/trunk/drivers/char/snsc.c b/trunk/drivers/char/snsc.c index 07e0b75f2338..afc6eda602f7 100644 --- a/trunk/drivers/char/snsc.c +++ b/trunk/drivers/char/snsc.c @@ -374,12 +374,7 @@ scdrv_init(void) struct sysctl_data_s *scd; void *salbuf; dev_t first_dev, dev; - nasid_t event_nasid; - - if (!ia64_platform_is("sn2")) - return -ENODEV; - - event_nasid = ia64_sn_get_console_nasid(); + nasid_t event_nasid = ia64_sn_get_console_nasid(); if (alloc_chrdev_region(&first_dev, 0, num_cnodes, SYSCTL_BASENAME) < 0) { diff --git a/trunk/drivers/char/synclink_gt.c b/trunk/drivers/char/synclink_gt.c index 2f07b085536b..b2dbbdb1bf81 100644 --- a/trunk/drivers/char/synclink_gt.c +++ b/trunk/drivers/char/synclink_gt.c @@ -391,8 +391,8 @@ static MGSL_PARAMS default_params = { #define DESC_LIST_SIZE 4096 #define MASK_PARITY BIT1 -#define MASK_FRAMING BIT0 -#define MASK_BREAK BIT14 +#define MASK_FRAMING BIT2 +#define MASK_BREAK BIT3 #define MASK_OVERRUN BIT4 #define GSR 0x00 /* global status */ @@ -1800,17 +1800,17 @@ static void rx_async(struct slgt_info *info) stat = 0; - if ((status = *(p+1) & (BIT1 + BIT0))) { - if (status & BIT1) + if ((status = *(p+1) & (BIT9 + BIT8))) { + if (status & BIT9) icount->parity++; - else if (status & BIT0) + else if (status & BIT8) icount->frame++; /* discard char if tty control flags say so */ if (status & info->ignore_status_mask) continue; - if (status & BIT1) + if (status & BIT9) stat = TTY_PARITY; - else if (status & BIT0) + else if (status & BIT8) stat = TTY_FRAME; } if (tty) { diff --git a/trunk/drivers/char/tpm/tpm_atmel.h b/trunk/drivers/char/tpm/tpm_atmel.h index aefd683c60b7..2e68eeb8a2cd 100644 --- a/trunk/drivers/char/tpm/tpm_atmel.h +++ b/trunk/drivers/char/tpm/tpm_atmel.h @@ -37,7 +37,7 @@ static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) { struct device_node *dn; unsigned long address, size; - const unsigned int *reg; + unsigned int *reg; int reglen; int naddrc; int nsizec; @@ -52,7 +52,7 @@ static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) return NULL; } - reg = get_property(dn, "reg", ®len); + reg = (unsigned int *) get_property(dn, "reg", ®len); naddrc = prom_n_addr_cells(dn); nsizec = prom_n_size_cells(dn); diff --git a/trunk/drivers/char/tty_io.c b/trunk/drivers/char/tty_io.c index bb0d9199e994..bfdb90242a90 100644 --- a/trunk/drivers/char/tty_io.c +++ b/trunk/drivers/char/tty_io.c @@ -153,15 +153,6 @@ int tty_ioctl(struct inode * inode, struct file * file, static int tty_fasync(int fd, struct file * filp, int on); static void release_mem(struct tty_struct *tty, int idx); -/** - * alloc_tty_struct - allocate a tty object - * - * Return a new empty tty structure. The data fields have not - * been initialized in any way but has been zeroed - * - * Locking: none - * FIXME: use kzalloc - */ static struct tty_struct *alloc_tty_struct(void) { @@ -175,15 +166,6 @@ static struct tty_struct *alloc_tty_struct(void) static void tty_buffer_free_all(struct tty_struct *); -/** - * free_tty_struct - free a disused tty - * @tty: tty struct to free - * - * Free the write buffers, tty queue and tty memory itself. - * - * Locking: none. Must be called after tty is definitely unused - */ - static inline void free_tty_struct(struct tty_struct *tty) { kfree(tty->write_buf); @@ -193,17 +175,6 @@ static inline void free_tty_struct(struct tty_struct *tty) #define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base) -/** - * tty_name - return tty naming - * @tty: tty structure - * @buf: buffer for output - * - * Convert a tty structure into a name. The name reflects the kernel - * naming policy and if udev is in use may not reflect user space - * - * Locking: none - */ - char *tty_name(struct tty_struct *tty, char *buf) { if (!tty) /* Hmm. NULL pointer. That's fun. */ @@ -264,28 +235,6 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) * Tty buffer allocation management */ - -/** - * tty_buffer_free_all - free buffers used by a tty - * @tty: tty to free from - * - * Remove all the buffers pending on a tty whether queued with data - * or in the free ring. Must be called when the tty is no longer in use - * - * Locking: none - */ - - -/** - * tty_buffer_free_all - free buffers used by a tty - * @tty: tty to free from - * - * Remove all the buffers pending on a tty whether queued with data - * or in the free ring. Must be called when the tty is no longer in use - * - * Locking: none - */ - static void tty_buffer_free_all(struct tty_struct *tty) { struct tty_buffer *thead; @@ -298,47 +247,19 @@ static void tty_buffer_free_all(struct tty_struct *tty) kfree(thead); } tty->buf.tail = NULL; - tty->buf.memory_used = 0; } -/** - * tty_buffer_init - prepare a tty buffer structure - * @tty: tty to initialise - * - * Set up the initial state of the buffer management for a tty device. - * Must be called before the other tty buffer functions are used. - * - * Locking: none - */ - static void tty_buffer_init(struct tty_struct *tty) { spin_lock_init(&tty->buf.lock); tty->buf.head = NULL; tty->buf.tail = NULL; tty->buf.free = NULL; - tty->buf.memory_used = 0; } -/** - * tty_buffer_alloc - allocate a tty buffer - * @tty: tty device - * @size: desired size (characters) - * - * Allocate a new tty buffer to hold the desired number of characters. - * Return NULL if out of memory or the allocation would exceed the - * per device queue - * - * Locking: Caller must hold tty->buf.lock - */ - -static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size) +static struct tty_buffer *tty_buffer_alloc(size_t size) { - struct tty_buffer *p; - - if (tty->buf.memory_used + size > 65536) - return NULL; - p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); + struct tty_buffer *p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); if(p == NULL) return NULL; p->used = 0; @@ -348,27 +269,17 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size) p->read = 0; p->char_buf_ptr = (char *)(p->data); p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; - tty->buf.memory_used += size; +/* printk("Flip create %p\n", p); */ return p; } -/** - * tty_buffer_free - free a tty buffer - * @tty: tty owning the buffer - * @b: the buffer to free - * - * Free a tty buffer, or add it to the free list according to our - * internal strategy - * - * Locking: Caller must hold tty->buf.lock - */ +/* Must be called with the tty_read lock held. This needs to acquire strategy + code to decide if we should kfree or relink a given expired buffer */ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) { /* Dumb strategy for now - should keep some stats */ - tty->buf.memory_used -= b->size; - WARN_ON(tty->buf.memory_used < 0); - +/* printk("Flip dispose %p\n", b); */ if(b->size >= 512) kfree(b); else { @@ -377,18 +288,6 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) } } -/** - * tty_buffer_find - find a free tty buffer - * @tty: tty owning the buffer - * @size: characters wanted - * - * Locate an existing suitable tty buffer or if we are lacking one then - * allocate a new one. We round our buffers off in 256 character chunks - * to get better allocation behaviour. - * - * Locking: Caller must hold tty->buf.lock - */ - static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) { struct tty_buffer **tbh = &tty->buf.free; @@ -400,28 +299,20 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) t->used = 0; t->commit = 0; t->read = 0; - tty->buf.memory_used += t->size; + /* DEBUG ONLY */ +/* memset(t->data, '*', size); */ +/* printk("Flip recycle %p\n", t); */ return t; } tbh = &((*tbh)->next); } /* Round the buffer size out */ size = (size + 0xFF) & ~ 0xFF; - return tty_buffer_alloc(tty, size); + return tty_buffer_alloc(size); /* Should possibly check if this fails for the largest buffer we have queued and recycle that ? */ } -/** - * tty_buffer_request_room - grow tty buffer if needed - * @tty: tty structure - * @size: size desired - * - * Make at least size bytes of linear space available for the tty - * buffer. If we fail return the size we managed to find. - * - * Locking: Takes tty->buf.lock - */ int tty_buffer_request_room(struct tty_struct *tty, size_t size) { struct tty_buffer *b, *n; @@ -456,18 +347,6 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) } EXPORT_SYMBOL_GPL(tty_buffer_request_room); -/** - * tty_insert_flip_string - Add characters to the tty buffer - * @tty: tty structure - * @chars: characters - * @size: size - * - * Queue a series of bytes to the tty buffering. All the characters - * passed are marked as without error. Returns the number added. - * - * Locking: Called functions may take tty->buf.lock - */ - int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size) { @@ -491,20 +370,6 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, } EXPORT_SYMBOL(tty_insert_flip_string); -/** - * tty_insert_flip_string_flags - Add characters to the tty buffer - * @tty: tty structure - * @chars: characters - * @flags: flag bytes - * @size: size - * - * Queue a series of bytes to the tty buffering. For each character - * the flags array indicates the status of the character. Returns the - * number added. - * - * Locking: Called functions may take tty->buf.lock - */ - int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size) { @@ -529,17 +394,6 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, } EXPORT_SYMBOL(tty_insert_flip_string_flags); -/** - * tty_schedule_flip - push characters to ldisc - * @tty: tty to push from - * - * Takes any pending buffers and transfers their ownership to the - * ldisc side of the queue. It then schedules those characters for - * processing by the line discipline. - * - * Locking: Takes tty->buf.lock - */ - void tty_schedule_flip(struct tty_struct *tty) { unsigned long flags; @@ -551,19 +405,12 @@ void tty_schedule_flip(struct tty_struct *tty) } EXPORT_SYMBOL(tty_schedule_flip); -/** - * tty_prepare_flip_string - make room for characters - * @tty: tty - * @chars: return pointer for character write area - * @size: desired size - * +/* * Prepare a block of space in the buffer for data. Returns the length * available and buffer pointer to the space which is now allocated and * accounted for as ready for normal characters. This is used for drivers * that need their own block copy routines into the buffer. There is no * guarantee the buffer is a DMA target! - * - * Locking: May call functions taking tty->buf.lock */ int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size) @@ -580,20 +427,12 @@ int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_ EXPORT_SYMBOL_GPL(tty_prepare_flip_string); -/** - * tty_prepare_flip_string_flags - make room for characters - * @tty: tty - * @chars: return pointer for character write area - * @flags: return pointer for status flag write area - * @size: desired size - * +/* * Prepare a block of space in the buffer for data. Returns the length * available and buffer pointer to the space which is now allocated and * accounted for as ready for characters. This is used for drivers * that need their own block copy routines into the buffer. There is no * guarantee the buffer is a DMA target! - * - * Locking: May call functions taking tty->buf.lock */ int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size) @@ -612,16 +451,10 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); -/** - * tty_set_termios_ldisc - set ldisc field - * @tty: tty structure - * @num: line discipline number - * +/* * This is probably overkill for real world processors but * they are not on hot paths so a little discipline won't do * any harm. - * - * Locking: takes termios_sem */ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) @@ -641,19 +474,6 @@ static DEFINE_SPINLOCK(tty_ldisc_lock); static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ -/** - * tty_register_ldisc - install a line discipline - * @disc: ldisc number - * @new_ldisc: pointer to the ldisc object - * - * Installs a new line discipline into the kernel. The discipline - * is set up as unreferenced and then made available to the kernel - * from this point onwards. - * - * Locking: - * takes tty_ldisc_lock to guard against ldisc races - */ - int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) { unsigned long flags; @@ -673,18 +493,6 @@ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) } EXPORT_SYMBOL(tty_register_ldisc); -/** - * tty_unregister_ldisc - unload a line discipline - * @disc: ldisc number - * @new_ldisc: pointer to the ldisc object - * - * Remove a line discipline from the kernel providing it is not - * currently in use. - * - * Locking: - * takes tty_ldisc_lock to guard against ldisc races - */ - int tty_unregister_ldisc(int disc) { unsigned long flags; @@ -704,19 +512,6 @@ int tty_unregister_ldisc(int disc) } EXPORT_SYMBOL(tty_unregister_ldisc); -/** - * tty_ldisc_get - take a reference to an ldisc - * @disc: ldisc number - * - * Takes a reference to a line discipline. Deals with refcounts and - * module locking counts. Returns NULL if the discipline is not available. - * Returns a pointer to the discipline and bumps the ref count if it is - * available - * - * Locking: - * takes tty_ldisc_lock to guard against ldisc races - */ - struct tty_ldisc *tty_ldisc_get(int disc) { unsigned long flags; @@ -745,17 +540,6 @@ struct tty_ldisc *tty_ldisc_get(int disc) EXPORT_SYMBOL_GPL(tty_ldisc_get); -/** - * tty_ldisc_put - drop ldisc reference - * @disc: ldisc number - * - * Drop a reference to a line discipline. Manage refcounts and - * module usage counts - * - * Locking: - * takes tty_ldisc_lock to guard against ldisc races - */ - void tty_ldisc_put(int disc) { struct tty_ldisc *ld; @@ -773,19 +557,6 @@ void tty_ldisc_put(int disc) EXPORT_SYMBOL_GPL(tty_ldisc_put); -/** - * tty_ldisc_assign - set ldisc on a tty - * @tty: tty to assign - * @ld: line discipline - * - * Install an instance of a line discipline into a tty structure. The - * ldisc must have a reference count above zero to ensure it remains/ - * The tty instance refcount starts at zero. - * - * Locking: - * Caller must hold references - */ - static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) { tty->ldisc = *ld; @@ -800,8 +571,6 @@ static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) * the tty ldisc. Return 0 on failure or 1 on success. This is * used to implement both the waiting and non waiting versions * of tty_ldisc_ref - * - * Locking: takes tty_ldisc_lock */ static int tty_ldisc_try(struct tty_struct *tty) @@ -833,8 +602,6 @@ static int tty_ldisc_try(struct tty_struct *tty) * must also be careful not to hold other locks that will deadlock * against a discipline change, such as an existing ldisc reference * (which we check for) - * - * Locking: call functions take tty_ldisc_lock */ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) @@ -855,8 +622,6 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); * Dereference the line discipline for the terminal and take a * reference to it. If the line discipline is in flux then * return NULL. Can be called from IRQ and timer functions. - * - * Locking: called functions take tty_ldisc_lock */ struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) @@ -874,8 +639,6 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref); * * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May * be called in IRQ context. - * - * Locking: takes tty_ldisc_lock */ void tty_ldisc_deref(struct tty_ldisc *ld) @@ -920,9 +683,6 @@ static void tty_ldisc_enable(struct tty_struct *tty) * * Set the discipline of a tty line. Must be called from a process * context. - * - * Locking: takes tty_ldisc_lock. - * called functions take termios_sem */ static int tty_set_ldisc(struct tty_struct *tty, int ldisc) @@ -1086,17 +846,9 @@ static int tty_set_ldisc(struct tty_struct *tty, int ldisc) return retval; } -/** - * get_tty_driver - find device of a tty - * @dev_t: device identifier - * @index: returns the index of the tty - * - * This routine returns a tty driver structure, given a device number - * and also passes back the index number. - * - * Locking: caller must hold tty_mutex +/* + * This routine returns a tty driver structure, given a device number */ - static struct tty_driver *get_tty_driver(dev_t device, int *index) { struct tty_driver *p; @@ -1111,17 +863,11 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index) return NULL; } -/** - * tty_check_change - check for POSIX terminal changes - * @tty: tty to check - * - * If we try to write to, or set the state of, a terminal and we're - * not in the foreground, send a SIGTTOU. If the signal is blocked or - * ignored, go ahead and perform the operation. (POSIX 7.2) - * - * Locking: none +/* + * If we try to write to, or set the state of, a terminal and we're + * not in the foreground, send a SIGTTOU. If the signal is blocked or + * ignored, go ahead and perform the operation. (POSIX 7.2) */ - int tty_check_change(struct tty_struct * tty) { if (current->signal->tty != tty) @@ -1259,27 +1005,10 @@ void tty_ldisc_flush(struct tty_struct *tty) EXPORT_SYMBOL_GPL(tty_ldisc_flush); -/** - * do_tty_hangup - actual handler for hangup events - * @data: tty device - * - * This can be called by the "eventd" kernel thread. That is process - * synchronous but doesn't hold any locks, so we need to make sure we - * have the appropriate locks for what we're doing. - * - * The hangup event clears any pending redirections onto the hung up - * device. It ensures future writes will error and it does the needed - * line discipline hangup and signal delivery. The tty object itself - * remains intact. - * - * Locking: - * BKL - * redirect lock for undoing redirection - * file list lock for manipulating list of ttys - * tty_ldisc_lock from called functions - * termios_sem resetting termios data - * tasklist_lock to walk task list for hangup event - * +/* + * This can be called by the "eventd" kernel thread. That is process synchronous, + * but doesn't hold any locks, so we need to make sure we have the appropriate + * locks for what we're doing.. */ static void do_tty_hangup(void *data) { @@ -1404,14 +1133,6 @@ static void do_tty_hangup(void *data) fput(f); } -/** - * tty_hangup - trigger a hangup event - * @tty: tty to hangup - * - * A carrier loss (virtual or otherwise) has occurred on this like - * schedule a hangup sequence to run after this event. - */ - void tty_hangup(struct tty_struct * tty) { #ifdef TTY_DEBUG_HANGUP @@ -1424,15 +1145,6 @@ void tty_hangup(struct tty_struct * tty) EXPORT_SYMBOL(tty_hangup); -/** - * tty_vhangup - process vhangup - * @tty: tty to hangup - * - * The user has asked via system call for the terminal to be hung up. - * We do this synchronously so that when the syscall returns the process - * is complete. That guarantee is neccessary for security reasons. - */ - void tty_vhangup(struct tty_struct * tty) { #ifdef TTY_DEBUG_HANGUP @@ -1444,14 +1156,6 @@ void tty_vhangup(struct tty_struct * tty) } EXPORT_SYMBOL(tty_vhangup); -/** - * tty_hung_up_p - was tty hung up - * @filp: file pointer of tty - * - * Return true if the tty has been subject to a vhangup or a carrier - * loss - */ - int tty_hung_up_p(struct file * filp) { return (filp->f_op == &hung_up_tty_fops); @@ -1459,28 +1163,19 @@ int tty_hung_up_p(struct file * filp) EXPORT_SYMBOL(tty_hung_up_p); -/** - * disassociate_ctty - disconnect controlling tty - * @on_exit: true if exiting so need to "hang up" the session - * - * This function is typically called only by the session leader, when - * it wants to disassociate itself from its controlling tty. +/* + * This function is typically called only by the session leader, when + * it wants to disassociate itself from its controlling tty. * - * It performs the following functions: + * It performs the following functions: * (1) Sends a SIGHUP and SIGCONT to the foreground process group * (2) Clears the tty from being controlling the session * (3) Clears the controlling tty for all processes in the * session group. * - * The argument on_exit is set to 1 if called when a process is - * exiting; it is 0 if called by the ioctl TIOCNOTTY. - * - * Locking: tty_mutex is taken to protect current->signal->tty - * BKL is taken for hysterical raisins - * Tasklist lock is taken (under tty_mutex) to walk process - * lists for the session. + * The argument on_exit is set to 1 if called when a process is + * exiting; it is 0 if called by the ioctl TIOCNOTTY. */ - void disassociate_ctty(int on_exit) { struct tty_struct *tty; @@ -1527,25 +1222,6 @@ void disassociate_ctty(int on_exit) unlock_kernel(); } - -/** - * stop_tty - propogate flow control - * @tty: tty to stop - * - * Perform flow control to the driver. For PTY/TTY pairs we - * must also propogate the TIOCKPKT status. May be called - * on an already stopped device and will not re-call the driver - * method. - * - * This functionality is used by both the line disciplines for - * halting incoming flow and by the driver. It may therefore be - * called from any context, may be under the tty atomic_write_lock - * but not always. - * - * Locking: - * Broken. Relies on BKL which is unsafe here. - */ - void stop_tty(struct tty_struct *tty) { if (tty->stopped) @@ -1562,19 +1238,6 @@ void stop_tty(struct tty_struct *tty) EXPORT_SYMBOL(stop_tty); -/** - * start_tty - propogate flow control - * @tty: tty to start - * - * Start a tty that has been stopped if at all possible. Perform - * any neccessary wakeups and propogate the TIOCPKT status. If this - * is the tty was previous stopped and is being started then the - * driver start method is invoked and the line discipline woken. - * - * Locking: - * Broken. Relies on BKL which is unsafe here. - */ - void start_tty(struct tty_struct *tty) { if (!tty->stopped || tty->flow_stopped) @@ -1595,23 +1258,6 @@ void start_tty(struct tty_struct *tty) EXPORT_SYMBOL(start_tty); -/** - * tty_read - read method for tty device files - * @file: pointer to tty file - * @buf: user buffer - * @count: size of user buffer - * @ppos: unused - * - * Perform the read system call function on this terminal device. Checks - * for hung up devices before calling the line discipline method. - * - * Locking: - * Locks the line discipline internally while needed - * For historical reasons the line discipline read method is - * invoked under the BKL. This will go away in time so do not rely on it - * in new code. Multiple read calls may be outstanding in parallel. - */ - static ssize_t tty_read(struct file * file, char __user * buf, size_t count, loff_t *ppos) { @@ -1656,7 +1302,6 @@ static inline ssize_t do_tty_write( ssize_t ret = 0, written = 0; unsigned int chunk; - /* FIXME: O_NDELAY ... */ if (mutex_lock_interruptible(&tty->atomic_write_lock)) { return -ERESTARTSYS; } @@ -1673,9 +1318,6 @@ static inline ssize_t do_tty_write( * layer has problems with bigger chunks. It will * claim to be able to handle more characters than * it actually does. - * - * FIXME: This can probably go away now except that 64K chunks - * are too likely to fail unless switched to vmalloc... */ chunk = 2048; if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags)) @@ -1733,24 +1375,6 @@ static inline ssize_t do_tty_write( } -/** - * tty_write - write method for tty device file - * @file: tty file pointer - * @buf: user data to write - * @count: bytes to write - * @ppos: unused - * - * Write data to a tty device via the line discipline. - * - * Locking: - * Locks the line discipline as required - * Writes to the tty driver are serialized by the atomic_write_lock - * and are then processed in chunks to the device. The line discipline - * write method will not be involked in parallel for each device - * The line discipline write method is called under the big - * kernel lock for historical reasons. New code should not rely on this. - */ - static ssize_t tty_write(struct file * file, const char __user * buf, size_t count, loff_t *ppos) { @@ -1798,18 +1422,7 @@ ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t static char ptychar[] = "pqrstuvwxyzabcde"; -/** - * pty_line_name - generate name for a pty - * @driver: the tty driver in use - * @index: the minor number - * @p: output buffer of at least 6 bytes - * - * Generate a name from a driver reference and write it to the output - * buffer. - * - * Locking: None - */ -static void pty_line_name(struct tty_driver *driver, int index, char *p) +static inline void pty_line_name(struct tty_driver *driver, int index, char *p) { int i = index + driver->name_base; /* ->name is initialized to "ttyp", but "tty" is expected */ @@ -1818,53 +1431,24 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p) ptychar[i >> 4 & 0xf], i & 0xf); } -/** - * pty_line_name - generate name for a tty - * @driver: the tty driver in use - * @index: the minor number - * @p: output buffer of at least 7 bytes - * - * Generate a name from a driver reference and write it to the output - * buffer. - * - * Locking: None - */ -static void tty_line_name(struct tty_driver *driver, int index, char *p) +static inline void tty_line_name(struct tty_driver *driver, int index, char *p) { sprintf(p, "%s%d", driver->name, index + driver->name_base); } -/** - * init_dev - initialise a tty device - * @driver: tty driver we are opening a device on - * @idx: device index - * @tty: returned tty structure - * - * Prepare a tty device. This may not be a "new" clean device but - * could also be an active device. The pty drivers require special - * handling because of this. - * - * Locking: - * The function is called under the tty_mutex, which - * protects us from the tty struct or driver itself going away. - * - * On exit the tty device has the line discipline attached and - * a reference count of 1. If a pair was created for pty/tty use - * and the other was a pty master then it too has a reference count of 1. - * +/* * WSH 06/09/97: Rewritten to remove races and properly clean up after a * failed open. The new code protects the open with a mutex, so it's * really quite straightforward. The mutex locking can probably be * relaxed for the (most common) case of reopening a tty. */ - static int init_dev(struct tty_driver *driver, int idx, struct tty_struct **ret_tty) { struct tty_struct *tty, *o_tty; struct termios *tp, **tp_loc, *o_tp, **o_tp_loc; struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; - int retval = 0; + int retval=0; /* check whether we're reopening an existing tty */ if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { @@ -2078,20 +1662,10 @@ static int init_dev(struct tty_driver *driver, int idx, goto end_init; } -/** - * release_mem - release tty structure memory - * - * Releases memory associated with a tty structure, and clears out the - * driver table slots. This function is called when a device is no longer - * in use. It also gets called when setup of a device fails. - * - * Locking: - * tty_mutex - sometimes only - * takes the file list lock internally when working on the list - * of ttys that the driver keeps. - * FIXME: should we require tty_mutex is held here ?? +/* + * Releases memory associated with a tty structure, and clears out the + * driver table slots. */ - static void release_mem(struct tty_struct *tty, int idx) { struct tty_struct *o_tty; @@ -2432,27 +2006,18 @@ static void release_dev(struct file * filp) } -/** - * tty_open - open a tty device - * @inode: inode of device file - * @filp: file pointer to tty - * - * tty_open and tty_release keep up the tty count that contains the - * number of opens done on a tty. We cannot use the inode-count, as - * different inodes might point to the same tty. - * - * Open-counting is needed for pty masters, as well as for keeping - * track of serial lines: DTR is dropped when the last close happens. - * (This is not done solely through tty->count, now. - Ted 1/27/92) +/* + * tty_open and tty_release keep up the tty count that contains the + * number of opens done on a tty. We cannot use the inode-count, as + * different inodes might point to the same tty. * - * The termios state of a pty is reset on first open so that - * settings don't persist across reuse. + * Open-counting is needed for pty masters, as well as for keeping + * track of serial lines: DTR is dropped when the last close happens. + * (This is not done solely through tty->count, now. - Ted 1/27/92) * - * Locking: tty_mutex protects current->signal->tty, get_tty_driver and - * init_dev work. tty->count should protect the rest. - * task_lock is held to update task details for sessions + * The termios state of a pty is reset on first open so that + * settings don't persist across reuse. */ - static int tty_open(struct inode * inode, struct file * filp) { struct tty_struct *tty; @@ -2567,18 +2132,6 @@ static int tty_open(struct inode * inode, struct file * filp) } #ifdef CONFIG_UNIX98_PTYS -/** - * ptmx_open - open a unix 98 pty master - * @inode: inode of device file - * @filp: file pointer to tty - * - * Allocate a unix98 pty master device from the ptmx driver. - * - * Locking: tty_mutex protects theinit_dev work. tty->count should - protect the rest. - * allocated_ptys_lock handles the list of free pty numbers - */ - static int ptmx_open(struct inode * inode, struct file * filp) { struct tty_struct *tty; @@ -2638,18 +2191,6 @@ static int ptmx_open(struct inode * inode, struct file * filp) } #endif -/** - * tty_release - vfs callback for close - * @inode: inode of tty - * @filp: file pointer for handle to tty - * - * Called the last time each file handle is closed that references - * this tty. There may however be several such references. - * - * Locking: - * Takes bkl. See release_dev - */ - static int tty_release(struct inode * inode, struct file * filp) { lock_kernel(); @@ -2658,18 +2199,7 @@ static int tty_release(struct inode * inode, struct file * filp) return 0; } -/** - * tty_poll - check tty status - * @filp: file being polled - * @wait: poll wait structures to update - * - * Call the line discipline polling method to obtain the poll - * status of the device. - * - * Locking: locks called line discipline but ldisc poll method - * may be re-entered freely by other callers. - */ - +/* No kernel lock held - fine */ static unsigned int tty_poll(struct file * filp, poll_table * wait) { struct tty_struct * tty; @@ -2713,21 +2243,6 @@ static int tty_fasync(int fd, struct file * filp, int on) return 0; } -/** - * tiocsti - fake input character - * @tty: tty to fake input into - * @p: pointer to character - * - * Fake input to a tty device. Does the neccessary locking and - * input management. - * - * FIXME: does not honour flow control ?? - * - * Locking: - * Called functions take tty_ldisc_lock - * current->signal->tty check is safe without locks - */ - static int tiocsti(struct tty_struct *tty, char __user *p) { char ch, mbz = 0; @@ -2743,18 +2258,6 @@ static int tiocsti(struct tty_struct *tty, char __user *p) return 0; } -/** - * tiocgwinsz - implement window query ioctl - * @tty; tty - * @arg: user buffer for result - * - * Copies the kernel idea of the window size into the user buffer. No - * locking is done. - * - * FIXME: Returning random values racing a window size set is wrong - * should lock here against that - */ - static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg) { if (copy_to_user(arg, &tty->winsize, sizeof(*arg))) @@ -2762,24 +2265,6 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg) return 0; } -/** - * tiocswinsz - implement window size set ioctl - * @tty; tty - * @arg: user buffer for result - * - * Copies the user idea of the window size to the kernel. Traditionally - * this is just advisory information but for the Linux console it - * actually has driver level meaning and triggers a VC resize. - * - * Locking: - * The console_sem is used to ensure we do not try and resize - * the console twice at once. - * FIXME: Two racing size sets may leave the console and kernel - * parameters disagreeing. Is this exploitable ? - * FIXME: Random values racing a window size get is wrong - * should lock here against that - */ - static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, struct winsize __user * arg) { @@ -2809,15 +2294,6 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty, return 0; } -/** - * tioccons - allow admin to move logical console - * @file: the file to become console - * - * Allow the adminstrator to move the redirected console device - * - * Locking: uses redirect_lock to guard the redirect information - */ - static int tioccons(struct file *file) { if (!capable(CAP_SYS_ADMIN)) @@ -2843,17 +2319,6 @@ static int tioccons(struct file *file) return 0; } -/** - * fionbio - non blocking ioctl - * @file: file to set blocking value - * @p: user parameter - * - * Historical tty interfaces had a blocking control ioctl before - * the generic functionality existed. This piece of history is preserved - * in the expected tty API of posix OS's. - * - * Locking: none, the open fle handle ensures it won't go away. - */ static int fionbio(struct file *file, int __user *p) { @@ -2869,23 +2334,6 @@ static int fionbio(struct file *file, int __user *p) return 0; } -/** - * tiocsctty - set controlling tty - * @tty: tty structure - * @arg: user argument - * - * This ioctl is used to manage job control. It permits a session - * leader to set this tty as the controlling tty for the session. - * - * Locking: - * Takes tasklist lock internally to walk sessions - * Takes task_lock() when updating signal->tty - * - * FIXME: tty_mutex is needed to protect signal->tty references. - * FIXME: why task_lock on the signal->tty reference ?? - * - */ - static int tiocsctty(struct tty_struct *tty, int arg) { struct task_struct *p; @@ -2926,18 +2374,6 @@ static int tiocsctty(struct tty_struct *tty, int arg) return 0; } -/** - * tiocgpgrp - get process group - * @tty: tty passed by user - * @real_tty: tty side of the tty pased by the user if a pty else the tty - * @p: returned pid - * - * Obtain the process group of the tty. If there is no process group - * return an error. - * - * Locking: none. Reference to ->signal->tty is safe. - */ - static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) { /* @@ -2949,20 +2385,6 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t return put_user(real_tty->pgrp, p); } -/** - * tiocspgrp - attempt to set process group - * @tty: tty passed by user - * @real_tty: tty side device matching tty passed by user - * @p: pid pointer - * - * Set the process group of the tty to the session passed. Only - * permitted where the tty session is our session. - * - * Locking: None - * - * FIXME: current->signal->tty referencing is unsafe. - */ - static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) { pid_t pgrp; @@ -2986,18 +2408,6 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t return 0; } -/** - * tiocgsid - get session id - * @tty: tty passed by user - * @real_tty: tty side of the tty pased by the user if a pty else the tty - * @p: pointer to returned session id - * - * Obtain the session id of the tty. If there is no session - * return an error. - * - * Locking: none. Reference to ->signal->tty is safe. - */ - static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) { /* @@ -3011,16 +2421,6 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _ return put_user(real_tty->session, p); } -/** - * tiocsetd - set line discipline - * @tty: tty device - * @p: pointer to user data - * - * Set the line discipline according to user request. - * - * Locking: see tty_set_ldisc, this function is just a helper - */ - static int tiocsetd(struct tty_struct *tty, int __user *p) { int ldisc; @@ -3030,21 +2430,6 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) return tty_set_ldisc(tty, ldisc); } -/** - * send_break - performed time break - * @tty: device to break on - * @duration: timeout in mS - * - * Perform a timed break on hardware that lacks its own driver level - * timed break functionality. - * - * Locking: - * None - * - * FIXME: - * What if two overlap - */ - static int send_break(struct tty_struct *tty, unsigned int duration) { tty->driver->break_ctl(tty, -1); @@ -3057,19 +2442,8 @@ static int send_break(struct tty_struct *tty, unsigned int duration) return 0; } -/** - * tiocmget - get modem status - * @tty: tty device - * @file: user file pointer - * @p: pointer to result - * - * Obtain the modem status bits from the tty driver if the feature - * is supported. Return -EINVAL if it is not available. - * - * Locking: none (up to the driver) - */ - -static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p) +static int +tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p) { int retval = -EINVAL; @@ -3082,20 +2456,8 @@ static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p return retval; } -/** - * tiocmset - set modem status - * @tty: tty device - * @file: user file pointer - * @cmd: command - clear bits, set bits or set all - * @p: pointer to desired bits - * - * Set the modem status bits from the tty driver if the feature - * is supported. Return -EINVAL if it is not available. - * - * Locking: none (up to the driver) - */ - -static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd, +static int +tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned __user *p) { int retval = -EINVAL; @@ -3211,7 +2573,6 @@ int tty_ioctl(struct inode * inode, struct file * file, clear_bit(TTY_EXCLUSIVE, &tty->flags); return 0; case TIOCNOTTY: - /* FIXME: taks lock or tty_mutex ? */ if (current->signal->tty != tty) return -ENOTTY; if (current->signal->leader) @@ -3392,16 +2753,9 @@ void do_SAK(struct tty_struct *tty) EXPORT_SYMBOL(do_SAK); -/** - * flush_to_ldisc - * @private_: tty structure passed from work queue. - * - * This routine is called out of the software interrupt to flush data - * from the buffer chain to the line discipline. - * - * Locking: holds tty->buf.lock to guard buffer list. Drops the lock - * while invoking the line discipline receive_buf method. The - * receive_buf method is single threaded for each tty instance. +/* + * This routine is called out of the software interrupt to flush data + * from the buffer chain to the line discipline. */ static void flush_to_ldisc(void *private_) @@ -3477,8 +2831,6 @@ static int n_baud_table = ARRAY_SIZE(baud_table); * Convert termios baud rate data into a speed. This should be called * with the termios lock held if this termios is a terminal termios * structure. May change the termios data. - * - * Locking: none */ int tty_termios_baud_rate(struct termios *termios) @@ -3507,8 +2859,6 @@ EXPORT_SYMBOL(tty_termios_baud_rate); * Returns the baud rate as an integer for this terminal. The * termios lock must be held by the caller and the terminal bit * flags may be updated. - * - * Locking: none */ int tty_get_baud_rate(struct tty_struct *tty) @@ -3538,8 +2888,6 @@ EXPORT_SYMBOL(tty_get_baud_rate); * * In the event of the queue being busy for flipping the work will be * held off and retried later. - * - * Locking: tty buffer lock. Driver locks in low latency mode. */ void tty_flip_buffer_push(struct tty_struct *tty) @@ -3559,16 +2907,9 @@ void tty_flip_buffer_push(struct tty_struct *tty) EXPORT_SYMBOL(tty_flip_buffer_push); -/** - * initialize_tty_struct - * @tty: tty to initialize - * - * This subroutine initializes a tty structure that has been newly - * allocated. - * - * Locking: none - tty in question must not be exposed at this point +/* + * This subroutine initializes a tty structure. */ - static void initialize_tty_struct(struct tty_struct *tty) { memset(tty, 0, sizeof(struct tty_struct)); @@ -3594,7 +2935,6 @@ static void initialize_tty_struct(struct tty_struct *tty) /* * The default put_char routine if the driver did not define one. */ - static void tty_default_put_char(struct tty_struct *tty, unsigned char ch) { tty->driver->write(tty, &ch, 1); @@ -3603,23 +2943,19 @@ static void tty_default_put_char(struct tty_struct *tty, unsigned char ch) static struct class *tty_class; /** - * tty_register_device - register a tty device - * @driver: the tty driver that describes the tty device - * @index: the index in the tty driver for this tty device - * @device: a struct device that is associated with this tty device. - * This field is optional, if there is no known struct device - * for this tty device it can be set to NULL safely. + * tty_register_device - register a tty device + * @driver: the tty driver that describes the tty device + * @index: the index in the tty driver for this tty device + * @device: a struct device that is associated with this tty device. + * This field is optional, if there is no known struct device for this + * tty device it can be set to NULL safely. * - * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error). + * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error). * - * This call is required to be made to register an individual tty device - * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If - * that bit is not set, this function should not be called by a tty - * driver. - * - * Locking: ?? + * This call is required to be made to register an individual tty device if + * the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If that + * bit is not set, this function should not be called by a tty driver. */ - struct class_device *tty_register_device(struct tty_driver *driver, unsigned index, struct device *device) { @@ -3641,16 +2977,13 @@ struct class_device *tty_register_device(struct tty_driver *driver, } /** - * tty_unregister_device - unregister a tty device - * @driver: the tty driver that describes the tty device - * @index: the index in the tty driver for this tty device + * tty_unregister_device - unregister a tty device + * @driver: the tty driver that describes the tty device + * @index: the index in the tty driver for this tty device * - * If a tty device is registered with a call to tty_register_device() then - * this function must be called when the tty device is gone. - * - * Locking: ?? + * If a tty device is registered with a call to tty_register_device() then + * this function must be made when the tty device is gone. */ - void tty_unregister_device(struct tty_driver *driver, unsigned index) { class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index); @@ -3761,6 +3094,7 @@ int tty_register_driver(struct tty_driver *driver) driver->cdev.owner = driver->owner; error = cdev_add(&driver->cdev, dev, driver->num); if (error) { + cdev_del(&driver->cdev); unregister_chrdev_region(dev, driver->num); driver->ttys = NULL; driver->termios = driver->termios_locked = NULL; diff --git a/trunk/drivers/char/tty_ioctl.c b/trunk/drivers/char/tty_ioctl.c index 4ad47d321bd4..f19cf9d7792d 100644 --- a/trunk/drivers/char/tty_ioctl.c +++ b/trunk/drivers/char/tty_ioctl.c @@ -36,18 +36,6 @@ #define TERMIOS_WAIT 2 #define TERMIOS_TERMIO 4 - -/** - * tty_wait_until_sent - wait for I/O to finish - * @tty: tty we are waiting for - * @timeout: how long we will wait - * - * Wait for characters pending in a tty driver to hit the wire, or - * for a timeout to occur (eg due to flow control) - * - * Locking: none - */ - void tty_wait_until_sent(struct tty_struct * tty, long timeout) { DECLARE_WAITQUEUE(wait, current); @@ -106,18 +94,6 @@ static void unset_locked_termios(struct termios *termios, old->c_cc[i] : termios->c_cc[i]; } -/** - * change_termios - update termios values - * @tty: tty to update - * @new_termios: desired new value - * - * Perform updates to the termios values set on this terminal. There - * is a bit of layering violation here with n_tty in terms of the - * internal knowledge of this function. - * - * Locking: termios_sem - */ - static void change_termios(struct tty_struct * tty, struct termios * new_termios) { int canon_change; @@ -179,19 +155,6 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios up(&tty->termios_sem); } -/** - * set_termios - set termios values for a tty - * @tty: terminal device - * @arg: user data - * @opt: option information - * - * Helper function to prepare termios data and run neccessary other - * functions before using change_termios to do the actual changes. - * - * Locking: - * Called functions take ldisc and termios_sem locks - */ - static int set_termios(struct tty_struct * tty, void __user *arg, int opt) { struct termios tmp_termios; @@ -321,17 +284,6 @@ static void set_sgflags(struct termios * termios, int flags) } } -/** - * set_sgttyb - set legacy terminal values - * @tty: tty structure - * @sgttyb: pointer to old style terminal structure - * - * Updates a terminal from the legacy BSD style terminal information - * structure. - * - * Locking: termios_sem - */ - static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) { int retval; @@ -417,16 +369,9 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars) } #endif -/** - * send_prio_char - send priority character - * - * Send a high priority character to the tty even if stopped - * - * Locking: none - * - * FIXME: overlapping calls with start/stop tty lose state of tty +/* + * Send a high priority character to the tty. */ - static void send_prio_char(struct tty_struct *tty, char ch) { int was_stopped = tty->stopped; diff --git a/trunk/drivers/char/viocons.c b/trunk/drivers/char/viocons.c index f3efeaf2826e..766f7864c6c6 100644 --- a/trunk/drivers/char/viocons.c +++ b/trunk/drivers/char/viocons.c @@ -43,6 +43,7 @@ #include #include + #include #include #include @@ -66,6 +67,35 @@ static int vio_sysrq_pressed; extern int sysrq_enabled; #endif +/* + * The structure of the events that flow between us and OS/400. You can't + * mess with this unless the OS/400 side changes too + */ +struct viocharlpevent { + struct HvLpEvent event; + u32 reserved; + u16 version; + u16 subtype_result_code; + u8 virtual_device; + u8 len; + u8 data[VIOCHAR_MAX_DATA]; +}; + +#define VIOCHAR_WINDOW 10 +#define VIOCHAR_HIGHWATERMARK 3 + +enum viocharsubtype { + viocharopen = 0x0001, + viocharclose = 0x0002, + viochardata = 0x0003, + viocharack = 0x0004, + viocharconfig = 0x0005 +}; + +enum viochar_rc { + viochar_rc_ebusy = 1 +}; + #define VIOCHAR_NUM_BUF 16 /* @@ -1153,7 +1183,6 @@ static int __init viocons_init(void) port_info[i].magic = VIOTTY_MAGIC; } HvCall_setLogBufferFormatAndCodepage(HvCall_LogBuffer_ASCII, 437); - add_preferred_console("viocons", 0, NULL); register_console(&viocons_early); return 0; } diff --git a/trunk/drivers/char/viotape.c b/trunk/drivers/char/viotape.c index 73c78bf75d7f..b72b2049aaae 100644 --- a/trunk/drivers/char/viotape.c +++ b/trunk/drivers/char/viotape.c @@ -940,6 +940,7 @@ static void vioHandleTapeEvent(struct HvLpEvent *event) static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id) { + char tapename[32]; int i = vdev->unit_address; int j; @@ -955,9 +956,10 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id) "iseries!vt%d", i); class_device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), NULL, "iseries!nvt%d", i); - printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries " + sprintf(tapename, "iseries/vt%d", i); + printk(VIOTAPE_KERN_INFO "tape %s is iSeries " "resource %10.10s type %4.4s, model %3.3s\n", - i, viotape_unitinfo[i].rsrcname, + tapename, viotape_unitinfo[i].rsrcname, viotape_unitinfo[i].type, viotape_unitinfo[i].model); return 0; } diff --git a/trunk/drivers/char/vt_ioctl.c b/trunk/drivers/char/vt_ioctl.c index a5628a8b6620..eccffaf26faa 100644 --- a/trunk/drivers/char/vt_ioctl.c +++ b/trunk/drivers/char/vt_ioctl.c @@ -1011,8 +1011,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, return -EPERM; vt_dont_switch = 0; return 0; - case VT_GETHIFONTMASK: - return put_user(vc->vc_hi_font_mask, (unsigned short __user *)arg); default: return -ENOIOCTLCMD; } diff --git a/trunk/drivers/char/watchdog/Kconfig b/trunk/drivers/char/watchdog/Kconfig index fff89c2d88fd..d53f664a4dd8 100644 --- a/trunk/drivers/char/watchdog/Kconfig +++ b/trunk/drivers/char/watchdog/Kconfig @@ -45,7 +45,7 @@ config WATCHDOG_NOWAYOUT comment "Watchdog Device Drivers" depends on WATCHDOG -# Architecture Independent +# Architecture Independant config SOFT_WATCHDOG tristate "Software watchdog" @@ -127,7 +127,7 @@ config S3C2410_WATCHDOG enabled. The driver is limited by the speed of the system's PCLK - signal, so with reasonably fast systems (PCLK around 50-66MHz) + signal, so with reasonbaly fast systems (PCLK around 50-66MHz) then watchdog intervals of over approximately 20seconds are unavailable. @@ -423,7 +423,7 @@ config SBC_EPX_C3_WATCHDOG is no way to know if writing to its IO address will corrupt your system or have any real effect. The only way to be sure that this driver does what you want is to make sure you - are running it on an EPX-C3 from Winsystems with the watchdog + are runnning it on an EPX-C3 from Winsystems with the watchdog timer at IO address 0x1ee and 0x1ef. It will write to both those IO ports. Basically, the assumption is made that if you compile this driver into your kernel and/or load it as a module, that you @@ -472,7 +472,7 @@ config INDYDOG tristate "Indy/I2 Hardware Watchdog" depends on WATCHDOG && SGI_IP22 help - Hardware driver for the Indy's/I2's watchdog. This is a + Hardwaredriver for the Indy's/I2's watchdog. This is a watchdog timer that will reboot the machine after a 60 second timer expired and no process has written to /dev/watchdog during that time. diff --git a/trunk/drivers/char/watchdog/sbc8360.c b/trunk/drivers/char/watchdog/sbc8360.c index 41fc6f80c493..1035be5b5019 100644 --- a/trunk/drivers/char/watchdog/sbc8360.c +++ b/trunk/drivers/char/watchdog/sbc8360.c @@ -200,7 +200,7 @@ static int wd_margin = 0xB; static int wd_multiplier = 2; static int nowayout = WATCHDOG_NOWAYOUT; -module_param(timeout, int, 0); +module_param(timeout, int, 27); MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))"); module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, @@ -407,7 +407,7 @@ module_exit(sbc8360_exit); MODULE_AUTHOR("Ian E. Morgan "); MODULE_DESCRIPTION("SBC8360 watchdog driver"); MODULE_LICENSE("GPL"); -MODULE_VERSION("1.01"); +MODULE_VERSION("1.0"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); /* end of sbc8360.c */ diff --git a/trunk/drivers/connector/cn_proc.c b/trunk/drivers/connector/cn_proc.c index 3ece69231343..498aa37bca22 100644 --- a/trunk/drivers/connector/cn_proc.c +++ b/trunk/drivers/connector/cn_proc.c @@ -51,7 +51,6 @@ void proc_fork_connector(struct task_struct *task) struct cn_msg *msg; struct proc_event *ev; __u8 buffer[CN_PROC_MSG_SIZE]; - struct timespec ts; if (atomic_read(&proc_event_num_listeners) < 1) return; @@ -59,8 +58,7 @@ void proc_fork_connector(struct task_struct *task) msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - ev->timestamp_ns = timespec_to_ns(&ts); + ktime_get_ts(&ev->timestamp); /* get high res monotonic timestamp */ ev->what = PROC_EVENT_FORK; ev->event_data.fork.parent_pid = task->real_parent->pid; ev->event_data.fork.parent_tgid = task->real_parent->tgid; @@ -78,7 +76,6 @@ void proc_exec_connector(struct task_struct *task) { struct cn_msg *msg; struct proc_event *ev; - struct timespec ts; __u8 buffer[CN_PROC_MSG_SIZE]; if (atomic_read(&proc_event_num_listeners) < 1) @@ -87,8 +84,7 @@ void proc_exec_connector(struct task_struct *task) msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - ev->timestamp_ns = timespec_to_ns(&ts); + ktime_get_ts(&ev->timestamp); ev->what = PROC_EVENT_EXEC; ev->event_data.exec.process_pid = task->pid; ev->event_data.exec.process_tgid = task->tgid; @@ -104,7 +100,6 @@ void proc_id_connector(struct task_struct *task, int which_id) struct cn_msg *msg; struct proc_event *ev; __u8 buffer[CN_PROC_MSG_SIZE]; - struct timespec ts; if (atomic_read(&proc_event_num_listeners) < 1) return; @@ -123,8 +118,7 @@ void proc_id_connector(struct task_struct *task, int which_id) } else return; get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - ev->timestamp_ns = timespec_to_ns(&ts); + ktime_get_ts(&ev->timestamp); memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ @@ -137,7 +131,6 @@ void proc_exit_connector(struct task_struct *task) struct cn_msg *msg; struct proc_event *ev; __u8 buffer[CN_PROC_MSG_SIZE]; - struct timespec ts; if (atomic_read(&proc_event_num_listeners) < 1) return; @@ -145,8 +138,7 @@ void proc_exit_connector(struct task_struct *task) msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - ev->timestamp_ns = timespec_to_ns(&ts); + ktime_get_ts(&ev->timestamp); ev->what = PROC_EVENT_EXIT; ev->event_data.exit.process_pid = task->pid; ev->event_data.exit.process_tgid = task->tgid; @@ -172,7 +164,6 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) struct cn_msg *msg; struct proc_event *ev; __u8 buffer[CN_PROC_MSG_SIZE]; - struct timespec ts; if (atomic_read(&proc_event_num_listeners) < 1) return; @@ -180,8 +171,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; msg->seq = rcvd_seq; - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - ev->timestamp_ns = timespec_to_ns(&ts); + ktime_get_ts(&ev->timestamp); ev->cpu = -1; ev->what = PROC_EVENT_NONE; ev->event_data.ack.err = err; diff --git a/trunk/drivers/cpufreq/cpufreq.c b/trunk/drivers/cpufreq/cpufreq.c index d35a9f06ab7b..bc1088d9b379 100644 --- a/trunk/drivers/cpufreq/cpufreq.c +++ b/trunk/drivers/cpufreq/cpufreq.c @@ -32,7 +32,7 @@ #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg) /** - * The "cpufreq driver" - the arch- or hardware-dependent low + * The "cpufreq driver" - the arch- or hardware-dependend low * level driver of CPUFreq support, and its spinlock. This lock * also protects the cpufreq_cpu_data array. */ @@ -284,69 +284,39 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition); * SYSFS INTERFACE * *********************************************************************/ -static struct cpufreq_governor *__find_governor(const char *str_governor) -{ - struct cpufreq_governor *t; - - list_for_each_entry(t, &cpufreq_governor_list, governor_list) - if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) - return t; - - return NULL; -} - /** * cpufreq_parse_governor - parse a governor string */ static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor) { - int err = -EINVAL; - if (!cpufreq_driver) - goto out; - + return -EINVAL; if (cpufreq_driver->setpolicy) { if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { *policy = CPUFREQ_POLICY_PERFORMANCE; - err = 0; + return 0; } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { *policy = CPUFREQ_POLICY_POWERSAVE; - err = 0; + return 0; } - } else if (cpufreq_driver->target) { + return -EINVAL; + } else { struct cpufreq_governor *t; - mutex_lock(&cpufreq_governor_mutex); - - t = __find_governor(str_governor); - - if (t == NULL) { - char *name = kasprintf(GFP_KERNEL, "cpufreq_%s", str_governor); - - if (name) { - int ret; - + if (!cpufreq_driver || !cpufreq_driver->target) + goto out; + list_for_each_entry(t, &cpufreq_governor_list, governor_list) { + if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { + *governor = t; mutex_unlock(&cpufreq_governor_mutex); - ret = request_module(name); - mutex_lock(&cpufreq_governor_mutex); - - if (ret == 0) - t = __find_governor(str_governor); + return 0; } - - kfree(name); } - - if (t != NULL) { - *governor = t; - err = 0; - } - +out: mutex_unlock(&cpufreq_governor_mutex); } - out: - return err; + return -EINVAL; } @@ -1295,21 +1265,23 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) int cpufreq_register_governor(struct cpufreq_governor *governor) { - int err; + struct cpufreq_governor *t; if (!governor) return -EINVAL; mutex_lock(&cpufreq_governor_mutex); - err = -EBUSY; - if (__find_governor(governor->name) == NULL) { - err = 0; - list_add(&governor->governor_list, &cpufreq_governor_list); + list_for_each_entry(t, &cpufreq_governor_list, governor_list) { + if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) { + mutex_unlock(&cpufreq_governor_mutex); + return -EBUSY; + } } + list_add(&governor->governor_list, &cpufreq_governor_list); mutex_unlock(&cpufreq_governor_mutex); - return err; + return 0; } EXPORT_SYMBOL_GPL(cpufreq_register_governor); @@ -1371,11 +1343,6 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); - if (policy->min > data->min && policy->min > policy->max) { - ret = -EINVAL; - goto error_out; - } - /* verify the cpu speed can be set within this limit */ ret = cpufreq_driver->verify(policy); if (ret) diff --git a/trunk/drivers/cpufreq/cpufreq_ondemand.c b/trunk/drivers/cpufreq/cpufreq_ondemand.c index bf8aa45d4f01..52cf1f021825 100644 --- a/trunk/drivers/cpufreq/cpufreq_ondemand.c +++ b/trunk/drivers/cpufreq/cpufreq_ondemand.c @@ -55,10 +55,6 @@ struct cpu_dbs_info_s { struct cpufreq_policy *cur_policy; struct work_struct work; unsigned int enable; - struct cpufreq_frequency_table *freq_table; - unsigned int freq_lo; - unsigned int freq_lo_jiffies; - unsigned int freq_hi_jiffies; }; static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); @@ -76,15 +72,15 @@ static DEFINE_MUTEX(dbs_mutex); static struct workqueue_struct *kondemand_wq; -static struct dbs_tuners { +struct dbs_tuners { unsigned int sampling_rate; unsigned int up_threshold; unsigned int ignore_nice; - unsigned int powersave_bias; -} dbs_tuners_ins = { +}; + +static struct dbs_tuners dbs_tuners_ins = { .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, .ignore_nice = 0, - .powersave_bias = 0, }; static inline cputime64_t get_cpu_idle_time(unsigned int cpu) @@ -100,70 +96,6 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu) return retval; } -/* - * Find right freq to be set now with powersave_bias on. - * Returns the freq_hi to be used right now and will set freq_hi_jiffies, - * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs. - */ -static unsigned int powersave_bias_target(struct cpufreq_policy *policy, - unsigned int freq_next, - unsigned int relation) -{ - unsigned int freq_req, freq_reduc, freq_avg; - unsigned int freq_hi, freq_lo; - unsigned int index = 0; - unsigned int jiffies_total, jiffies_hi, jiffies_lo; - struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, policy->cpu); - - if (!dbs_info->freq_table) { - dbs_info->freq_lo = 0; - dbs_info->freq_lo_jiffies = 0; - return freq_next; - } - - cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next, - relation, &index); - freq_req = dbs_info->freq_table[index].frequency; - freq_reduc = freq_req * dbs_tuners_ins.powersave_bias / 1000; - freq_avg = freq_req - freq_reduc; - - /* Find freq bounds for freq_avg in freq_table */ - index = 0; - cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, - CPUFREQ_RELATION_H, &index); - freq_lo = dbs_info->freq_table[index].frequency; - index = 0; - cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, - CPUFREQ_RELATION_L, &index); - freq_hi = dbs_info->freq_table[index].frequency; - - /* Find out how long we have to be in hi and lo freqs */ - if (freq_hi == freq_lo) { - dbs_info->freq_lo = 0; - dbs_info->freq_lo_jiffies = 0; - return freq_lo; - } - jiffies_total = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); - jiffies_hi = (freq_avg - freq_lo) * jiffies_total; - jiffies_hi += ((freq_hi - freq_lo) / 2); - jiffies_hi /= (freq_hi - freq_lo); - jiffies_lo = jiffies_total - jiffies_hi; - dbs_info->freq_lo = freq_lo; - dbs_info->freq_lo_jiffies = jiffies_lo; - dbs_info->freq_hi_jiffies = jiffies_hi; - return freq_hi; -} - -static void ondemand_powersave_bias_init(void) -{ - int i; - for_each_online_cpu(i) { - struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, i); - dbs_info->freq_table = cpufreq_frequency_get_table(i); - dbs_info->freq_lo = 0; - } -} - /************************** sysfs interface ************************/ static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) { @@ -192,7 +124,6 @@ static ssize_t show_##file_name \ show_one(sampling_rate, sampling_rate); show_one(up_threshold, up_threshold); show_one(ignore_nice_load, ignore_nice); -show_one(powersave_bias, powersave_bias); static ssize_t store_sampling_rate(struct cpufreq_policy *unused, const char *buf, size_t count) @@ -267,27 +198,6 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, return count; } -static ssize_t store_powersave_bias(struct cpufreq_policy *unused, - const char *buf, size_t count) -{ - unsigned int input; - int ret; - ret = sscanf(buf, "%u", &input); - - if (ret != 1) - return -EINVAL; - - if (input > 1000) - input = 1000; - - mutex_lock(&dbs_mutex); - dbs_tuners_ins.powersave_bias = input; - ondemand_powersave_bias_init(); - mutex_unlock(&dbs_mutex); - - return count; -} - #define define_one_rw(_name) \ static struct freq_attr _name = \ __ATTR(_name, 0644, show_##_name, store_##_name) @@ -295,7 +205,6 @@ __ATTR(_name, 0644, show_##_name, store_##_name) define_one_rw(sampling_rate); define_one_rw(up_threshold); define_one_rw(ignore_nice_load); -define_one_rw(powersave_bias); static struct attribute * dbs_attributes[] = { &sampling_rate_max.attr, @@ -303,7 +212,6 @@ static struct attribute * dbs_attributes[] = { &sampling_rate.attr, &up_threshold.attr, &ignore_nice_load.attr, - &powersave_bias.attr, NULL }; @@ -326,7 +234,6 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) if (!this_dbs_info->enable) return; - this_dbs_info->freq_lo = 0; policy = this_dbs_info->cur_policy; cur_jiffies = jiffies64_to_cputime64(get_jiffies_64()); total_ticks = (unsigned int) cputime64_sub(cur_jiffies, @@ -367,18 +274,11 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) /* Check for frequency increase */ if (load > dbs_tuners_ins.up_threshold) { /* if we are already at full speed then break out early */ - if (!dbs_tuners_ins.powersave_bias) { - if (policy->cur == policy->max) - return; - - __cpufreq_driver_target(policy, policy->max, - CPUFREQ_RELATION_H); - } else { - int freq = powersave_bias_target(policy, policy->max, - CPUFREQ_RELATION_H); - __cpufreq_driver_target(policy, freq, - CPUFREQ_RELATION_L); - } + if (policy->cur == policy->max) + return; + + __cpufreq_driver_target(policy, policy->max, + CPUFREQ_RELATION_H); return; } @@ -393,64 +293,37 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) * policy. To be safe, we focus 10 points under the threshold. */ if (load < (dbs_tuners_ins.up_threshold - 10)) { - unsigned int freq_next = (policy->cur * load) / + unsigned int freq_next; + freq_next = (policy->cur * load) / (dbs_tuners_ins.up_threshold - 10); - if (!dbs_tuners_ins.powersave_bias) { - __cpufreq_driver_target(policy, freq_next, - CPUFREQ_RELATION_L); - } else { - int freq = powersave_bias_target(policy, freq_next, - CPUFREQ_RELATION_L); - __cpufreq_driver_target(policy, freq, - CPUFREQ_RELATION_L); - } + + __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); } } -/* Sampling types */ -enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; - static void do_dbs_timer(void *data) { unsigned int cpu = smp_processor_id(); struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); - /* We want all CPUs to do sampling nearly on same jiffy */ - int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); - delay -= jiffies % delay; if (!dbs_info->enable) return; - /* Common NORMAL_SAMPLE setup */ - INIT_WORK(&dbs_info->work, do_dbs_timer, (void *)DBS_NORMAL_SAMPLE); - if (!dbs_tuners_ins.powersave_bias || - (unsigned long) data == DBS_NORMAL_SAMPLE) { - lock_cpu_hotplug(); - dbs_check_cpu(dbs_info); - unlock_cpu_hotplug(); - if (dbs_info->freq_lo) { - /* Setup timer for SUB_SAMPLE */ - INIT_WORK(&dbs_info->work, do_dbs_timer, - (void *)DBS_SUB_SAMPLE); - delay = dbs_info->freq_hi_jiffies; - } - } else { - __cpufreq_driver_target(dbs_info->cur_policy, - dbs_info->freq_lo, - CPUFREQ_RELATION_H); - } - queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay); + + lock_cpu_hotplug(); + dbs_check_cpu(dbs_info); + unlock_cpu_hotplug(); + queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, + usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); } static inline void dbs_timer_init(unsigned int cpu) { struct cpu_dbs_info_s *dbs_info = &per_cpu(cpu_dbs_info, cpu); - /* We want all CPUs to do sampling nearly on same jiffy */ - int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); - delay -= jiffies % delay; - ondemand_powersave_bias_init(); - INIT_WORK(&dbs_info->work, do_dbs_timer, NULL); - queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay); + INIT_WORK(&dbs_info->work, do_dbs_timer, 0); + queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, + usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); + return; } static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) diff --git a/trunk/drivers/cpufreq/cpufreq_stats.c b/trunk/drivers/cpufreq/cpufreq_stats.c index c2ecc599dc5f..25eee5394201 100644 --- a/trunk/drivers/cpufreq/cpufreq_stats.c +++ b/trunk/drivers/cpufreq/cpufreq_stats.c @@ -350,10 +350,12 @@ __init cpufreq_stats_init(void) } register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); + lock_cpu_hotplug(); for_each_online_cpu(cpu) { cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE, (void *)(long)cpu); } + unlock_cpu_hotplug(); return 0; } static void diff --git a/trunk/drivers/crypto/Kconfig b/trunk/drivers/crypto/Kconfig index adb554153f67..4263935443cc 100644 --- a/trunk/drivers/crypto/Kconfig +++ b/trunk/drivers/crypto/Kconfig @@ -2,53 +2,22 @@ menu "Hardware crypto devices" config CRYPTO_DEV_PADLOCK tristate "Support for VIA PadLock ACE" - depends on X86_32 - select CRYPTO_ALGAPI - default m + depends on CRYPTO && X86_32 help Some VIA processors come with an integrated crypto engine (so called VIA PadLock ACE, Advanced Cryptography Engine) - that provides instructions for very fast cryptographic - operations with supported algorithms. + that provides instructions for very fast {en,de}cryption + with some algorithms. The instructions are used only when the CPU supports them. - Otherwise software encryption is used. - - Selecting M for this option will compile a helper module - padlock.ko that should autoload all below configured - algorithms. Don't worry if your hardware does not support - some or all of them. In such case padlock.ko will - simply write a single line into the kernel log informing - about its failure but everything will keep working fine. - - If you are unsure, say M. The compiled module will be - called padlock.ko + Otherwise software encryption is used. If you are unsure, + say Y. config CRYPTO_DEV_PADLOCK_AES - tristate "PadLock driver for AES algorithm" + bool "Support for AES in VIA PadLock" depends on CRYPTO_DEV_PADLOCK - select CRYPTO_BLKCIPHER - default m + default y help Use VIA PadLock for AES algorithm. - Available in VIA C3 and newer CPUs. - - If unsure say M. The compiled module will be - called padlock-aes.ko - -config CRYPTO_DEV_PADLOCK_SHA - tristate "PadLock driver for SHA1 and SHA256 algorithms" - depends on CRYPTO_DEV_PADLOCK - select CRYPTO_SHA1 - select CRYPTO_SHA256 - default m - help - Use VIA PadLock for SHA1/SHA256 algorithms. - - Available in VIA C7 and newer processors. - - If unsure say M. The compiled module will be - called padlock-sha.ko - endmenu diff --git a/trunk/drivers/crypto/Makefile b/trunk/drivers/crypto/Makefile index 4c3d0ec1cf80..45426ca19a23 100644 --- a/trunk/drivers/crypto/Makefile +++ b/trunk/drivers/crypto/Makefile @@ -1,3 +1,7 @@ + obj-$(CONFIG_CRYPTO_DEV_PADLOCK) += padlock.o -obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o -obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o + +padlock-objs-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o + +padlock-objs := padlock-generic.o $(padlock-objs-y) + diff --git a/trunk/drivers/crypto/padlock-aes.c b/trunk/drivers/crypto/padlock-aes.c index d4501dc7e650..b643d71298a9 100644 --- a/trunk/drivers/crypto/padlock-aes.c +++ b/trunk/drivers/crypto/padlock-aes.c @@ -43,11 +43,11 @@ * --------------------------------------------------------------------------- */ -#include #include #include #include #include +#include #include #include #include @@ -59,17 +59,6 @@ #define AES_EXTENDED_KEY_SIZE 64 /* in uint32_t units */ #define AES_EXTENDED_KEY_SIZE_B (AES_EXTENDED_KEY_SIZE * sizeof(uint32_t)) -/* Control word. */ -struct cword { - unsigned int __attribute__ ((__packed__)) - rounds:4, - algo:3, - keygen:1, - interm:1, - encdec:1, - ksize:2; -} __attribute__ ((__aligned__(PADLOCK_ALIGNMENT))); - /* Whenever making any changes to the following * structure *make sure* you keep E, d_data * and cword aligned on 16 Bytes boundaries!!! */ @@ -297,9 +286,9 @@ aes_hw_extkey_available(uint8_t key_len) return 0; } -static inline struct aes_ctx *aes_ctx_common(void *ctx) +static inline struct aes_ctx *aes_ctx(struct crypto_tfm *tfm) { - unsigned long addr = (unsigned long)ctx; + unsigned long addr = (unsigned long)crypto_tfm_ctx(tfm); unsigned long align = PADLOCK_ALIGNMENT; if (align <= crypto_tfm_ctx_alignment()) @@ -307,27 +296,16 @@ static inline struct aes_ctx *aes_ctx_common(void *ctx) return (struct aes_ctx *)ALIGN(addr, align); } -static inline struct aes_ctx *aes_ctx(struct crypto_tfm *tfm) -{ - return aes_ctx_common(crypto_tfm_ctx(tfm)); -} - -static inline struct aes_ctx *blk_aes_ctx(struct crypto_blkcipher *tfm) -{ - return aes_ctx_common(crypto_blkcipher_ctx(tfm)); -} - static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, - unsigned int key_len) + unsigned int key_len, u32 *flags) { struct aes_ctx *ctx = aes_ctx(tfm); const __le32 *key = (const __le32 *)in_key; - u32 *flags = &tfm->crt_flags; uint32_t i, t, u, v, w; uint32_t P[AES_EXTENDED_KEY_SIZE]; uint32_t rounds; - if (key_len % 8) { + if (key_len != 16 && key_len != 24 && key_len != 32) { *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } @@ -452,212 +430,80 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt, 1); } -static struct crypto_alg aes_alg = { - .cra_name = "aes", - .cra_driver_name = "aes-padlock", - .cra_priority = PADLOCK_CRA_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_CIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct aes_ctx), - .cra_alignmask = PADLOCK_ALIGNMENT - 1, - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), - .cra_u = { - .cipher = { - .cia_min_keysize = AES_MIN_KEY_SIZE, - .cia_max_keysize = AES_MAX_KEY_SIZE, - .cia_setkey = aes_set_key, - .cia_encrypt = aes_encrypt, - .cia_decrypt = aes_decrypt, - } - } -}; - -static int ecb_aes_encrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) +static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) { - struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); - - while ((nbytes = walk.nbytes)) { - padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr, - ctx->E, &ctx->cword.encrypt, - nbytes / AES_BLOCK_SIZE); - nbytes &= AES_BLOCK_SIZE - 1; - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - return err; + struct aes_ctx *ctx = aes_ctx(desc->tfm); + padlock_xcrypt_ecb(in, out, ctx->E, &ctx->cword.encrypt, + nbytes / AES_BLOCK_SIZE); + return nbytes & ~(AES_BLOCK_SIZE - 1); } -static int ecb_aes_decrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) +static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) { - struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); - - while ((nbytes = walk.nbytes)) { - padlock_xcrypt_ecb(walk.src.virt.addr, walk.dst.virt.addr, - ctx->D, &ctx->cword.decrypt, - nbytes / AES_BLOCK_SIZE); - nbytes &= AES_BLOCK_SIZE - 1; - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - return err; + struct aes_ctx *ctx = aes_ctx(desc->tfm); + padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt, + nbytes / AES_BLOCK_SIZE); + return nbytes & ~(AES_BLOCK_SIZE - 1); } -static struct crypto_alg ecb_aes_alg = { - .cra_name = "ecb(aes)", - .cra_driver_name = "ecb-aes-padlock", - .cra_priority = PADLOCK_COMPOSITE_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, - .cra_blocksize = AES_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct aes_ctx), - .cra_alignmask = PADLOCK_ALIGNMENT - 1, - .cra_type = &crypto_blkcipher_type, - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(ecb_aes_alg.cra_list), - .cra_u = { - .blkcipher = { - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .setkey = aes_set_key, - .encrypt = ecb_aes_encrypt, - .decrypt = ecb_aes_decrypt, - } - } -}; - -static int cbc_aes_encrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) +static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) { - struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); - - while ((nbytes = walk.nbytes)) { - u8 *iv = padlock_xcrypt_cbc(walk.src.virt.addr, - walk.dst.virt.addr, ctx->E, - walk.iv, &ctx->cword.encrypt, - nbytes / AES_BLOCK_SIZE); - memcpy(walk.iv, iv, AES_BLOCK_SIZE); - nbytes &= AES_BLOCK_SIZE - 1; - err = blkcipher_walk_done(desc, &walk, nbytes); - } + struct aes_ctx *ctx = aes_ctx(desc->tfm); + u8 *iv; - return err; + iv = padlock_xcrypt_cbc(in, out, ctx->E, desc->info, + &ctx->cword.encrypt, nbytes / AES_BLOCK_SIZE); + memcpy(desc->info, iv, AES_BLOCK_SIZE); + + return nbytes & ~(AES_BLOCK_SIZE - 1); } -static int cbc_aes_decrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes) +static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out, + const u8 *in, unsigned int nbytes) { - struct aes_ctx *ctx = blk_aes_ctx(desc->tfm); - struct blkcipher_walk walk; - int err; - - blkcipher_walk_init(&walk, dst, src, nbytes); - err = blkcipher_walk_virt(desc, &walk); - - while ((nbytes = walk.nbytes)) { - padlock_xcrypt_cbc(walk.src.virt.addr, walk.dst.virt.addr, - ctx->D, walk.iv, &ctx->cword.decrypt, - nbytes / AES_BLOCK_SIZE); - nbytes &= AES_BLOCK_SIZE - 1; - err = blkcipher_walk_done(desc, &walk, nbytes); - } - - return err; + struct aes_ctx *ctx = aes_ctx(desc->tfm); + padlock_xcrypt_cbc(in, out, ctx->D, desc->info, &ctx->cword.decrypt, + nbytes / AES_BLOCK_SIZE); + return nbytes & ~(AES_BLOCK_SIZE - 1); } -static struct crypto_alg cbc_aes_alg = { - .cra_name = "cbc(aes)", - .cra_driver_name = "cbc-aes-padlock", - .cra_priority = PADLOCK_COMPOSITE_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, +static struct crypto_alg aes_alg = { + .cra_name = "aes", + .cra_driver_name = "aes-padlock", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct aes_ctx), .cra_alignmask = PADLOCK_ALIGNMENT - 1, - .cra_type = &crypto_blkcipher_type, .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(cbc_aes_alg.cra_list), + .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), .cra_u = { - .blkcipher = { - .min_keysize = AES_MIN_KEY_SIZE, - .max_keysize = AES_MAX_KEY_SIZE, - .ivsize = AES_BLOCK_SIZE, - .setkey = aes_set_key, - .encrypt = cbc_aes_encrypt, - .decrypt = cbc_aes_decrypt, + .cipher = { + .cia_min_keysize = AES_MIN_KEY_SIZE, + .cia_max_keysize = AES_MAX_KEY_SIZE, + .cia_setkey = aes_set_key, + .cia_encrypt = aes_encrypt, + .cia_decrypt = aes_decrypt, + .cia_encrypt_ecb = aes_encrypt_ecb, + .cia_decrypt_ecb = aes_decrypt_ecb, + .cia_encrypt_cbc = aes_encrypt_cbc, + .cia_decrypt_cbc = aes_decrypt_cbc, } } }; -static int __init padlock_init(void) +int __init padlock_init_aes(void) { - int ret; - - if (!cpu_has_xcrypt) { - printk(KERN_ERR PFX "VIA PadLock not detected.\n"); - return -ENODEV; - } - - if (!cpu_has_xcrypt_enabled) { - printk(KERN_ERR PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n"); - return -ENODEV; - } - - gen_tabs(); - if ((ret = crypto_register_alg(&aes_alg))) - goto aes_err; - - if ((ret = crypto_register_alg(&ecb_aes_alg))) - goto ecb_aes_err; - - if ((ret = crypto_register_alg(&cbc_aes_alg))) - goto cbc_aes_err; - printk(KERN_NOTICE PFX "Using VIA PadLock ACE for AES algorithm.\n"); -out: - return ret; - -cbc_aes_err: - crypto_unregister_alg(&ecb_aes_alg); -ecb_aes_err: - crypto_unregister_alg(&aes_alg); -aes_err: - printk(KERN_ERR PFX "VIA PadLock AES initialization failed.\n"); - goto out; + gen_tabs(); + return crypto_register_alg(&aes_alg); } -static void __exit padlock_fini(void) +void __exit padlock_fini_aes(void) { - crypto_unregister_alg(&cbc_aes_alg); - crypto_unregister_alg(&ecb_aes_alg); crypto_unregister_alg(&aes_alg); } - -module_init(padlock_init); -module_exit(padlock_fini); - -MODULE_DESCRIPTION("VIA PadLock AES algorithm support"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Michal Ludvig"); - -MODULE_ALIAS("aes-padlock"); diff --git a/trunk/drivers/crypto/padlock-generic.c b/trunk/drivers/crypto/padlock-generic.c new file mode 100644 index 000000000000..18cf0e8274a7 --- /dev/null +++ b/trunk/drivers/crypto/padlock-generic.c @@ -0,0 +1,63 @@ +/* + * Cryptographic API. + * + * Support for VIA PadLock hardware crypto engine. + * + * Copyright (c) 2004 Michal Ludvig + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include "padlock.h" + +static int __init +padlock_init(void) +{ + int ret = -ENOSYS; + + if (!cpu_has_xcrypt) { + printk(KERN_ERR PFX "VIA PadLock not detected.\n"); + return -ENODEV; + } + + if (!cpu_has_xcrypt_enabled) { + printk(KERN_ERR PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n"); + return -ENODEV; + } + +#ifdef CONFIG_CRYPTO_DEV_PADLOCK_AES + if ((ret = padlock_init_aes())) { + printk(KERN_ERR PFX "VIA PadLock AES initialization failed.\n"); + return ret; + } +#endif + + if (ret == -ENOSYS) + printk(KERN_ERR PFX "Hmm, VIA PadLock was compiled without any algorithm.\n"); + + return ret; +} + +static void __exit +padlock_fini(void) +{ +#ifdef CONFIG_CRYPTO_DEV_PADLOCK_AES + padlock_fini_aes(); +#endif +} + +module_init(padlock_init); +module_exit(padlock_fini); + +MODULE_DESCRIPTION("VIA PadLock crypto engine support."); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Michal Ludvig"); diff --git a/trunk/drivers/crypto/padlock-sha.c b/trunk/drivers/crypto/padlock-sha.c deleted file mode 100644 index a781fd23b607..000000000000 --- a/trunk/drivers/crypto/padlock-sha.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Cryptographic API. - * - * Support for VIA PadLock hardware crypto engine. - * - * Copyright (c) 2006 Michal Ludvig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "padlock.h" - -#define SHA1_DEFAULT_FALLBACK "sha1-generic" -#define SHA1_DIGEST_SIZE 20 -#define SHA1_HMAC_BLOCK_SIZE 64 - -#define SHA256_DEFAULT_FALLBACK "sha256-generic" -#define SHA256_DIGEST_SIZE 32 -#define SHA256_HMAC_BLOCK_SIZE 64 - -struct padlock_sha_ctx { - char *data; - size_t used; - int bypass; - void (*f_sha_padlock)(const char *in, char *out, int count); - struct hash_desc fallback; -}; - -static inline struct padlock_sha_ctx *ctx(struct crypto_tfm *tfm) -{ - return crypto_tfm_ctx(tfm); -} - -/* We'll need aligned address on the stack */ -#define NEAREST_ALIGNED(ptr) \ - ((void *)ALIGN((size_t)(ptr), PADLOCK_ALIGNMENT)) - -static struct crypto_alg sha1_alg, sha256_alg; - -static void padlock_sha_bypass(struct crypto_tfm *tfm) -{ - if (ctx(tfm)->bypass) - return; - - crypto_hash_init(&ctx(tfm)->fallback); - if (ctx(tfm)->data && ctx(tfm)->used) { - struct scatterlist sg; - - sg_set_buf(&sg, ctx(tfm)->data, ctx(tfm)->used); - crypto_hash_update(&ctx(tfm)->fallback, &sg, sg.length); - } - - ctx(tfm)->used = 0; - ctx(tfm)->bypass = 1; -} - -static void padlock_sha_init(struct crypto_tfm *tfm) -{ - ctx(tfm)->used = 0; - ctx(tfm)->bypass = 0; -} - -static void padlock_sha_update(struct crypto_tfm *tfm, - const uint8_t *data, unsigned int length) -{ - /* Our buffer is always one page. */ - if (unlikely(!ctx(tfm)->bypass && - (ctx(tfm)->used + length > PAGE_SIZE))) - padlock_sha_bypass(tfm); - - if (unlikely(ctx(tfm)->bypass)) { - struct scatterlist sg; - sg_set_buf(&sg, (uint8_t *)data, length); - crypto_hash_update(&ctx(tfm)->fallback, &sg, length); - return; - } - - memcpy(ctx(tfm)->data + ctx(tfm)->used, data, length); - ctx(tfm)->used += length; -} - -static inline void padlock_output_block(uint32_t *src, - uint32_t *dst, size_t count) -{ - while (count--) - *dst++ = swab32(*src++); -} - -static void padlock_do_sha1(const char *in, char *out, int count) -{ - /* We can't store directly to *out as it may be unaligned. */ - /* BTW Don't reduce the buffer size below 128 Bytes! - * PadLock microcode needs it that big. */ - char buf[128+16]; - char *result = NEAREST_ALIGNED(buf); - - ((uint32_t *)result)[0] = 0x67452301; - ((uint32_t *)result)[1] = 0xEFCDAB89; - ((uint32_t *)result)[2] = 0x98BADCFE; - ((uint32_t *)result)[3] = 0x10325476; - ((uint32_t *)result)[4] = 0xC3D2E1F0; - - asm volatile (".byte 0xf3,0x0f,0xa6,0xc8" /* rep xsha1 */ - : "+S"(in), "+D"(result) - : "c"(count), "a"(0)); - - padlock_output_block((uint32_t *)result, (uint32_t *)out, 5); -} - -static void padlock_do_sha256(const char *in, char *out, int count) -{ - /* We can't store directly to *out as it may be unaligned. */ - /* BTW Don't reduce the buffer size below 128 Bytes! - * PadLock microcode needs it that big. */ - char buf[128+16]; - char *result = NEAREST_ALIGNED(buf); - - ((uint32_t *)result)[0] = 0x6A09E667; - ((uint32_t *)result)[1] = 0xBB67AE85; - ((uint32_t *)result)[2] = 0x3C6EF372; - ((uint32_t *)result)[3] = 0xA54FF53A; - ((uint32_t *)result)[4] = 0x510E527F; - ((uint32_t *)result)[5] = 0x9B05688C; - ((uint32_t *)result)[6] = 0x1F83D9AB; - ((uint32_t *)result)[7] = 0x5BE0CD19; - - asm volatile (".byte 0xf3,0x0f,0xa6,0xd0" /* rep xsha256 */ - : "+S"(in), "+D"(result) - : "c"(count), "a"(0)); - - padlock_output_block((uint32_t *)result, (uint32_t *)out, 8); -} - -static void padlock_sha_final(struct crypto_tfm *tfm, uint8_t *out) -{ - if (unlikely(ctx(tfm)->bypass)) { - crypto_hash_final(&ctx(tfm)->fallback, out); - ctx(tfm)->bypass = 0; - return; - } - - /* Pass the input buffer to PadLock microcode... */ - ctx(tfm)->f_sha_padlock(ctx(tfm)->data, out, ctx(tfm)->used); - - ctx(tfm)->used = 0; -} - -static int padlock_cra_init(struct crypto_tfm *tfm) -{ - const char *fallback_driver_name = tfm->__crt_alg->cra_name; - struct crypto_hash *fallback_tfm; - - /* For now we'll allocate one page. This - * could eventually be configurable one day. */ - ctx(tfm)->data = (char *)__get_free_page(GFP_KERNEL); - if (!ctx(tfm)->data) - return -ENOMEM; - - /* Allocate a fallback and abort if it failed. */ - fallback_tfm = crypto_alloc_hash(fallback_driver_name, 0, - CRYPTO_ALG_ASYNC | - CRYPTO_ALG_NEED_FALLBACK); - if (IS_ERR(fallback_tfm)) { - printk(KERN_WARNING PFX "Fallback driver '%s' could not be loaded!\n", - fallback_driver_name); - free_page((unsigned long)(ctx(tfm)->data)); - return PTR_ERR(fallback_tfm); - } - - ctx(tfm)->fallback.tfm = fallback_tfm; - return 0; -} - -static int padlock_sha1_cra_init(struct crypto_tfm *tfm) -{ - ctx(tfm)->f_sha_padlock = padlock_do_sha1; - - return padlock_cra_init(tfm); -} - -static int padlock_sha256_cra_init(struct crypto_tfm *tfm) -{ - ctx(tfm)->f_sha_padlock = padlock_do_sha256; - - return padlock_cra_init(tfm); -} - -static void padlock_cra_exit(struct crypto_tfm *tfm) -{ - if (ctx(tfm)->data) { - free_page((unsigned long)(ctx(tfm)->data)); - ctx(tfm)->data = NULL; - } - - crypto_free_hash(ctx(tfm)->fallback.tfm); - ctx(tfm)->fallback.tfm = NULL; -} - -static struct crypto_alg sha1_alg = { - .cra_name = "sha1", - .cra_driver_name = "sha1-padlock", - .cra_priority = PADLOCK_CRA_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_DIGEST | - CRYPTO_ALG_NEED_FALLBACK, - .cra_blocksize = SHA1_HMAC_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct padlock_sha_ctx), - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(sha1_alg.cra_list), - .cra_init = padlock_sha1_cra_init, - .cra_exit = padlock_cra_exit, - .cra_u = { - .digest = { - .dia_digestsize = SHA1_DIGEST_SIZE, - .dia_init = padlock_sha_init, - .dia_update = padlock_sha_update, - .dia_final = padlock_sha_final, - } - } -}; - -static struct crypto_alg sha256_alg = { - .cra_name = "sha256", - .cra_driver_name = "sha256-padlock", - .cra_priority = PADLOCK_CRA_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_DIGEST | - CRYPTO_ALG_NEED_FALLBACK, - .cra_blocksize = SHA256_HMAC_BLOCK_SIZE, - .cra_ctxsize = sizeof(struct padlock_sha_ctx), - .cra_module = THIS_MODULE, - .cra_list = LIST_HEAD_INIT(sha256_alg.cra_list), - .cra_init = padlock_sha256_cra_init, - .cra_exit = padlock_cra_exit, - .cra_u = { - .digest = { - .dia_digestsize = SHA256_DIGEST_SIZE, - .dia_init = padlock_sha_init, - .dia_update = padlock_sha_update, - .dia_final = padlock_sha_final, - } - } -}; - -static void __init padlock_sha_check_fallbacks(void) -{ - if (!crypto_has_hash("sha1", 0, CRYPTO_ALG_ASYNC | - CRYPTO_ALG_NEED_FALLBACK)) - printk(KERN_WARNING PFX - "Couldn't load fallback module for sha1.\n"); - - if (!crypto_has_hash("sha256", 0, CRYPTO_ALG_ASYNC | - CRYPTO_ALG_NEED_FALLBACK)) - printk(KERN_WARNING PFX - "Couldn't load fallback module for sha256.\n"); -} - -static int __init padlock_init(void) -{ - int rc = -ENODEV; - - if (!cpu_has_phe) { - printk(KERN_ERR PFX "VIA PadLock Hash Engine not detected.\n"); - return -ENODEV; - } - - if (!cpu_has_phe_enabled) { - printk(KERN_ERR PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n"); - return -ENODEV; - } - - padlock_sha_check_fallbacks(); - - rc = crypto_register_alg(&sha1_alg); - if (rc) - goto out; - - rc = crypto_register_alg(&sha256_alg); - if (rc) - goto out_unreg1; - - printk(KERN_NOTICE PFX "Using VIA PadLock ACE for SHA1/SHA256 algorithms.\n"); - - return 0; - -out_unreg1: - crypto_unregister_alg(&sha1_alg); -out: - printk(KERN_ERR PFX "VIA PadLock SHA1/SHA256 initialization failed.\n"); - return rc; -} - -static void __exit padlock_fini(void) -{ - crypto_unregister_alg(&sha1_alg); - crypto_unregister_alg(&sha256_alg); -} - -module_init(padlock_init); -module_exit(padlock_fini); - -MODULE_DESCRIPTION("VIA PadLock SHA1/SHA256 algorithms support."); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Michal Ludvig"); - -MODULE_ALIAS("sha1-padlock"); -MODULE_ALIAS("sha256-padlock"); diff --git a/trunk/drivers/crypto/padlock.c b/trunk/drivers/crypto/padlock.c deleted file mode 100644 index d6d7dd5bb98c..000000000000 --- a/trunk/drivers/crypto/padlock.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Cryptographic API. - * - * Support for VIA PadLock hardware crypto engine. - * - * Copyright (c) 2006 Michal Ludvig - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "padlock.h" - -static int __init padlock_init(void) -{ - int success = 0; - - if (crypto_has_cipher("aes-padlock", 0, 0)) - success++; - - if (crypto_has_hash("sha1-padlock", 0, 0)) - success++; - - if (crypto_has_hash("sha256-padlock", 0, 0)) - success++; - - if (!success) { - printk(KERN_WARNING PFX "No VIA PadLock drivers have been loaded.\n"); - return -ENODEV; - } - - printk(KERN_NOTICE PFX "%d drivers are available.\n", success); - - return 0; -} - -static void __exit padlock_fini(void) -{ -} - -module_init(padlock_init); -module_exit(padlock_fini); - -MODULE_DESCRIPTION("Load all configured PadLock algorithms."); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Michal Ludvig"); - diff --git a/trunk/drivers/crypto/padlock.h b/trunk/drivers/crypto/padlock.h index b728e4518bd1..b78489bc298a 100644 --- a/trunk/drivers/crypto/padlock.h +++ b/trunk/drivers/crypto/padlock.h @@ -15,9 +15,22 @@ #define PADLOCK_ALIGNMENT 16 +/* Control word. */ +struct cword { + unsigned int __attribute__ ((__packed__)) + rounds:4, + algo:3, + keygen:1, + interm:1, + encdec:1, + ksize:2; +} __attribute__ ((__aligned__(PADLOCK_ALIGNMENT))); + #define PFX "padlock: " -#define PADLOCK_CRA_PRIORITY 300 -#define PADLOCK_COMPOSITE_PRIORITY 400 +#ifdef CONFIG_CRYPTO_DEV_PADLOCK_AES +int padlock_init_aes(void); +void padlock_fini_aes(void); +#endif #endif /* _CRYPTO_PADLOCK_H */ diff --git a/trunk/drivers/edac/edac_mc.h b/trunk/drivers/edac/edac_mc.h index a1cfd4e3c97d..bf6ab8a8d5ed 100644 --- a/trunk/drivers/edac/edac_mc.h +++ b/trunk/drivers/edac/edac_mc.h @@ -29,7 +29,6 @@ #include #include #include -#include #define EDAC_MC_LABEL_LEN 31 #define MC_PROC_NAME_MAX_LEN 7 diff --git a/trunk/drivers/hwmon/abituguru.c b/trunk/drivers/hwmon/abituguru.c index 35ad1b032726..cc15c4f2e9ec 100644 --- a/trunk/drivers/hwmon/abituguru.c +++ b/trunk/drivers/hwmon/abituguru.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -65,17 +64,17 @@ #define ABIT_UGURU_IN_SENSOR 0 #define ABIT_UGURU_TEMP_SENSOR 1 #define ABIT_UGURU_NC 2 -/* In many cases we need to wait for the uGuru to reach a certain status, most - of the time it will reach this status within 30 - 90 ISA reads, and thus we - can best busy wait. This define gives the total amount of reads to try. */ -#define ABIT_UGURU_WAIT_TIMEOUT 125 -/* However sometimes older versions of the uGuru seem to be distracted and they - do not respond for a long time. To handle this we sleep before each of the - last ABIT_UGURU_WAIT_TIMEOUT_SLEEP tries. */ -#define ABIT_UGURU_WAIT_TIMEOUT_SLEEP 5 +/* Timeouts / Retries, if these turn out to need a lot of fiddling we could + convert them to params. */ +/* 250 was determined by trial and error, 200 works most of the time, but not + always. I assume this is cpu-speed independent, since the ISA-bus and not + the CPU should be the bottleneck. Note that 250 sometimes is still not + enough (only reported on AN7 mb) this is handled by a higher layer. */ +#define ABIT_UGURU_WAIT_TIMEOUT 250 /* Normally all expected status in abituguru_ready, are reported after the - first read, but sometimes not and we need to poll. */ -#define ABIT_UGURU_READY_TIMEOUT 5 + first read, but sometimes not and we need to poll, 5 polls was not enough + 50 sofar is. */ +#define ABIT_UGURU_READY_TIMEOUT 50 /* Maximum 3 retries on timedout reads/writes, delay 200 ms before retrying */ #define ABIT_UGURU_MAX_RETRIES 3 #define ABIT_UGURU_RETRY_DELAY (HZ/5) @@ -227,10 +226,6 @@ static int abituguru_wait(struct abituguru_data *data, u8 state) timeout--; if (timeout == 0) return -EBUSY; - /* sleep a bit before our last few tries, see the comment on - this where ABIT_UGURU_WAIT_TIMEOUT_SLEEP is defined. */ - if (timeout <= ABIT_UGURU_WAIT_TIMEOUT_SLEEP) - msleep(0); } return 0; } @@ -261,7 +256,6 @@ static int abituguru_ready(struct abituguru_data *data) "CMD reg does not hold 0xAC after ready command\n"); return -EIO; } - msleep(0); } /* After this the ABIT_UGURU_DATA port should contain @@ -274,7 +268,6 @@ static int abituguru_ready(struct abituguru_data *data) "state != more input after ready command\n"); return -EIO; } - msleep(0); } data->uguru_ready = 1; @@ -338,8 +331,7 @@ static int abituguru_read(struct abituguru_data *data, /* And read the data */ for (i = 0; i < count; i++) { if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) { - ABIT_UGURU_DEBUG(retries ? 1 : 3, - "timeout exceeded waiting for " + ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for " "read state (bank: %d, sensor: %d)\n", (int)bank_addr, (int)sensor_addr); break; @@ -358,9 +350,7 @@ static int abituguru_read(struct abituguru_data *data, static int abituguru_write(struct abituguru_data *data, u8 bank_addr, u8 sensor_addr, u8 *buf, int count) { - /* We use the ready timeout as we have to wait for 0xAC just like the - ready function */ - int i, timeout = ABIT_UGURU_READY_TIMEOUT; + int i; /* Send the address */ i = abituguru_send_address(data, bank_addr, sensor_addr, @@ -380,8 +370,7 @@ static int abituguru_write(struct abituguru_data *data, } /* Now we need to wait till the chip is ready to be read again, - so that we can read 0xAC as confirmation that our write has - succeeded. */ + don't ask why */ if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) { ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for read state " "after write (bank: %d, sensor: %d)\n", (int)bank_addr, @@ -390,15 +379,11 @@ static int abituguru_write(struct abituguru_data *data, } /* Cmd port MUST be read now and should contain 0xAC */ - while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) { - timeout--; - if (timeout == 0) { - ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after " - "write (bank: %d, sensor: %d)\n", - (int)bank_addr, (int)sensor_addr); - return -EIO; - } - msleep(0); + if (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) { + ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after write " + "(bank: %d, sensor: %d)\n", (int)bank_addr, + (int)sensor_addr); + return -EIO; } /* Last put the chip back in ready state */ @@ -418,7 +403,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, u8 sensor_addr) { u8 val, buf[3]; - int i, ret = -ENODEV; /* error is the most common used retval :| */ + int ret = ABIT_UGURU_NC; /* If overriden by the user return the user selected type */ if (bank1_types[sensor_addr] >= ABIT_UGURU_IN_SENSOR && @@ -454,7 +439,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, buf[2] = 250; if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, buf, 3) != 3) - goto abituguru_detect_bank1_sensor_type_exit; + return -ENODEV; /* Now we need 20 ms to give the uguru time to read the sensors and raise a voltage alarm */ set_current_state(TASK_UNINTERRUPTIBLE); @@ -462,16 +447,21 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, /* Check for alarm and check the alarm is a volt low alarm. */ if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, ABIT_UGURU_MAX_RETRIES) != 3) - goto abituguru_detect_bank1_sensor_type_exit; + return -ENODEV; if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, sensor_addr, buf, 3, ABIT_UGURU_MAX_RETRIES) != 3) - goto abituguru_detect_bank1_sensor_type_exit; + return -ENODEV; if (buf[0] & ABIT_UGURU_VOLT_LOW_ALARM_FLAG) { + /* Restore original settings */ + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, + sensor_addr, + data->bank1_settings[sensor_addr], + 3) != 3) + return -ENODEV; ABIT_UGURU_DEBUG(2, " found volt sensor\n"); - ret = ABIT_UGURU_IN_SENSOR; - goto abituguru_detect_bank1_sensor_type_exit; + return ABIT_UGURU_IN_SENSOR; } else ABIT_UGURU_DEBUG(2, " alarm raised during volt " "sensor test, but volt low flag not set\n"); @@ -487,7 +477,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, buf[2] = 10; if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, buf, 3) != 3) - goto abituguru_detect_bank1_sensor_type_exit; + return -ENODEV; /* Now we need 50 ms to give the uguru time to read the sensors and raise a temp alarm */ set_current_state(TASK_UNINTERRUPTIBLE); @@ -495,16 +485,15 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, /* Check for alarm and check the alarm is a temp high alarm. */ if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, ABIT_UGURU_MAX_RETRIES) != 3) - goto abituguru_detect_bank1_sensor_type_exit; + return -ENODEV; if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, sensor_addr, buf, 3, ABIT_UGURU_MAX_RETRIES) != 3) - goto abituguru_detect_bank1_sensor_type_exit; + return -ENODEV; if (buf[0] & ABIT_UGURU_TEMP_HIGH_ALARM_FLAG) { - ABIT_UGURU_DEBUG(2, " found temp sensor\n"); ret = ABIT_UGURU_TEMP_SENSOR; - goto abituguru_detect_bank1_sensor_type_exit; + ABIT_UGURU_DEBUG(2, " found temp sensor\n"); } else ABIT_UGURU_DEBUG(2, " alarm raised during temp " "sensor test, but temp high flag not set\n"); @@ -512,23 +501,11 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data, ABIT_UGURU_DEBUG(2, " alarm not raised during temp sensor " "test\n"); - ret = ABIT_UGURU_NC; -abituguru_detect_bank1_sensor_type_exit: - /* Restore original settings, failing here is really BAD, it has been - reported that some BIOS-es hang when entering the uGuru menu with - invalid settings present in the uGuru, so we try this 3 times. */ - for (i = 0; i < 3; i++) - if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, - sensor_addr, data->bank1_settings[sensor_addr], - 3) == 3) - break; - if (i == 3) { - printk(KERN_ERR ABIT_UGURU_NAME - ": Fatal error could not restore original settings. " - "This should never happen please report this to the " - "abituguru maintainer (see MAINTAINERS)\n"); + /* Restore original settings */ + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, + data->bank1_settings[sensor_addr], 3) != 3) return -ENODEV; - } + return ret; } @@ -1328,7 +1305,7 @@ static struct abituguru_data *abituguru_update_device(struct device *dev) data->update_timeouts = 0; LEAVE_UPDATE: /* handle timeout condition */ - if (!success && (err == -EBUSY || err >= 0)) { + if (err == -EBUSY) { /* No overflow please */ if (data->update_timeouts < 255u) data->update_timeouts++; diff --git a/trunk/drivers/i2c/busses/i2c-powermac.c b/trunk/drivers/i2c/busses/i2c-powermac.c index d658d9107955..53bb43593863 100644 --- a/trunk/drivers/i2c/busses/i2c-powermac.c +++ b/trunk/drivers/i2c/busses/i2c-powermac.c @@ -207,8 +207,7 @@ static int i2c_powermac_probe(struct device *dev) struct pmac_i2c_bus *bus = dev->platform_data; struct device_node *parent = NULL; struct i2c_adapter *adapter; - char name[32]; - const char *basename; + char name[32], *basename; int rc; if (bus == NULL) diff --git a/trunk/drivers/i2c/busses/scx200_acb.c b/trunk/drivers/i2c/busses/scx200_acb.c index eae9e81be375..ced309ff056f 100644 --- a/trunk/drivers/i2c/busses/scx200_acb.c +++ b/trunk/drivers/i2c/busses/scx200_acb.c @@ -232,7 +232,7 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) unsigned long timeout; timeout = jiffies + POLL_TIMEOUT; - while (1) { + while (time_before(jiffies, timeout)) { status = inb(ACBST); /* Reset the status register to avoid the hang */ @@ -242,10 +242,7 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) scx200_acb_machine(iface, status); return; } - if (time_after(jiffies, timeout)) - break; - cpu_relax(); - cond_resched(); + yield(); } dev_err(&iface->adapter.dev, "timeout in state %s\n", diff --git a/trunk/drivers/i2c/chips/tps65010.c b/trunk/drivers/i2c/chips/tps65010.c index 0be6fd6a267d..e7e27049fbfa 100644 --- a/trunk/drivers/i2c/chips/tps65010.c +++ b/trunk/drivers/i2c/chips/tps65010.c @@ -43,12 +43,13 @@ /*-------------------------------------------------------------------------*/ #define DRIVER_VERSION "2 May 2005" -#define DRIVER_NAME (tps65010_driver.driver.name) +#define DRIVER_NAME (tps65010_driver.name) MODULE_DESCRIPTION("TPS6501x Power Management Driver"); MODULE_LICENSE("GPL"); static unsigned short normal_i2c[] = { 0x48, /* 0x49, */ I2C_CLIENT_END }; +static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; I2C_CLIENT_INSMOD; @@ -99,7 +100,7 @@ struct tps65010 { /* not currently tracking GPIO state */ }; -#define POWER_POLL_DELAY msecs_to_jiffies(5000) +#define POWER_POLL_DELAY msecs_to_jiffies(800) /*-------------------------------------------------------------------------*/ @@ -519,11 +520,8 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) goto fail1; } - /* the IRQ is active low, but many gpio lines can't support that - * so this driver can use falling-edge triggers instead. - */ - irqflags = IRQF_SAMPLE_RANDOM; #ifdef CONFIG_ARM + irqflags = IRQF_SAMPLE_RANDOM | IRQF_TRIGGER_LOW; if (machine_is_omap_h2()) { tps->model = TPS65010; omap_cfg_reg(W4_GPIO58); @@ -545,6 +543,8 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) // FIXME set up this board's IRQ ... } +#else + irqflags = IRQF_SAMPLE_RANDOM; #endif if (tps->irq > 0) { diff --git a/trunk/drivers/ide/Kconfig b/trunk/drivers/ide/Kconfig index b6fb167e20f6..d1266fe2d1ab 100644 --- a/trunk/drivers/ide/Kconfig +++ b/trunk/drivers/ide/Kconfig @@ -682,7 +682,6 @@ config BLK_DEV_SVWKS config BLK_DEV_SGIIOC4 tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support" depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4 - select IDEPCI_SHARE_IRQ help This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4 chipset, which has one channel and can support two devices. @@ -774,6 +773,20 @@ config BLK_DEV_IDEDMA_PMAC to transfer data to and from memory. Saying Y is safe and improves performance. +config BLK_DEV_IDE_PMAC_BLINK + bool "Blink laptop LED on drive activity (DEPRECATED)" + depends on BLK_DEV_IDE_PMAC && ADB_PMU + select ADB_PMU_LED + select LEDS_TRIGGERS + select LEDS_TRIGGER_IDE_DISK + help + This option enables the use of the sleep LED as a hard drive + activity LED. + This option is deprecated, it only selects ADB_PMU_LED and + LEDS_TRIGGER_IDE_DISK and changes the code in the new led class + device to default to the ide-disk trigger (which should be set + from userspace via sysfs). + config BLK_DEV_IDE_SWARM tristate "IDE for Sibyte evaluation boards" depends on SIBYTE_SB1xxx_SOC diff --git a/trunk/drivers/ide/ide-disk.c b/trunk/drivers/ide/ide-disk.c index 7cf3eb023521..f712e4cfd9dc 100644 --- a/trunk/drivers/ide/ide-disk.c +++ b/trunk/drivers/ide/ide-disk.c @@ -776,7 +776,7 @@ static void update_ordered(ide_drive_t *drive) * not available so we don't need to recheck that. */ capacity = idedisk_capacity(drive); - barrier = ide_id_has_flush_cache(id) && !drive->noflush && + barrier = ide_id_has_flush_cache(id) && (drive->addressing == 0 || capacity <= (1ULL << 28) || ide_id_has_flush_cache_ext(id)); diff --git a/trunk/drivers/ide/ide-dma.c b/trunk/drivers/ide/ide-dma.c index 7c3a13e1cf64..98918fb6b2ce 100644 --- a/trunk/drivers/ide/ide-dma.c +++ b/trunk/drivers/ide/ide-dma.c @@ -750,7 +750,7 @@ void ide_dma_verbose(ide_drive_t *drive) goto bug_dma_off; printk(", DMA"); } else if (id->field_valid & 1) { - goto bug_dma_off; + printk(", BUG"); } return; bug_dma_off: diff --git a/trunk/drivers/ide/ide-iops.c b/trunk/drivers/ide/ide-iops.c index 77703acaec17..657165297dc7 100644 --- a/trunk/drivers/ide/ide-iops.c +++ b/trunk/drivers/ide/ide-iops.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -1244,7 +1243,6 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout) if (stat == 0xff) return -ENODEV; touch_softlockup_watchdog(); - touch_nmi_watchdog(); } return -EBUSY; } diff --git a/trunk/drivers/ide/ide-proc.c b/trunk/drivers/ide/ide-proc.c index 41b74b13a00c..c12f1b71e934 100644 --- a/trunk/drivers/ide/ide-proc.c +++ b/trunk/drivers/ide/ide-proc.c @@ -376,8 +376,6 @@ static int proc_ide_read_media break; case ide_floppy:media = "floppy\n"; break; - case ide_optical:media = "optical\n"; - break; default: media = "UNKNOWN\n"; break; } diff --git a/trunk/drivers/ide/ide.c b/trunk/drivers/ide/ide.c index defd4b4bd374..05fbd9298db7 100644 --- a/trunk/drivers/ide/ide.c +++ b/trunk/drivers/ide/ide.c @@ -1539,7 +1539,7 @@ static int __init ide_setup(char *s) const char *hd_words[] = { "none", "noprobe", "nowerr", "cdrom", "serialize", "autotune", "noautotune", "minus8", "swapdata", "bswap", - "noflush", "remap", "remap63", "scsi", NULL }; + "minus11", "remap", "remap63", "scsi", NULL }; unit = s[2] - 'a'; hw = unit / MAX_DRIVES; unit = unit % MAX_DRIVES; @@ -1578,9 +1578,6 @@ static int __init ide_setup(char *s) case -10: /* "bswap" */ drive->bswap = 1; goto done; - case -11: /* noflush */ - drive->noflush = 1; - goto done; case -12: /* "remap" */ drive->remap_0_to_1 = 1; goto done; diff --git a/trunk/drivers/ide/pci/aec62xx.c b/trunk/drivers/ide/pci/aec62xx.c index f286079d233f..a7c725f8bf64 100644 --- a/trunk/drivers/ide/pci/aec62xx.c +++ b/trunk/drivers/ide/pci/aec62xx.c @@ -425,12 +425,12 @@ static int __devinit aec62xx_init_one(struct pci_dev *dev, const struct pci_devi return d->init_setup(dev, d); } -static struct pci_device_id aec62xx_pci_tbl[] = { - { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, - { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, - { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, - { PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, +static const struct pci_device_id aec62xx_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF), 0 }, + { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860), 1 }, + { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R), 2 }, + { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865), 3 }, + { PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R), 4 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl); diff --git a/trunk/drivers/ide/pci/alim15x3.c b/trunk/drivers/ide/pci/alim15x3.c index d419e4bb54f4..351dab2fcacf 100644 --- a/trunk/drivers/ide/pci/alim15x3.c +++ b/trunk/drivers/ide/pci/alim15x3.c @@ -730,7 +730,7 @@ static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif) if(m5229_revision <= 0x20) tmpbyte = (tmpbyte & (~0x02)) | 0x01; - else if (m5229_revision == 0xc7 || m5229_revision == 0xc8) + else if (m5229_revision == 0xc7) tmpbyte |= 0x03; else tmpbyte |= 0x01; diff --git a/trunk/drivers/ide/pci/generic.c b/trunk/drivers/ide/pci/generic.c index 78810ba982e9..2f962cfa3f7f 100644 --- a/trunk/drivers/ide/pci/generic.c +++ b/trunk/drivers/ide/pci/generic.c @@ -180,36 +180,6 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = { .channels = 2, .autodma = AUTODMA, .bootable = OFF_BOARD, - },{ /* 15 */ - .name = "JMB361", - .init_hwif = init_hwif_generic, - .channels = 2, - .autodma = AUTODMA, - .bootable = OFF_BOARD, - },{ /* 16 */ - .name = "JMB363", - .init_hwif = init_hwif_generic, - .channels = 2, - .autodma = AUTODMA, - .bootable = OFF_BOARD, - },{ /* 17 */ - .name = "JMB365", - .init_hwif = init_hwif_generic, - .channels = 2, - .autodma = AUTODMA, - .bootable = OFF_BOARD, - },{ /* 18 */ - .name = "JMB366", - .init_hwif = init_hwif_generic, - .channels = 2, - .autodma = AUTODMA, - .bootable = OFF_BOARD, - },{ /* 19 */ - .name = "JMB368", - .init_hwif = init_hwif_generic, - .channels = 2, - .autodma = AUTODMA, - .bootable = OFF_BOARD, } }; diff --git a/trunk/drivers/ide/pci/it821x.c b/trunk/drivers/ide/pci/it821x.c index e9bad185968a..3cb04424d351 100644 --- a/trunk/drivers/ide/pci/it821x.c +++ b/trunk/drivers/ide/pci/it821x.c @@ -498,14 +498,9 @@ static int config_chipset_for_dma (ide_drive_t *drive) { u8 speed = ide_dma_speed(drive, it821x_ratemask(drive)); - if (speed) { - config_it821x_chipset_for_pio(drive, 0); - it821x_tune_chipset(drive, speed); - - return ide_dma_enable(drive); - } - - return 0; + config_it821x_chipset_for_pio(drive, !speed); + it821x_tune_chipset(drive, speed); + return ide_dma_enable(drive); } /** diff --git a/trunk/drivers/ide/pci/serverworks.c b/trunk/drivers/ide/pci/serverworks.c index f063d954236c..03677bff0d72 100644 --- a/trunk/drivers/ide/pci/serverworks.c +++ b/trunk/drivers/ide/pci/serverworks.c @@ -649,11 +649,11 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device } static struct pci_device_id svwks_pci_tbl[] = { - { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, - { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, - { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3}, - { PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0}, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE), 1}, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE), 2}, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2), 3}, + { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE), 4}, { 0, }, }; MODULE_DEVICE_TABLE(pci, svwks_pci_tbl); diff --git a/trunk/drivers/ide/pci/sgiioc4.c b/trunk/drivers/ide/pci/sgiioc4.c index d8a0d87df734..e125032bb403 100644 --- a/trunk/drivers/ide/pci/sgiioc4.c +++ b/trunk/drivers/ide/pci/sgiioc4.c @@ -367,13 +367,12 @@ sgiioc4_INB(unsigned long port) static void __devinit ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) { - void __iomem *virt_dma_base; int num_ports = sizeof (ioc4_dma_regs_t); printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name, dma_base, dma_base + num_ports - 1); - if (!request_mem_region(dma_base, num_ports, hwif->name)) { + if (!request_region(dma_base, num_ports, hwif->name)) { printk(KERN_ERR "%s(%s) -- ERROR, Addresses 0x%p to 0x%p " "ALREADY in use\n", @@ -382,21 +381,13 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) goto dma_alloc_failure; } - virt_dma_base = ioremap(dma_base, num_ports); - if (virt_dma_base == NULL) { - printk(KERN_ERR - "%s(%s) -- ERROR, Unable to map addresses 0x%lx to 0x%lx\n", - __FUNCTION__, hwif->name, dma_base, dma_base + num_ports - 1); - goto dma_remap_failure; - } - hwif->dma_base = (unsigned long) virt_dma_base; - + hwif->dma_base = dma_base; hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES, &hwif->dmatable_dma); if (!hwif->dmatable_cpu) - goto dma_pci_alloc_failure; + goto dma_alloc_failure; hwif->sg_max_nents = IOC4_PRD_ENTRIES; @@ -420,12 +411,6 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base) printk(KERN_INFO "Changing from DMA to PIO mode for Drive %s\n", hwif->name); -dma_pci_alloc_failure: - iounmap(virt_dma_base); - -dma_remap_failure: - release_mem_region(dma_base, num_ports); - dma_alloc_failure: /* Disable DMA because we couldnot allocate any DMA maps */ hwif->autodma = 0; @@ -622,15 +607,18 @@ ide_init_sgiioc4(ide_hwif_t * hwif) hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq; hwif->ide_dma_timeout = &__ide_dma_timeout; + /* + * The IOC4 uses MMIO rather than Port IO. + * It also needs special workarounds for INB. + */ + default_hwif_mmiops(hwif); hwif->INB = &sgiioc4_INB; } static int __devinit sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) { - unsigned long cmd_base, dma_base, irqport; - unsigned long bar0, cmd_phys_base, ctl; - void __iomem *virt_base; + unsigned long base, ctl, dma_base, irqport; ide_hwif_t *hwif; int h; @@ -648,32 +636,23 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) } /* Get the CmdBlk and CtrlBlk Base Registers */ - bar0 = pci_resource_start(dev, 0); - virt_base = ioremap(bar0, pci_resource_len(dev, 0)); - if (virt_base == NULL) { - printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n", - d->name, bar0); - return -ENOMEM; - } - cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET; - ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET; - irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET; + base = pci_resource_start(dev, 0) + IOC4_CMD_OFFSET; + ctl = pci_resource_start(dev, 0) + IOC4_CTRL_OFFSET; + irqport = pci_resource_start(dev, 0) + IOC4_INTR_OFFSET; dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET; - cmd_phys_base = bar0 + IOC4_CMD_OFFSET; - if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE, - hwif->name)) { + if (!request_region(base, IOC4_CMD_CTL_BLK_SIZE, hwif->name)) { printk(KERN_ERR - "%s : %s -- ERROR, Addresses " + "%s : %s -- ERROR, Port Addresses " "0x%p to 0x%p ALREADY in use\n", - __FUNCTION__, hwif->name, (void *) cmd_phys_base, - (void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE); + __FUNCTION__, hwif->name, (void *) base, + (void *) base + IOC4_CMD_CTL_BLK_SIZE); return -ENOMEM; } - if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) { + if (hwif->io_ports[IDE_DATA_OFFSET] != base) { /* Initialize the IO registers */ - sgiioc4_init_hwif_ports(&hwif->hw, cmd_base, ctl, irqport); + sgiioc4_init_hwif_ports(&hwif->hw, base, ctl, irqport); memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof (hwif->io_ports)); hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; @@ -686,9 +665,6 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d) hwif->cds = (struct ide_pci_device_s *) d; hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */ - /* The IOC4 uses MMIO rather than Port IO. */ - default_hwif_mmiops(hwif); - /* Initializing chipset IRQ Registers */ hwif->OUTL(0x03, irqport + IOC4_INTR_SET * 4); diff --git a/trunk/drivers/ide/pci/siimage.c b/trunk/drivers/ide/pci/siimage.c index 20b392948f36..25ceb4a39ed2 100644 --- a/trunk/drivers/ide/pci/siimage.c +++ b/trunk/drivers/ide/pci/siimage.c @@ -1082,10 +1082,10 @@ static int __devinit siimage_init_one(struct pci_dev *dev, const struct pci_devi } static struct pci_device_id siimage_pci_tbl[] = { - { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_DEVICE(PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680), 0}, #ifdef CONFIG_BLK_DEV_IDE_SATA - { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1}, - { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2}, + { PCI_DEVICE(PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112), 1}, + { PCI_DEVICE(PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA), 2}, #endif { 0, }, }; diff --git a/trunk/drivers/ide/pci/sis5513.c b/trunk/drivers/ide/pci/sis5513.c index f03196c5db37..8a6c23ac8cc1 100644 --- a/trunk/drivers/ide/pci/sis5513.c +++ b/trunk/drivers/ide/pci/sis5513.c @@ -86,8 +86,6 @@ static const struct { u8 chipset_family; u8 flags; } SiSHostChipInfo[] = { - { "SiS968", PCI_DEVICE_ID_SI_968, ATA_133 }, - { "SiS966", PCI_DEVICE_ID_SI_966, ATA_133 }, { "SiS965", PCI_DEVICE_ID_SI_965, ATA_133 }, { "SiS745", PCI_DEVICE_ID_SI_745, ATA_100 }, { "SiS735", PCI_DEVICE_ID_SI_735, ATA_100 }, diff --git a/trunk/drivers/ide/pci/via82cxxx.c b/trunk/drivers/ide/pci/via82cxxx.c index 9b7589e8e93e..afdaee3c15c9 100644 --- a/trunk/drivers/ide/pci/via82cxxx.c +++ b/trunk/drivers/ide/pci/via82cxxx.c @@ -6,7 +6,7 @@ * * vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, * vt82c686, vt82c686a, vt82c686b, vt8231, vt8233, vt8233c, vt8233a, - * vt8235, vt8237, vt8237a + * vt8235, vt8237 * * Copyright (c) 2000-2002 Vojtech Pavlik * @@ -81,7 +81,6 @@ static struct via_isa_bridge { { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, - { "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 }, diff --git a/trunk/drivers/ide/ppc/pmac.c b/trunk/drivers/ide/ppc/pmac.c index 996c694341bc..ebf961f1718d 100644 --- a/trunk/drivers/ide/ppc/pmac.c +++ b/trunk/drivers/ide/ppc/pmac.c @@ -1154,7 +1154,7 @@ static int pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) { struct device_node *np = pmif->node; - const int *bidp; + int *bidp; pmif->cable_80 = 0; pmif->broken_dma = pmif->broken_dma_warn = 0; @@ -1176,14 +1176,14 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif) pmif->broken_dma = 1; } - bidp = get_property(np, "AAPL,bus-id", NULL); + bidp = (int *)get_property(np, "AAPL,bus-id", NULL); pmif->aapl_bus_id = bidp ? *bidp : 0; /* Get cable type from device-tree */ if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6 || pmif->kind == controller_sh_ata6) { - const char* cable = get_property(np, "cable-type", NULL); + char* cable = get_property(np, "cable-type", NULL); if (cable && !strncmp(cable, "80-", 3)) pmif->cable_80 = 1; } @@ -1326,7 +1326,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match) if (macio_irq_count(mdev) == 0) { printk(KERN_WARNING "ide%d: no intrs for device %s, using 13\n", i, mdev->ofdev.node->full_name); - irq = irq_create_mapping(NULL, 13); + irq = 13; } else irq = macio_irq(mdev, 0); diff --git a/trunk/drivers/ieee1394/ohci1394.c b/trunk/drivers/ieee1394/ohci1394.c index 448df2773377..d4bad6704bbe 100644 --- a/trunk/drivers/ieee1394/ohci1394.c +++ b/trunk/drivers/ieee1394/ohci1394.c @@ -3552,8 +3552,6 @@ static int ohci1394_pci_resume (struct pci_dev *pdev) static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) { - pci_save_state(pdev); - #ifdef CONFIG_PPC_PMAC if (machine_is(powermac)) { struct device_node *of_node; @@ -3565,6 +3563,8 @@ static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) } #endif + pci_save_state(pdev); + return 0; } diff --git a/trunk/drivers/ieee1394/sbp2.c b/trunk/drivers/ieee1394/sbp2.c index b08755e2e68f..aaa74f293aaf 100644 --- a/trunk/drivers/ieee1394/sbp2.c +++ b/trunk/drivers/ieee1394/sbp2.c @@ -2515,9 +2515,6 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev) sdev->skip_ms_page_8 = 1; if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) sdev->fix_capacity = 1; - if (scsi_id->ne->guid_vendor_id == 0x0010b9 && /* Maxtor's OUI */ - (sdev->type == TYPE_DISK || sdev->type == TYPE_RBC)) - sdev->allow_restart = 1; return 0; } diff --git a/trunk/drivers/infiniband/Kconfig b/trunk/drivers/infiniband/Kconfig index 9edfacee7d84..69a53d476b5b 100644 --- a/trunk/drivers/infiniband/Kconfig +++ b/trunk/drivers/infiniband/Kconfig @@ -14,7 +14,7 @@ config INFINIBAND_USER_MAD ---help--- Userspace InfiniBand Management Datagram (MAD) support. This is the kernel side of the userspace MAD support, which allows - userspace processes to send and receive MADs. You will also + userspace processes to send and receive MADs. You will also need libibumad from . config INFINIBAND_USER_ACCESS @@ -36,8 +36,6 @@ config INFINIBAND_ADDR_TRANS source "drivers/infiniband/hw/mthca/Kconfig" source "drivers/infiniband/hw/ipath/Kconfig" -source "drivers/infiniband/hw/ehca/Kconfig" -source "drivers/infiniband/hw/amso1100/Kconfig" source "drivers/infiniband/ulp/ipoib/Kconfig" diff --git a/trunk/drivers/infiniband/Makefile b/trunk/drivers/infiniband/Makefile index 2b5d1098ef45..c7ff58c1d0e5 100644 --- a/trunk/drivers/infiniband/Makefile +++ b/trunk/drivers/infiniband/Makefile @@ -1,8 +1,6 @@ obj-$(CONFIG_INFINIBAND) += core/ obj-$(CONFIG_INFINIBAND_MTHCA) += hw/mthca/ -obj-$(CONFIG_INFINIBAND_IPATH) += hw/ipath/ -obj-$(CONFIG_INFINIBAND_EHCA) += hw/ehca/ -obj-$(CONFIG_INFINIBAND_AMSO1100) += hw/amso1100/ +obj-$(CONFIG_IPATH_CORE) += hw/ipath/ obj-$(CONFIG_INFINIBAND_IPOIB) += ulp/ipoib/ obj-$(CONFIG_INFINIBAND_SRP) += ulp/srp/ obj-$(CONFIG_INFINIBAND_ISER) += ulp/iser/ diff --git a/trunk/drivers/infiniband/core/Makefile b/trunk/drivers/infiniband/core/Makefile index 163d991eb8c9..68e73ec2d1f8 100644 --- a/trunk/drivers/infiniband/core/Makefile +++ b/trunk/drivers/infiniband/core/Makefile @@ -1,7 +1,7 @@ infiniband-$(CONFIG_INFINIBAND_ADDR_TRANS) := ib_addr.o rdma_cm.o obj-$(CONFIG_INFINIBAND) += ib_core.o ib_mad.o ib_sa.o \ - ib_cm.o iw_cm.o $(infiniband-y) + ib_cm.o $(infiniband-y) obj-$(CONFIG_INFINIBAND_USER_MAD) += ib_umad.o obj-$(CONFIG_INFINIBAND_USER_ACCESS) += ib_uverbs.o ib_ucm.o @@ -14,8 +14,6 @@ ib_sa-y := sa_query.o ib_cm-y := cm.o -iw_cm-y := iwcm.o - rdma_cm-y := cma.o ib_addr-y := addr.o diff --git a/trunk/drivers/infiniband/core/addr.c b/trunk/drivers/infiniband/core/addr.c index 9cbf09e2052f..d294bbc42f09 100644 --- a/trunk/drivers/infiniband/core/addr.c +++ b/trunk/drivers/infiniband/core/addr.c @@ -35,7 +35,6 @@ #include #include #include -#include #include MODULE_AUTHOR("Sean Hefty"); @@ -61,15 +60,12 @@ static LIST_HEAD(req_list); static DECLARE_WORK(work, process_req, NULL); static struct workqueue_struct *addr_wq; -int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, - const unsigned char *dst_dev_addr) +static int copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, + unsigned char *dst_dev_addr) { switch (dev->type) { case ARPHRD_INFINIBAND: - dev_addr->dev_type = RDMA_NODE_IB_CA; - break; - case ARPHRD_ETHER: - dev_addr->dev_type = RDMA_NODE_RNIC; + dev_addr->dev_type = IB_NODE_CA; break; default: return -EADDRNOTAVAIL; @@ -81,7 +77,6 @@ int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, memcpy(dev_addr->dst_dev_addr, dst_dev_addr, MAX_ADDR_LEN); return 0; } -EXPORT_SYMBOL(rdma_copy_addr); int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) { @@ -93,7 +88,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) if (!dev) return -EADDRNOTAVAIL; - ret = rdma_copy_addr(dev_addr, dev, NULL); + ret = copy_addr(dev_addr, dev, NULL); dev_put(dev); return ret; } @@ -165,7 +160,7 @@ static int addr_resolve_remote(struct sockaddr_in *src_in, /* If the device does ARP internally, return 'done' */ if (rt->idev->dev->flags & IFF_NOARP) { - rdma_copy_addr(addr, rt->idev->dev, NULL); + copy_addr(addr, rt->idev->dev, NULL); goto put; } @@ -185,7 +180,7 @@ static int addr_resolve_remote(struct sockaddr_in *src_in, src_in->sin_addr.s_addr = rt->rt_src; } - ret = rdma_copy_addr(addr, neigh->dev, neigh->ha); + ret = copy_addr(addr, neigh->dev, neigh->ha); release: neigh_release(neigh); put: @@ -249,7 +244,7 @@ static int addr_resolve_local(struct sockaddr_in *src_in, if (ZERONET(src_ip)) { src_in->sin_family = dst_in->sin_family; src_in->sin_addr.s_addr = dst_ip; - ret = rdma_copy_addr(addr, dev, dev->dev_addr); + ret = copy_addr(addr, dev, dev->dev_addr); } else if (LOOPBACK(src_ip)) { ret = rdma_translate_ip((struct sockaddr *)dst_in, addr); if (!ret) @@ -331,22 +326,25 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr) } EXPORT_SYMBOL(rdma_addr_cancel); -static int netevent_callback(struct notifier_block *self, unsigned long event, - void *ctx) +static int addr_arp_recv(struct sk_buff *skb, struct net_device *dev, + struct packet_type *pkt, struct net_device *orig_dev) { - if (event == NETEVENT_NEIGH_UPDATE) { - struct neighbour *neigh = ctx; + struct arphdr *arp_hdr; - if (neigh->dev->type == ARPHRD_INFINIBAND && - (neigh->nud_state & NUD_VALID)) { - set_timeout(jiffies); - } - } + arp_hdr = (struct arphdr *) skb->nh.raw; + + if (arp_hdr->ar_op == htons(ARPOP_REQUEST) || + arp_hdr->ar_op == htons(ARPOP_REPLY)) + set_timeout(jiffies); + + kfree_skb(skb); return 0; } -static struct notifier_block nb = { - .notifier_call = netevent_callback +static struct packet_type addr_arp = { + .type = __constant_htons(ETH_P_ARP), + .func = addr_arp_recv, + .af_packet_priv = (void*) 1, }; static int addr_init(void) @@ -355,13 +353,13 @@ static int addr_init(void) if (!addr_wq) return -ENOMEM; - register_netevent_notifier(&nb); + dev_add_pack(&addr_arp); return 0; } static void addr_cleanup(void) { - unregister_netevent_notifier(&nb); + dev_remove_pack(&addr_arp); destroy_workqueue(addr_wq); } diff --git a/trunk/drivers/infiniband/core/cache.c b/trunk/drivers/infiniband/core/cache.c index 20e9f64e67a6..e05ca2cdc73f 100644 --- a/trunk/drivers/infiniband/core/cache.c +++ b/trunk/drivers/infiniband/core/cache.c @@ -62,13 +62,12 @@ struct ib_update_work { static inline int start_port(struct ib_device *device) { - return (device->node_type == RDMA_NODE_IB_SWITCH) ? 0 : 1; + return device->node_type == IB_NODE_SWITCH ? 0 : 1; } static inline int end_port(struct ib_device *device) { - return (device->node_type == RDMA_NODE_IB_SWITCH) ? - 0 : device->phys_port_cnt; + return device->node_type == IB_NODE_SWITCH ? 0 : device->phys_port_cnt; } int ib_get_cached_gid(struct ib_device *device, @@ -302,8 +301,7 @@ static void ib_cache_event(struct ib_event_handler *handler, event->event == IB_EVENT_PORT_ACTIVE || event->event == IB_EVENT_LID_CHANGE || event->event == IB_EVENT_PKEY_CHANGE || - event->event == IB_EVENT_SM_CHANGE || - event->event == IB_EVENT_CLIENT_REREGISTER) { + event->event == IB_EVENT_SM_CHANGE) { work = kmalloc(sizeof *work, GFP_ATOMIC); if (work) { INIT_WORK(&work->work, ib_cache_task, work); diff --git a/trunk/drivers/infiniband/core/cm.c b/trunk/drivers/infiniband/core/cm.c index f35fcc4c0638..f85c97f7500a 100644 --- a/trunk/drivers/infiniband/core/cm.c +++ b/trunk/drivers/infiniband/core/cm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2006 Intel Corporation. All rights reserved. + * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved. * Copyright (c) 2004 Topspin Corporation. All rights reserved. * Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -74,7 +73,6 @@ static struct ib_cm { struct rb_root remote_id_table; struct rb_root remote_sidr_table; struct idr local_id_table; - __be32 random_id_operand; struct workqueue_struct *wq; } cm; @@ -179,7 +177,7 @@ static int cm_alloc_msg(struct cm_id_private *cm_id_priv, if (IS_ERR(ah)) return PTR_ERR(ah); - m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn, + m = ib_create_send_mad(mad_agent, cm_id_priv->id.remote_cm_qpn, cm_id_priv->av.pkey_index, 0, IB_MGMT_MAD_HDR, IB_MGMT_MAD_DATA, GFP_ATOMIC); @@ -301,17 +299,15 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av) static int cm_alloc_id(struct cm_id_private *cm_id_priv) { unsigned long flags; - int ret, id; + int ret; static int next_id; do { spin_lock_irqsave(&cm.lock, flags); - ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, - next_id++, &id); + ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, next_id++, + (__force int *) &cm_id_priv->id.local_id); spin_unlock_irqrestore(&cm.lock, flags); } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) ); - - cm_id_priv->id.local_id = (__force __be32) (id ^ cm.random_id_operand); return ret; } @@ -320,8 +316,7 @@ static void cm_free_id(__be32 local_id) unsigned long flags; spin_lock_irqsave(&cm.lock, flags); - idr_remove(&cm.local_id_table, - (__force int) (local_id ^ cm.random_id_operand)); + idr_remove(&cm.local_id_table, (__force int) local_id); spin_unlock_irqrestore(&cm.lock, flags); } @@ -329,8 +324,7 @@ static struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id) { struct cm_id_private *cm_id_priv; - cm_id_priv = idr_find(&cm.local_id_table, - (__force int) (local_id ^ cm.random_id_operand)); + cm_id_priv = idr_find(&cm.local_id_table, (__force int) local_id); if (cm_id_priv) { if (cm_id_priv->id.remote_id == remote_id) atomic_inc(&cm_id_priv->refcount); @@ -685,8 +679,6 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv) { int wait_time; - cm_cleanup_timewait(cm_id_priv->timewait_info); - /* * The cm_id could be destroyed by the user before we exit timewait. * To protect against this, we search for the cm_id after exiting @@ -983,10 +975,8 @@ int ib_send_cm_req(struct ib_cm_id *cm_id, cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv-> id.local_id); - if (IS_ERR(cm_id_priv->timewait_info)) { - ret = PTR_ERR(cm_id_priv->timewait_info); + if (IS_ERR(cm_id_priv->timewait_info)) goto out; - } ret = cm_init_av_by_path(param->primary_path, &cm_id_priv->av); if (ret) @@ -1362,7 +1352,7 @@ static int cm_req_handler(struct cm_work *work) id.local_id); if (IS_ERR(cm_id_priv->timewait_info)) { ret = PTR_ERR(cm_id_priv->timewait_info); - goto destroy; + goto error1; } cm_id_priv->timewait_info->work.remote_id = req_msg->local_comm_id; cm_id_priv->timewait_info->remote_ca_guid = req_msg->local_ca_guid; @@ -1371,8 +1361,7 @@ static int cm_req_handler(struct cm_work *work) listen_cm_id_priv = cm_match_req(work, cm_id_priv); if (!listen_cm_id_priv) { ret = -EINVAL; - kfree(cm_id_priv->timewait_info); - goto destroy; + goto error2; } cm_id_priv->id.cm_handler = listen_cm_id_priv->id.cm_handler; @@ -1382,22 +1371,12 @@ static int cm_req_handler(struct cm_work *work) cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]); ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av); - if (ret) { - ib_get_cached_gid(work->port->cm_dev->device, - work->port->port_num, 0, &work->path[0].sgid); - ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_GID, - &work->path[0].sgid, sizeof work->path[0].sgid, - NULL, 0); - goto rejected; - } + if (ret) + goto error3; if (req_msg->alt_local_lid) { ret = cm_init_av_by_path(&work->path[1], &cm_id_priv->alt_av); - if (ret) { - ib_send_cm_rej(cm_id, IB_CM_REJ_INVALID_ALT_GID, - &work->path[0].sgid, - sizeof work->path[0].sgid, NULL, 0); - goto rejected; - } + if (ret) + goto error3; } cm_id_priv->tid = req_msg->hdr.tid; cm_id_priv->timeout_ms = cm_convert_to_ms( @@ -1419,11 +1398,12 @@ static int cm_req_handler(struct cm_work *work) cm_deref_id(listen_cm_id_priv); return 0; -rejected: - atomic_dec(&cm_id_priv->refcount); +error3: atomic_dec(&cm_id_priv->refcount); cm_deref_id(listen_cm_id_priv); -destroy: - ib_destroy_cm_id(cm_id); + cm_cleanup_timewait(cm_id_priv->timewait_info); +error2: kfree(cm_id_priv->timewait_info); + cm_id_priv->timewait_info = NULL; +error1: ib_destroy_cm_id(&cm_id_priv->id); return ret; } @@ -2090,9 +2070,8 @@ static struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg) spin_unlock_irqrestore(&cm.lock, flags); return NULL; } - cm_id_priv = idr_find(&cm.local_id_table, (__force int) - (timewait_info->work.local_id ^ - cm.random_id_operand)); + cm_id_priv = idr_find(&cm.local_id_table, + (__force int) timewait_info->work.local_id); if (cm_id_priv) { if (cm_id_priv->id.remote_id == remote_id) atomic_inc(&cm_id_priv->refcount); @@ -3144,8 +3123,7 @@ static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv, qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE; if (cm_id_priv->responder_resources) - qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_READ | - IB_ACCESS_REMOTE_ATOMIC; + qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_READ; qp_attr->pkey_index = cm_id_priv->av.pkey_index; qp_attr->port_num = cm_id_priv->av.port->port_num; ret = 0; @@ -3282,9 +3260,6 @@ static void cm_add_one(struct ib_device *device) int ret; u8 i; - if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) - return; - cm_dev = kmalloc(sizeof(*cm_dev) + sizeof(*port) * device->phys_port_cnt, GFP_KERNEL); if (!cm_dev) @@ -3372,7 +3347,6 @@ static int __init ib_cm_init(void) cm.remote_qp_table = RB_ROOT; cm.remote_sidr_table = RB_ROOT; idr_init(&cm.local_id_table); - get_random_bytes(&cm.random_id_operand, sizeof cm.random_id_operand); idr_pre_get(&cm.local_id_table, GFP_KERNEL); cm.wq = create_workqueue("ib_cm"); diff --git a/trunk/drivers/infiniband/core/cma.c b/trunk/drivers/infiniband/core/cma.c index 1178bd434d1b..d6f99d5720fc 100644 --- a/trunk/drivers/infiniband/core/cma.c +++ b/trunk/drivers/infiniband/core/cma.c @@ -35,7 +35,6 @@ #include #include #include -#include #include @@ -44,14 +43,13 @@ #include #include #include -#include MODULE_AUTHOR("Sean Hefty"); MODULE_DESCRIPTION("Generic RDMA CM Agent"); MODULE_LICENSE("Dual BSD/GPL"); #define CMA_CM_RESPONSE_TIMEOUT 20 -#define CMA_MAX_CM_RETRIES 15 +#define CMA_MAX_CM_RETRIES 3 static void cma_add_one(struct ib_device *device); static void cma_remove_one(struct ib_device *device); @@ -62,7 +60,6 @@ static struct ib_client cma_client = { .remove = cma_remove_one }; -static struct ib_sa_client sa_client; static LIST_HEAD(dev_list); static LIST_HEAD(listen_any_list); static DEFINE_MUTEX(lock); @@ -127,7 +124,6 @@ struct rdma_id_private { int query_id; union { struct ib_cm_id *ib; - struct iw_cm_id *iw; } cm_id; u32 seq_num; @@ -263,24 +259,15 @@ static void cma_detach_from_dev(struct rdma_id_private *id_priv) id_priv->cma_dev = NULL; } -static int cma_acquire_dev(struct rdma_id_private *id_priv) +static int cma_acquire_ib_dev(struct rdma_id_private *id_priv) { - enum rdma_node_type dev_type = id_priv->id.route.addr.dev_addr.dev_type; struct cma_device *cma_dev; union ib_gid gid; int ret = -ENODEV; - switch (rdma_node_get_transport(dev_type)) { - case RDMA_TRANSPORT_IB: - ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid); - break; - case RDMA_TRANSPORT_IWARP: - iw_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid); - break; - default: - return -ENODEV; - } + ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid), + mutex_lock(&lock); list_for_each_entry(cma_dev, &dev_list, list) { ret = ib_find_cached_gid(cma_dev->device, &gid, &id_priv->id.port_num, NULL); @@ -289,9 +276,20 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv) break; } } + mutex_unlock(&lock); return ret; } +static int cma_acquire_dev(struct rdma_id_private *id_priv) +{ + switch (id_priv->id.route.addr.dev_addr.dev_type) { + case IB_NODE_CA: + return cma_acquire_ib_dev(id_priv); + default: + return -ENODEV; + } +} + static void cma_deref_id(struct rdma_id_private *id_priv) { if (atomic_dec_and_test(&id_priv->refcount)) @@ -349,16 +347,6 @@ static int cma_init_ib_qp(struct rdma_id_private *id_priv, struct ib_qp *qp) IB_QP_PKEY_INDEX | IB_QP_PORT); } -static int cma_init_iw_qp(struct rdma_id_private *id_priv, struct ib_qp *qp) -{ - struct ib_qp_attr qp_attr; - - qp_attr.qp_state = IB_QPS_INIT; - qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE; - - return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS); -} - int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd, struct ib_qp_init_attr *qp_init_attr) { @@ -374,13 +362,10 @@ int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd, if (IS_ERR(qp)) return PTR_ERR(qp); - switch (rdma_node_get_transport(id->device->node_type)) { - case RDMA_TRANSPORT_IB: + switch (id->device->node_type) { + case IB_NODE_CA: ret = cma_init_ib_qp(id_priv, qp); break; - case RDMA_TRANSPORT_IWARP: - ret = cma_init_iw_qp(id_priv, qp); - break; default: ret = -ENOSYS; break; @@ -466,17 +451,13 @@ int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr, int ret; id_priv = container_of(id, struct rdma_id_private, id); - switch (rdma_node_get_transport(id_priv->id.device->node_type)) { - case RDMA_TRANSPORT_IB: + switch (id_priv->id.device->node_type) { + case IB_NODE_CA: ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr, qp_attr_mask); if (qp_attr->qp_state == IB_QPS_RTR) qp_attr->rq_psn = id_priv->seq_num; break; - case RDMA_TRANSPORT_IWARP: - ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr, - qp_attr_mask); - break; default: ret = -ENOSYS; break; @@ -609,8 +590,8 @@ static int cma_notify_user(struct rdma_id_private *id_priv, static void cma_cancel_route(struct rdma_id_private *id_priv) { - switch (rdma_node_get_transport(id_priv->id.device->node_type)) { - case RDMA_TRANSPORT_IB: + switch (id_priv->id.device->node_type) { + case IB_NODE_CA: if (id_priv->query) ib_sa_cancel_query(id_priv->query_id, id_priv->query); break; @@ -630,15 +611,11 @@ static void cma_destroy_listen(struct rdma_id_private *id_priv) cma_exch(id_priv, CMA_DESTROYING); if (id_priv->cma_dev) { - switch (rdma_node_get_transport(id_priv->id.device->node_type)) { - case RDMA_TRANSPORT_IB: - if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib)) + switch (id_priv->id.device->node_type) { + case IB_NODE_CA: + if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib)) ib_destroy_cm_id(id_priv->cm_id.ib); break; - case RDMA_TRANSPORT_IWARP: - if (id_priv->cm_id.iw && !IS_ERR(id_priv->cm_id.iw)) - iw_destroy_cm_id(id_priv->cm_id.iw); - break; default: break; } @@ -712,25 +689,19 @@ void rdma_destroy_id(struct rdma_cm_id *id) state = cma_exch(id_priv, CMA_DESTROYING); cma_cancel_operation(id_priv, state); - mutex_lock(&lock); if (id_priv->cma_dev) { - mutex_unlock(&lock); - switch (rdma_node_get_transport(id->device->node_type)) { - case RDMA_TRANSPORT_IB: - if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib)) + switch (id->device->node_type) { + case IB_NODE_CA: + if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib)) ib_destroy_cm_id(id_priv->cm_id.ib); break; - case RDMA_TRANSPORT_IWARP: - if (id_priv->cm_id.iw && !IS_ERR(id_priv->cm_id.iw)) - iw_destroy_cm_id(id_priv->cm_id.iw); - break; default: break; } - mutex_lock(&lock); + mutex_lock(&lock); cma_detach_from_dev(id_priv); + mutex_unlock(&lock); } - mutex_unlock(&lock); cma_release_port(id_priv); cma_deref_id(id_priv); @@ -898,7 +869,7 @@ static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id, ib_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid); ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid); ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey)); - rt->addr.dev_addr.dev_type = RDMA_NODE_IB_CA; + rt->addr.dev_addr.dev_type = IB_NODE_CA; id_priv = container_of(id, struct rdma_id_private, id); id_priv->state = CMA_CONNECT; @@ -927,9 +898,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) } atomic_inc(&conn_id->dev_remove); - mutex_lock(&lock); - ret = cma_acquire_dev(conn_id); - mutex_unlock(&lock); + ret = cma_acquire_ib_dev(conn_id); if (ret) { ret = -ENODEV; cma_release_remove(conn_id); @@ -1013,130 +982,6 @@ static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr, } } -static int cma_iw_handler(struct iw_cm_id *iw_id, struct iw_cm_event *iw_event) -{ - struct rdma_id_private *id_priv = iw_id->context; - enum rdma_cm_event_type event = 0; - struct sockaddr_in *sin; - int ret = 0; - - atomic_inc(&id_priv->dev_remove); - - switch (iw_event->event) { - case IW_CM_EVENT_CLOSE: - event = RDMA_CM_EVENT_DISCONNECTED; - break; - case IW_CM_EVENT_CONNECT_REPLY: - sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr; - *sin = iw_event->local_addr; - sin = (struct sockaddr_in *) &id_priv->id.route.addr.dst_addr; - *sin = iw_event->remote_addr; - if (iw_event->status) - event = RDMA_CM_EVENT_REJECTED; - else - event = RDMA_CM_EVENT_ESTABLISHED; - break; - case IW_CM_EVENT_ESTABLISHED: - event = RDMA_CM_EVENT_ESTABLISHED; - break; - default: - BUG_ON(1); - } - - ret = cma_notify_user(id_priv, event, iw_event->status, - iw_event->private_data, - iw_event->private_data_len); - if (ret) { - /* Destroy the CM ID by returning a non-zero value. */ - id_priv->cm_id.iw = NULL; - cma_exch(id_priv, CMA_DESTROYING); - cma_release_remove(id_priv); - rdma_destroy_id(&id_priv->id); - return ret; - } - - cma_release_remove(id_priv); - return ret; -} - -static int iw_conn_req_handler(struct iw_cm_id *cm_id, - struct iw_cm_event *iw_event) -{ - struct rdma_cm_id *new_cm_id; - struct rdma_id_private *listen_id, *conn_id; - struct sockaddr_in *sin; - struct net_device *dev = NULL; - int ret; - - listen_id = cm_id->context; - atomic_inc(&listen_id->dev_remove); - if (!cma_comp(listen_id, CMA_LISTEN)) { - ret = -ECONNABORTED; - goto out; - } - - /* Create a new RDMA id for the new IW CM ID */ - new_cm_id = rdma_create_id(listen_id->id.event_handler, - listen_id->id.context, - RDMA_PS_TCP); - if (!new_cm_id) { - ret = -ENOMEM; - goto out; - } - conn_id = container_of(new_cm_id, struct rdma_id_private, id); - atomic_inc(&conn_id->dev_remove); - conn_id->state = CMA_CONNECT; - - dev = ip_dev_find(iw_event->local_addr.sin_addr.s_addr); - if (!dev) { - ret = -EADDRNOTAVAIL; - cma_release_remove(conn_id); - rdma_destroy_id(new_cm_id); - goto out; - } - ret = rdma_copy_addr(&conn_id->id.route.addr.dev_addr, dev, NULL); - if (ret) { - cma_release_remove(conn_id); - rdma_destroy_id(new_cm_id); - goto out; - } - - mutex_lock(&lock); - ret = cma_acquire_dev(conn_id); - mutex_unlock(&lock); - if (ret) { - cma_release_remove(conn_id); - rdma_destroy_id(new_cm_id); - goto out; - } - - conn_id->cm_id.iw = cm_id; - cm_id->context = conn_id; - cm_id->cm_handler = cma_iw_handler; - - sin = (struct sockaddr_in *) &new_cm_id->route.addr.src_addr; - *sin = iw_event->local_addr; - sin = (struct sockaddr_in *) &new_cm_id->route.addr.dst_addr; - *sin = iw_event->remote_addr; - - ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0, - iw_event->private_data, - iw_event->private_data_len); - if (ret) { - /* User wants to destroy the CM ID */ - conn_id->cm_id.iw = NULL; - cma_exch(conn_id, CMA_DESTROYING); - cma_release_remove(conn_id); - rdma_destroy_id(&conn_id->id); - } - -out: - if (dev) - dev_put(dev); - cma_release_remove(listen_id); - return ret; -} - static int cma_ib_listen(struct rdma_id_private *id_priv) { struct ib_cm_compare_data compare_data; @@ -1166,30 +1011,6 @@ static int cma_ib_listen(struct rdma_id_private *id_priv) return ret; } -static int cma_iw_listen(struct rdma_id_private *id_priv, int backlog) -{ - int ret; - struct sockaddr_in *sin; - - id_priv->cm_id.iw = iw_create_cm_id(id_priv->id.device, - iw_conn_req_handler, - id_priv); - if (IS_ERR(id_priv->cm_id.iw)) - return PTR_ERR(id_priv->cm_id.iw); - - sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr; - id_priv->cm_id.iw->local_addr = *sin; - - ret = iw_cm_listen(id_priv->cm_id.iw, backlog); - - if (ret) { - iw_destroy_cm_id(id_priv->cm_id.iw); - id_priv->cm_id.iw = NULL; - } - - return ret; -} - static int cma_listen_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) { @@ -1266,17 +1087,12 @@ int rdma_listen(struct rdma_cm_id *id, int backlog) id_priv->backlog = backlog; if (id->device) { - switch (rdma_node_get_transport(id->device->node_type)) { - case RDMA_TRANSPORT_IB: + switch (id->device->node_type) { + case IB_NODE_CA: ret = cma_ib_listen(id_priv); if (ret) goto err; break; - case RDMA_TRANSPORT_IWARP: - ret = cma_iw_listen(id_priv, backlog); - if (ret) - goto err; - break; default: ret = -ENOSYS; goto err; @@ -1324,7 +1140,7 @@ static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(addr)); path_rec.numb_path = 1; - id_priv->query_id = ib_sa_path_rec_get(&sa_client, id_priv->id.device, + id_priv->query_id = ib_sa_path_rec_get(id_priv->id.device, id_priv->id.port_num, &path_rec, IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID | IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH, @@ -1415,23 +1231,6 @@ int rdma_set_ib_paths(struct rdma_cm_id *id, } EXPORT_SYMBOL(rdma_set_ib_paths); -static int cma_resolve_iw_route(struct rdma_id_private *id_priv, int timeout_ms) -{ - struct cma_work *work; - - work = kzalloc(sizeof *work, GFP_KERNEL); - if (!work) - return -ENOMEM; - - work->id = id_priv; - INIT_WORK(&work->work, cma_work_handler, work); - work->old_state = CMA_ROUTE_QUERY; - work->new_state = CMA_ROUTE_RESOLVED; - work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; - queue_work(cma_wq, &work->work); - return 0; -} - int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms) { struct rdma_id_private *id_priv; @@ -1442,13 +1241,10 @@ int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms) return -EINVAL; atomic_inc(&id_priv->refcount); - switch (rdma_node_get_transport(id->device->node_type)) { - case RDMA_TRANSPORT_IB: + switch (id->device->node_type) { + case IB_NODE_CA: ret = cma_resolve_ib_route(id_priv, timeout_ms); break; - case RDMA_TRANSPORT_IWARP: - ret = cma_resolve_iw_route(id_priv, timeout_ms); - break; default: ret = -ENOSYS; break; @@ -1513,26 +1309,16 @@ static void addr_handler(int status, struct sockaddr *src_addr, enum rdma_cm_event_type event; atomic_inc(&id_priv->dev_remove); - - /* - * Grab mutex to block rdma_destroy_id() from removing the device while - * we're trying to acquire it. - */ - mutex_lock(&lock); - if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED)) { - mutex_unlock(&lock); - goto out; - } - - if (!status && !id_priv->cma_dev) + if (!id_priv->cma_dev && !status) status = cma_acquire_dev(id_priv); - mutex_unlock(&lock); if (status) { - if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ADDR_BOUND)) + if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND)) goto out; event = RDMA_CM_EVENT_ADDR_ERROR; } else { + if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED)) + goto out; memcpy(&id_priv->id.route.addr.src_addr, src_addr, ip_addr_size(src_addr)); event = RDMA_CM_EVENT_ADDR_RESOLVED; @@ -1706,7 +1492,7 @@ static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv) hlist_for_each_entry(cur_id, node, &bind_list->owners, node) { if (cma_any_addr(&cur_id->id.route.addr.src_addr)) return -EADDRNOTAVAIL; - + cur_sin = (struct sockaddr_in *) &cur_id->id.route.addr.src_addr; if (sin->sin_addr.s_addr == cur_sin->sin_addr.s_addr) return -EADDRINUSE; @@ -1756,11 +1542,8 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) if (!cma_any_addr(addr)) { ret = rdma_translate_ip(addr, &id->route.addr.dev_addr); - if (!ret) { - mutex_lock(&lock); + if (!ret) ret = cma_acquire_dev(id_priv); - mutex_unlock(&lock); - } if (ret) goto err; } @@ -1866,47 +1649,6 @@ static int cma_connect_ib(struct rdma_id_private *id_priv, return ret; } -static int cma_connect_iw(struct rdma_id_private *id_priv, - struct rdma_conn_param *conn_param) -{ - struct iw_cm_id *cm_id; - struct sockaddr_in* sin; - int ret; - struct iw_cm_conn_param iw_param; - - cm_id = iw_create_cm_id(id_priv->id.device, cma_iw_handler, id_priv); - if (IS_ERR(cm_id)) { - ret = PTR_ERR(cm_id); - goto out; - } - - id_priv->cm_id.iw = cm_id; - - sin = (struct sockaddr_in*) &id_priv->id.route.addr.src_addr; - cm_id->local_addr = *sin; - - sin = (struct sockaddr_in*) &id_priv->id.route.addr.dst_addr; - cm_id->remote_addr = *sin; - - ret = cma_modify_qp_rtr(&id_priv->id); - if (ret) { - iw_destroy_cm_id(cm_id); - return ret; - } - - iw_param.ord = conn_param->initiator_depth; - iw_param.ird = conn_param->responder_resources; - iw_param.private_data = conn_param->private_data; - iw_param.private_data_len = conn_param->private_data_len; - if (id_priv->id.qp) - iw_param.qpn = id_priv->qp_num; - else - iw_param.qpn = conn_param->qp_num; - ret = iw_cm_connect(cm_id, &iw_param); -out: - return ret; -} - int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) { struct rdma_id_private *id_priv; @@ -1922,13 +1664,10 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) id_priv->srq = conn_param->srq; } - switch (rdma_node_get_transport(id->device->node_type)) { - case RDMA_TRANSPORT_IB: + switch (id->device->node_type) { + case IB_NODE_CA: ret = cma_connect_ib(id_priv, conn_param); break; - case RDMA_TRANSPORT_IWARP: - ret = cma_connect_iw(id_priv, conn_param); - break; default: ret = -ENOSYS; break; @@ -1969,28 +1708,6 @@ static int cma_accept_ib(struct rdma_id_private *id_priv, return ib_send_cm_rep(id_priv->cm_id.ib, &rep); } -static int cma_accept_iw(struct rdma_id_private *id_priv, - struct rdma_conn_param *conn_param) -{ - struct iw_cm_conn_param iw_param; - int ret; - - ret = cma_modify_qp_rtr(&id_priv->id); - if (ret) - return ret; - - iw_param.ord = conn_param->initiator_depth; - iw_param.ird = conn_param->responder_resources; - iw_param.private_data = conn_param->private_data; - iw_param.private_data_len = conn_param->private_data_len; - if (id_priv->id.qp) { - iw_param.qpn = id_priv->qp_num; - } else - iw_param.qpn = conn_param->qp_num; - - return iw_cm_accept(id_priv->cm_id.iw, &iw_param); -} - int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) { struct rdma_id_private *id_priv; @@ -2006,16 +1723,13 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) id_priv->srq = conn_param->srq; } - switch (rdma_node_get_transport(id->device->node_type)) { - case RDMA_TRANSPORT_IB: + switch (id->device->node_type) { + case IB_NODE_CA: if (conn_param) ret = cma_accept_ib(id_priv, conn_param); else ret = cma_rep_recv(id_priv); break; - case RDMA_TRANSPORT_IWARP: - ret = cma_accept_iw(id_priv, conn_param); - break; default: ret = -ENOSYS; break; @@ -2042,16 +1756,12 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data, if (!cma_comp(id_priv, CMA_CONNECT)) return -EINVAL; - switch (rdma_node_get_transport(id->device->node_type)) { - case RDMA_TRANSPORT_IB: + switch (id->device->node_type) { + case IB_NODE_CA: ret = ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED, NULL, 0, private_data, private_data_len); break; - case RDMA_TRANSPORT_IWARP: - ret = iw_cm_reject(id_priv->cm_id.iw, - private_data, private_data_len); - break; default: ret = -ENOSYS; break; @@ -2070,20 +1780,17 @@ int rdma_disconnect(struct rdma_cm_id *id) !cma_comp(id_priv, CMA_DISCONNECT)) return -EINVAL; - switch (rdma_node_get_transport(id->device->node_type)) { - case RDMA_TRANSPORT_IB: - ret = cma_modify_qp_err(id); - if (ret) - goto out; + ret = cma_modify_qp_err(id); + if (ret) + goto out; + + switch (id->device->node_type) { + case IB_NODE_CA: /* Initiate or respond to a disconnect. */ if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0)) ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0); break; - case RDMA_TRANSPORT_IWARP: - ret = iw_cm_disconnect(id_priv->cm_id.iw, 0); - break; default: - ret = -EINVAL; break; } out: @@ -2200,15 +1907,12 @@ static int cma_init(void) if (!cma_wq) return -ENOMEM; - ib_sa_register_client(&sa_client); - ret = ib_register_client(&cma_client); if (ret) goto err; return 0; err: - ib_sa_unregister_client(&sa_client); destroy_workqueue(cma_wq); return ret; } @@ -2216,7 +1920,6 @@ static int cma_init(void) static void cma_cleanup(void) { ib_unregister_client(&cma_client); - ib_sa_unregister_client(&sa_client); destroy_workqueue(cma_wq); idr_destroy(&sdp_ps); idr_destroy(&tcp_ps); diff --git a/trunk/drivers/infiniband/core/device.c b/trunk/drivers/infiniband/core/device.c index 63d2a39fb82c..b2f3cb91d9bc 100644 --- a/trunk/drivers/infiniband/core/device.c +++ b/trunk/drivers/infiniband/core/device.c @@ -385,7 +385,7 @@ void *ib_get_client_data(struct ib_device *device, struct ib_client *client) EXPORT_SYMBOL(ib_get_client_data); /** - * ib_set_client_data - Set IB client context + * ib_set_client_data - Get IB client context * @device:Device to set context for * @client:Client to set context for * @data:Context to set @@ -505,7 +505,7 @@ int ib_query_port(struct ib_device *device, u8 port_num, struct ib_port_attr *port_attr) { - if (device->node_type == RDMA_NODE_IB_SWITCH) { + if (device->node_type == IB_NODE_SWITCH) { if (port_num) return -EINVAL; } else if (port_num < 1 || port_num > device->phys_port_cnt) @@ -580,7 +580,7 @@ int ib_modify_port(struct ib_device *device, u8 port_num, int port_modify_mask, struct ib_port_modify *port_modify) { - if (device->node_type == RDMA_NODE_IB_SWITCH) { + if (device->node_type == IB_NODE_SWITCH) { if (port_num) return -EINVAL; } else if (port_num < 1 || port_num > device->phys_port_cnt) diff --git a/trunk/drivers/infiniband/core/iwcm.c b/trunk/drivers/infiniband/core/iwcm.c deleted file mode 100644 index c3fb304a4e86..000000000000 --- a/trunk/drivers/infiniband/core/iwcm.c +++ /dev/null @@ -1,1019 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved. - * Copyright (c) 2004 Topspin Corporation. All rights reserved. - * Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved. - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * Copyright (c) 2005 Network Appliance, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "iwcm.h" - -MODULE_AUTHOR("Tom Tucker"); -MODULE_DESCRIPTION("iWARP CM"); -MODULE_LICENSE("Dual BSD/GPL"); - -static struct workqueue_struct *iwcm_wq; -struct iwcm_work { - struct work_struct work; - struct iwcm_id_private *cm_id; - struct list_head list; - struct iw_cm_event event; - struct list_head free_list; -}; - -/* - * The following services provide a mechanism for pre-allocating iwcm_work - * elements. The design pre-allocates them based on the cm_id type: - * LISTENING IDS: Get enough elements preallocated to handle the - * listen backlog. - * ACTIVE IDS: 4: CONNECT_REPLY, ESTABLISHED, DISCONNECT, CLOSE - * PASSIVE IDS: 3: ESTABLISHED, DISCONNECT, CLOSE - * - * Allocating them in connect and listen avoids having to deal - * with allocation failures on the event upcall from the provider (which - * is called in the interrupt context). - * - * One exception is when creating the cm_id for incoming connection requests. - * There are two cases: - * 1) in the event upcall, cm_event_handler(), for a listening cm_id. If - * the backlog is exceeded, then no more connection request events will - * be processed. cm_event_handler() returns -ENOMEM in this case. Its up - * to the provider to reject the connectino request. - * 2) in the connection request workqueue handler, cm_conn_req_handler(). - * If work elements cannot be allocated for the new connect request cm_id, - * then IWCM will call the provider reject method. This is ok since - * cm_conn_req_handler() runs in the workqueue thread context. - */ - -static struct iwcm_work *get_work(struct iwcm_id_private *cm_id_priv) -{ - struct iwcm_work *work; - - if (list_empty(&cm_id_priv->work_free_list)) - return NULL; - work = list_entry(cm_id_priv->work_free_list.next, struct iwcm_work, - free_list); - list_del_init(&work->free_list); - return work; -} - -static void put_work(struct iwcm_work *work) -{ - list_add(&work->free_list, &work->cm_id->work_free_list); -} - -static void dealloc_work_entries(struct iwcm_id_private *cm_id_priv) -{ - struct list_head *e, *tmp; - - list_for_each_safe(e, tmp, &cm_id_priv->work_free_list) - kfree(list_entry(e, struct iwcm_work, free_list)); -} - -static int alloc_work_entries(struct iwcm_id_private *cm_id_priv, int count) -{ - struct iwcm_work *work; - - BUG_ON(!list_empty(&cm_id_priv->work_free_list)); - while (count--) { - work = kmalloc(sizeof(struct iwcm_work), GFP_KERNEL); - if (!work) { - dealloc_work_entries(cm_id_priv); - return -ENOMEM; - } - work->cm_id = cm_id_priv; - INIT_LIST_HEAD(&work->list); - put_work(work); - } - return 0; -} - -/* - * Save private data from incoming connection requests in the - * cm_id_priv so the low level driver doesn't have to. Adjust - * the event ptr to point to the local copy. - */ -static int copy_private_data(struct iwcm_id_private *cm_id_priv, - struct iw_cm_event *event) -{ - void *p; - - p = kmalloc(event->private_data_len, GFP_ATOMIC); - if (!p) - return -ENOMEM; - memcpy(p, event->private_data, event->private_data_len); - event->private_data = p; - return 0; -} - -/* - * Release a reference on cm_id. If the last reference is being removed - * and iw_destroy_cm_id is waiting, wake up the waiting thread. - */ -static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv) -{ - int ret = 0; - - BUG_ON(atomic_read(&cm_id_priv->refcount)==0); - if (atomic_dec_and_test(&cm_id_priv->refcount)) { - BUG_ON(!list_empty(&cm_id_priv->work_list)); - if (waitqueue_active(&cm_id_priv->destroy_comp.wait)) { - BUG_ON(cm_id_priv->state != IW_CM_STATE_DESTROYING); - BUG_ON(test_bit(IWCM_F_CALLBACK_DESTROY, - &cm_id_priv->flags)); - ret = 1; - } - complete(&cm_id_priv->destroy_comp); - } - - return ret; -} - -static void add_ref(struct iw_cm_id *cm_id) -{ - struct iwcm_id_private *cm_id_priv; - cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); - atomic_inc(&cm_id_priv->refcount); -} - -static void rem_ref(struct iw_cm_id *cm_id) -{ - struct iwcm_id_private *cm_id_priv; - cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); - iwcm_deref_id(cm_id_priv); -} - -static int cm_event_handler(struct iw_cm_id *cm_id, struct iw_cm_event *event); - -struct iw_cm_id *iw_create_cm_id(struct ib_device *device, - iw_cm_handler cm_handler, - void *context) -{ - struct iwcm_id_private *cm_id_priv; - - cm_id_priv = kzalloc(sizeof(*cm_id_priv), GFP_KERNEL); - if (!cm_id_priv) - return ERR_PTR(-ENOMEM); - - cm_id_priv->state = IW_CM_STATE_IDLE; - cm_id_priv->id.device = device; - cm_id_priv->id.cm_handler = cm_handler; - cm_id_priv->id.context = context; - cm_id_priv->id.event_handler = cm_event_handler; - cm_id_priv->id.add_ref = add_ref; - cm_id_priv->id.rem_ref = rem_ref; - spin_lock_init(&cm_id_priv->lock); - atomic_set(&cm_id_priv->refcount, 1); - init_waitqueue_head(&cm_id_priv->connect_wait); - init_completion(&cm_id_priv->destroy_comp); - INIT_LIST_HEAD(&cm_id_priv->work_list); - INIT_LIST_HEAD(&cm_id_priv->work_free_list); - - return &cm_id_priv->id; -} -EXPORT_SYMBOL(iw_create_cm_id); - - -static int iwcm_modify_qp_err(struct ib_qp *qp) -{ - struct ib_qp_attr qp_attr; - - if (!qp) - return -EINVAL; - - qp_attr.qp_state = IB_QPS_ERR; - return ib_modify_qp(qp, &qp_attr, IB_QP_STATE); -} - -/* - * This is really the RDMAC CLOSING state. It is most similar to the - * IB SQD QP state. - */ -static int iwcm_modify_qp_sqd(struct ib_qp *qp) -{ - struct ib_qp_attr qp_attr; - - BUG_ON(qp == NULL); - qp_attr.qp_state = IB_QPS_SQD; - return ib_modify_qp(qp, &qp_attr, IB_QP_STATE); -} - -/* - * CM_ID <-- CLOSING - * - * Block if a passive or active connection is currenlty being processed. Then - * process the event as follows: - * - If we are ESTABLISHED, move to CLOSING and modify the QP state - * based on the abrupt flag - * - If the connection is already in the CLOSING or IDLE state, the peer is - * disconnecting concurrently with us and we've already seen the - * DISCONNECT event -- ignore the request and return 0 - * - Disconnect on a listening endpoint returns -EINVAL - */ -int iw_cm_disconnect(struct iw_cm_id *cm_id, int abrupt) -{ - struct iwcm_id_private *cm_id_priv; - unsigned long flags; - int ret = 0; - struct ib_qp *qp = NULL; - - cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); - /* Wait if we're currently in a connect or accept downcall */ - wait_event(cm_id_priv->connect_wait, - !test_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags)); - - spin_lock_irqsave(&cm_id_priv->lock, flags); - switch (cm_id_priv->state) { - case IW_CM_STATE_ESTABLISHED: - cm_id_priv->state = IW_CM_STATE_CLOSING; - - /* QP could be for user-mode client */ - if (cm_id_priv->qp) - qp = cm_id_priv->qp; - else - ret = -EINVAL; - break; - case IW_CM_STATE_LISTEN: - ret = -EINVAL; - break; - case IW_CM_STATE_CLOSING: - /* remote peer closed first */ - case IW_CM_STATE_IDLE: - /* accept or connect returned !0 */ - break; - case IW_CM_STATE_CONN_RECV: - /* - * App called disconnect before/without calling accept after - * connect_request event delivered. - */ - break; - case IW_CM_STATE_CONN_SENT: - /* Can only get here if wait above fails */ - default: - BUG(); - } - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - - if (qp) { - if (abrupt) - ret = iwcm_modify_qp_err(qp); - else - ret = iwcm_modify_qp_sqd(qp); - - /* - * If both sides are disconnecting the QP could - * already be in ERR or SQD states - */ - ret = 0; - } - - return ret; -} -EXPORT_SYMBOL(iw_cm_disconnect); - -/* - * CM_ID <-- DESTROYING - * - * Clean up all resources associated with the connection and release - * the initial reference taken by iw_create_cm_id. - */ -static void destroy_cm_id(struct iw_cm_id *cm_id) -{ - struct iwcm_id_private *cm_id_priv; - unsigned long flags; - int ret; - - cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); - /* - * Wait if we're currently in a connect or accept downcall. A - * listening endpoint should never block here. - */ - wait_event(cm_id_priv->connect_wait, - !test_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags)); - - spin_lock_irqsave(&cm_id_priv->lock, flags); - switch (cm_id_priv->state) { - case IW_CM_STATE_LISTEN: - cm_id_priv->state = IW_CM_STATE_DESTROYING; - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - /* destroy the listening endpoint */ - ret = cm_id->device->iwcm->destroy_listen(cm_id); - spin_lock_irqsave(&cm_id_priv->lock, flags); - break; - case IW_CM_STATE_ESTABLISHED: - cm_id_priv->state = IW_CM_STATE_DESTROYING; - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - /* Abrupt close of the connection */ - (void)iwcm_modify_qp_err(cm_id_priv->qp); - spin_lock_irqsave(&cm_id_priv->lock, flags); - break; - case IW_CM_STATE_IDLE: - case IW_CM_STATE_CLOSING: - cm_id_priv->state = IW_CM_STATE_DESTROYING; - break; - case IW_CM_STATE_CONN_RECV: - /* - * App called destroy before/without calling accept after - * receiving connection request event notification. - */ - cm_id_priv->state = IW_CM_STATE_DESTROYING; - break; - case IW_CM_STATE_CONN_SENT: - case IW_CM_STATE_DESTROYING: - default: - BUG(); - break; - } - if (cm_id_priv->qp) { - cm_id_priv->id.device->iwcm->rem_ref(cm_id_priv->qp); - cm_id_priv->qp = NULL; - } - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - - (void)iwcm_deref_id(cm_id_priv); -} - -/* - * This function is only called by the application thread and cannot - * be called by the event thread. The function will wait for all - * references to be released on the cm_id and then kfree the cm_id - * object. - */ -void iw_destroy_cm_id(struct iw_cm_id *cm_id) -{ - struct iwcm_id_private *cm_id_priv; - - cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); - BUG_ON(test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)); - - destroy_cm_id(cm_id); - - wait_for_completion(&cm_id_priv->destroy_comp); - - dealloc_work_entries(cm_id_priv); - - kfree(cm_id_priv); -} -EXPORT_SYMBOL(iw_destroy_cm_id); - -/* - * CM_ID <-- LISTEN - * - * Start listening for connect requests. Generates one CONNECT_REQUEST - * event for each inbound connect request. - */ -int iw_cm_listen(struct iw_cm_id *cm_id, int backlog) -{ - struct iwcm_id_private *cm_id_priv; - unsigned long flags; - int ret = 0; - - cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); - - ret = alloc_work_entries(cm_id_priv, backlog); - if (ret) - return ret; - - spin_lock_irqsave(&cm_id_priv->lock, flags); - switch (cm_id_priv->state) { - case IW_CM_STATE_IDLE: - cm_id_priv->state = IW_CM_STATE_LISTEN; - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - ret = cm_id->device->iwcm->create_listen(cm_id, backlog); - if (ret) - cm_id_priv->state = IW_CM_STATE_IDLE; - spin_lock_irqsave(&cm_id_priv->lock, flags); - break; - default: - ret = -EINVAL; - } - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - - return ret; -} -EXPORT_SYMBOL(iw_cm_listen); - -/* - * CM_ID <-- IDLE - * - * Rejects an inbound connection request. No events are generated. - */ -int iw_cm_reject(struct iw_cm_id *cm_id, - const void *private_data, - u8 private_data_len) -{ - struct iwcm_id_private *cm_id_priv; - unsigned long flags; - int ret; - - cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); - set_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); - - spin_lock_irqsave(&cm_id_priv->lock, flags); - if (cm_id_priv->state != IW_CM_STATE_CONN_RECV) { - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); - wake_up_all(&cm_id_priv->connect_wait); - return -EINVAL; - } - cm_id_priv->state = IW_CM_STATE_IDLE; - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - - ret = cm_id->device->iwcm->reject(cm_id, private_data, - private_data_len); - - clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); - wake_up_all(&cm_id_priv->connect_wait); - - return ret; -} -EXPORT_SYMBOL(iw_cm_reject); - -/* - * CM_ID <-- ESTABLISHED - * - * Accepts an inbound connection request and generates an ESTABLISHED - * event. Callers of iw_cm_disconnect and iw_destroy_cm_id will block - * until the ESTABLISHED event is received from the provider. - */ -int iw_cm_accept(struct iw_cm_id *cm_id, - struct iw_cm_conn_param *iw_param) -{ - struct iwcm_id_private *cm_id_priv; - struct ib_qp *qp; - unsigned long flags; - int ret; - - cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); - set_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); - - spin_lock_irqsave(&cm_id_priv->lock, flags); - if (cm_id_priv->state != IW_CM_STATE_CONN_RECV) { - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); - wake_up_all(&cm_id_priv->connect_wait); - return -EINVAL; - } - /* Get the ib_qp given the QPN */ - qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn); - if (!qp) { - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - return -EINVAL; - } - cm_id->device->iwcm->add_ref(qp); - cm_id_priv->qp = qp; - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - - ret = cm_id->device->iwcm->accept(cm_id, iw_param); - if (ret) { - /* An error on accept precludes provider events */ - BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_RECV); - cm_id_priv->state = IW_CM_STATE_IDLE; - spin_lock_irqsave(&cm_id_priv->lock, flags); - if (cm_id_priv->qp) { - cm_id->device->iwcm->rem_ref(qp); - cm_id_priv->qp = NULL; - } - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); - wake_up_all(&cm_id_priv->connect_wait); - } - - return ret; -} -EXPORT_SYMBOL(iw_cm_accept); - -/* - * Active Side: CM_ID <-- CONN_SENT - * - * If successful, results in the generation of a CONNECT_REPLY - * event. iw_cm_disconnect and iw_cm_destroy will block until the - * CONNECT_REPLY event is received from the provider. - */ -int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param) -{ - struct iwcm_id_private *cm_id_priv; - int ret = 0; - unsigned long flags; - struct ib_qp *qp; - - cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); - - ret = alloc_work_entries(cm_id_priv, 4); - if (ret) - return ret; - - set_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); - spin_lock_irqsave(&cm_id_priv->lock, flags); - - if (cm_id_priv->state != IW_CM_STATE_IDLE) { - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); - wake_up_all(&cm_id_priv->connect_wait); - return -EINVAL; - } - - /* Get the ib_qp given the QPN */ - qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn); - if (!qp) { - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - return -EINVAL; - } - cm_id->device->iwcm->add_ref(qp); - cm_id_priv->qp = qp; - cm_id_priv->state = IW_CM_STATE_CONN_SENT; - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - - ret = cm_id->device->iwcm->connect(cm_id, iw_param); - if (ret) { - spin_lock_irqsave(&cm_id_priv->lock, flags); - if (cm_id_priv->qp) { - cm_id->device->iwcm->rem_ref(qp); - cm_id_priv->qp = NULL; - } - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_SENT); - cm_id_priv->state = IW_CM_STATE_IDLE; - clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); - wake_up_all(&cm_id_priv->connect_wait); - } - - return ret; -} -EXPORT_SYMBOL(iw_cm_connect); - -/* - * Passive Side: new CM_ID <-- CONN_RECV - * - * Handles an inbound connect request. The function creates a new - * iw_cm_id to represent the new connection and inherits the client - * callback function and other attributes from the listening parent. - * - * The work item contains a pointer to the listen_cm_id and the event. The - * listen_cm_id contains the client cm_handler, context and - * device. These are copied when the device is cloned. The event - * contains the new four tuple. - * - * An error on the child should not affect the parent, so this - * function does not return a value. - */ -static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv, - struct iw_cm_event *iw_event) -{ - unsigned long flags; - struct iw_cm_id *cm_id; - struct iwcm_id_private *cm_id_priv; - int ret; - - /* - * The provider should never generate a connection request - * event with a bad status. - */ - BUG_ON(iw_event->status); - - /* - * We could be destroying the listening id. If so, ignore this - * upcall. - */ - spin_lock_irqsave(&listen_id_priv->lock, flags); - if (listen_id_priv->state != IW_CM_STATE_LISTEN) { - spin_unlock_irqrestore(&listen_id_priv->lock, flags); - return; - } - spin_unlock_irqrestore(&listen_id_priv->lock, flags); - - cm_id = iw_create_cm_id(listen_id_priv->id.device, - listen_id_priv->id.cm_handler, - listen_id_priv->id.context); - /* If the cm_id could not be created, ignore the request */ - if (IS_ERR(cm_id)) - return; - - cm_id->provider_data = iw_event->provider_data; - cm_id->local_addr = iw_event->local_addr; - cm_id->remote_addr = iw_event->remote_addr; - - cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); - cm_id_priv->state = IW_CM_STATE_CONN_RECV; - - ret = alloc_work_entries(cm_id_priv, 3); - if (ret) { - iw_cm_reject(cm_id, NULL, 0); - iw_destroy_cm_id(cm_id); - return; - } - - /* Call the client CM handler */ - ret = cm_id->cm_handler(cm_id, iw_event); - if (ret) { - set_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags); - destroy_cm_id(cm_id); - if (atomic_read(&cm_id_priv->refcount)==0) - kfree(cm_id); - } - - if (iw_event->private_data_len) - kfree(iw_event->private_data); -} - -/* - * Passive Side: CM_ID <-- ESTABLISHED - * - * The provider generated an ESTABLISHED event which means that - * the MPA negotion has completed successfully and we are now in MPA - * FPDU mode. - * - * This event can only be received in the CONN_RECV state. If the - * remote peer closed, the ESTABLISHED event would be received followed - * by the CLOSE event. If the app closes, it will block until we wake - * it up after processing this event. - */ -static int cm_conn_est_handler(struct iwcm_id_private *cm_id_priv, - struct iw_cm_event *iw_event) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&cm_id_priv->lock, flags); - - /* - * We clear the CONNECT_WAIT bit here to allow the callback - * function to call iw_cm_disconnect. Calling iw_destroy_cm_id - * from a callback handler is not allowed. - */ - clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); - BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_RECV); - cm_id_priv->state = IW_CM_STATE_ESTABLISHED; - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event); - wake_up_all(&cm_id_priv->connect_wait); - - return ret; -} - -/* - * Active Side: CM_ID <-- ESTABLISHED - * - * The app has called connect and is waiting for the established event to - * post it's requests to the server. This event will wake up anyone - * blocked in iw_cm_disconnect or iw_destroy_id. - */ -static int cm_conn_rep_handler(struct iwcm_id_private *cm_id_priv, - struct iw_cm_event *iw_event) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&cm_id_priv->lock, flags); - /* - * Clear the connect wait bit so a callback function calling - * iw_cm_disconnect will not wait and deadlock this thread - */ - clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags); - BUG_ON(cm_id_priv->state != IW_CM_STATE_CONN_SENT); - if (iw_event->status == IW_CM_EVENT_STATUS_ACCEPTED) { - cm_id_priv->id.local_addr = iw_event->local_addr; - cm_id_priv->id.remote_addr = iw_event->remote_addr; - cm_id_priv->state = IW_CM_STATE_ESTABLISHED; - } else { - /* REJECTED or RESET */ - cm_id_priv->id.device->iwcm->rem_ref(cm_id_priv->qp); - cm_id_priv->qp = NULL; - cm_id_priv->state = IW_CM_STATE_IDLE; - } - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event); - - if (iw_event->private_data_len) - kfree(iw_event->private_data); - - /* Wake up waiters on connect complete */ - wake_up_all(&cm_id_priv->connect_wait); - - return ret; -} - -/* - * CM_ID <-- CLOSING - * - * If in the ESTABLISHED state, move to CLOSING. - */ -static void cm_disconnect_handler(struct iwcm_id_private *cm_id_priv, - struct iw_cm_event *iw_event) -{ - unsigned long flags; - - spin_lock_irqsave(&cm_id_priv->lock, flags); - if (cm_id_priv->state == IW_CM_STATE_ESTABLISHED) - cm_id_priv->state = IW_CM_STATE_CLOSING; - spin_unlock_irqrestore(&cm_id_priv->lock, flags); -} - -/* - * CM_ID <-- IDLE - * - * If in the ESTBLISHED or CLOSING states, the QP will have have been - * moved by the provider to the ERR state. Disassociate the CM_ID from - * the QP, move to IDLE, and remove the 'connected' reference. - * - * If in some other state, the cm_id was destroyed asynchronously. - * This is the last reference that will result in waking up - * the app thread blocked in iw_destroy_cm_id. - */ -static int cm_close_handler(struct iwcm_id_private *cm_id_priv, - struct iw_cm_event *iw_event) -{ - unsigned long flags; - int ret = 0; - spin_lock_irqsave(&cm_id_priv->lock, flags); - - if (cm_id_priv->qp) { - cm_id_priv->id.device->iwcm->rem_ref(cm_id_priv->qp); - cm_id_priv->qp = NULL; - } - switch (cm_id_priv->state) { - case IW_CM_STATE_ESTABLISHED: - case IW_CM_STATE_CLOSING: - cm_id_priv->state = IW_CM_STATE_IDLE; - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - ret = cm_id_priv->id.cm_handler(&cm_id_priv->id, iw_event); - spin_lock_irqsave(&cm_id_priv->lock, flags); - break; - case IW_CM_STATE_DESTROYING: - break; - default: - BUG(); - } - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - - return ret; -} - -static int process_event(struct iwcm_id_private *cm_id_priv, - struct iw_cm_event *iw_event) -{ - int ret = 0; - - switch (iw_event->event) { - case IW_CM_EVENT_CONNECT_REQUEST: - cm_conn_req_handler(cm_id_priv, iw_event); - break; - case IW_CM_EVENT_CONNECT_REPLY: - ret = cm_conn_rep_handler(cm_id_priv, iw_event); - break; - case IW_CM_EVENT_ESTABLISHED: - ret = cm_conn_est_handler(cm_id_priv, iw_event); - break; - case IW_CM_EVENT_DISCONNECT: - cm_disconnect_handler(cm_id_priv, iw_event); - break; - case IW_CM_EVENT_CLOSE: - ret = cm_close_handler(cm_id_priv, iw_event); - break; - default: - BUG(); - } - - return ret; -} - -/* - * Process events on the work_list for the cm_id. If the callback - * function requests that the cm_id be deleted, a flag is set in the - * cm_id flags to indicate that when the last reference is - * removed, the cm_id is to be destroyed. This is necessary to - * distinguish between an object that will be destroyed by the app - * thread asleep on the destroy_comp list vs. an object destroyed - * here synchronously when the last reference is removed. - */ -static void cm_work_handler(void *arg) -{ - struct iwcm_work *work = arg, lwork; - struct iwcm_id_private *cm_id_priv = work->cm_id; - unsigned long flags; - int empty; - int ret = 0; - - spin_lock_irqsave(&cm_id_priv->lock, flags); - empty = list_empty(&cm_id_priv->work_list); - while (!empty) { - work = list_entry(cm_id_priv->work_list.next, - struct iwcm_work, list); - list_del_init(&work->list); - empty = list_empty(&cm_id_priv->work_list); - lwork = *work; - put_work(work); - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - - ret = process_event(cm_id_priv, &work->event); - if (ret) { - set_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags); - destroy_cm_id(&cm_id_priv->id); - } - BUG_ON(atomic_read(&cm_id_priv->refcount)==0); - if (iwcm_deref_id(cm_id_priv)) - return; - - if (atomic_read(&cm_id_priv->refcount)==0 && - test_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags)) { - dealloc_work_entries(cm_id_priv); - kfree(cm_id_priv); - return; - } - spin_lock_irqsave(&cm_id_priv->lock, flags); - } - spin_unlock_irqrestore(&cm_id_priv->lock, flags); -} - -/* - * This function is called on interrupt context. Schedule events on - * the iwcm_wq thread to allow callback functions to downcall into - * the CM and/or block. Events are queued to a per-CM_ID - * work_list. If this is the first event on the work_list, the work - * element is also queued on the iwcm_wq thread. - * - * Each event holds a reference on the cm_id. Until the last posted - * event has been delivered and processed, the cm_id cannot be - * deleted. - * - * Returns: - * 0 - the event was handled. - * -ENOMEM - the event was not handled due to lack of resources. - */ -static int cm_event_handler(struct iw_cm_id *cm_id, - struct iw_cm_event *iw_event) -{ - struct iwcm_work *work; - struct iwcm_id_private *cm_id_priv; - unsigned long flags; - int ret = 0; - - cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); - - spin_lock_irqsave(&cm_id_priv->lock, flags); - work = get_work(cm_id_priv); - if (!work) { - ret = -ENOMEM; - goto out; - } - - INIT_WORK(&work->work, cm_work_handler, work); - work->cm_id = cm_id_priv; - work->event = *iw_event; - - if ((work->event.event == IW_CM_EVENT_CONNECT_REQUEST || - work->event.event == IW_CM_EVENT_CONNECT_REPLY) && - work->event.private_data_len) { - ret = copy_private_data(cm_id_priv, &work->event); - if (ret) { - put_work(work); - goto out; - } - } - - atomic_inc(&cm_id_priv->refcount); - if (list_empty(&cm_id_priv->work_list)) { - list_add_tail(&work->list, &cm_id_priv->work_list); - queue_work(iwcm_wq, &work->work); - } else - list_add_tail(&work->list, &cm_id_priv->work_list); -out: - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - return ret; -} - -static int iwcm_init_qp_init_attr(struct iwcm_id_private *cm_id_priv, - struct ib_qp_attr *qp_attr, - int *qp_attr_mask) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&cm_id_priv->lock, flags); - switch (cm_id_priv->state) { - case IW_CM_STATE_IDLE: - case IW_CM_STATE_CONN_SENT: - case IW_CM_STATE_CONN_RECV: - case IW_CM_STATE_ESTABLISHED: - *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS; - qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE | - IB_ACCESS_REMOTE_WRITE| - IB_ACCESS_REMOTE_READ; - ret = 0; - break; - default: - ret = -EINVAL; - break; - } - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - return ret; -} - -static int iwcm_init_qp_rts_attr(struct iwcm_id_private *cm_id_priv, - struct ib_qp_attr *qp_attr, - int *qp_attr_mask) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&cm_id_priv->lock, flags); - switch (cm_id_priv->state) { - case IW_CM_STATE_IDLE: - case IW_CM_STATE_CONN_SENT: - case IW_CM_STATE_CONN_RECV: - case IW_CM_STATE_ESTABLISHED: - *qp_attr_mask = 0; - ret = 0; - break; - default: - ret = -EINVAL; - break; - } - spin_unlock_irqrestore(&cm_id_priv->lock, flags); - return ret; -} - -int iw_cm_init_qp_attr(struct iw_cm_id *cm_id, - struct ib_qp_attr *qp_attr, - int *qp_attr_mask) -{ - struct iwcm_id_private *cm_id_priv; - int ret; - - cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); - switch (qp_attr->qp_state) { - case IB_QPS_INIT: - case IB_QPS_RTR: - ret = iwcm_init_qp_init_attr(cm_id_priv, - qp_attr, qp_attr_mask); - break; - case IB_QPS_RTS: - ret = iwcm_init_qp_rts_attr(cm_id_priv, - qp_attr, qp_attr_mask); - break; - default: - ret = -EINVAL; - break; - } - return ret; -} -EXPORT_SYMBOL(iw_cm_init_qp_attr); - -static int __init iw_cm_init(void) -{ - iwcm_wq = create_singlethread_workqueue("iw_cm_wq"); - if (!iwcm_wq) - return -ENOMEM; - - return 0; -} - -static void __exit iw_cm_cleanup(void) -{ - destroy_workqueue(iwcm_wq); -} - -module_init(iw_cm_init); -module_exit(iw_cm_cleanup); diff --git a/trunk/drivers/infiniband/core/iwcm.h b/trunk/drivers/infiniband/core/iwcm.h deleted file mode 100644 index 3f6cc82564c8..000000000000 --- a/trunk/drivers/infiniband/core/iwcm.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2005 Network Appliance, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef IWCM_H -#define IWCM_H - -enum iw_cm_state { - IW_CM_STATE_IDLE, /* unbound, inactive */ - IW_CM_STATE_LISTEN, /* listen waiting for connect */ - IW_CM_STATE_CONN_RECV, /* inbound waiting for user accept */ - IW_CM_STATE_CONN_SENT, /* outbound waiting for peer accept */ - IW_CM_STATE_ESTABLISHED, /* established */ - IW_CM_STATE_CLOSING, /* disconnect */ - IW_CM_STATE_DESTROYING /* object being deleted */ -}; - -struct iwcm_id_private { - struct iw_cm_id id; - enum iw_cm_state state; - unsigned long flags; - struct ib_qp *qp; - struct completion destroy_comp; - wait_queue_head_t connect_wait; - struct list_head work_list; - spinlock_t lock; - atomic_t refcount; - struct list_head work_free_list; -}; - -#define IWCM_F_CALLBACK_DESTROY 1 -#define IWCM_F_CONNECT_WAIT 2 - -#endif /* IWCM_H */ diff --git a/trunk/drivers/infiniband/core/mad.c b/trunk/drivers/infiniband/core/mad.c index 082f03c158f0..1c3cfbbe6a97 100644 --- a/trunk/drivers/infiniband/core/mad.c +++ b/trunk/drivers/infiniband/core/mad.c @@ -1246,8 +1246,8 @@ static int find_vendor_oui(struct ib_mad_mgmt_vendor_class *vendor_class, int i; for (i = 0; i < MAX_MGMT_OUI; i++) - /* Is there matching OUI for this vendor class ? */ - if (!memcmp(vendor_class->oui[i], oui, 3)) + /* Is there matching OUI for this vendor class ? */ + if (!memcmp(vendor_class->oui[i], oui, 3)) return i; return -1; @@ -2237,7 +2237,7 @@ static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv) list_for_each_entry_safe(mad_send_wr, temp_mad_send_wr, &mad_agent_priv->send_list, agent_list) { if (mad_send_wr->status == IB_WC_SUCCESS) { - mad_send_wr->status = IB_WC_WR_FLUSH_ERR; + mad_send_wr->status = IB_WC_WR_FLUSH_ERR; mad_send_wr->refcount -= (mad_send_wr->timeout > 0); } } @@ -2528,10 +2528,10 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info, } } sg_list.addr = dma_map_single(qp_info->port_priv-> - device->dma_device, + device->dma_device, &mad_priv->grh, sizeof *mad_priv - - sizeof mad_priv->header, + sizeof mad_priv->header, DMA_FROM_DEVICE); pci_unmap_addr_set(&mad_priv->header, mapping, sg_list.addr); recv_wr.wr_id = (unsigned long)&mad_priv->header.mad_list; @@ -2606,7 +2606,7 @@ static int ib_mad_port_start(struct ib_mad_port_private *port_priv) struct ib_qp *qp; attr = kmalloc(sizeof *attr, GFP_KERNEL); - if (!attr) { + if (!attr) { printk(KERN_ERR PFX "Couldn't kmalloc ib_qp_attr\n"); return -ENOMEM; } @@ -2876,10 +2876,7 @@ static void ib_mad_init_device(struct ib_device *device) { int start, end, i; - if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) - return; - - if (device->node_type == RDMA_NODE_IB_SWITCH) { + if (device->node_type == IB_NODE_SWITCH) { start = 0; end = 0; } else { @@ -2926,7 +2923,7 @@ static void ib_mad_remove_device(struct ib_device *device) { int i, num_ports, cur_port; - if (device->node_type == RDMA_NODE_IB_SWITCH) { + if (device->node_type == IB_NODE_SWITCH) { num_ports = 1; cur_port = 0; } else { diff --git a/trunk/drivers/infiniband/core/mad_priv.h b/trunk/drivers/infiniband/core/mad_priv.h index d06b59083f6e..d147f3bad2ce 100644 --- a/trunk/drivers/infiniband/core/mad_priv.h +++ b/trunk/drivers/infiniband/core/mad_priv.h @@ -38,8 +38,8 @@ #define __IB_MAD_PRIV_H__ #include -#include #include +#include #include #include #include diff --git a/trunk/drivers/infiniband/core/mad_rmpp.c b/trunk/drivers/infiniband/core/mad_rmpp.c index 1ef79d015a1e..ebcd5b181770 100644 --- a/trunk/drivers/infiniband/core/mad_rmpp.c +++ b/trunk/drivers/infiniband/core/mad_rmpp.c @@ -33,6 +33,8 @@ * $Id: mad_rmpp.c 1921 2005-03-02 22:58:44Z sean.hefty $ */ +#include + #include "mad_priv.h" #include "mad_rmpp.h" @@ -58,7 +60,6 @@ struct mad_rmpp_recv { int last_ack; int seg_num; int newwin; - int repwin; __be64 tid; u32 src_qp; @@ -169,32 +170,6 @@ static struct ib_mad_send_buf *alloc_response_msg(struct ib_mad_agent *agent, return msg; } -static void ack_ds_ack(struct ib_mad_agent_private *agent, - struct ib_mad_recv_wc *recv_wc) -{ - struct ib_mad_send_buf *msg; - struct ib_rmpp_mad *rmpp_mad; - int ret; - - msg = alloc_response_msg(&agent->agent, recv_wc); - if (IS_ERR(msg)) - return; - - rmpp_mad = msg->mad; - memcpy(rmpp_mad, recv_wc->recv_buf.mad, msg->hdr_len); - - rmpp_mad->mad_hdr.method ^= IB_MGMT_METHOD_RESP; - ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE); - rmpp_mad->rmpp_hdr.seg_num = 0; - rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(1); - - ret = ib_post_send_mad(msg, NULL); - if (ret) { - ib_destroy_ah(msg->ah); - ib_free_send_mad(msg); - } -} - void ib_rmpp_send_handler(struct ib_mad_send_wc *mad_send_wc) { struct ib_rmpp_mad *rmpp_mad = mad_send_wc->send_buf->mad; @@ -296,7 +271,6 @@ create_rmpp_recv(struct ib_mad_agent_private *agent, rmpp_recv->newwin = 1; rmpp_recv->seg_num = 1; rmpp_recv->last_ack = 0; - rmpp_recv->repwin = 1; mad_hdr = &mad_recv_wc->recv_buf.mad->mad_hdr; rmpp_recv->tid = mad_hdr->tid; @@ -391,7 +365,7 @@ static inline int window_size(struct ib_mad_agent_private *agent) static struct ib_mad_recv_buf * find_seg_location(struct list_head *rmpp_list, int seg_num) { - struct ib_mad_recv_buf *seg_buf; + struct ib_mad_recv_buf *seg_buf; int cur_seg_num; list_for_each_entry_reverse(seg_buf, rmpp_list, list) { @@ -617,16 +591,6 @@ static inline void adjust_last_ack(struct ib_mad_send_wr_private *wr, break; } -static void process_ds_ack(struct ib_mad_agent_private *agent, - struct ib_mad_recv_wc *mad_recv_wc, int newwin) -{ - struct mad_rmpp_recv *rmpp_recv; - - rmpp_recv = find_rmpp_recv(agent, mad_recv_wc); - if (rmpp_recv && rmpp_recv->state == RMPP_STATE_COMPLETE) - rmpp_recv->repwin = newwin; -} - static void process_rmpp_ack(struct ib_mad_agent_private *agent, struct ib_mad_recv_wc *mad_recv_wc) { @@ -652,18 +616,8 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, spin_lock_irqsave(&agent->lock, flags); mad_send_wr = ib_find_send_mad(agent, mad_recv_wc); - if (!mad_send_wr) { - if (!seg_num) - process_ds_ack(agent, mad_recv_wc, newwin); - goto out; /* Unmatched or DS RMPP ACK */ - } - - if ((mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) && - (mad_send_wr->timeout)) { - spin_unlock_irqrestore(&agent->lock, flags); - ack_ds_ack(agent, mad_recv_wc); - return; /* Repeated ACK for DS RMPP transaction */ - } + if (!mad_send_wr) + goto out; /* Unmatched ACK */ if ((mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) || (!mad_send_wr->timeout) || (mad_send_wr->status != IB_WC_SUCCESS)) @@ -702,9 +656,6 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent, if (mad_send_wr->refcount == 1) ib_reset_mad_timeout(mad_send_wr, mad_send_wr->send_buf.timeout_ms); - spin_unlock_irqrestore(&agent->lock, flags); - ack_ds_ack(agent, mad_recv_wc); - return; } else if (mad_send_wr->refcount == 1 && mad_send_wr->seg_num < mad_send_wr->newwin && mad_send_wr->seg_num < mad_send_wr->send_buf.seg_count) { @@ -821,39 +772,6 @@ ib_process_rmpp_recv_wc(struct ib_mad_agent_private *agent, return NULL; } -static int init_newwin(struct ib_mad_send_wr_private *mad_send_wr) -{ - struct ib_mad_agent_private *agent = mad_send_wr->mad_agent_priv; - struct ib_mad_hdr *mad_hdr = mad_send_wr->send_buf.mad; - struct mad_rmpp_recv *rmpp_recv; - struct ib_ah_attr ah_attr; - unsigned long flags; - int newwin = 1; - - if (!(mad_hdr->method & IB_MGMT_METHOD_RESP)) - goto out; - - spin_lock_irqsave(&agent->lock, flags); - list_for_each_entry(rmpp_recv, &agent->rmpp_list, list) { - if (rmpp_recv->tid != mad_hdr->tid || - rmpp_recv->mgmt_class != mad_hdr->mgmt_class || - rmpp_recv->class_version != mad_hdr->class_version || - (rmpp_recv->method & IB_MGMT_METHOD_RESP)) - continue; - - if (ib_query_ah(mad_send_wr->send_buf.ah, &ah_attr)) - continue; - - if (rmpp_recv->slid == ah_attr.dlid) { - newwin = rmpp_recv->repwin; - break; - } - } - spin_unlock_irqrestore(&agent->lock, flags); -out: - return newwin; -} - int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr) { struct ib_rmpp_mad *rmpp_mad; @@ -869,7 +787,7 @@ int ib_send_rmpp_mad(struct ib_mad_send_wr_private *mad_send_wr) return IB_RMPP_RESULT_INTERNAL; } - mad_send_wr->newwin = init_newwin(mad_send_wr); + mad_send_wr->newwin = 1; /* We need to wait for the final ACK even if there isn't a response */ mad_send_wr->refcount += (mad_send_wr->timeout == 0); diff --git a/trunk/drivers/infiniband/core/sa_query.c b/trunk/drivers/infiniband/core/sa_query.c index 1706d3c7e95e..aeda484ffd82 100644 --- a/trunk/drivers/infiniband/core/sa_query.c +++ b/trunk/drivers/infiniband/core/sa_query.c @@ -1,7 +1,6 @@ /* * Copyright (c) 2004 Topspin Communications. All rights reserved. * Copyright (c) 2005 Voltaire, Inc.  All rights reserved. - * Copyright (c) 2006 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -76,7 +75,6 @@ struct ib_sa_device { struct ib_sa_query { void (*callback)(struct ib_sa_query *, int, struct ib_sa_mad *); void (*release)(struct ib_sa_query *); - struct ib_sa_client *client; struct ib_sa_port *port; struct ib_mad_send_buf *mad_buf; struct ib_sa_sm_ah *sm_ah; @@ -407,8 +405,7 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event event->event == IB_EVENT_PORT_ACTIVE || event->event == IB_EVENT_LID_CHANGE || event->event == IB_EVENT_PKEY_CHANGE || - event->event == IB_EVENT_SM_CHANGE || - event->event == IB_EVENT_CLIENT_REREGISTER) { + event->event == IB_EVENT_SM_CHANGE) { struct ib_sa_device *sa_dev; sa_dev = container_of(handler, typeof(*sa_dev), event_handler); @@ -417,31 +414,6 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event } } -void ib_sa_register_client(struct ib_sa_client *client) -{ - atomic_set(&client->users, 1); - init_completion(&client->comp); -} -EXPORT_SYMBOL(ib_sa_register_client); - -static inline void ib_sa_client_get(struct ib_sa_client *client) -{ - atomic_inc(&client->users); -} - -static inline void ib_sa_client_put(struct ib_sa_client *client) -{ - if (atomic_dec_and_test(&client->users)) - complete(&client->comp); -} - -void ib_sa_unregister_client(struct ib_sa_client *client) -{ - ib_sa_client_put(client); - wait_for_completion(&client->comp); -} -EXPORT_SYMBOL(ib_sa_unregister_client); - /** * ib_sa_cancel_query - try to cancel an SA query * @id:ID of query to cancel @@ -584,7 +556,6 @@ static void ib_sa_path_rec_release(struct ib_sa_query *sa_query) /** * ib_sa_path_rec_get - Start a Path get query - * @client:SA client * @device:device to send query on * @port_num: port number to send query on * @rec:Path Record to send in query @@ -607,8 +578,7 @@ static void ib_sa_path_rec_release(struct ib_sa_query *sa_query) * error code. Otherwise it is a query ID that can be used to cancel * the query. */ -int ib_sa_path_rec_get(struct ib_sa_client *client, - struct ib_device *device, u8 port_num, +int ib_sa_path_rec_get(struct ib_device *device, u8 port_num, struct ib_sa_path_rec *rec, ib_sa_comp_mask comp_mask, int timeout_ms, gfp_t gfp_mask, @@ -643,10 +613,8 @@ int ib_sa_path_rec_get(struct ib_sa_client *client, goto err1; } - ib_sa_client_get(client); - query->sa_query.client = client; - query->callback = callback; - query->context = context; + query->callback = callback; + query->context = context; mad = query->sa_query.mad_buf->mad; init_mad(mad, agent); @@ -670,7 +638,6 @@ int ib_sa_path_rec_get(struct ib_sa_client *client, err2: *sa_query = NULL; - ib_sa_client_put(query->sa_query.client); ib_free_send_mad(query->sa_query.mad_buf); err1: @@ -703,7 +670,6 @@ static void ib_sa_service_rec_release(struct ib_sa_query *sa_query) /** * ib_sa_service_rec_query - Start Service Record operation - * @client:SA client * @device:device to send request on * @port_num: port number to send request on * @method:SA method - should be get, set, or delete @@ -728,8 +694,7 @@ static void ib_sa_service_rec_release(struct ib_sa_query *sa_query) * error code. Otherwise it is a request ID that can be used to cancel * the query. */ -int ib_sa_service_rec_query(struct ib_sa_client *client, - struct ib_device *device, u8 port_num, u8 method, +int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method, struct ib_sa_service_rec *rec, ib_sa_comp_mask comp_mask, int timeout_ms, gfp_t gfp_mask, @@ -769,10 +734,8 @@ int ib_sa_service_rec_query(struct ib_sa_client *client, goto err1; } - ib_sa_client_get(client); - query->sa_query.client = client; - query->callback = callback; - query->context = context; + query->callback = callback; + query->context = context; mad = query->sa_query.mad_buf->mad; init_mad(mad, agent); @@ -797,7 +760,6 @@ int ib_sa_service_rec_query(struct ib_sa_client *client, err2: *sa_query = NULL; - ib_sa_client_put(query->sa_query.client); ib_free_send_mad(query->sa_query.mad_buf); err1: @@ -828,8 +790,7 @@ static void ib_sa_mcmember_rec_release(struct ib_sa_query *sa_query) kfree(container_of(sa_query, struct ib_sa_mcmember_query, sa_query)); } -int ib_sa_mcmember_rec_query(struct ib_sa_client *client, - struct ib_device *device, u8 port_num, +int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num, u8 method, struct ib_sa_mcmember_rec *rec, ib_sa_comp_mask comp_mask, @@ -865,10 +826,8 @@ int ib_sa_mcmember_rec_query(struct ib_sa_client *client, goto err1; } - ib_sa_client_get(client); - query->sa_query.client = client; - query->callback = callback; - query->context = context; + query->callback = callback; + query->context = context; mad = query->sa_query.mad_buf->mad; init_mad(mad, agent); @@ -893,7 +852,6 @@ int ib_sa_mcmember_rec_query(struct ib_sa_client *client, err2: *sa_query = NULL; - ib_sa_client_put(query->sa_query.client); ib_free_send_mad(query->sa_query.mad_buf); err1: @@ -928,9 +886,8 @@ static void send_handler(struct ib_mad_agent *agent, idr_remove(&query_idr, query->id); spin_unlock_irqrestore(&idr_lock, flags); - ib_free_send_mad(mad_send_wc->send_buf); + ib_free_send_mad(mad_send_wc->send_buf); kref_put(&query->sm_ah->ref, free_sm_ah); - ib_sa_client_put(query->client); query->release(query); } @@ -961,10 +918,7 @@ static void ib_sa_add_one(struct ib_device *device) struct ib_sa_device *sa_dev; int s, e, i; - if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) - return; - - if (device->node_type == RDMA_NODE_IB_SWITCH) + if (device->node_type == IB_NODE_SWITCH) s = e = 0; else { s = 1; diff --git a/trunk/drivers/infiniband/core/smi.c b/trunk/drivers/infiniband/core/smi.c index 54b81e17ad50..35852e794e26 100644 --- a/trunk/drivers/infiniband/core/smi.c +++ b/trunk/drivers/infiniband/core/smi.c @@ -64,7 +64,7 @@ int smi_handle_dr_smp_send(struct ib_smp *smp, /* C14-9:2 */ if (hop_ptr && hop_ptr < hop_cnt) { - if (node_type != RDMA_NODE_IB_SWITCH) + if (node_type != IB_NODE_SWITCH) return 0; /* smp->return_path set when received */ @@ -77,7 +77,7 @@ int smi_handle_dr_smp_send(struct ib_smp *smp, if (hop_ptr == hop_cnt) { /* smp->return_path set when received */ smp->hop_ptr++; - return (node_type == RDMA_NODE_IB_SWITCH || + return (node_type == IB_NODE_SWITCH || smp->dr_dlid == IB_LID_PERMISSIVE); } @@ -95,7 +95,7 @@ int smi_handle_dr_smp_send(struct ib_smp *smp, /* C14-13:2 */ if (2 <= hop_ptr && hop_ptr <= hop_cnt) { - if (node_type != RDMA_NODE_IB_SWITCH) + if (node_type != IB_NODE_SWITCH) return 0; smp->hop_ptr--; @@ -107,7 +107,7 @@ int smi_handle_dr_smp_send(struct ib_smp *smp, if (hop_ptr == 1) { smp->hop_ptr--; /* C14-13:3 -- SMPs destined for SM shouldn't be here */ - return (node_type == RDMA_NODE_IB_SWITCH || + return (node_type == IB_NODE_SWITCH || smp->dr_slid == IB_LID_PERMISSIVE); } @@ -142,7 +142,7 @@ int smi_handle_dr_smp_recv(struct ib_smp *smp, /* C14-9:2 -- intermediate hop */ if (hop_ptr && hop_ptr < hop_cnt) { - if (node_type != RDMA_NODE_IB_SWITCH) + if (node_type != IB_NODE_SWITCH) return 0; smp->return_path[hop_ptr] = port_num; @@ -156,7 +156,7 @@ int smi_handle_dr_smp_recv(struct ib_smp *smp, smp->return_path[hop_ptr] = port_num; /* smp->hop_ptr updated when sending */ - return (node_type == RDMA_NODE_IB_SWITCH || + return (node_type == IB_NODE_SWITCH || smp->dr_dlid == IB_LID_PERMISSIVE); } @@ -175,7 +175,7 @@ int smi_handle_dr_smp_recv(struct ib_smp *smp, /* C14-13:2 */ if (2 <= hop_ptr && hop_ptr <= hop_cnt) { - if (node_type != RDMA_NODE_IB_SWITCH) + if (node_type != IB_NODE_SWITCH) return 0; /* smp->hop_ptr updated when sending */ @@ -190,7 +190,7 @@ int smi_handle_dr_smp_recv(struct ib_smp *smp, return 1; } /* smp->hop_ptr updated when sending */ - return (node_type == RDMA_NODE_IB_SWITCH); + return (node_type == IB_NODE_SWITCH); } /* C14-13:4 -- hop_ptr = 0 -> give to SM */ diff --git a/trunk/drivers/infiniband/core/sysfs.c b/trunk/drivers/infiniband/core/sysfs.c index 709323c14c5d..21f9282c1b25 100644 --- a/trunk/drivers/infiniband/core/sysfs.c +++ b/trunk/drivers/infiniband/core/sysfs.c @@ -68,7 +68,7 @@ struct port_table_attribute { int index; }; -static inline int ibdev_is_alive(const struct ib_device *dev) +static inline int ibdev_is_alive(const struct ib_device *dev) { return dev->reg_state == IB_DEV_REGISTERED; } @@ -589,11 +589,10 @@ static ssize_t show_node_type(struct class_device *cdev, char *buf) return -ENODEV; switch (dev->node_type) { - case RDMA_NODE_IB_CA: return sprintf(buf, "%d: CA\n", dev->node_type); - case RDMA_NODE_RNIC: return sprintf(buf, "%d: RNIC\n", dev->node_type); - case RDMA_NODE_IB_SWITCH: return sprintf(buf, "%d: switch\n", dev->node_type); - case RDMA_NODE_IB_ROUTER: return sprintf(buf, "%d: router\n", dev->node_type); - default: return sprintf(buf, "%d: \n", dev->node_type); + case IB_NODE_CA: return sprintf(buf, "%d: CA\n", dev->node_type); + case IB_NODE_SWITCH: return sprintf(buf, "%d: switch\n", dev->node_type); + case IB_NODE_ROUTER: return sprintf(buf, "%d: router\n", dev->node_type); + default: return sprintf(buf, "%d: \n", dev->node_type); } } @@ -709,7 +708,7 @@ int ib_device_register_sysfs(struct ib_device *device) if (ret) goto err_put; - if (device->node_type == RDMA_NODE_IB_SWITCH) { + if (device->node_type == IB_NODE_SWITCH) { ret = add_port(device, 0); if (ret) goto err_put; diff --git a/trunk/drivers/infiniband/core/ucm.c b/trunk/drivers/infiniband/core/ucm.c index ad4f4d5c2924..c1c6fda9452c 100644 --- a/trunk/drivers/infiniband/core/ucm.c +++ b/trunk/drivers/infiniband/core/ucm.c @@ -309,9 +309,9 @@ static int ib_ucm_event_process(struct ib_cm_event *evt, info = evt->param.apr_rcvd.apr_info; break; case IB_CM_SIDR_REQ_RECEIVED: - uvt->resp.u.sidr_req_resp.pkey = + uvt->resp.u.sidr_req_resp.pkey = evt->param.sidr_req_rcvd.pkey; - uvt->resp.u.sidr_req_resp.port = + uvt->resp.u.sidr_req_resp.port = evt->param.sidr_req_rcvd.port; uvt->data_len = IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE; break; @@ -1237,7 +1237,7 @@ static struct class ucm_class = { static ssize_t show_ibdev(struct class_device *class_dev, char *buf) { struct ib_ucm_device *dev; - + dev = container_of(class_dev, struct ib_ucm_device, class_dev); return sprintf(buf, "%s\n", dev->ib_dev->name); } @@ -1247,8 +1247,7 @@ static void ib_ucm_add_one(struct ib_device *device) { struct ib_ucm_device *ucm_dev; - if (!device->alloc_ucontext || - rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) + if (!device->alloc_ucontext) return; ucm_dev = kzalloc(sizeof *ucm_dev, GFP_KERNEL); diff --git a/trunk/drivers/infiniband/core/user_mad.c b/trunk/drivers/infiniband/core/user_mad.c index 807fbd6b8414..1273f8807e84 100644 --- a/trunk/drivers/infiniband/core/user_mad.c +++ b/trunk/drivers/infiniband/core/user_mad.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2004 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Voltaire, Inc. All rights reserved. + * Copyright (c) 2005 Voltaire, Inc. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. * * This software is available to you under a choice of one of two @@ -1032,10 +1032,7 @@ static void ib_umad_add_one(struct ib_device *device) struct ib_umad_device *umad_dev; int s, e, i; - if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) - return; - - if (device->node_type == RDMA_NODE_IB_SWITCH) + if (device->node_type == IB_NODE_SWITCH) s = e = 0; else { s = 1; diff --git a/trunk/drivers/infiniband/core/uverbs.h b/trunk/drivers/infiniband/core/uverbs.h index 102a59c033ff..bb9bee56a824 100644 --- a/trunk/drivers/infiniband/core/uverbs.h +++ b/trunk/drivers/infiniband/core/uverbs.h @@ -42,7 +42,6 @@ #include #include #include -#include #include #include @@ -70,7 +69,6 @@ struct ib_uverbs_device { struct kref ref; - struct completion comp; int devnum; struct cdev *dev; struct class_device *class_dev; diff --git a/trunk/drivers/infiniband/core/uverbs_cmd.c b/trunk/drivers/infiniband/core/uverbs_cmd.c index b72c7f69ca90..30923eb68ec7 100644 --- a/trunk/drivers/infiniband/core/uverbs_cmd.c +++ b/trunk/drivers/infiniband/core/uverbs_cmd.c @@ -155,7 +155,7 @@ static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id, } static struct ib_uobject *idr_read_uobj(struct idr *idr, int id, - struct ib_ucontext *context, int nested) + struct ib_ucontext *context) { struct ib_uobject *uobj; @@ -163,10 +163,7 @@ static struct ib_uobject *idr_read_uobj(struct idr *idr, int id, if (!uobj) return NULL; - if (nested) - down_read_nested(&uobj->mutex, SINGLE_DEPTH_NESTING); - else - down_read(&uobj->mutex); + down_read(&uobj->mutex); if (!uobj->live) { put_uobj_read(uobj); return NULL; @@ -193,18 +190,17 @@ static struct ib_uobject *idr_write_uobj(struct idr *idr, int id, return uobj; } -static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context, - int nested) +static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context) { struct ib_uobject *uobj; - uobj = idr_read_uobj(idr, id, context, nested); + uobj = idr_read_uobj(idr, id, context); return uobj ? uobj->object : NULL; } static struct ib_pd *idr_read_pd(int pd_handle, struct ib_ucontext *context) { - return idr_read_obj(&ib_uverbs_pd_idr, pd_handle, context, 0); + return idr_read_obj(&ib_uverbs_pd_idr, pd_handle, context); } static void put_pd_read(struct ib_pd *pd) @@ -212,9 +208,9 @@ static void put_pd_read(struct ib_pd *pd) put_uobj_read(pd->uobject); } -static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context, int nested) +static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context) { - return idr_read_obj(&ib_uverbs_cq_idr, cq_handle, context, nested); + return idr_read_obj(&ib_uverbs_cq_idr, cq_handle, context); } static void put_cq_read(struct ib_cq *cq) @@ -224,7 +220,7 @@ static void put_cq_read(struct ib_cq *cq) static struct ib_ah *idr_read_ah(int ah_handle, struct ib_ucontext *context) { - return idr_read_obj(&ib_uverbs_ah_idr, ah_handle, context, 0); + return idr_read_obj(&ib_uverbs_ah_idr, ah_handle, context); } static void put_ah_read(struct ib_ah *ah) @@ -234,7 +230,7 @@ static void put_ah_read(struct ib_ah *ah) static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context) { - return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context, 0); + return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context); } static void put_qp_read(struct ib_qp *qp) @@ -244,7 +240,7 @@ static void put_qp_read(struct ib_qp *qp) static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context) { - return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context, 0); + return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context); } static void put_srq_read(struct ib_srq *srq) @@ -841,6 +837,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, err_copy: idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject); + err_free: ib_destroy_cq(cq); @@ -870,7 +867,7 @@ ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file, (unsigned long) cmd.response + sizeof resp, in_len - sizeof cmd, out_len - sizeof resp); - cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0); + cq = idr_read_cq(cmd.cq_handle, file->ucontext); if (!cq) return -EINVAL; @@ -878,10 +875,11 @@ ssize_t ib_uverbs_resize_cq(struct ib_uverbs_file *file, if (ret) goto out; + memset(&resp, 0, sizeof resp); resp.cqe = cq->cqe; if (copy_to_user((void __user *) (unsigned long) cmd.response, - &resp, sizeof resp.cqe)) + &resp, sizeof resp)) ret = -EFAULT; out: @@ -896,6 +894,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, { struct ib_uverbs_poll_cq cmd; struct ib_uverbs_poll_cq_resp *resp; + struct ib_uobject *uobj; struct ib_cq *cq; struct ib_wc *wc; int ret = 0; @@ -916,15 +915,16 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, goto out_wc; } - cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0); - if (!cq) { + uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext); + if (!uobj) { ret = -EINVAL; goto out; } + cq = uobj->object; resp->count = ib_poll_cq(cq, cmd.ne, wc); - put_cq_read(cq); + put_uobj_read(uobj); for (i = 0; i < resp->count; i++) { resp->wc[i].wr_id = wc[i].wr_id; @@ -959,19 +959,21 @@ ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file, int out_len) { struct ib_uverbs_req_notify_cq cmd; + struct ib_uobject *uobj; struct ib_cq *cq; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - cq = idr_read_cq(cmd.cq_handle, file->ucontext, 0); - if (!cq) + uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext); + if (!uobj) return -EINVAL; + cq = uobj->object; ib_req_notify_cq(cq, cmd.solicited_only ? IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); - put_cq_read(cq); + put_uobj_read(uobj); return in_len; } @@ -1062,9 +1064,9 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL; pd = idr_read_pd(cmd.pd_handle, file->ucontext); - scq = idr_read_cq(cmd.send_cq_handle, file->ucontext, 0); + scq = idr_read_cq(cmd.send_cq_handle, file->ucontext); rcq = cmd.recv_cq_handle == cmd.send_cq_handle ? - scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1); + scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext); if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) { ret = -EINVAL; @@ -1272,7 +1274,6 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, int out_len) { struct ib_uverbs_modify_qp cmd; - struct ib_udata udata; struct ib_qp *qp; struct ib_qp_attr *attr; int ret; @@ -1280,9 +1281,6 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd, - out_len); - attr = kmalloc(sizeof *attr, GFP_KERNEL); if (!attr) return -ENOMEM; @@ -1339,7 +1337,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0; attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; - ret = qp->device->modify_qp(qp, attr, cmd.attr_mask, &udata); + ret = ib_modify_qp(qp, attr, cmd.attr_mask); put_qp_read(qp); @@ -1676,6 +1674,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file, break; } + if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) ret = -EFAULT; @@ -1725,6 +1724,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, break; } + if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) ret = -EFAULT; @@ -2055,7 +2055,6 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, int out_len) { struct ib_uverbs_modify_srq cmd; - struct ib_udata udata; struct ib_srq *srq; struct ib_srq_attr attr; int ret; @@ -2063,9 +2062,6 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd, - out_len); - srq = idr_read_srq(cmd.srq_handle, file->ucontext); if (!srq) return -EINVAL; @@ -2073,7 +2069,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, attr.max_wr = cmd.max_wr; attr.srq_limit = cmd.srq_limit; - ret = srq->device->modify_srq(srq, &attr, cmd.attr_mask, &udata); + ret = ib_modify_srq(srq, &attr, cmd.attr_mask); put_srq_read(srq); diff --git a/trunk/drivers/infiniband/core/uverbs_main.c b/trunk/drivers/infiniband/core/uverbs_main.c index 4e16314e8e6d..e725cccc7cde 100644 --- a/trunk/drivers/infiniband/core/uverbs_main.c +++ b/trunk/drivers/infiniband/core/uverbs_main.c @@ -122,7 +122,7 @@ static void ib_uverbs_release_dev(struct kref *ref) struct ib_uverbs_device *dev = container_of(ref, struct ib_uverbs_device, ref); - complete(&dev->comp); + kfree(dev); } void ib_uverbs_release_ucq(struct ib_uverbs_file *file, @@ -740,7 +740,6 @@ static void ib_uverbs_add_one(struct ib_device *device) return; kref_init(&uverbs_dev->ref); - init_completion(&uverbs_dev->comp); spin_lock(&map_lock); uverbs_dev->devnum = find_first_zero_bit(dev_map, IB_UVERBS_MAX_DEVICES); @@ -794,8 +793,6 @@ static void ib_uverbs_add_one(struct ib_device *device) err: kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); - wait_for_completion(&uverbs_dev->comp); - kfree(uverbs_dev); return; } @@ -815,10 +812,7 @@ static void ib_uverbs_remove_one(struct ib_device *device) spin_unlock(&map_lock); clear_bit(uverbs_dev->devnum, dev_map); - kref_put(&uverbs_dev->ref, ib_uverbs_release_dev); - wait_for_completion(&uverbs_dev->comp); - kfree(uverbs_dev); } static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags, diff --git a/trunk/drivers/infiniband/core/verbs.c b/trunk/drivers/infiniband/core/verbs.c index 8b5dd3649bbf..468999c38803 100644 --- a/trunk/drivers/infiniband/core/verbs.c +++ b/trunk/drivers/infiniband/core/verbs.c @@ -79,23 +79,6 @@ enum ib_rate mult_to_ib_rate(int mult) } EXPORT_SYMBOL(mult_to_ib_rate); -enum rdma_transport_type -rdma_node_get_transport(enum rdma_node_type node_type) -{ - switch (node_type) { - case RDMA_NODE_IB_CA: - case RDMA_NODE_IB_SWITCH: - case RDMA_NODE_IB_ROUTER: - return RDMA_TRANSPORT_IB; - case RDMA_NODE_RNIC: - return RDMA_TRANSPORT_IWARP; - default: - BUG(); - return 0; - } -} -EXPORT_SYMBOL(rdma_node_get_transport); - /* Protection domains */ struct ib_pd *ib_alloc_pd(struct ib_device *device) @@ -248,7 +231,7 @@ int ib_modify_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr, enum ib_srq_attr_mask srq_attr_mask) { - return srq->device->modify_srq(srq, srq_attr, srq_attr_mask, NULL); + return srq->device->modify_srq(srq, srq_attr, srq_attr_mask); } EXPORT_SYMBOL(ib_modify_srq); @@ -564,7 +547,7 @@ int ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr, int qp_attr_mask) { - return qp->device->modify_qp(qp, qp_attr, qp_attr_mask, NULL); + return qp->device->modify_qp(qp, qp_attr, qp_attr_mask); } EXPORT_SYMBOL(ib_modify_qp); diff --git a/trunk/drivers/infiniband/hw/amso1100/Kbuild b/trunk/drivers/infiniband/hw/amso1100/Kbuild deleted file mode 100644 index 06964c4af849..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/Kbuild +++ /dev/null @@ -1,8 +0,0 @@ -ifdef CONFIG_INFINIBAND_AMSO1100_DEBUG -EXTRA_CFLAGS += -DDEBUG -endif - -obj-$(CONFIG_INFINIBAND_AMSO1100) += iw_c2.o - -iw_c2-y := c2.o c2_provider.o c2_rnic.o c2_alloc.o c2_mq.o c2_ae.o c2_vq.o \ - c2_intr.o c2_cq.o c2_qp.o c2_cm.o c2_mm.o c2_pd.o diff --git a/trunk/drivers/infiniband/hw/amso1100/Kconfig b/trunk/drivers/infiniband/hw/amso1100/Kconfig deleted file mode 100644 index 809cb14ac6de..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ -config INFINIBAND_AMSO1100 - tristate "Ammasso 1100 HCA support" - depends on PCI && INET && INFINIBAND - ---help--- - This is a low-level driver for the Ammasso 1100 host - channel adapter (HCA). - -config INFINIBAND_AMSO1100_DEBUG - bool "Verbose debugging output" - depends on INFINIBAND_AMSO1100 - default n - ---help--- - This option causes the amso1100 driver to produce a bunch of - debug messages. Select this if you are developing the driver - or trying to diagnose a problem. diff --git a/trunk/drivers/infiniband/hw/amso1100/c2.c b/trunk/drivers/infiniband/hw/amso1100/c2.c deleted file mode 100644 index 9e9120f36019..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2.c +++ /dev/null @@ -1,1255 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include "c2.h" -#include "c2_provider.h" - -MODULE_AUTHOR("Tom Tucker "); -MODULE_DESCRIPTION("Ammasso AMSO1100 Low-level iWARP Driver"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION(DRV_VERSION); - -static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK - | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN; - -static int debug = -1; /* defaults above */ -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); - -static int c2_up(struct net_device *netdev); -static int c2_down(struct net_device *netdev); -static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev); -static void c2_tx_interrupt(struct net_device *netdev); -static void c2_rx_interrupt(struct net_device *netdev); -static irqreturn_t c2_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void c2_tx_timeout(struct net_device *netdev); -static int c2_change_mtu(struct net_device *netdev, int new_mtu); -static void c2_reset(struct c2_port *c2_port); -static struct net_device_stats *c2_get_stats(struct net_device *netdev); - -static struct pci_device_id c2_pci_table[] = { - { PCI_DEVICE(0x18b8, 0xb001) }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, c2_pci_table); - -static void c2_print_macaddr(struct net_device *netdev) -{ - pr_debug("%s: MAC %02X:%02X:%02X:%02X:%02X:%02X, " - "IRQ %u\n", netdev->name, - netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], - netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5], - netdev->irq); -} - -static void c2_set_rxbufsize(struct c2_port *c2_port) -{ - struct net_device *netdev = c2_port->netdev; - - if (netdev->mtu > RX_BUF_SIZE) - c2_port->rx_buf_size = - netdev->mtu + ETH_HLEN + sizeof(struct c2_rxp_hdr) + - NET_IP_ALIGN; - else - c2_port->rx_buf_size = sizeof(struct c2_rxp_hdr) + RX_BUF_SIZE; -} - -/* - * Allocate TX ring elements and chain them together. - * One-to-one association of adapter descriptors with ring elements. - */ -static int c2_tx_ring_alloc(struct c2_ring *tx_ring, void *vaddr, - dma_addr_t base, void __iomem * mmio_txp_ring) -{ - struct c2_tx_desc *tx_desc; - struct c2_txp_desc __iomem *txp_desc; - struct c2_element *elem; - int i; - - tx_ring->start = kmalloc(sizeof(*elem) * tx_ring->count, GFP_KERNEL); - if (!tx_ring->start) - return -ENOMEM; - - elem = tx_ring->start; - tx_desc = vaddr; - txp_desc = mmio_txp_ring; - for (i = 0; i < tx_ring->count; i++, elem++, tx_desc++, txp_desc++) { - tx_desc->len = 0; - tx_desc->status = 0; - - /* Set TXP_HTXD_UNINIT */ - __raw_writeq(cpu_to_be64(0x1122334455667788ULL), - (void __iomem *) txp_desc + C2_TXP_ADDR); - __raw_writew(0, (void __iomem *) txp_desc + C2_TXP_LEN); - __raw_writew(cpu_to_be16(TXP_HTXD_UNINIT), - (void __iomem *) txp_desc + C2_TXP_FLAGS); - - elem->skb = NULL; - elem->ht_desc = tx_desc; - elem->hw_desc = txp_desc; - - if (i == tx_ring->count - 1) { - elem->next = tx_ring->start; - tx_desc->next_offset = base; - } else { - elem->next = elem + 1; - tx_desc->next_offset = - base + (i + 1) * sizeof(*tx_desc); - } - } - - tx_ring->to_use = tx_ring->to_clean = tx_ring->start; - - return 0; -} - -/* - * Allocate RX ring elements and chain them together. - * One-to-one association of adapter descriptors with ring elements. - */ -static int c2_rx_ring_alloc(struct c2_ring *rx_ring, void *vaddr, - dma_addr_t base, void __iomem * mmio_rxp_ring) -{ - struct c2_rx_desc *rx_desc; - struct c2_rxp_desc __iomem *rxp_desc; - struct c2_element *elem; - int i; - - rx_ring->start = kmalloc(sizeof(*elem) * rx_ring->count, GFP_KERNEL); - if (!rx_ring->start) - return -ENOMEM; - - elem = rx_ring->start; - rx_desc = vaddr; - rxp_desc = mmio_rxp_ring; - for (i = 0; i < rx_ring->count; i++, elem++, rx_desc++, rxp_desc++) { - rx_desc->len = 0; - rx_desc->status = 0; - - /* Set RXP_HRXD_UNINIT */ - __raw_writew(cpu_to_be16(RXP_HRXD_OK), - (void __iomem *) rxp_desc + C2_RXP_STATUS); - __raw_writew(0, (void __iomem *) rxp_desc + C2_RXP_COUNT); - __raw_writew(0, (void __iomem *) rxp_desc + C2_RXP_LEN); - __raw_writeq(cpu_to_be64(0x99aabbccddeeffULL), - (void __iomem *) rxp_desc + C2_RXP_ADDR); - __raw_writew(cpu_to_be16(RXP_HRXD_UNINIT), - (void __iomem *) rxp_desc + C2_RXP_FLAGS); - - elem->skb = NULL; - elem->ht_desc = rx_desc; - elem->hw_desc = rxp_desc; - - if (i == rx_ring->count - 1) { - elem->next = rx_ring->start; - rx_desc->next_offset = base; - } else { - elem->next = elem + 1; - rx_desc->next_offset = - base + (i + 1) * sizeof(*rx_desc); - } - } - - rx_ring->to_use = rx_ring->to_clean = rx_ring->start; - - return 0; -} - -/* Setup buffer for receiving */ -static inline int c2_rx_alloc(struct c2_port *c2_port, struct c2_element *elem) -{ - struct c2_dev *c2dev = c2_port->c2dev; - struct c2_rx_desc *rx_desc = elem->ht_desc; - struct sk_buff *skb; - dma_addr_t mapaddr; - u32 maplen; - struct c2_rxp_hdr *rxp_hdr; - - skb = dev_alloc_skb(c2_port->rx_buf_size); - if (unlikely(!skb)) { - pr_debug("%s: out of memory for receive\n", - c2_port->netdev->name); - return -ENOMEM; - } - - /* Zero out the rxp hdr in the sk_buff */ - memset(skb->data, 0, sizeof(*rxp_hdr)); - - skb->dev = c2_port->netdev; - - maplen = c2_port->rx_buf_size; - mapaddr = - pci_map_single(c2dev->pcidev, skb->data, maplen, - PCI_DMA_FROMDEVICE); - - /* Set the sk_buff RXP_header to RXP_HRXD_READY */ - rxp_hdr = (struct c2_rxp_hdr *) skb->data; - rxp_hdr->flags = RXP_HRXD_READY; - - __raw_writew(0, elem->hw_desc + C2_RXP_STATUS); - __raw_writew(cpu_to_be16((u16) maplen - sizeof(*rxp_hdr)), - elem->hw_desc + C2_RXP_LEN); - __raw_writeq(cpu_to_be64(mapaddr), elem->hw_desc + C2_RXP_ADDR); - __raw_writew(cpu_to_be16(RXP_HRXD_READY), elem->hw_desc + C2_RXP_FLAGS); - - elem->skb = skb; - elem->mapaddr = mapaddr; - elem->maplen = maplen; - rx_desc->len = maplen; - - return 0; -} - -/* - * Allocate buffers for the Rx ring - * For receive: rx_ring.to_clean is next received frame - */ -static int c2_rx_fill(struct c2_port *c2_port) -{ - struct c2_ring *rx_ring = &c2_port->rx_ring; - struct c2_element *elem; - int ret = 0; - - elem = rx_ring->start; - do { - if (c2_rx_alloc(c2_port, elem)) { - ret = 1; - break; - } - } while ((elem = elem->next) != rx_ring->start); - - rx_ring->to_clean = rx_ring->start; - return ret; -} - -/* Free all buffers in RX ring, assumes receiver stopped */ -static void c2_rx_clean(struct c2_port *c2_port) -{ - struct c2_dev *c2dev = c2_port->c2dev; - struct c2_ring *rx_ring = &c2_port->rx_ring; - struct c2_element *elem; - struct c2_rx_desc *rx_desc; - - elem = rx_ring->start; - do { - rx_desc = elem->ht_desc; - rx_desc->len = 0; - - __raw_writew(0, elem->hw_desc + C2_RXP_STATUS); - __raw_writew(0, elem->hw_desc + C2_RXP_COUNT); - __raw_writew(0, elem->hw_desc + C2_RXP_LEN); - __raw_writeq(cpu_to_be64(0x99aabbccddeeffULL), - elem->hw_desc + C2_RXP_ADDR); - __raw_writew(cpu_to_be16(RXP_HRXD_UNINIT), - elem->hw_desc + C2_RXP_FLAGS); - - if (elem->skb) { - pci_unmap_single(c2dev->pcidev, elem->mapaddr, - elem->maplen, PCI_DMA_FROMDEVICE); - dev_kfree_skb(elem->skb); - elem->skb = NULL; - } - } while ((elem = elem->next) != rx_ring->start); -} - -static inline int c2_tx_free(struct c2_dev *c2dev, struct c2_element *elem) -{ - struct c2_tx_desc *tx_desc = elem->ht_desc; - - tx_desc->len = 0; - - pci_unmap_single(c2dev->pcidev, elem->mapaddr, elem->maplen, - PCI_DMA_TODEVICE); - - if (elem->skb) { - dev_kfree_skb_any(elem->skb); - elem->skb = NULL; - } - - return 0; -} - -/* Free all buffers in TX ring, assumes transmitter stopped */ -static void c2_tx_clean(struct c2_port *c2_port) -{ - struct c2_ring *tx_ring = &c2_port->tx_ring; - struct c2_element *elem; - struct c2_txp_desc txp_htxd; - int retry; - unsigned long flags; - - spin_lock_irqsave(&c2_port->tx_lock, flags); - - elem = tx_ring->start; - - do { - retry = 0; - do { - txp_htxd.flags = - readw(elem->hw_desc + C2_TXP_FLAGS); - - if (txp_htxd.flags == TXP_HTXD_READY) { - retry = 1; - __raw_writew(0, - elem->hw_desc + C2_TXP_LEN); - __raw_writeq(0, - elem->hw_desc + C2_TXP_ADDR); - __raw_writew(cpu_to_be16(TXP_HTXD_DONE), - elem->hw_desc + C2_TXP_FLAGS); - c2_port->netstats.tx_dropped++; - break; - } else { - __raw_writew(0, - elem->hw_desc + C2_TXP_LEN); - __raw_writeq(cpu_to_be64(0x1122334455667788ULL), - elem->hw_desc + C2_TXP_ADDR); - __raw_writew(cpu_to_be16(TXP_HTXD_UNINIT), - elem->hw_desc + C2_TXP_FLAGS); - } - - c2_tx_free(c2_port->c2dev, elem); - - } while ((elem = elem->next) != tx_ring->start); - } while (retry); - - c2_port->tx_avail = c2_port->tx_ring.count - 1; - c2_port->c2dev->cur_tx = tx_ring->to_use - tx_ring->start; - - if (c2_port->tx_avail > MAX_SKB_FRAGS + 1) - netif_wake_queue(c2_port->netdev); - - spin_unlock_irqrestore(&c2_port->tx_lock, flags); -} - -/* - * Process transmit descriptors marked 'DONE' by the firmware, - * freeing up their unneeded sk_buffs. - */ -static void c2_tx_interrupt(struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - struct c2_dev *c2dev = c2_port->c2dev; - struct c2_ring *tx_ring = &c2_port->tx_ring; - struct c2_element *elem; - struct c2_txp_desc txp_htxd; - - spin_lock(&c2_port->tx_lock); - - for (elem = tx_ring->to_clean; elem != tx_ring->to_use; - elem = elem->next) { - txp_htxd.flags = - be16_to_cpu(readw(elem->hw_desc + C2_TXP_FLAGS)); - - if (txp_htxd.flags != TXP_HTXD_DONE) - break; - - if (netif_msg_tx_done(c2_port)) { - /* PCI reads are expensive in fast path */ - txp_htxd.len = - be16_to_cpu(readw(elem->hw_desc + C2_TXP_LEN)); - pr_debug("%s: tx done slot %3Zu status 0x%x len " - "%5u bytes\n", - netdev->name, elem - tx_ring->start, - txp_htxd.flags, txp_htxd.len); - } - - c2_tx_free(c2dev, elem); - ++(c2_port->tx_avail); - } - - tx_ring->to_clean = elem; - - if (netif_queue_stopped(netdev) - && c2_port->tx_avail > MAX_SKB_FRAGS + 1) - netif_wake_queue(netdev); - - spin_unlock(&c2_port->tx_lock); -} - -static void c2_rx_error(struct c2_port *c2_port, struct c2_element *elem) -{ - struct c2_rx_desc *rx_desc = elem->ht_desc; - struct c2_rxp_hdr *rxp_hdr = (struct c2_rxp_hdr *) elem->skb->data; - - if (rxp_hdr->status != RXP_HRXD_OK || - rxp_hdr->len > (rx_desc->len - sizeof(*rxp_hdr))) { - pr_debug("BAD RXP_HRXD\n"); - pr_debug(" rx_desc : %p\n", rx_desc); - pr_debug(" index : %Zu\n", - elem - c2_port->rx_ring.start); - pr_debug(" len : %u\n", rx_desc->len); - pr_debug(" rxp_hdr : %p [PA %p]\n", rxp_hdr, - (void *) __pa((unsigned long) rxp_hdr)); - pr_debug(" flags : 0x%x\n", rxp_hdr->flags); - pr_debug(" status: 0x%x\n", rxp_hdr->status); - pr_debug(" len : %u\n", rxp_hdr->len); - pr_debug(" rsvd : 0x%x\n", rxp_hdr->rsvd); - } - - /* Setup the skb for reuse since we're dropping this pkt */ - elem->skb->tail = elem->skb->data = elem->skb->head; - - /* Zero out the rxp hdr in the sk_buff */ - memset(elem->skb->data, 0, sizeof(*rxp_hdr)); - - /* Write the descriptor to the adapter's rx ring */ - __raw_writew(0, elem->hw_desc + C2_RXP_STATUS); - __raw_writew(0, elem->hw_desc + C2_RXP_COUNT); - __raw_writew(cpu_to_be16((u16) elem->maplen - sizeof(*rxp_hdr)), - elem->hw_desc + C2_RXP_LEN); - __raw_writeq(cpu_to_be64(elem->mapaddr), elem->hw_desc + C2_RXP_ADDR); - __raw_writew(cpu_to_be16(RXP_HRXD_READY), elem->hw_desc + C2_RXP_FLAGS); - - pr_debug("packet dropped\n"); - c2_port->netstats.rx_dropped++; -} - -static void c2_rx_interrupt(struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - struct c2_dev *c2dev = c2_port->c2dev; - struct c2_ring *rx_ring = &c2_port->rx_ring; - struct c2_element *elem; - struct c2_rx_desc *rx_desc; - struct c2_rxp_hdr *rxp_hdr; - struct sk_buff *skb; - dma_addr_t mapaddr; - u32 maplen, buflen; - unsigned long flags; - - spin_lock_irqsave(&c2dev->lock, flags); - - /* Begin where we left off */ - rx_ring->to_clean = rx_ring->start + c2dev->cur_rx; - - for (elem = rx_ring->to_clean; elem->next != rx_ring->to_clean; - elem = elem->next) { - rx_desc = elem->ht_desc; - mapaddr = elem->mapaddr; - maplen = elem->maplen; - skb = elem->skb; - rxp_hdr = (struct c2_rxp_hdr *) skb->data; - - if (rxp_hdr->flags != RXP_HRXD_DONE) - break; - buflen = rxp_hdr->len; - - /* Sanity check the RXP header */ - if (rxp_hdr->status != RXP_HRXD_OK || - buflen > (rx_desc->len - sizeof(*rxp_hdr))) { - c2_rx_error(c2_port, elem); - continue; - } - - /* - * Allocate and map a new skb for replenishing the host - * RX desc - */ - if (c2_rx_alloc(c2_port, elem)) { - c2_rx_error(c2_port, elem); - continue; - } - - /* Unmap the old skb */ - pci_unmap_single(c2dev->pcidev, mapaddr, maplen, - PCI_DMA_FROMDEVICE); - - prefetch(skb->data); - - /* - * Skip past the leading 8 bytes comprising of the - * "struct c2_rxp_hdr", prepended by the adapter - * to the usual Ethernet header ("struct ethhdr"), - * to the start of the raw Ethernet packet. - * - * Fix up the various fields in the sk_buff before - * passing it up to netif_rx(). The transfer size - * (in bytes) specified by the adapter len field of - * the "struct rxp_hdr_t" does NOT include the - * "sizeof(struct c2_rxp_hdr)". - */ - skb->data += sizeof(*rxp_hdr); - skb->tail = skb->data + buflen; - skb->len = buflen; - skb->dev = netdev; - skb->protocol = eth_type_trans(skb, netdev); - - netif_rx(skb); - - netdev->last_rx = jiffies; - c2_port->netstats.rx_packets++; - c2_port->netstats.rx_bytes += buflen; - } - - /* Save where we left off */ - rx_ring->to_clean = elem; - c2dev->cur_rx = elem - rx_ring->start; - C2_SET_CUR_RX(c2dev, c2dev->cur_rx); - - spin_unlock_irqrestore(&c2dev->lock, flags); -} - -/* - * Handle netisr0 TX & RX interrupts. - */ -static irqreturn_t c2_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned int netisr0, dmaisr; - int handled = 0; - struct c2_dev *c2dev = (struct c2_dev *) dev_id; - - /* Process CCILNET interrupts */ - netisr0 = readl(c2dev->regs + C2_NISR0); - if (netisr0) { - - /* - * There is an issue with the firmware that always - * provides the status of RX for both TX & RX - * interrupts. So process both queues here. - */ - c2_rx_interrupt(c2dev->netdev); - c2_tx_interrupt(c2dev->netdev); - - /* Clear the interrupt */ - writel(netisr0, c2dev->regs + C2_NISR0); - handled++; - } - - /* Process RNIC interrupts */ - dmaisr = readl(c2dev->regs + C2_DISR); - if (dmaisr) { - writel(dmaisr, c2dev->regs + C2_DISR); - c2_rnic_interrupt(c2dev); - handled++; - } - - if (handled) { - return IRQ_HANDLED; - } else { - return IRQ_NONE; - } -} - -static int c2_up(struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - struct c2_dev *c2dev = c2_port->c2dev; - struct c2_element *elem; - struct c2_rxp_hdr *rxp_hdr; - struct in_device *in_dev; - size_t rx_size, tx_size; - int ret, i; - unsigned int netimr0; - - if (netif_msg_ifup(c2_port)) - pr_debug("%s: enabling interface\n", netdev->name); - - /* Set the Rx buffer size based on MTU */ - c2_set_rxbufsize(c2_port); - - /* Allocate DMA'able memory for Tx/Rx host descriptor rings */ - rx_size = c2_port->rx_ring.count * sizeof(struct c2_rx_desc); - tx_size = c2_port->tx_ring.count * sizeof(struct c2_tx_desc); - - c2_port->mem_size = tx_size + rx_size; - c2_port->mem = pci_alloc_consistent(c2dev->pcidev, c2_port->mem_size, - &c2_port->dma); - if (c2_port->mem == NULL) { - pr_debug("Unable to allocate memory for " - "host descriptor rings\n"); - return -ENOMEM; - } - - memset(c2_port->mem, 0, c2_port->mem_size); - - /* Create the Rx host descriptor ring */ - if ((ret = - c2_rx_ring_alloc(&c2_port->rx_ring, c2_port->mem, c2_port->dma, - c2dev->mmio_rxp_ring))) { - pr_debug("Unable to create RX ring\n"); - goto bail0; - } - - /* Allocate Rx buffers for the host descriptor ring */ - if (c2_rx_fill(c2_port)) { - pr_debug("Unable to fill RX ring\n"); - goto bail1; - } - - /* Create the Tx host descriptor ring */ - if ((ret = c2_tx_ring_alloc(&c2_port->tx_ring, c2_port->mem + rx_size, - c2_port->dma + rx_size, - c2dev->mmio_txp_ring))) { - pr_debug("Unable to create TX ring\n"); - goto bail1; - } - - /* Set the TX pointer to where we left off */ - c2_port->tx_avail = c2_port->tx_ring.count - 1; - c2_port->tx_ring.to_use = c2_port->tx_ring.to_clean = - c2_port->tx_ring.start + c2dev->cur_tx; - - /* missing: Initialize MAC */ - - BUG_ON(c2_port->tx_ring.to_use != c2_port->tx_ring.to_clean); - - /* Reset the adapter, ensures the driver is in sync with the RXP */ - c2_reset(c2_port); - - /* Reset the READY bit in the sk_buff RXP headers & adapter HRXDQ */ - for (i = 0, elem = c2_port->rx_ring.start; i < c2_port->rx_ring.count; - i++, elem++) { - rxp_hdr = (struct c2_rxp_hdr *) elem->skb->data; - rxp_hdr->flags = 0; - __raw_writew(cpu_to_be16(RXP_HRXD_READY), - elem->hw_desc + C2_RXP_FLAGS); - } - - /* Enable network packets */ - netif_start_queue(netdev); - - /* Enable IRQ */ - writel(0, c2dev->regs + C2_IDIS); - netimr0 = readl(c2dev->regs + C2_NIMR0); - netimr0 &= ~(C2_PCI_HTX_INT | C2_PCI_HRX_INT); - writel(netimr0, c2dev->regs + C2_NIMR0); - - /* Tell the stack to ignore arp requests for ipaddrs bound to - * other interfaces. This is needed to prevent the host stack - * from responding to arp requests to the ipaddr bound on the - * rdma interface. - */ - in_dev = in_dev_get(netdev); - in_dev->cnf.arp_ignore = 1; - in_dev_put(in_dev); - - return 0; - - bail1: - c2_rx_clean(c2_port); - kfree(c2_port->rx_ring.start); - - bail0: - pci_free_consistent(c2dev->pcidev, c2_port->mem_size, c2_port->mem, - c2_port->dma); - - return ret; -} - -static int c2_down(struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - struct c2_dev *c2dev = c2_port->c2dev; - - if (netif_msg_ifdown(c2_port)) - pr_debug("%s: disabling interface\n", - netdev->name); - - /* Wait for all the queued packets to get sent */ - c2_tx_interrupt(netdev); - - /* Disable network packets */ - netif_stop_queue(netdev); - - /* Disable IRQs by clearing the interrupt mask */ - writel(1, c2dev->regs + C2_IDIS); - writel(0, c2dev->regs + C2_NIMR0); - - /* missing: Stop transmitter */ - - /* missing: Stop receiver */ - - /* Reset the adapter, ensures the driver is in sync with the RXP */ - c2_reset(c2_port); - - /* missing: Turn off LEDs here */ - - /* Free all buffers in the host descriptor rings */ - c2_tx_clean(c2_port); - c2_rx_clean(c2_port); - - /* Free the host descriptor rings */ - kfree(c2_port->rx_ring.start); - kfree(c2_port->tx_ring.start); - pci_free_consistent(c2dev->pcidev, c2_port->mem_size, c2_port->mem, - c2_port->dma); - - return 0; -} - -static void c2_reset(struct c2_port *c2_port) -{ - struct c2_dev *c2dev = c2_port->c2dev; - unsigned int cur_rx = c2dev->cur_rx; - - /* Tell the hardware to quiesce */ - C2_SET_CUR_RX(c2dev, cur_rx | C2_PCI_HRX_QUI); - - /* - * The hardware will reset the C2_PCI_HRX_QUI bit once - * the RXP is quiesced. Wait 2 seconds for this. - */ - ssleep(2); - - cur_rx = C2_GET_CUR_RX(c2dev); - - if (cur_rx & C2_PCI_HRX_QUI) - pr_debug("c2_reset: failed to quiesce the hardware!\n"); - - cur_rx &= ~C2_PCI_HRX_QUI; - - c2dev->cur_rx = cur_rx; - - pr_debug("Current RX: %u\n", c2dev->cur_rx); -} - -static int c2_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - struct c2_dev *c2dev = c2_port->c2dev; - struct c2_ring *tx_ring = &c2_port->tx_ring; - struct c2_element *elem; - dma_addr_t mapaddr; - u32 maplen; - unsigned long flags; - unsigned int i; - - spin_lock_irqsave(&c2_port->tx_lock, flags); - - if (unlikely(c2_port->tx_avail < (skb_shinfo(skb)->nr_frags + 1))) { - netif_stop_queue(netdev); - spin_unlock_irqrestore(&c2_port->tx_lock, flags); - - pr_debug("%s: Tx ring full when queue awake!\n", - netdev->name); - return NETDEV_TX_BUSY; - } - - maplen = skb_headlen(skb); - mapaddr = - pci_map_single(c2dev->pcidev, skb->data, maplen, PCI_DMA_TODEVICE); - - elem = tx_ring->to_use; - elem->skb = skb; - elem->mapaddr = mapaddr; - elem->maplen = maplen; - - /* Tell HW to xmit */ - __raw_writeq(cpu_to_be64(mapaddr), elem->hw_desc + C2_TXP_ADDR); - __raw_writew(cpu_to_be16(maplen), elem->hw_desc + C2_TXP_LEN); - __raw_writew(cpu_to_be16(TXP_HTXD_READY), elem->hw_desc + C2_TXP_FLAGS); - - c2_port->netstats.tx_packets++; - c2_port->netstats.tx_bytes += maplen; - - /* Loop thru additional data fragments and queue them */ - if (skb_shinfo(skb)->nr_frags) { - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - maplen = frag->size; - mapaddr = - pci_map_page(c2dev->pcidev, frag->page, - frag->page_offset, maplen, - PCI_DMA_TODEVICE); - - elem = elem->next; - elem->skb = NULL; - elem->mapaddr = mapaddr; - elem->maplen = maplen; - - /* Tell HW to xmit */ - __raw_writeq(cpu_to_be64(mapaddr), - elem->hw_desc + C2_TXP_ADDR); - __raw_writew(cpu_to_be16(maplen), - elem->hw_desc + C2_TXP_LEN); - __raw_writew(cpu_to_be16(TXP_HTXD_READY), - elem->hw_desc + C2_TXP_FLAGS); - - c2_port->netstats.tx_packets++; - c2_port->netstats.tx_bytes += maplen; - } - } - - tx_ring->to_use = elem->next; - c2_port->tx_avail -= (skb_shinfo(skb)->nr_frags + 1); - - if (c2_port->tx_avail <= MAX_SKB_FRAGS + 1) { - netif_stop_queue(netdev); - if (netif_msg_tx_queued(c2_port)) - pr_debug("%s: transmit queue full\n", - netdev->name); - } - - spin_unlock_irqrestore(&c2_port->tx_lock, flags); - - netdev->trans_start = jiffies; - - return NETDEV_TX_OK; -} - -static struct net_device_stats *c2_get_stats(struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - - return &c2_port->netstats; -} - -static void c2_tx_timeout(struct net_device *netdev) -{ - struct c2_port *c2_port = netdev_priv(netdev); - - if (netif_msg_timer(c2_port)) - pr_debug("%s: tx timeout\n", netdev->name); - - c2_tx_clean(c2_port); -} - -static int c2_change_mtu(struct net_device *netdev, int new_mtu) -{ - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) - return -EINVAL; - - netdev->mtu = new_mtu; - - if (netif_running(netdev)) { - c2_down(netdev); - - c2_up(netdev); - } - - return ret; -} - -/* Initialize network device */ -static struct net_device *c2_devinit(struct c2_dev *c2dev, - void __iomem * mmio_addr) -{ - struct c2_port *c2_port = NULL; - struct net_device *netdev = alloc_etherdev(sizeof(*c2_port)); - - if (!netdev) { - pr_debug("c2_port etherdev alloc failed"); - return NULL; - } - - SET_MODULE_OWNER(netdev); - SET_NETDEV_DEV(netdev, &c2dev->pcidev->dev); - - netdev->open = c2_up; - netdev->stop = c2_down; - netdev->hard_start_xmit = c2_xmit_frame; - netdev->get_stats = c2_get_stats; - netdev->tx_timeout = c2_tx_timeout; - netdev->change_mtu = c2_change_mtu; - netdev->watchdog_timeo = C2_TX_TIMEOUT; - netdev->irq = c2dev->pcidev->irq; - - c2_port = netdev_priv(netdev); - c2_port->netdev = netdev; - c2_port->c2dev = c2dev; - c2_port->msg_enable = netif_msg_init(debug, default_msg); - c2_port->tx_ring.count = C2_NUM_TX_DESC; - c2_port->rx_ring.count = C2_NUM_RX_DESC; - - spin_lock_init(&c2_port->tx_lock); - - /* Copy our 48-bit ethernet hardware address */ - memcpy_fromio(netdev->dev_addr, mmio_addr + C2_REGS_ENADDR, 6); - - /* Validate the MAC address */ - if (!is_valid_ether_addr(netdev->dev_addr)) { - pr_debug("Invalid MAC Address\n"); - c2_print_macaddr(netdev); - free_netdev(netdev); - return NULL; - } - - c2dev->netdev = netdev; - - return netdev; -} - -static int __devinit c2_probe(struct pci_dev *pcidev, - const struct pci_device_id *ent) -{ - int ret = 0, i; - unsigned long reg0_start, reg0_flags, reg0_len; - unsigned long reg2_start, reg2_flags, reg2_len; - unsigned long reg4_start, reg4_flags, reg4_len; - unsigned kva_map_size; - struct net_device *netdev = NULL; - struct c2_dev *c2dev = NULL; - void __iomem *mmio_regs = NULL; - - printk(KERN_INFO PFX "AMSO1100 Gigabit Ethernet driver v%s loaded\n", - DRV_VERSION); - - /* Enable PCI device */ - ret = pci_enable_device(pcidev); - if (ret) { - printk(KERN_ERR PFX "%s: Unable to enable PCI device\n", - pci_name(pcidev)); - goto bail0; - } - - reg0_start = pci_resource_start(pcidev, BAR_0); - reg0_len = pci_resource_len(pcidev, BAR_0); - reg0_flags = pci_resource_flags(pcidev, BAR_0); - - reg2_start = pci_resource_start(pcidev, BAR_2); - reg2_len = pci_resource_len(pcidev, BAR_2); - reg2_flags = pci_resource_flags(pcidev, BAR_2); - - reg4_start = pci_resource_start(pcidev, BAR_4); - reg4_len = pci_resource_len(pcidev, BAR_4); - reg4_flags = pci_resource_flags(pcidev, BAR_4); - - pr_debug("BAR0 size = 0x%lX bytes\n", reg0_len); - pr_debug("BAR2 size = 0x%lX bytes\n", reg2_len); - pr_debug("BAR4 size = 0x%lX bytes\n", reg4_len); - - /* Make sure PCI base addr are MMIO */ - if (!(reg0_flags & IORESOURCE_MEM) || - !(reg2_flags & IORESOURCE_MEM) || !(reg4_flags & IORESOURCE_MEM)) { - printk(KERN_ERR PFX "PCI regions not an MMIO resource\n"); - ret = -ENODEV; - goto bail1; - } - - /* Check for weird/broken PCI region reporting */ - if ((reg0_len < C2_REG0_SIZE) || - (reg2_len < C2_REG2_SIZE) || (reg4_len < C2_REG4_SIZE)) { - printk(KERN_ERR PFX "Invalid PCI region sizes\n"); - ret = -ENODEV; - goto bail1; - } - - /* Reserve PCI I/O and memory resources */ - ret = pci_request_regions(pcidev, DRV_NAME); - if (ret) { - printk(KERN_ERR PFX "%s: Unable to request regions\n", - pci_name(pcidev)); - goto bail1; - } - - if ((sizeof(dma_addr_t) > 4)) { - ret = pci_set_dma_mask(pcidev, DMA_64BIT_MASK); - if (ret < 0) { - printk(KERN_ERR PFX "64b DMA configuration failed\n"); - goto bail2; - } - } else { - ret = pci_set_dma_mask(pcidev, DMA_32BIT_MASK); - if (ret < 0) { - printk(KERN_ERR PFX "32b DMA configuration failed\n"); - goto bail2; - } - } - - /* Enables bus-mastering on the device */ - pci_set_master(pcidev); - - /* Remap the adapter PCI registers in BAR4 */ - mmio_regs = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET, - sizeof(struct c2_adapter_pci_regs)); - if (mmio_regs == 0UL) { - printk(KERN_ERR PFX - "Unable to remap adapter PCI registers in BAR4\n"); - ret = -EIO; - goto bail2; - } - - /* Validate PCI regs magic */ - for (i = 0; i < sizeof(c2_magic); i++) { - if (c2_magic[i] != readb(mmio_regs + C2_REGS_MAGIC + i)) { - printk(KERN_ERR PFX "Downlevel Firmware boot loader " - "[%d/%Zd: got 0x%x, exp 0x%x]. Use the cc_flash " - "utility to update your boot loader\n", - i + 1, sizeof(c2_magic), - readb(mmio_regs + C2_REGS_MAGIC + i), - c2_magic[i]); - printk(KERN_ERR PFX "Adapter not claimed\n"); - iounmap(mmio_regs); - ret = -EIO; - goto bail2; - } - } - - /* Validate the adapter version */ - if (be32_to_cpu(readl(mmio_regs + C2_REGS_VERS)) != C2_VERSION) { - printk(KERN_ERR PFX "Version mismatch " - "[fw=%u, c2=%u], Adapter not claimed\n", - be32_to_cpu(readl(mmio_regs + C2_REGS_VERS)), - C2_VERSION); - ret = -EINVAL; - iounmap(mmio_regs); - goto bail2; - } - - /* Validate the adapter IVN */ - if (be32_to_cpu(readl(mmio_regs + C2_REGS_IVN)) != C2_IVN) { - printk(KERN_ERR PFX "Downlevel FIrmware level. You should be using " - "the OpenIB device support kit. " - "[fw=0x%x, c2=0x%x], Adapter not claimed\n", - be32_to_cpu(readl(mmio_regs + C2_REGS_IVN)), - C2_IVN); - ret = -EINVAL; - iounmap(mmio_regs); - goto bail2; - } - - /* Allocate hardware structure */ - c2dev = (struct c2_dev *) ib_alloc_device(sizeof(*c2dev)); - if (!c2dev) { - printk(KERN_ERR PFX "%s: Unable to alloc hardware struct\n", - pci_name(pcidev)); - ret = -ENOMEM; - iounmap(mmio_regs); - goto bail2; - } - - memset(c2dev, 0, sizeof(*c2dev)); - spin_lock_init(&c2dev->lock); - c2dev->pcidev = pcidev; - c2dev->cur_tx = 0; - - /* Get the last RX index */ - c2dev->cur_rx = - (be32_to_cpu(readl(mmio_regs + C2_REGS_HRX_CUR)) - - 0xffffc000) / sizeof(struct c2_rxp_desc); - - /* Request an interrupt line for the driver */ - ret = request_irq(pcidev->irq, c2_interrupt, SA_SHIRQ, DRV_NAME, c2dev); - if (ret) { - printk(KERN_ERR PFX "%s: requested IRQ %u is busy\n", - pci_name(pcidev), pcidev->irq); - iounmap(mmio_regs); - goto bail3; - } - - /* Set driver specific data */ - pci_set_drvdata(pcidev, c2dev); - - /* Initialize network device */ - if ((netdev = c2_devinit(c2dev, mmio_regs)) == NULL) { - iounmap(mmio_regs); - goto bail4; - } - - /* Save off the actual size prior to unmapping mmio_regs */ - kva_map_size = be32_to_cpu(readl(mmio_regs + C2_REGS_PCI_WINSIZE)); - - /* Unmap the adapter PCI registers in BAR4 */ - iounmap(mmio_regs); - - /* Register network device */ - ret = register_netdev(netdev); - if (ret) { - printk(KERN_ERR PFX "Unable to register netdev, ret = %d\n", - ret); - goto bail5; - } - - /* Disable network packets */ - netif_stop_queue(netdev); - - /* Remap the adapter HRXDQ PA space to kernel VA space */ - c2dev->mmio_rxp_ring = ioremap_nocache(reg4_start + C2_RXP_HRXDQ_OFFSET, - C2_RXP_HRXDQ_SIZE); - if (c2dev->mmio_rxp_ring == 0UL) { - printk(KERN_ERR PFX "Unable to remap MMIO HRXDQ region\n"); - ret = -EIO; - goto bail6; - } - - /* Remap the adapter HTXDQ PA space to kernel VA space */ - c2dev->mmio_txp_ring = ioremap_nocache(reg4_start + C2_TXP_HTXDQ_OFFSET, - C2_TXP_HTXDQ_SIZE); - if (c2dev->mmio_txp_ring == 0UL) { - printk(KERN_ERR PFX "Unable to remap MMIO HTXDQ region\n"); - ret = -EIO; - goto bail7; - } - - /* Save off the current RX index in the last 4 bytes of the TXP Ring */ - C2_SET_CUR_RX(c2dev, c2dev->cur_rx); - - /* Remap the PCI registers in adapter BAR0 to kernel VA space */ - c2dev->regs = ioremap_nocache(reg0_start, reg0_len); - if (c2dev->regs == 0UL) { - printk(KERN_ERR PFX "Unable to remap BAR0\n"); - ret = -EIO; - goto bail8; - } - - /* Remap the PCI registers in adapter BAR4 to kernel VA space */ - c2dev->pa = reg4_start + C2_PCI_REGS_OFFSET; - c2dev->kva = ioremap_nocache(reg4_start + C2_PCI_REGS_OFFSET, - kva_map_size); - if (c2dev->kva == 0UL) { - printk(KERN_ERR PFX "Unable to remap BAR4\n"); - ret = -EIO; - goto bail9; - } - - /* Print out the MAC address */ - c2_print_macaddr(netdev); - - ret = c2_rnic_init(c2dev); - if (ret) { - printk(KERN_ERR PFX "c2_rnic_init failed: %d\n", ret); - goto bail10; - } - - c2_register_device(c2dev); - - return 0; - - bail10: - iounmap(c2dev->kva); - - bail9: - iounmap(c2dev->regs); - - bail8: - iounmap(c2dev->mmio_txp_ring); - - bail7: - iounmap(c2dev->mmio_rxp_ring); - - bail6: - unregister_netdev(netdev); - - bail5: - free_netdev(netdev); - - bail4: - free_irq(pcidev->irq, c2dev); - - bail3: - ib_dealloc_device(&c2dev->ibdev); - - bail2: - pci_release_regions(pcidev); - - bail1: - pci_disable_device(pcidev); - - bail0: - return ret; -} - -static void __devexit c2_remove(struct pci_dev *pcidev) -{ - struct c2_dev *c2dev = pci_get_drvdata(pcidev); - struct net_device *netdev = c2dev->netdev; - - /* Unregister with OpenIB */ - c2_unregister_device(c2dev); - - /* Clean up the RNIC resources */ - c2_rnic_term(c2dev); - - /* Remove network device from the kernel */ - unregister_netdev(netdev); - - /* Free network device */ - free_netdev(netdev); - - /* Free the interrupt line */ - free_irq(pcidev->irq, c2dev); - - /* missing: Turn LEDs off here */ - - /* Unmap adapter PA space */ - iounmap(c2dev->kva); - iounmap(c2dev->regs); - iounmap(c2dev->mmio_txp_ring); - iounmap(c2dev->mmio_rxp_ring); - - /* Free the hardware structure */ - ib_dealloc_device(&c2dev->ibdev); - - /* Release reserved PCI I/O and memory resources */ - pci_release_regions(pcidev); - - /* Disable PCI device */ - pci_disable_device(pcidev); - - /* Clear driver specific data */ - pci_set_drvdata(pcidev, NULL); -} - -static struct pci_driver c2_pci_driver = { - .name = DRV_NAME, - .id_table = c2_pci_table, - .probe = c2_probe, - .remove = __devexit_p(c2_remove), -}; - -static int __init c2_init_module(void) -{ - return pci_module_init(&c2_pci_driver); -} - -static void __exit c2_exit_module(void) -{ - pci_unregister_driver(&c2_pci_driver); -} - -module_init(c2_init_module); -module_exit(c2_exit_module); diff --git a/trunk/drivers/infiniband/hw/amso1100/c2.h b/trunk/drivers/infiniband/hw/amso1100/c2.h deleted file mode 100644 index 1b17dcdd0505..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2.h +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef __C2_H -#define __C2_H - -#include -#include -#include -#include -#include -#include -#include - -#include "c2_provider.h" -#include "c2_mq.h" -#include "c2_status.h" - -#define DRV_NAME "c2" -#define DRV_VERSION "1.1" -#define PFX DRV_NAME ": " - -#define BAR_0 0 -#define BAR_2 2 -#define BAR_4 4 - -#define RX_BUF_SIZE (1536 + 8) -#define ETH_JUMBO_MTU 9000 -#define C2_MAGIC "CEPHEUS" -#define C2_VERSION 4 -#define C2_IVN (18 & 0x7fffffff) - -#define C2_REG0_SIZE (16 * 1024) -#define C2_REG2_SIZE (2 * 1024 * 1024) -#define C2_REG4_SIZE (256 * 1024 * 1024) -#define C2_NUM_TX_DESC 341 -#define C2_NUM_RX_DESC 256 -#define C2_PCI_REGS_OFFSET (0x10000) -#define C2_RXP_HRXDQ_OFFSET (((C2_REG4_SIZE)/2)) -#define C2_RXP_HRXDQ_SIZE (4096) -#define C2_TXP_HTXDQ_OFFSET (((C2_REG4_SIZE)/2) + C2_RXP_HRXDQ_SIZE) -#define C2_TXP_HTXDQ_SIZE (4096) -#define C2_TX_TIMEOUT (6*HZ) - -/* CEPHEUS */ -static const u8 c2_magic[] = { - 0x43, 0x45, 0x50, 0x48, 0x45, 0x55, 0x53 -}; - -enum adapter_pci_regs { - C2_REGS_MAGIC = 0x0000, - C2_REGS_VERS = 0x0008, - C2_REGS_IVN = 0x000C, - C2_REGS_PCI_WINSIZE = 0x0010, - C2_REGS_Q0_QSIZE = 0x0014, - C2_REGS_Q0_MSGSIZE = 0x0018, - C2_REGS_Q0_POOLSTART = 0x001C, - C2_REGS_Q0_SHARED = 0x0020, - C2_REGS_Q1_QSIZE = 0x0024, - C2_REGS_Q1_MSGSIZE = 0x0028, - C2_REGS_Q1_SHARED = 0x0030, - C2_REGS_Q2_QSIZE = 0x0034, - C2_REGS_Q2_MSGSIZE = 0x0038, - C2_REGS_Q2_SHARED = 0x0040, - C2_REGS_ENADDR = 0x004C, - C2_REGS_RDMA_ENADDR = 0x0054, - C2_REGS_HRX_CUR = 0x006C, -}; - -struct c2_adapter_pci_regs { - char reg_magic[8]; - u32 version; - u32 ivn; - u32 pci_window_size; - u32 q0_q_size; - u32 q0_msg_size; - u32 q0_pool_start; - u32 q0_shared; - u32 q1_q_size; - u32 q1_msg_size; - u32 q1_pool_start; - u32 q1_shared; - u32 q2_q_size; - u32 q2_msg_size; - u32 q2_pool_start; - u32 q2_shared; - u32 log_start; - u32 log_size; - u8 host_enaddr[8]; - u8 rdma_enaddr[8]; - u32 crash_entry; - u32 crash_ready[2]; - u32 fw_txd_cur; - u32 fw_hrxd_cur; - u32 fw_rxd_cur; -}; - -enum pci_regs { - C2_HISR = 0x0000, - C2_DISR = 0x0004, - C2_HIMR = 0x0008, - C2_DIMR = 0x000C, - C2_NISR0 = 0x0010, - C2_NISR1 = 0x0014, - C2_NIMR0 = 0x0018, - C2_NIMR1 = 0x001C, - C2_IDIS = 0x0020, -}; - -enum { - C2_PCI_HRX_INT = 1 << 8, - C2_PCI_HTX_INT = 1 << 17, - C2_PCI_HRX_QUI = 1 << 31, -}; - -/* - * Cepheus registers in BAR0. - */ -struct c2_pci_regs { - u32 hostisr; - u32 dmaisr; - u32 hostimr; - u32 dmaimr; - u32 netisr0; - u32 netisr1; - u32 netimr0; - u32 netimr1; - u32 int_disable; -}; - -/* TXP flags */ -enum c2_txp_flags { - TXP_HTXD_DONE = 0, - TXP_HTXD_READY = 1 << 0, - TXP_HTXD_UNINIT = 1 << 1, -}; - -/* RXP flags */ -enum c2_rxp_flags { - RXP_HRXD_UNINIT = 0, - RXP_HRXD_READY = 1 << 0, - RXP_HRXD_DONE = 1 << 1, -}; - -/* RXP status */ -enum c2_rxp_status { - RXP_HRXD_ZERO = 0, - RXP_HRXD_OK = 1 << 0, - RXP_HRXD_BUF_OV = 1 << 1, -}; - -/* TXP descriptor fields */ -enum txp_desc { - C2_TXP_FLAGS = 0x0000, - C2_TXP_LEN = 0x0002, - C2_TXP_ADDR = 0x0004, -}; - -/* RXP descriptor fields */ -enum rxp_desc { - C2_RXP_FLAGS = 0x0000, - C2_RXP_STATUS = 0x0002, - C2_RXP_COUNT = 0x0004, - C2_RXP_LEN = 0x0006, - C2_RXP_ADDR = 0x0008, -}; - -struct c2_txp_desc { - u16 flags; - u16 len; - u64 addr; -} __attribute__ ((packed)); - -struct c2_rxp_desc { - u16 flags; - u16 status; - u16 count; - u16 len; - u64 addr; -} __attribute__ ((packed)); - -struct c2_rxp_hdr { - u16 flags; - u16 status; - u16 len; - u16 rsvd; -} __attribute__ ((packed)); - -struct c2_tx_desc { - u32 len; - u32 status; - dma_addr_t next_offset; -}; - -struct c2_rx_desc { - u32 len; - u32 status; - dma_addr_t next_offset; -}; - -struct c2_alloc { - u32 last; - u32 max; - spinlock_t lock; - unsigned long *table; -}; - -struct c2_array { - struct { - void **page; - int used; - } *page_list; -}; - -/* - * The MQ shared pointer pool is organized as a linked list of - * chunks. Each chunk contains a linked list of free shared pointers - * that can be allocated to a given user mode client. - * - */ -struct sp_chunk { - struct sp_chunk *next; - dma_addr_t dma_addr; - DECLARE_PCI_UNMAP_ADDR(mapping); - u16 head; - u16 shared_ptr[0]; -}; - -struct c2_pd_table { - u32 last; - u32 max; - spinlock_t lock; - unsigned long *table; -}; - -struct c2_qp_table { - struct idr idr; - spinlock_t lock; - int last; -}; - -struct c2_element { - struct c2_element *next; - void *ht_desc; /* host descriptor */ - void __iomem *hw_desc; /* hardware descriptor */ - struct sk_buff *skb; - dma_addr_t mapaddr; - u32 maplen; -}; - -struct c2_ring { - struct c2_element *to_clean; - struct c2_element *to_use; - struct c2_element *start; - unsigned long count; -}; - -struct c2_dev { - struct ib_device ibdev; - void __iomem *regs; - void __iomem *mmio_txp_ring; /* remapped adapter memory for hw rings */ - void __iomem *mmio_rxp_ring; - spinlock_t lock; - struct pci_dev *pcidev; - struct net_device *netdev; - struct net_device *pseudo_netdev; - unsigned int cur_tx; - unsigned int cur_rx; - u32 adapter_handle; - int device_cap_flags; - void __iomem *kva; /* KVA device memory */ - unsigned long pa; /* PA device memory */ - void **qptr_array; - - kmem_cache_t *host_msg_cache; - - struct list_head cca_link; /* adapter list */ - struct list_head eh_wakeup_list; /* event wakeup list */ - wait_queue_head_t req_vq_wo; - - /* Cached RNIC properties */ - struct ib_device_attr props; - - struct c2_pd_table pd_table; - struct c2_qp_table qp_table; - int ports; /* num of GigE ports */ - int devnum; - spinlock_t vqlock; /* sync vbs req MQ */ - - /* Verbs Queues */ - struct c2_mq req_vq; /* Verbs Request MQ */ - struct c2_mq rep_vq; /* Verbs Reply MQ */ - struct c2_mq aeq; /* Async Events MQ */ - - /* Kernel client MQs */ - struct sp_chunk *kern_mqsp_pool; - - /* Device updates these values when posting messages to a host - * target queue */ - u16 req_vq_shared; - u16 rep_vq_shared; - u16 aeq_shared; - u16 irq_claimed; - - /* - * Shared host target pages for user-accessible MQs. - */ - int hthead; /* index of first free entry */ - void *htpages; /* kernel vaddr */ - int htlen; /* length of htpages memory */ - void *htuva; /* user mapped vaddr */ - spinlock_t htlock; /* serialize allocation */ - - u64 adapter_hint_uva; /* access to the activity FIFO */ - - // spinlock_t aeq_lock; - // spinlock_t rnic_lock; - - u16 *hint_count; - dma_addr_t hint_count_dma; - u16 hints_read; - - int init; /* TRUE if it's ready */ - char ae_cache_name[16]; - char vq_cache_name[16]; -}; - -struct c2_port { - u32 msg_enable; - struct c2_dev *c2dev; - struct net_device *netdev; - - spinlock_t tx_lock; - u32 tx_avail; - struct c2_ring tx_ring; - struct c2_ring rx_ring; - - void *mem; /* PCI memory for host rings */ - dma_addr_t dma; - unsigned long mem_size; - - u32 rx_buf_size; - - struct net_device_stats netstats; -}; - -/* - * Activity FIFO registers in BAR0. - */ -#define PCI_BAR0_HOST_HINT 0x100 -#define PCI_BAR0_ADAPTER_HINT 0x2000 - -/* - * Ammasso PCI vendor id and Cepheus PCI device id. - */ -#define CQ_ARMED 0x01 -#define CQ_WAIT_FOR_DMA 0x80 - -/* - * The format of a hint is as follows: - * Lower 16 bits are the count of hints for the queue. - * Next 15 bits are the qp_index - * Upper most bit depends on who reads it: - * If read by producer, then it means Full (1) or Not-Full (0) - * If read by consumer, then it means Empty (1) or Not-Empty (0) - */ -#define C2_HINT_MAKE(q_index, hint_count) (((q_index) << 16) | hint_count) -#define C2_HINT_GET_INDEX(hint) (((hint) & 0x7FFF0000) >> 16) -#define C2_HINT_GET_COUNT(hint) ((hint) & 0x0000FFFF) - - -/* - * The following defines the offset in SDRAM for the c2_adapter_pci_regs_t - * struct. - */ -#define C2_ADAPTER_PCI_REGS_OFFSET 0x10000 - -#ifndef readq -static inline u64 readq(const void __iomem * addr) -{ - u64 ret = readl(addr + 4); - ret <<= 32; - ret |= readl(addr); - - return ret; -} -#endif - -#ifndef writeq -static inline void __raw_writeq(u64 val, void __iomem * addr) -{ - __raw_writel((u32) (val), addr); - __raw_writel((u32) (val >> 32), (addr + 4)); -} -#endif - -#define C2_SET_CUR_RX(c2dev, cur_rx) \ - __raw_writel(cpu_to_be32(cur_rx), c2dev->mmio_txp_ring + 4092) - -#define C2_GET_CUR_RX(c2dev) \ - be32_to_cpu(readl(c2dev->mmio_txp_ring + 4092)) - -static inline struct c2_dev *to_c2dev(struct ib_device *ibdev) -{ - return container_of(ibdev, struct c2_dev, ibdev); -} - -static inline int c2_errno(void *reply) -{ - switch (c2_wr_get_result(reply)) { - case C2_OK: - return 0; - case CCERR_NO_BUFS: - case CCERR_INSUFFICIENT_RESOURCES: - case CCERR_ZERO_RDMA_READ_RESOURCES: - return -ENOMEM; - case CCERR_MR_IN_USE: - case CCERR_QP_IN_USE: - return -EBUSY; - case CCERR_ADDR_IN_USE: - return -EADDRINUSE; - case CCERR_ADDR_NOT_AVAIL: - return -EADDRNOTAVAIL; - case CCERR_CONN_RESET: - return -ECONNRESET; - case CCERR_NOT_IMPLEMENTED: - case CCERR_INVALID_WQE: - return -ENOSYS; - case CCERR_QP_NOT_PRIVILEGED: - return -EPERM; - case CCERR_STACK_ERROR: - return -EPROTO; - case CCERR_ACCESS_VIOLATION: - case CCERR_BASE_AND_BOUNDS_VIOLATION: - return -EFAULT; - case CCERR_STAG_STATE_NOT_INVALID: - case CCERR_INVALID_ADDRESS: - case CCERR_INVALID_CQ: - case CCERR_INVALID_EP: - case CCERR_INVALID_MODIFIER: - case CCERR_INVALID_MTU: - case CCERR_INVALID_PD_ID: - case CCERR_INVALID_QP: - case CCERR_INVALID_RNIC: - case CCERR_INVALID_STAG: - return -EINVAL; - default: - return -EAGAIN; - } -} - -/* Device */ -extern int c2_register_device(struct c2_dev *c2dev); -extern void c2_unregister_device(struct c2_dev *c2dev); -extern int c2_rnic_init(struct c2_dev *c2dev); -extern void c2_rnic_term(struct c2_dev *c2dev); -extern void c2_rnic_interrupt(struct c2_dev *c2dev); -extern int c2_del_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask); -extern int c2_add_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask); - -/* QPs */ -extern int c2_alloc_qp(struct c2_dev *c2dev, struct c2_pd *pd, - struct ib_qp_init_attr *qp_attrs, struct c2_qp *qp); -extern void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp); -extern struct ib_qp *c2_get_qp(struct ib_device *device, int qpn); -extern int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp, - struct ib_qp_attr *attr, int attr_mask); -extern int c2_qp_set_read_limits(struct c2_dev *c2dev, struct c2_qp *qp, - int ord, int ird); -extern int c2_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, - struct ib_send_wr **bad_wr); -extern int c2_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, - struct ib_recv_wr **bad_wr); -extern void __devinit c2_init_qp_table(struct c2_dev *c2dev); -extern void __devexit c2_cleanup_qp_table(struct c2_dev *c2dev); -extern void c2_set_qp_state(struct c2_qp *, int); -extern struct c2_qp *c2_find_qpn(struct c2_dev *c2dev, int qpn); - -/* PDs */ -extern int c2_pd_alloc(struct c2_dev *c2dev, int privileged, struct c2_pd *pd); -extern void c2_pd_free(struct c2_dev *c2dev, struct c2_pd *pd); -extern int __devinit c2_init_pd_table(struct c2_dev *c2dev); -extern void __devexit c2_cleanup_pd_table(struct c2_dev *c2dev); - -/* CQs */ -extern int c2_init_cq(struct c2_dev *c2dev, int entries, - struct c2_ucontext *ctx, struct c2_cq *cq); -extern void c2_free_cq(struct c2_dev *c2dev, struct c2_cq *cq); -extern void c2_cq_event(struct c2_dev *c2dev, u32 mq_index); -extern void c2_cq_clean(struct c2_dev *c2dev, struct c2_qp *qp, u32 mq_index); -extern int c2_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry); -extern int c2_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify); - -/* CM */ -extern int c2_llp_connect(struct iw_cm_id *cm_id, - struct iw_cm_conn_param *iw_param); -extern int c2_llp_accept(struct iw_cm_id *cm_id, - struct iw_cm_conn_param *iw_param); -extern int c2_llp_reject(struct iw_cm_id *cm_id, const void *pdata, - u8 pdata_len); -extern int c2_llp_service_create(struct iw_cm_id *cm_id, int backlog); -extern int c2_llp_service_destroy(struct iw_cm_id *cm_id); - -/* MM */ -extern int c2_nsmr_register_phys_kern(struct c2_dev *c2dev, u64 *addr_list, - int page_size, int pbl_depth, u32 length, - u32 off, u64 *va, enum c2_acf acf, - struct c2_mr *mr); -extern int c2_stag_dealloc(struct c2_dev *c2dev, u32 stag_index); - -/* AE */ -extern void c2_ae_event(struct c2_dev *c2dev, u32 mq_index); - -/* MQSP Allocator */ -extern int c2_init_mqsp_pool(struct c2_dev *c2dev, gfp_t gfp_mask, - struct sp_chunk **root); -extern void c2_free_mqsp_pool(struct c2_dev *c2dev, struct sp_chunk *root); -extern u16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head, - dma_addr_t *dma_addr, gfp_t gfp_mask); -extern void c2_free_mqsp(u16 * mqsp); -#endif diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_ae.c b/trunk/drivers/infiniband/hw/amso1100/c2_ae.c deleted file mode 100644 index 08f46c83a3a4..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_ae.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "c2.h" -#include -#include "c2_status.h" -#include "c2_ae.h" - -static int c2_convert_cm_status(u32 c2_status) -{ - switch (c2_status) { - case C2_CONN_STATUS_SUCCESS: - return 0; - case C2_CONN_STATUS_REJECTED: - return -ENETRESET; - case C2_CONN_STATUS_REFUSED: - return -ECONNREFUSED; - case C2_CONN_STATUS_TIMEDOUT: - return -ETIMEDOUT; - case C2_CONN_STATUS_NETUNREACH: - return -ENETUNREACH; - case C2_CONN_STATUS_HOSTUNREACH: - return -EHOSTUNREACH; - case C2_CONN_STATUS_INVALID_RNIC: - return -EINVAL; - case C2_CONN_STATUS_INVALID_QP: - return -EINVAL; - case C2_CONN_STATUS_INVALID_QP_STATE: - return -EINVAL; - case C2_CONN_STATUS_ADDR_NOT_AVAIL: - return -EADDRNOTAVAIL; - default: - printk(KERN_ERR PFX - "%s - Unable to convert CM status: %d\n", - __FUNCTION__, c2_status); - return -EIO; - } -} - -#ifdef DEBUG -static const char* to_event_str(int event) -{ - static const char* event_str[] = { - "CCAE_REMOTE_SHUTDOWN", - "CCAE_ACTIVE_CONNECT_RESULTS", - "CCAE_CONNECTION_REQUEST", - "CCAE_LLP_CLOSE_COMPLETE", - "CCAE_TERMINATE_MESSAGE_RECEIVED", - "CCAE_LLP_CONNECTION_RESET", - "CCAE_LLP_CONNECTION_LOST", - "CCAE_LLP_SEGMENT_SIZE_INVALID", - "CCAE_LLP_INVALID_CRC", - "CCAE_LLP_BAD_FPDU", - "CCAE_INVALID_DDP_VERSION", - "CCAE_INVALID_RDMA_VERSION", - "CCAE_UNEXPECTED_OPCODE", - "CCAE_INVALID_DDP_QUEUE_NUMBER", - "CCAE_RDMA_READ_NOT_ENABLED", - "CCAE_RDMA_WRITE_NOT_ENABLED", - "CCAE_RDMA_READ_TOO_SMALL", - "CCAE_NO_L_BIT", - "CCAE_TAGGED_INVALID_STAG", - "CCAE_TAGGED_BASE_BOUNDS_VIOLATION", - "CCAE_TAGGED_ACCESS_RIGHTS_VIOLATION", - "CCAE_TAGGED_INVALID_PD", - "CCAE_WRAP_ERROR", - "CCAE_BAD_CLOSE", - "CCAE_BAD_LLP_CLOSE", - "CCAE_INVALID_MSN_RANGE", - "CCAE_INVALID_MSN_GAP", - "CCAE_IRRQ_OVERFLOW", - "CCAE_IRRQ_MSN_GAP", - "CCAE_IRRQ_MSN_RANGE", - "CCAE_IRRQ_INVALID_STAG", - "CCAE_IRRQ_BASE_BOUNDS_VIOLATION", - "CCAE_IRRQ_ACCESS_RIGHTS_VIOLATION", - "CCAE_IRRQ_INVALID_PD", - "CCAE_IRRQ_WRAP_ERROR", - "CCAE_CQ_SQ_COMPLETION_OVERFLOW", - "CCAE_CQ_RQ_COMPLETION_ERROR", - "CCAE_QP_SRQ_WQE_ERROR", - "CCAE_QP_LOCAL_CATASTROPHIC_ERROR", - "CCAE_CQ_OVERFLOW", - "CCAE_CQ_OPERATION_ERROR", - "CCAE_SRQ_LIMIT_REACHED", - "CCAE_QP_RQ_LIMIT_REACHED", - "CCAE_SRQ_CATASTROPHIC_ERROR", - "CCAE_RNIC_CATASTROPHIC_ERROR" - }; - - if (event < CCAE_REMOTE_SHUTDOWN || - event > CCAE_RNIC_CATASTROPHIC_ERROR) - return ""; - - event -= CCAE_REMOTE_SHUTDOWN; - return event_str[event]; -} - -static const char *to_qp_state_str(int state) -{ - switch (state) { - case C2_QP_STATE_IDLE: - return "C2_QP_STATE_IDLE"; - case C2_QP_STATE_CONNECTING: - return "C2_QP_STATE_CONNECTING"; - case C2_QP_STATE_RTS: - return "C2_QP_STATE_RTS"; - case C2_QP_STATE_CLOSING: - return "C2_QP_STATE_CLOSING"; - case C2_QP_STATE_TERMINATE: - return "C2_QP_STATE_TERMINATE"; - case C2_QP_STATE_ERROR: - return "C2_QP_STATE_ERROR"; - default: - return ""; - }; -} -#endif - -void c2_ae_event(struct c2_dev *c2dev, u32 mq_index) -{ - struct c2_mq *mq = c2dev->qptr_array[mq_index]; - union c2wr *wr; - void *resource_user_context; - struct iw_cm_event cm_event; - struct ib_event ib_event; - enum c2_resource_indicator resource_indicator; - enum c2_event_id event_id; - unsigned long flags; - int status; - - /* - * retreive the message - */ - wr = c2_mq_consume(mq); - if (!wr) - return; - - memset(&ib_event, 0, sizeof(ib_event)); - memset(&cm_event, 0, sizeof(cm_event)); - - event_id = c2_wr_get_id(wr); - resource_indicator = be32_to_cpu(wr->ae.ae_generic.resource_type); - resource_user_context = - (void *) (unsigned long) wr->ae.ae_generic.user_context; - - status = cm_event.status = c2_convert_cm_status(c2_wr_get_result(wr)); - - pr_debug("event received c2_dev=%p, event_id=%d, " - "resource_indicator=%d, user_context=%p, status = %d\n", - c2dev, event_id, resource_indicator, resource_user_context, - status); - - switch (resource_indicator) { - case C2_RES_IND_QP:{ - - struct c2_qp *qp = (struct c2_qp *)resource_user_context; - struct iw_cm_id *cm_id = qp->cm_id; - struct c2wr_ae_active_connect_results *res; - - if (!cm_id) { - pr_debug("event received, but cm_id is , qp=%p!\n", - qp); - goto ignore_it; - } - pr_debug("%s: event = %s, user_context=%llx, " - "resource_type=%x, " - "resource=%x, qp_state=%s\n", - __FUNCTION__, - to_event_str(event_id), - be64_to_cpu(wr->ae.ae_generic.user_context), - be32_to_cpu(wr->ae.ae_generic.resource_type), - be32_to_cpu(wr->ae.ae_generic.resource), - to_qp_state_str(be32_to_cpu(wr->ae.ae_generic.qp_state))); - - c2_set_qp_state(qp, be32_to_cpu(wr->ae.ae_generic.qp_state)); - - switch (event_id) { - case CCAE_ACTIVE_CONNECT_RESULTS: - res = &wr->ae.ae_active_connect_results; - cm_event.event = IW_CM_EVENT_CONNECT_REPLY; - cm_event.local_addr.sin_addr.s_addr = res->laddr; - cm_event.remote_addr.sin_addr.s_addr = res->raddr; - cm_event.local_addr.sin_port = res->lport; - cm_event.remote_addr.sin_port = res->rport; - if (status == 0) { - cm_event.private_data_len = - be32_to_cpu(res->private_data_length); - cm_event.private_data = res->private_data; - } else { - spin_lock_irqsave(&qp->lock, flags); - if (qp->cm_id) { - qp->cm_id->rem_ref(qp->cm_id); - qp->cm_id = NULL; - } - spin_unlock_irqrestore(&qp->lock, flags); - cm_event.private_data_len = 0; - cm_event.private_data = NULL; - } - if (cm_id->event_handler) - cm_id->event_handler(cm_id, &cm_event); - break; - case CCAE_TERMINATE_MESSAGE_RECEIVED: - case CCAE_CQ_SQ_COMPLETION_OVERFLOW: - ib_event.device = &c2dev->ibdev; - ib_event.element.qp = &qp->ibqp; - ib_event.event = IB_EVENT_QP_REQ_ERR; - - if (qp->ibqp.event_handler) - qp->ibqp.event_handler(&ib_event, - qp->ibqp. - qp_context); - break; - case CCAE_BAD_CLOSE: - case CCAE_LLP_CLOSE_COMPLETE: - case CCAE_LLP_CONNECTION_RESET: - case CCAE_LLP_CONNECTION_LOST: - BUG_ON(cm_id->event_handler==(void*)0x6b6b6b6b); - - spin_lock_irqsave(&qp->lock, flags); - if (qp->cm_id) { - qp->cm_id->rem_ref(qp->cm_id); - qp->cm_id = NULL; - } - spin_unlock_irqrestore(&qp->lock, flags); - cm_event.event = IW_CM_EVENT_CLOSE; - cm_event.status = 0; - if (cm_id->event_handler) - cm_id->event_handler(cm_id, &cm_event); - break; - default: - BUG_ON(1); - pr_debug("%s:%d Unexpected event_id=%d on QP=%p, " - "CM_ID=%p\n", - __FUNCTION__, __LINE__, - event_id, qp, cm_id); - break; - } - break; - } - - case C2_RES_IND_EP:{ - - struct c2wr_ae_connection_request *req = - &wr->ae.ae_connection_request; - struct iw_cm_id *cm_id = - (struct iw_cm_id *)resource_user_context; - - pr_debug("C2_RES_IND_EP event_id=%d\n", event_id); - if (event_id != CCAE_CONNECTION_REQUEST) { - pr_debug("%s: Invalid event_id: %d\n", - __FUNCTION__, event_id); - break; - } - cm_event.event = IW_CM_EVENT_CONNECT_REQUEST; - cm_event.provider_data = (void*)(unsigned long)req->cr_handle; - cm_event.local_addr.sin_addr.s_addr = req->laddr; - cm_event.remote_addr.sin_addr.s_addr = req->raddr; - cm_event.local_addr.sin_port = req->lport; - cm_event.remote_addr.sin_port = req->rport; - cm_event.private_data_len = - be32_to_cpu(req->private_data_length); - cm_event.private_data = req->private_data; - - if (cm_id->event_handler) - cm_id->event_handler(cm_id, &cm_event); - break; - } - - case C2_RES_IND_CQ:{ - struct c2_cq *cq = - (struct c2_cq *) resource_user_context; - - pr_debug("IB_EVENT_CQ_ERR\n"); - ib_event.device = &c2dev->ibdev; - ib_event.element.cq = &cq->ibcq; - ib_event.event = IB_EVENT_CQ_ERR; - - if (cq->ibcq.event_handler) - cq->ibcq.event_handler(&ib_event, - cq->ibcq.cq_context); - } - - default: - printk("Bad resource indicator = %d\n", - resource_indicator); - break; - } - - ignore_it: - c2_mq_free(mq); -} diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_ae.h b/trunk/drivers/infiniband/hw/amso1100/c2_ae.h deleted file mode 100644 index 3a065c33b83b..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_ae.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _C2_AE_H_ -#define _C2_AE_H_ - -/* - * WARNING: If you change this file, also bump C2_IVN_BASE - * in common/include/clustercore/c2_ivn.h. - */ - -/* - * Asynchronous Event Identifiers - * - * These start at 0x80 only so it's obvious from inspection that - * they are not work-request statuses. This isn't critical. - * - * NOTE: these event id's must fit in eight bits. - */ -enum c2_event_id { - CCAE_REMOTE_SHUTDOWN = 0x80, - CCAE_ACTIVE_CONNECT_RESULTS, - CCAE_CONNECTION_REQUEST, - CCAE_LLP_CLOSE_COMPLETE, - CCAE_TERMINATE_MESSAGE_RECEIVED, - CCAE_LLP_CONNECTION_RESET, - CCAE_LLP_CONNECTION_LOST, - CCAE_LLP_SEGMENT_SIZE_INVALID, - CCAE_LLP_INVALID_CRC, - CCAE_LLP_BAD_FPDU, - CCAE_INVALID_DDP_VERSION, - CCAE_INVALID_RDMA_VERSION, - CCAE_UNEXPECTED_OPCODE, - CCAE_INVALID_DDP_QUEUE_NUMBER, - CCAE_RDMA_READ_NOT_ENABLED, - CCAE_RDMA_WRITE_NOT_ENABLED, - CCAE_RDMA_READ_TOO_SMALL, - CCAE_NO_L_BIT, - CCAE_TAGGED_INVALID_STAG, - CCAE_TAGGED_BASE_BOUNDS_VIOLATION, - CCAE_TAGGED_ACCESS_RIGHTS_VIOLATION, - CCAE_TAGGED_INVALID_PD, - CCAE_WRAP_ERROR, - CCAE_BAD_CLOSE, - CCAE_BAD_LLP_CLOSE, - CCAE_INVALID_MSN_RANGE, - CCAE_INVALID_MSN_GAP, - CCAE_IRRQ_OVERFLOW, - CCAE_IRRQ_MSN_GAP, - CCAE_IRRQ_MSN_RANGE, - CCAE_IRRQ_INVALID_STAG, - CCAE_IRRQ_BASE_BOUNDS_VIOLATION, - CCAE_IRRQ_ACCESS_RIGHTS_VIOLATION, - CCAE_IRRQ_INVALID_PD, - CCAE_IRRQ_WRAP_ERROR, - CCAE_CQ_SQ_COMPLETION_OVERFLOW, - CCAE_CQ_RQ_COMPLETION_ERROR, - CCAE_QP_SRQ_WQE_ERROR, - CCAE_QP_LOCAL_CATASTROPHIC_ERROR, - CCAE_CQ_OVERFLOW, - CCAE_CQ_OPERATION_ERROR, - CCAE_SRQ_LIMIT_REACHED, - CCAE_QP_RQ_LIMIT_REACHED, - CCAE_SRQ_CATASTROPHIC_ERROR, - CCAE_RNIC_CATASTROPHIC_ERROR -/* WARNING If you add more id's, make sure their values fit in eight bits. */ -}; - -/* - * Resource Indicators and Identifiers - */ -enum c2_resource_indicator { - C2_RES_IND_QP = 1, - C2_RES_IND_EP, - C2_RES_IND_CQ, - C2_RES_IND_SRQ, -}; - -#endif /* _C2_AE_H_ */ diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_alloc.c b/trunk/drivers/infiniband/hw/amso1100/c2_alloc.c deleted file mode 100644 index 1d2529992c0c..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_alloc.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2004 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include - -#include "c2.h" - -static int c2_alloc_mqsp_chunk(struct c2_dev *c2dev, gfp_t gfp_mask, - struct sp_chunk **head) -{ - int i; - struct sp_chunk *new_head; - - new_head = (struct sp_chunk *) __get_free_page(gfp_mask); - if (new_head == NULL) - return -ENOMEM; - - new_head->dma_addr = dma_map_single(c2dev->ibdev.dma_device, new_head, - PAGE_SIZE, DMA_FROM_DEVICE); - pci_unmap_addr_set(new_head, mapping, new_head->dma_addr); - - new_head->next = NULL; - new_head->head = 0; - - /* build list where each index is the next free slot */ - for (i = 0; - i < (PAGE_SIZE - sizeof(struct sp_chunk) - - sizeof(u16)) / sizeof(u16) - 1; - i++) { - new_head->shared_ptr[i] = i + 1; - } - /* terminate list */ - new_head->shared_ptr[i] = 0xFFFF; - - *head = new_head; - return 0; -} - -int c2_init_mqsp_pool(struct c2_dev *c2dev, gfp_t gfp_mask, - struct sp_chunk **root) -{ - return c2_alloc_mqsp_chunk(c2dev, gfp_mask, root); -} - -void c2_free_mqsp_pool(struct c2_dev *c2dev, struct sp_chunk *root) -{ - struct sp_chunk *next; - - while (root) { - next = root->next; - dma_unmap_single(c2dev->ibdev.dma_device, - pci_unmap_addr(root, mapping), PAGE_SIZE, - DMA_FROM_DEVICE); - __free_page((struct page *) root); - root = next; - } -} - -u16 *c2_alloc_mqsp(struct c2_dev *c2dev, struct sp_chunk *head, - dma_addr_t *dma_addr, gfp_t gfp_mask) -{ - u16 mqsp; - - while (head) { - mqsp = head->head; - if (mqsp != 0xFFFF) { - head->head = head->shared_ptr[mqsp]; - break; - } else if (head->next == NULL) { - if (c2_alloc_mqsp_chunk(c2dev, gfp_mask, &head->next) == - 0) { - head = head->next; - mqsp = head->head; - head->head = head->shared_ptr[mqsp]; - break; - } else - return NULL; - } else - head = head->next; - } - if (head) { - *dma_addr = head->dma_addr + - ((unsigned long) &(head->shared_ptr[mqsp]) - - (unsigned long) head); - pr_debug("%s addr %p dma_addr %llx\n", __FUNCTION__, - &(head->shared_ptr[mqsp]), (u64)*dma_addr); - return &(head->shared_ptr[mqsp]); - } - return NULL; -} - -void c2_free_mqsp(u16 * mqsp) -{ - struct sp_chunk *head; - u16 idx; - - /* The chunk containing this ptr begins at the page boundary */ - head = (struct sp_chunk *) ((unsigned long) mqsp & PAGE_MASK); - - /* Link head to new mqsp */ - *mqsp = head->head; - - /* Compute the shared_ptr index */ - idx = ((unsigned long) mqsp & ~PAGE_MASK) >> 1; - idx -= (unsigned long) &(((struct sp_chunk *) 0)->shared_ptr[0]) >> 1; - - /* Point this index at the head */ - head->shared_ptr[idx] = head->head; - - /* Point head at this index */ - head->head = idx; -} diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_cm.c b/trunk/drivers/infiniband/hw/amso1100/c2_cm.c deleted file mode 100644 index 485254efdd1e..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_cm.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ -#include "c2.h" -#include "c2_wr.h" -#include "c2_vq.h" -#include - -int c2_llp_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param) -{ - struct c2_dev *c2dev = to_c2dev(cm_id->device); - struct ib_qp *ibqp; - struct c2_qp *qp; - struct c2wr_qp_connect_req *wr; /* variable size needs a malloc. */ - struct c2_vq_req *vq_req; - int err; - - ibqp = c2_get_qp(cm_id->device, iw_param->qpn); - if (!ibqp) - return -EINVAL; - qp = to_c2qp(ibqp); - - /* Associate QP <--> CM_ID */ - cm_id->provider_data = qp; - cm_id->add_ref(cm_id); - qp->cm_id = cm_id; - - /* - * only support the max private_data length - */ - if (iw_param->private_data_len > C2_MAX_PRIVATE_DATA_SIZE) { - err = -EINVAL; - goto bail0; - } - /* - * Set the rdma read limits - */ - err = c2_qp_set_read_limits(c2dev, qp, iw_param->ord, iw_param->ird); - if (err) - goto bail0; - - /* - * Create and send a WR_QP_CONNECT... - */ - wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL); - if (!wr) { - err = -ENOMEM; - goto bail0; - } - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) { - err = -ENOMEM; - goto bail1; - } - - c2_wr_set_id(wr, CCWR_QP_CONNECT); - wr->hdr.context = 0; - wr->rnic_handle = c2dev->adapter_handle; - wr->qp_handle = qp->adapter_handle; - - wr->remote_addr = cm_id->remote_addr.sin_addr.s_addr; - wr->remote_port = cm_id->remote_addr.sin_port; - - /* - * Move any private data from the callers's buf into - * the WR. - */ - if (iw_param->private_data) { - wr->private_data_length = - cpu_to_be32(iw_param->private_data_len); - memcpy(&wr->private_data[0], iw_param->private_data, - iw_param->private_data_len); - } else - wr->private_data_length = 0; - - /* - * Send WR to adapter. NOTE: There is no synch reply from - * the adapter. - */ - err = vq_send_wr(c2dev, (union c2wr *) wr); - vq_req_free(c2dev, vq_req); - - bail1: - kfree(wr); - bail0: - if (err) { - /* - * If we fail, release reference on QP and - * disassociate QP from CM_ID - */ - cm_id->provider_data = NULL; - qp->cm_id = NULL; - cm_id->rem_ref(cm_id); - } - return err; -} - -int c2_llp_service_create(struct iw_cm_id *cm_id, int backlog) -{ - struct c2_dev *c2dev; - struct c2wr_ep_listen_create_req wr; - struct c2wr_ep_listen_create_rep *reply; - struct c2_vq_req *vq_req; - int err; - - c2dev = to_c2dev(cm_id->device); - if (c2dev == NULL) - return -EINVAL; - - /* - * Allocate verbs request. - */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - /* - * Build the WR - */ - c2_wr_set_id(&wr, CCWR_EP_LISTEN_CREATE); - wr.hdr.context = (u64) (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.local_addr = cm_id->local_addr.sin_addr.s_addr; - wr.local_port = cm_id->local_addr.sin_port; - wr.backlog = cpu_to_be32(backlog); - wr.user_context = (u64) (unsigned long) cm_id; - - /* - * Reference the request struct. Dereferenced in the int handler. - */ - vq_req_get(c2dev, vq_req); - - /* - * Send WR to adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - /* - * Wait for reply from adapter - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail0; - - /* - * Process reply - */ - reply = - (struct c2wr_ep_listen_create_rep *) (unsigned long) vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail1; - } - - if ((err = c2_errno(reply)) != 0) - goto bail1; - - /* - * Keep the adapter handle. Used in subsequent destroy - */ - cm_id->provider_data = (void*)(unsigned long) reply->ep_handle; - - /* - * free vq stuff - */ - vq_repbuf_free(c2dev, reply); - vq_req_free(c2dev, vq_req); - - return 0; - - bail1: - vq_repbuf_free(c2dev, reply); - bail0: - vq_req_free(c2dev, vq_req); - return err; -} - - -int c2_llp_service_destroy(struct iw_cm_id *cm_id) -{ - - struct c2_dev *c2dev; - struct c2wr_ep_listen_destroy_req wr; - struct c2wr_ep_listen_destroy_rep *reply; - struct c2_vq_req *vq_req; - int err; - - c2dev = to_c2dev(cm_id->device); - if (c2dev == NULL) - return -EINVAL; - - /* - * Allocate verbs request. - */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - /* - * Build the WR - */ - c2_wr_set_id(&wr, CCWR_EP_LISTEN_DESTROY); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.ep_handle = (u32)(unsigned long)cm_id->provider_data; - - /* - * reference the request struct. dereferenced in the int handler. - */ - vq_req_get(c2dev, vq_req); - - /* - * Send WR to adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - /* - * Wait for reply from adapter - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail0; - - /* - * Process reply - */ - reply=(struct c2wr_ep_listen_destroy_rep *)(unsigned long)vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail0; - } - if ((err = c2_errno(reply)) != 0) - goto bail1; - - bail1: - vq_repbuf_free(c2dev, reply); - bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -int c2_llp_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param) -{ - struct c2_dev *c2dev = to_c2dev(cm_id->device); - struct c2_qp *qp; - struct ib_qp *ibqp; - struct c2wr_cr_accept_req *wr; /* variable length WR */ - struct c2_vq_req *vq_req; - struct c2wr_cr_accept_rep *reply; /* VQ Reply msg ptr. */ - int err; - - ibqp = c2_get_qp(cm_id->device, iw_param->qpn); - if (!ibqp) - return -EINVAL; - qp = to_c2qp(ibqp); - - /* Set the RDMA read limits */ - err = c2_qp_set_read_limits(c2dev, qp, iw_param->ord, iw_param->ird); - if (err) - goto bail0; - - /* Allocate verbs request. */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) { - err = -ENOMEM; - goto bail1; - } - vq_req->qp = qp; - vq_req->cm_id = cm_id; - vq_req->event = IW_CM_EVENT_ESTABLISHED; - - wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL); - if (!wr) { - err = -ENOMEM; - goto bail2; - } - - /* Build the WR */ - c2_wr_set_id(wr, CCWR_CR_ACCEPT); - wr->hdr.context = (unsigned long) vq_req; - wr->rnic_handle = c2dev->adapter_handle; - wr->ep_handle = (u32) (unsigned long) cm_id->provider_data; - wr->qp_handle = qp->adapter_handle; - - /* Replace the cr_handle with the QP after accept */ - cm_id->provider_data = qp; - cm_id->add_ref(cm_id); - qp->cm_id = cm_id; - - cm_id->provider_data = qp; - - /* Validate private_data length */ - if (iw_param->private_data_len > C2_MAX_PRIVATE_DATA_SIZE) { - err = -EINVAL; - goto bail2; - } - - if (iw_param->private_data) { - wr->private_data_length = cpu_to_be32(iw_param->private_data_len); - memcpy(&wr->private_data[0], - iw_param->private_data, iw_param->private_data_len); - } else - wr->private_data_length = 0; - - /* Reference the request struct. Dereferenced in the int handler. */ - vq_req_get(c2dev, vq_req); - - /* Send WR to adapter */ - err = vq_send_wr(c2dev, (union c2wr *) wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail2; - } - - /* Wait for reply from adapter */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail2; - - /* Check that reply is present */ - reply = (struct c2wr_cr_accept_rep *) (unsigned long) vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail2; - } - - err = c2_errno(reply); - vq_repbuf_free(c2dev, reply); - - if (!err) - c2_set_qp_state(qp, C2_QP_STATE_RTS); - bail2: - kfree(wr); - bail1: - vq_req_free(c2dev, vq_req); - bail0: - if (err) { - /* - * If we fail, release reference on QP and - * disassociate QP from CM_ID - */ - cm_id->provider_data = NULL; - qp->cm_id = NULL; - cm_id->rem_ref(cm_id); - } - return err; -} - -int c2_llp_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) -{ - struct c2_dev *c2dev; - struct c2wr_cr_reject_req wr; - struct c2_vq_req *vq_req; - struct c2wr_cr_reject_rep *reply; - int err; - - c2dev = to_c2dev(cm_id->device); - - /* - * Allocate verbs request. - */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - /* - * Build the WR - */ - c2_wr_set_id(&wr, CCWR_CR_REJECT); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.ep_handle = (u32) (unsigned long) cm_id->provider_data; - - /* - * reference the request struct. dereferenced in the int handler. - */ - vq_req_get(c2dev, vq_req); - - /* - * Send WR to adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - /* - * Wait for reply from adapter - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail0; - - /* - * Process reply - */ - reply = (struct c2wr_cr_reject_rep *) (unsigned long) - vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail0; - } - err = c2_errno(reply); - /* - * free vq stuff - */ - vq_repbuf_free(c2dev, reply); - - bail0: - vq_req_free(c2dev, vq_req); - return err; -} diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_cq.c b/trunk/drivers/infiniband/hw/amso1100/c2_cq.c deleted file mode 100644 index 9d7bcc5ade93..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_cq.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. - * Copyright (c) 2005 Cisco Systems, Inc. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2004 Voltaire, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ -#include "c2.h" -#include "c2_vq.h" -#include "c2_status.h" - -#define C2_CQ_MSG_SIZE ((sizeof(struct c2wr_ce) + 32-1) & ~(32-1)) - -static struct c2_cq *c2_cq_get(struct c2_dev *c2dev, int cqn) -{ - struct c2_cq *cq; - unsigned long flags; - - spin_lock_irqsave(&c2dev->lock, flags); - cq = c2dev->qptr_array[cqn]; - if (!cq) { - spin_unlock_irqrestore(&c2dev->lock, flags); - return NULL; - } - atomic_inc(&cq->refcount); - spin_unlock_irqrestore(&c2dev->lock, flags); - return cq; -} - -static void c2_cq_put(struct c2_cq *cq) -{ - if (atomic_dec_and_test(&cq->refcount)) - wake_up(&cq->wait); -} - -void c2_cq_event(struct c2_dev *c2dev, u32 mq_index) -{ - struct c2_cq *cq; - - cq = c2_cq_get(c2dev, mq_index); - if (!cq) { - printk("discarding events on destroyed CQN=%d\n", mq_index); - return; - } - - (*cq->ibcq.comp_handler) (&cq->ibcq, cq->ibcq.cq_context); - c2_cq_put(cq); -} - -void c2_cq_clean(struct c2_dev *c2dev, struct c2_qp *qp, u32 mq_index) -{ - struct c2_cq *cq; - struct c2_mq *q; - - cq = c2_cq_get(c2dev, mq_index); - if (!cq) - return; - - spin_lock_irq(&cq->lock); - q = &cq->mq; - if (q && !c2_mq_empty(q)) { - u16 priv = q->priv; - struct c2wr_ce *msg; - - while (priv != be16_to_cpu(*q->shared)) { - msg = (struct c2wr_ce *) - (q->msg_pool.host + priv * q->msg_size); - if (msg->qp_user_context == (u64) (unsigned long) qp) { - msg->qp_user_context = (u64) 0; - } - priv = (priv + 1) % q->q_size; - } - } - spin_unlock_irq(&cq->lock); - c2_cq_put(cq); -} - -static inline enum ib_wc_status c2_cqe_status_to_openib(u8 status) -{ - switch (status) { - case C2_OK: - return IB_WC_SUCCESS; - case CCERR_FLUSHED: - return IB_WC_WR_FLUSH_ERR; - case CCERR_BASE_AND_BOUNDS_VIOLATION: - return IB_WC_LOC_PROT_ERR; - case CCERR_ACCESS_VIOLATION: - return IB_WC_LOC_ACCESS_ERR; - case CCERR_TOTAL_LENGTH_TOO_BIG: - return IB_WC_LOC_LEN_ERR; - case CCERR_INVALID_WINDOW: - return IB_WC_MW_BIND_ERR; - default: - return IB_WC_GENERAL_ERR; - } -} - - -static inline int c2_poll_one(struct c2_dev *c2dev, - struct c2_cq *cq, struct ib_wc *entry) -{ - struct c2wr_ce *ce; - struct c2_qp *qp; - int is_recv = 0; - - ce = (struct c2wr_ce *) c2_mq_consume(&cq->mq); - if (!ce) { - return -EAGAIN; - } - - /* - * if the qp returned is null then this qp has already - * been freed and we are unable process the completion. - * try pulling the next message - */ - while ((qp = - (struct c2_qp *) (unsigned long) ce->qp_user_context) == NULL) { - c2_mq_free(&cq->mq); - ce = (struct c2wr_ce *) c2_mq_consume(&cq->mq); - if (!ce) - return -EAGAIN; - } - - entry->status = c2_cqe_status_to_openib(c2_wr_get_result(ce)); - entry->wr_id = ce->hdr.context; - entry->qp_num = ce->handle; - entry->wc_flags = 0; - entry->slid = 0; - entry->sl = 0; - entry->src_qp = 0; - entry->dlid_path_bits = 0; - entry->pkey_index = 0; - - switch (c2_wr_get_id(ce)) { - case C2_WR_TYPE_SEND: - entry->opcode = IB_WC_SEND; - break; - case C2_WR_TYPE_RDMA_WRITE: - entry->opcode = IB_WC_RDMA_WRITE; - break; - case C2_WR_TYPE_RDMA_READ: - entry->opcode = IB_WC_RDMA_READ; - break; - case C2_WR_TYPE_BIND_MW: - entry->opcode = IB_WC_BIND_MW; - break; - case C2_WR_TYPE_RECV: - entry->byte_len = be32_to_cpu(ce->bytes_rcvd); - entry->opcode = IB_WC_RECV; - is_recv = 1; - break; - default: - break; - } - - /* consume the WQEs */ - if (is_recv) - c2_mq_lconsume(&qp->rq_mq, 1); - else - c2_mq_lconsume(&qp->sq_mq, - be32_to_cpu(c2_wr_get_wqe_count(ce)) + 1); - - /* free the message */ - c2_mq_free(&cq->mq); - - return 0; -} - -int c2_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) -{ - struct c2_dev *c2dev = to_c2dev(ibcq->device); - struct c2_cq *cq = to_c2cq(ibcq); - unsigned long flags; - int npolled, err; - - spin_lock_irqsave(&cq->lock, flags); - - for (npolled = 0; npolled < num_entries; ++npolled) { - - err = c2_poll_one(c2dev, cq, entry + npolled); - if (err) - break; - } - - spin_unlock_irqrestore(&cq->lock, flags); - - return npolled; -} - -int c2_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify) -{ - struct c2_mq_shared __iomem *shared; - struct c2_cq *cq; - - cq = to_c2cq(ibcq); - shared = cq->mq.peer; - - if (notify == IB_CQ_NEXT_COMP) - writeb(C2_CQ_NOTIFICATION_TYPE_NEXT, &shared->notification_type); - else if (notify == IB_CQ_SOLICITED) - writeb(C2_CQ_NOTIFICATION_TYPE_NEXT_SE, &shared->notification_type); - else - return -EINVAL; - - writeb(CQ_WAIT_FOR_DMA | CQ_ARMED, &shared->armed); - - /* - * Now read back shared->armed to make the PCI - * write synchronous. This is necessary for - * correct cq notification semantics. - */ - readb(&shared->armed); - - return 0; -} - -static void c2_free_cq_buf(struct c2_dev *c2dev, struct c2_mq *mq) -{ - - dma_unmap_single(c2dev->ibdev.dma_device, pci_unmap_addr(mq, mapping), - mq->q_size * mq->msg_size, DMA_FROM_DEVICE); - free_pages((unsigned long) mq->msg_pool.host, - get_order(mq->q_size * mq->msg_size)); -} - -static int c2_alloc_cq_buf(struct c2_dev *c2dev, struct c2_mq *mq, int q_size, - int msg_size) -{ - unsigned long pool_start; - - pool_start = __get_free_pages(GFP_KERNEL, - get_order(q_size * msg_size)); - if (!pool_start) - return -ENOMEM; - - c2_mq_rep_init(mq, - 0, /* index (currently unknown) */ - q_size, - msg_size, - (u8 *) pool_start, - NULL, /* peer (currently unknown) */ - C2_MQ_HOST_TARGET); - - mq->host_dma = dma_map_single(c2dev->ibdev.dma_device, - (void *)pool_start, - q_size * msg_size, DMA_FROM_DEVICE); - pci_unmap_addr_set(mq, mapping, mq->host_dma); - - return 0; -} - -int c2_init_cq(struct c2_dev *c2dev, int entries, - struct c2_ucontext *ctx, struct c2_cq *cq) -{ - struct c2wr_cq_create_req wr; - struct c2wr_cq_create_rep *reply; - unsigned long peer_pa; - struct c2_vq_req *vq_req; - int err; - - might_sleep(); - - cq->ibcq.cqe = entries - 1; - cq->is_kernel = !ctx; - - /* Allocate a shared pointer */ - cq->mq.shared = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &cq->mq.shared_dma, GFP_KERNEL); - if (!cq->mq.shared) - return -ENOMEM; - - /* Allocate pages for the message pool */ - err = c2_alloc_cq_buf(c2dev, &cq->mq, entries + 1, C2_CQ_MSG_SIZE); - if (err) - goto bail0; - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) { - err = -ENOMEM; - goto bail1; - } - - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_CQ_CREATE); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.msg_size = cpu_to_be32(cq->mq.msg_size); - wr.depth = cpu_to_be32(cq->mq.q_size); - wr.shared_ht = cpu_to_be64(cq->mq.shared_dma); - wr.msg_pool = cpu_to_be64(cq->mq.host_dma); - wr.user_context = (u64) (unsigned long) (cq); - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail2; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail2; - - reply = (struct c2wr_cq_create_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail2; - } - - if ((err = c2_errno(reply)) != 0) - goto bail3; - - cq->adapter_handle = reply->cq_handle; - cq->mq.index = be32_to_cpu(reply->mq_index); - - peer_pa = c2dev->pa + be32_to_cpu(reply->adapter_shared); - cq->mq.peer = ioremap_nocache(peer_pa, PAGE_SIZE); - if (!cq->mq.peer) { - err = -ENOMEM; - goto bail3; - } - - vq_repbuf_free(c2dev, reply); - vq_req_free(c2dev, vq_req); - - spin_lock_init(&cq->lock); - atomic_set(&cq->refcount, 1); - init_waitqueue_head(&cq->wait); - - /* - * Use the MQ index allocated by the adapter to - * store the CQ in the qptr_array - */ - cq->cqn = cq->mq.index; - c2dev->qptr_array[cq->cqn] = cq; - - return 0; - - bail3: - vq_repbuf_free(c2dev, reply); - bail2: - vq_req_free(c2dev, vq_req); - bail1: - c2_free_cq_buf(c2dev, &cq->mq); - bail0: - c2_free_mqsp(cq->mq.shared); - - return err; -} - -void c2_free_cq(struct c2_dev *c2dev, struct c2_cq *cq) -{ - int err; - struct c2_vq_req *vq_req; - struct c2wr_cq_destroy_req wr; - struct c2wr_cq_destroy_rep *reply; - - might_sleep(); - - /* Clear CQ from the qptr array */ - spin_lock_irq(&c2dev->lock); - c2dev->qptr_array[cq->mq.index] = NULL; - atomic_dec(&cq->refcount); - spin_unlock_irq(&c2dev->lock); - - wait_event(cq->wait, !atomic_read(&cq->refcount)); - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) { - goto bail0; - } - - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_CQ_DESTROY); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.cq_handle = cq->adapter_handle; - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail1; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail1; - - reply = (struct c2wr_cq_destroy_rep *) (unsigned long) (vq_req->reply_msg); - - vq_repbuf_free(c2dev, reply); - bail1: - vq_req_free(c2dev, vq_req); - bail0: - if (cq->is_kernel) { - c2_free_cq_buf(c2dev, &cq->mq); - } - - return; -} diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_intr.c b/trunk/drivers/infiniband/hw/amso1100/c2_intr.c deleted file mode 100644 index 0d0bc33ca30a..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_intr.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "c2.h" -#include -#include "c2_vq.h" - -static void handle_mq(struct c2_dev *c2dev, u32 index); -static void handle_vq(struct c2_dev *c2dev, u32 mq_index); - -/* - * Handle RNIC interrupts - */ -void c2_rnic_interrupt(struct c2_dev *c2dev) -{ - unsigned int mq_index; - - while (c2dev->hints_read != be16_to_cpu(*c2dev->hint_count)) { - mq_index = readl(c2dev->regs + PCI_BAR0_HOST_HINT); - if (mq_index & 0x80000000) { - break; - } - - c2dev->hints_read++; - handle_mq(c2dev, mq_index); - } - -} - -/* - * Top level MQ handler - */ -static void handle_mq(struct c2_dev *c2dev, u32 mq_index) -{ - if (c2dev->qptr_array[mq_index] == NULL) { - pr_debug(KERN_INFO "handle_mq: stray activity for mq_index=%d\n", - mq_index); - return; - } - - switch (mq_index) { - case (0): - /* - * An index of 0 in the activity queue - * indicates the req vq now has messages - * available... - * - * Wake up any waiters waiting on req VQ - * message availability. - */ - wake_up(&c2dev->req_vq_wo); - break; - case (1): - handle_vq(c2dev, mq_index); - break; - case (2): - /* We have to purge the VQ in case there are pending - * accept reply requests that would result in the - * generation of an ESTABLISHED event. If we don't - * generate these first, a CLOSE event could end up - * being delivered before the ESTABLISHED event. - */ - handle_vq(c2dev, 1); - - c2_ae_event(c2dev, mq_index); - break; - default: - /* There is no event synchronization between CQ events - * and AE or CM events. In fact, CQE could be - * delivered for all of the I/O up to and including the - * FLUSH for a peer disconenct prior to the ESTABLISHED - * event being delivered to the app. The reason for this - * is that CM events are delivered on a thread, while AE - * and CM events are delivered on interrupt context. - */ - c2_cq_event(c2dev, mq_index); - break; - } - - return; -} - -/* - * Handles verbs WR replies. - */ -static void handle_vq(struct c2_dev *c2dev, u32 mq_index) -{ - void *adapter_msg, *reply_msg; - struct c2wr_hdr *host_msg; - struct c2wr_hdr tmp; - struct c2_mq *reply_vq; - struct c2_vq_req *req; - struct iw_cm_event cm_event; - int err; - - reply_vq = (struct c2_mq *) c2dev->qptr_array[mq_index]; - - /* - * get next msg from mq_index into adapter_msg. - * don't free it yet. - */ - adapter_msg = c2_mq_consume(reply_vq); - if (adapter_msg == NULL) { - return; - } - - host_msg = vq_repbuf_alloc(c2dev); - - /* - * If we can't get a host buffer, then we'll still - * wakeup the waiter, we just won't give him the msg. - * It is assumed the waiter will deal with this... - */ - if (!host_msg) { - pr_debug("handle_vq: no repbufs!\n"); - - /* - * just copy the WR header into a local variable. - * this allows us to still demux on the context - */ - host_msg = &tmp; - memcpy(host_msg, adapter_msg, sizeof(tmp)); - reply_msg = NULL; - } else { - memcpy(host_msg, adapter_msg, reply_vq->msg_size); - reply_msg = host_msg; - } - - /* - * consume the msg from the MQ - */ - c2_mq_free(reply_vq); - - /* - * wakeup the waiter. - */ - req = (struct c2_vq_req *) (unsigned long) host_msg->context; - if (req == NULL) { - /* - * We should never get here, as the adapter should - * never send us a reply that we're not expecting. - */ - vq_repbuf_free(c2dev, host_msg); - pr_debug("handle_vq: UNEXPECTEDLY got NULL req\n"); - return; - } - - err = c2_errno(reply_msg); - if (!err) switch (req->event) { - case IW_CM_EVENT_ESTABLISHED: - c2_set_qp_state(req->qp, - C2_QP_STATE_RTS); - case IW_CM_EVENT_CLOSE: - - /* - * Move the QP to RTS if this is - * the established event - */ - cm_event.event = req->event; - cm_event.status = 0; - cm_event.local_addr = req->cm_id->local_addr; - cm_event.remote_addr = req->cm_id->remote_addr; - cm_event.private_data = NULL; - cm_event.private_data_len = 0; - req->cm_id->event_handler(req->cm_id, &cm_event); - break; - default: - break; - } - - req->reply_msg = (u64) (unsigned long) (reply_msg); - atomic_set(&req->reply_ready, 1); - wake_up(&req->wait_object); - - /* - * If the request was cancelled, then this put will - * free the vq_req memory...and reply_msg!!! - */ - vq_req_put(c2dev, req); -} diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_mm.c b/trunk/drivers/infiniband/hw/amso1100/c2_mm.c deleted file mode 100644 index 1e4f46493fcb..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_mm.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "c2.h" -#include "c2_vq.h" - -#define PBL_VIRT 1 -#define PBL_PHYS 2 - -/* - * Send all the PBL messages to convey the remainder of the PBL - * Wait for the adapter's reply on the last one. - * This is indicated by setting the MEM_PBL_COMPLETE in the flags. - * - * NOTE: vq_req is _not_ freed by this function. The VQ Host - * Reply buffer _is_ freed by this function. - */ -static int -send_pbl_messages(struct c2_dev *c2dev, u32 stag_index, - unsigned long va, u32 pbl_depth, - struct c2_vq_req *vq_req, int pbl_type) -{ - u32 pbe_count; /* amt that fits in a PBL msg */ - u32 count; /* amt in this PBL MSG. */ - struct c2wr_nsmr_pbl_req *wr; /* PBL WR ptr */ - struct c2wr_nsmr_pbl_rep *reply; /* reply ptr */ - int err, pbl_virt, pbl_index, i; - - switch (pbl_type) { - case PBL_VIRT: - pbl_virt = 1; - break; - case PBL_PHYS: - pbl_virt = 0; - break; - default: - return -EINVAL; - break; - } - - pbe_count = (c2dev->req_vq.msg_size - - sizeof(struct c2wr_nsmr_pbl_req)) / sizeof(u64); - wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL); - if (!wr) { - return -ENOMEM; - } - c2_wr_set_id(wr, CCWR_NSMR_PBL); - - /* - * Only the last PBL message will generate a reply from the verbs, - * so we set the context to 0 indicating there is no kernel verbs - * handler blocked awaiting this reply. - */ - wr->hdr.context = 0; - wr->rnic_handle = c2dev->adapter_handle; - wr->stag_index = stag_index; /* already swapped */ - wr->flags = 0; - pbl_index = 0; - while (pbl_depth) { - count = min(pbe_count, pbl_depth); - wr->addrs_length = cpu_to_be32(count); - - /* - * If this is the last message, then reference the - * vq request struct cuz we're gonna wait for a reply. - * also make this PBL msg as the last one. - */ - if (count == pbl_depth) { - /* - * reference the request struct. dereferenced in the - * int handler. - */ - vq_req_get(c2dev, vq_req); - wr->flags = cpu_to_be32(MEM_PBL_COMPLETE); - - /* - * This is the last PBL message. - * Set the context to our VQ Request Object so we can - * wait for the reply. - */ - wr->hdr.context = (unsigned long) vq_req; - } - - /* - * If pbl_virt is set then va is a virtual address - * that describes a virtually contiguous memory - * allocation. The wr needs the start of each virtual page - * to be converted to the corresponding physical address - * of the page. If pbl_virt is not set then va is an array - * of physical addresses and there is no conversion to do. - * Just fill in the wr with what is in the array. - */ - for (i = 0; i < count; i++) { - if (pbl_virt) { - va += PAGE_SIZE; - } else { - wr->paddrs[i] = - cpu_to_be64(((u64 *)va)[pbl_index + i]); - } - } - - /* - * Send WR to adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) wr); - if (err) { - if (count <= pbe_count) { - vq_req_put(c2dev, vq_req); - } - goto bail0; - } - pbl_depth -= count; - pbl_index += count; - } - - /* - * Now wait for the reply... - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail0; - } - - /* - * Process reply - */ - reply = (struct c2wr_nsmr_pbl_rep *) (unsigned long) vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - err = c2_errno(reply); - - vq_repbuf_free(c2dev, reply); - bail0: - kfree(wr); - return err; -} - -#define C2_PBL_MAX_DEPTH 131072 -int -c2_nsmr_register_phys_kern(struct c2_dev *c2dev, u64 *addr_list, - int page_size, int pbl_depth, u32 length, - u32 offset, u64 *va, enum c2_acf acf, - struct c2_mr *mr) -{ - struct c2_vq_req *vq_req; - struct c2wr_nsmr_register_req *wr; - struct c2wr_nsmr_register_rep *reply; - u16 flags; - int i, pbe_count, count; - int err; - - if (!va || !length || !addr_list || !pbl_depth) - return -EINTR; - - /* - * Verify PBL depth is within rnic max - */ - if (pbl_depth > C2_PBL_MAX_DEPTH) { - return -EINTR; - } - - /* - * allocate verbs request object - */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL); - if (!wr) { - err = -ENOMEM; - goto bail0; - } - - /* - * build the WR - */ - c2_wr_set_id(wr, CCWR_NSMR_REGISTER); - wr->hdr.context = (unsigned long) vq_req; - wr->rnic_handle = c2dev->adapter_handle; - - flags = (acf | MEM_VA_BASED | MEM_REMOTE); - - /* - * compute how many pbes can fit in the message - */ - pbe_count = (c2dev->req_vq.msg_size - - sizeof(struct c2wr_nsmr_register_req)) / sizeof(u64); - - if (pbl_depth <= pbe_count) { - flags |= MEM_PBL_COMPLETE; - } - wr->flags = cpu_to_be16(flags); - wr->stag_key = 0; //stag_key; - wr->va = cpu_to_be64(*va); - wr->pd_id = mr->pd->pd_id; - wr->pbe_size = cpu_to_be32(page_size); - wr->length = cpu_to_be32(length); - wr->pbl_depth = cpu_to_be32(pbl_depth); - wr->fbo = cpu_to_be32(offset); - count = min(pbl_depth, pbe_count); - wr->addrs_length = cpu_to_be32(count); - - /* - * fill out the PBL for this message - */ - for (i = 0; i < count; i++) { - wr->paddrs[i] = cpu_to_be64(addr_list[i]); - } - - /* - * regerence the request struct - */ - vq_req_get(c2dev, vq_req); - - /* - * send the WR to the adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail1; - } - - /* - * wait for reply from adapter - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail1; - } - - /* - * process reply - */ - reply = - (struct c2wr_nsmr_register_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail1; - } - if ((err = c2_errno(reply))) { - goto bail2; - } - //*p_pb_entries = be32_to_cpu(reply->pbl_depth); - mr->ibmr.lkey = mr->ibmr.rkey = be32_to_cpu(reply->stag_index); - vq_repbuf_free(c2dev, reply); - - /* - * if there are still more PBEs we need to send them to - * the adapter and wait for a reply on the final one. - * reuse vq_req for this purpose. - */ - pbl_depth -= count; - if (pbl_depth) { - - vq_req->reply_msg = (unsigned long) NULL; - atomic_set(&vq_req->reply_ready, 0); - err = send_pbl_messages(c2dev, - cpu_to_be32(mr->ibmr.lkey), - (unsigned long) &addr_list[i], - pbl_depth, vq_req, PBL_PHYS); - if (err) { - goto bail1; - } - } - - vq_req_free(c2dev, vq_req); - kfree(wr); - - return err; - - bail2: - vq_repbuf_free(c2dev, reply); - bail1: - kfree(wr); - bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -int c2_stag_dealloc(struct c2_dev *c2dev, u32 stag_index) -{ - struct c2_vq_req *vq_req; /* verbs request object */ - struct c2wr_stag_dealloc_req wr; /* work request */ - struct c2wr_stag_dealloc_rep *reply; /* WR reply */ - int err; - - - /* - * allocate verbs request object - */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) { - return -ENOMEM; - } - - /* - * Build the WR - */ - c2_wr_set_id(&wr, CCWR_STAG_DEALLOC); - wr.hdr.context = (u64) (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.stag_index = cpu_to_be32(stag_index); - - /* - * reference the request struct. dereferenced in the int handler. - */ - vq_req_get(c2dev, vq_req); - - /* - * Send WR to adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - /* - * Wait for reply from adapter - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail0; - } - - /* - * Process reply - */ - reply = (struct c2wr_stag_dealloc_rep *) (unsigned long) vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - err = c2_errno(reply); - - vq_repbuf_free(c2dev, reply); - bail0: - vq_req_free(c2dev, vq_req); - return err; -} diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_mq.c b/trunk/drivers/infiniband/hw/amso1100/c2_mq.c deleted file mode 100644 index b88a75592102..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_mq.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "c2.h" -#include "c2_mq.h" - -void *c2_mq_alloc(struct c2_mq *q) -{ - BUG_ON(q->magic != C2_MQ_MAGIC); - BUG_ON(q->type != C2_MQ_ADAPTER_TARGET); - - if (c2_mq_full(q)) { - return NULL; - } else { -#ifdef DEBUG - struct c2wr_hdr *m = - (struct c2wr_hdr *) (q->msg_pool.host + q->priv * q->msg_size); -#ifdef CCMSGMAGIC - BUG_ON(m->magic != be32_to_cpu(~CCWR_MAGIC)); - m->magic = cpu_to_be32(CCWR_MAGIC); -#endif - return m; -#else - return q->msg_pool.host + q->priv * q->msg_size; -#endif - } -} - -void c2_mq_produce(struct c2_mq *q) -{ - BUG_ON(q->magic != C2_MQ_MAGIC); - BUG_ON(q->type != C2_MQ_ADAPTER_TARGET); - - if (!c2_mq_full(q)) { - q->priv = (q->priv + 1) % q->q_size; - q->hint_count++; - /* Update peer's offset. */ - __raw_writew(cpu_to_be16(q->priv), &q->peer->shared); - } -} - -void *c2_mq_consume(struct c2_mq *q) -{ - BUG_ON(q->magic != C2_MQ_MAGIC); - BUG_ON(q->type != C2_MQ_HOST_TARGET); - - if (c2_mq_empty(q)) { - return NULL; - } else { -#ifdef DEBUG - struct c2wr_hdr *m = (struct c2wr_hdr *) - (q->msg_pool.host + q->priv * q->msg_size); -#ifdef CCMSGMAGIC - BUG_ON(m->magic != be32_to_cpu(CCWR_MAGIC)); -#endif - return m; -#else - return q->msg_pool.host + q->priv * q->msg_size; -#endif - } -} - -void c2_mq_free(struct c2_mq *q) -{ - BUG_ON(q->magic != C2_MQ_MAGIC); - BUG_ON(q->type != C2_MQ_HOST_TARGET); - - if (!c2_mq_empty(q)) { - -#ifdef CCMSGMAGIC - { - struct c2wr_hdr __iomem *m = (struct c2wr_hdr __iomem *) - (q->msg_pool.adapter + q->priv * q->msg_size); - __raw_writel(cpu_to_be32(~CCWR_MAGIC), &m->magic); - } -#endif - q->priv = (q->priv + 1) % q->q_size; - /* Update peer's offset. */ - __raw_writew(cpu_to_be16(q->priv), &q->peer->shared); - } -} - - -void c2_mq_lconsume(struct c2_mq *q, u32 wqe_count) -{ - BUG_ON(q->magic != C2_MQ_MAGIC); - BUG_ON(q->type != C2_MQ_ADAPTER_TARGET); - - while (wqe_count--) { - BUG_ON(c2_mq_empty(q)); - *q->shared = cpu_to_be16((be16_to_cpu(*q->shared)+1) % q->q_size); - } -} - -#if 0 -u32 c2_mq_count(struct c2_mq *q) -{ - s32 count; - - if (q->type == C2_MQ_HOST_TARGET) - count = be16_to_cpu(*q->shared) - q->priv; - else - count = q->priv - be16_to_cpu(*q->shared); - - if (count < 0) - count += q->q_size; - - return (u32) count; -} -#endif /* 0 */ - -void c2_mq_req_init(struct c2_mq *q, u32 index, u32 q_size, u32 msg_size, - u8 __iomem *pool_start, u16 __iomem *peer, u32 type) -{ - BUG_ON(!q->shared); - - /* This code assumes the byte swapping has already been done! */ - q->index = index; - q->q_size = q_size; - q->msg_size = msg_size; - q->msg_pool.adapter = pool_start; - q->peer = (struct c2_mq_shared __iomem *) peer; - q->magic = C2_MQ_MAGIC; - q->type = type; - q->priv = 0; - q->hint_count = 0; - return; -} -void c2_mq_rep_init(struct c2_mq *q, u32 index, u32 q_size, u32 msg_size, - u8 *pool_start, u16 __iomem *peer, u32 type) -{ - BUG_ON(!q->shared); - - /* This code assumes the byte swapping has already been done! */ - q->index = index; - q->q_size = q_size; - q->msg_size = msg_size; - q->msg_pool.host = pool_start; - q->peer = (struct c2_mq_shared __iomem *) peer; - q->magic = C2_MQ_MAGIC; - q->type = type; - q->priv = 0; - q->hint_count = 0; - return; -} diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_mq.h b/trunk/drivers/infiniband/hw/amso1100/c2_mq.h deleted file mode 100644 index 9185bbb21658..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_mq.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _C2_MQ_H_ -#define _C2_MQ_H_ -#include -#include -#include "c2_wr.h" - -enum c2_shared_regs { - - C2_SHARED_ARMED = 0x10, - C2_SHARED_NOTIFY = 0x18, - C2_SHARED_SHARED = 0x40, -}; - -struct c2_mq_shared { - u16 unused1; - u8 armed; - u8 notification_type; - u32 unused2; - u16 shared; - /* Pad to 64 bytes. */ - u8 pad[64 - sizeof(u16) - 2 * sizeof(u8) - sizeof(u32) - sizeof(u16)]; -}; - -enum c2_mq_type { - C2_MQ_HOST_TARGET = 1, - C2_MQ_ADAPTER_TARGET = 2, -}; - -/* - * c2_mq_t is for kernel-mode MQs like the VQs Cand the AEQ. - * c2_user_mq_t (which is the same format) is for user-mode MQs... - */ -#define C2_MQ_MAGIC 0x4d512020 /* 'MQ ' */ -struct c2_mq { - u32 magic; - union { - u8 *host; - u8 __iomem *adapter; - } msg_pool; - dma_addr_t host_dma; - DECLARE_PCI_UNMAP_ADDR(mapping); - u16 hint_count; - u16 priv; - struct c2_mq_shared __iomem *peer; - u16 *shared; - dma_addr_t shared_dma; - u32 q_size; - u32 msg_size; - u32 index; - enum c2_mq_type type; -}; - -static __inline__ int c2_mq_empty(struct c2_mq *q) -{ - return q->priv == be16_to_cpu(*q->shared); -} - -static __inline__ int c2_mq_full(struct c2_mq *q) -{ - return q->priv == (be16_to_cpu(*q->shared) + q->q_size - 1) % q->q_size; -} - -extern void c2_mq_lconsume(struct c2_mq *q, u32 wqe_count); -extern void *c2_mq_alloc(struct c2_mq *q); -extern void c2_mq_produce(struct c2_mq *q); -extern void *c2_mq_consume(struct c2_mq *q); -extern void c2_mq_free(struct c2_mq *q); -extern void c2_mq_req_init(struct c2_mq *q, u32 index, u32 q_size, u32 msg_size, - u8 __iomem *pool_start, u16 __iomem *peer, u32 type); -extern void c2_mq_rep_init(struct c2_mq *q, u32 index, u32 q_size, u32 msg_size, - u8 *pool_start, u16 __iomem *peer, u32 type); - -#endif /* _C2_MQ_H_ */ diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_pd.c b/trunk/drivers/infiniband/hw/amso1100/c2_pd.c deleted file mode 100644 index 00c709926c8d..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_pd.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2004 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include "c2.h" -#include "c2_provider.h" - -int c2_pd_alloc(struct c2_dev *c2dev, int privileged, struct c2_pd *pd) -{ - u32 obj; - int ret = 0; - - spin_lock(&c2dev->pd_table.lock); - obj = find_next_zero_bit(c2dev->pd_table.table, c2dev->pd_table.max, - c2dev->pd_table.last); - if (obj >= c2dev->pd_table.max) - obj = find_first_zero_bit(c2dev->pd_table.table, - c2dev->pd_table.max); - if (obj < c2dev->pd_table.max) { - pd->pd_id = obj; - __set_bit(obj, c2dev->pd_table.table); - c2dev->pd_table.last = obj+1; - if (c2dev->pd_table.last >= c2dev->pd_table.max) - c2dev->pd_table.last = 0; - } else - ret = -ENOMEM; - spin_unlock(&c2dev->pd_table.lock); - return ret; -} - -void c2_pd_free(struct c2_dev *c2dev, struct c2_pd *pd) -{ - spin_lock(&c2dev->pd_table.lock); - __clear_bit(pd->pd_id, c2dev->pd_table.table); - spin_unlock(&c2dev->pd_table.lock); -} - -int __devinit c2_init_pd_table(struct c2_dev *c2dev) -{ - - c2dev->pd_table.last = 0; - c2dev->pd_table.max = c2dev->props.max_pd; - spin_lock_init(&c2dev->pd_table.lock); - c2dev->pd_table.table = kmalloc(BITS_TO_LONGS(c2dev->props.max_pd) * - sizeof(long), GFP_KERNEL); - if (!c2dev->pd_table.table) - return -ENOMEM; - bitmap_zero(c2dev->pd_table.table, c2dev->props.max_pd); - return 0; -} - -void __devexit c2_cleanup_pd_table(struct c2_dev *c2dev) -{ - kfree(c2dev->pd_table.table); -} diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_provider.c b/trunk/drivers/infiniband/hw/amso1100/c2_provider.c deleted file mode 100644 index dd6af551108b..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_provider.c +++ /dev/null @@ -1,870 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include "c2.h" -#include "c2_provider.h" -#include "c2_user.h" - -static int c2_query_device(struct ib_device *ibdev, - struct ib_device_attr *props) -{ - struct c2_dev *c2dev = to_c2dev(ibdev); - - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - - *props = c2dev->props; - return 0; -} - -static int c2_query_port(struct ib_device *ibdev, - u8 port, struct ib_port_attr *props) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - - props->max_mtu = IB_MTU_4096; - props->lid = 0; - props->lmc = 0; - props->sm_lid = 0; - props->sm_sl = 0; - props->state = IB_PORT_ACTIVE; - props->phys_state = 0; - props->port_cap_flags = - IB_PORT_CM_SUP | - IB_PORT_REINIT_SUP | - IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP; - props->gid_tbl_len = 1; - props->pkey_tbl_len = 1; - props->qkey_viol_cntr = 0; - props->active_width = 1; - props->active_speed = 1; - - return 0; -} - -static int c2_modify_port(struct ib_device *ibdev, - u8 port, int port_modify_mask, - struct ib_port_modify *props) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - return 0; -} - -static int c2_query_pkey(struct ib_device *ibdev, - u8 port, u16 index, u16 * pkey) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - *pkey = 0; - return 0; -} - -static int c2_query_gid(struct ib_device *ibdev, u8 port, - int index, union ib_gid *gid) -{ - struct c2_dev *c2dev = to_c2dev(ibdev); - - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - memset(&(gid->raw[0]), 0, sizeof(gid->raw)); - memcpy(&(gid->raw[0]), c2dev->pseudo_netdev->dev_addr, 6); - - return 0; -} - -/* Allocate the user context data structure. This keeps track - * of all objects associated with a particular user-mode client. - */ -static struct ib_ucontext *c2_alloc_ucontext(struct ib_device *ibdev, - struct ib_udata *udata) -{ - struct c2_ucontext *context; - - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - context = kmalloc(sizeof(*context), GFP_KERNEL); - if (!context) - return ERR_PTR(-ENOMEM); - - return &context->ibucontext; -} - -static int c2_dealloc_ucontext(struct ib_ucontext *context) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - kfree(context); - return 0; -} - -static int c2_mmap_uar(struct ib_ucontext *context, struct vm_area_struct *vma) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - return -ENOSYS; -} - -static struct ib_pd *c2_alloc_pd(struct ib_device *ibdev, - struct ib_ucontext *context, - struct ib_udata *udata) -{ - struct c2_pd *pd; - int err; - - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - - pd = kmalloc(sizeof(*pd), GFP_KERNEL); - if (!pd) - return ERR_PTR(-ENOMEM); - - err = c2_pd_alloc(to_c2dev(ibdev), !context, pd); - if (err) { - kfree(pd); - return ERR_PTR(err); - } - - if (context) { - if (ib_copy_to_udata(udata, &pd->pd_id, sizeof(__u32))) { - c2_pd_free(to_c2dev(ibdev), pd); - kfree(pd); - return ERR_PTR(-EFAULT); - } - } - - return &pd->ibpd; -} - -static int c2_dealloc_pd(struct ib_pd *pd) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - c2_pd_free(to_c2dev(pd->device), to_c2pd(pd)); - kfree(pd); - - return 0; -} - -static struct ib_ah *c2_ah_create(struct ib_pd *pd, struct ib_ah_attr *ah_attr) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - return ERR_PTR(-ENOSYS); -} - -static int c2_ah_destroy(struct ib_ah *ah) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - return -ENOSYS; -} - -static void c2_add_ref(struct ib_qp *ibqp) -{ - struct c2_qp *qp; - BUG_ON(!ibqp); - qp = to_c2qp(ibqp); - atomic_inc(&qp->refcount); -} - -static void c2_rem_ref(struct ib_qp *ibqp) -{ - struct c2_qp *qp; - BUG_ON(!ibqp); - qp = to_c2qp(ibqp); - if (atomic_dec_and_test(&qp->refcount)) - wake_up(&qp->wait); -} - -struct ib_qp *c2_get_qp(struct ib_device *device, int qpn) -{ - struct c2_dev* c2dev = to_c2dev(device); - struct c2_qp *qp; - - qp = c2_find_qpn(c2dev, qpn); - pr_debug("%s Returning QP=%p for QPN=%d, device=%p, refcount=%d\n", - __FUNCTION__, qp, qpn, device, - (qp?atomic_read(&qp->refcount):0)); - - return (qp?&qp->ibqp:NULL); -} - -static struct ib_qp *c2_create_qp(struct ib_pd *pd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata) -{ - struct c2_qp *qp; - int err; - - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - - switch (init_attr->qp_type) { - case IB_QPT_RC: - qp = kzalloc(sizeof(*qp), GFP_KERNEL); - if (!qp) { - pr_debug("%s: Unable to allocate QP\n", __FUNCTION__); - return ERR_PTR(-ENOMEM); - } - spin_lock_init(&qp->lock); - if (pd->uobject) { - /* userspace specific */ - } - - err = c2_alloc_qp(to_c2dev(pd->device), - to_c2pd(pd), init_attr, qp); - - if (err && pd->uobject) { - /* userspace specific */ - } - - break; - default: - pr_debug("%s: Invalid QP type: %d\n", __FUNCTION__, - init_attr->qp_type); - return ERR_PTR(-EINVAL); - break; - } - - if (err) { - kfree(qp); - return ERR_PTR(err); - } - - return &qp->ibqp; -} - -static int c2_destroy_qp(struct ib_qp *ib_qp) -{ - struct c2_qp *qp = to_c2qp(ib_qp); - - pr_debug("%s:%u qp=%p,qp->state=%d\n", - __FUNCTION__, __LINE__,ib_qp,qp->state); - c2_free_qp(to_c2dev(ib_qp->device), qp); - kfree(qp); - return 0; -} - -static struct ib_cq *c2_create_cq(struct ib_device *ibdev, int entries, - struct ib_ucontext *context, - struct ib_udata *udata) -{ - struct c2_cq *cq; - int err; - - cq = kmalloc(sizeof(*cq), GFP_KERNEL); - if (!cq) { - pr_debug("%s: Unable to allocate CQ\n", __FUNCTION__); - return ERR_PTR(-ENOMEM); - } - - err = c2_init_cq(to_c2dev(ibdev), entries, NULL, cq); - if (err) { - pr_debug("%s: error initializing CQ\n", __FUNCTION__); - kfree(cq); - return ERR_PTR(err); - } - - return &cq->ibcq; -} - -static int c2_destroy_cq(struct ib_cq *ib_cq) -{ - struct c2_cq *cq = to_c2cq(ib_cq); - - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - - c2_free_cq(to_c2dev(ib_cq->device), cq); - kfree(cq); - - return 0; -} - -static inline u32 c2_convert_access(int acc) -{ - return (acc & IB_ACCESS_REMOTE_WRITE ? C2_ACF_REMOTE_WRITE : 0) | - (acc & IB_ACCESS_REMOTE_READ ? C2_ACF_REMOTE_READ : 0) | - (acc & IB_ACCESS_LOCAL_WRITE ? C2_ACF_LOCAL_WRITE : 0) | - C2_ACF_LOCAL_READ | C2_ACF_WINDOW_BIND; -} - -static struct ib_mr *c2_reg_phys_mr(struct ib_pd *ib_pd, - struct ib_phys_buf *buffer_list, - int num_phys_buf, int acc, u64 * iova_start) -{ - struct c2_mr *mr; - u64 *page_list; - u32 total_len; - int err, i, j, k, page_shift, pbl_depth; - - pbl_depth = 0; - total_len = 0; - - page_shift = PAGE_SHIFT; - /* - * If there is only 1 buffer we assume this could - * be a map of all phy mem...use a 32k page_shift. - */ - if (num_phys_buf == 1) - page_shift += 3; - - for (i = 0; i < num_phys_buf; i++) { - - if (buffer_list[i].addr & ~PAGE_MASK) { - pr_debug("Unaligned Memory Buffer: 0x%x\n", - (unsigned int) buffer_list[i].addr); - return ERR_PTR(-EINVAL); - } - - if (!buffer_list[i].size) { - pr_debug("Invalid Buffer Size\n"); - return ERR_PTR(-EINVAL); - } - - total_len += buffer_list[i].size; - pbl_depth += ALIGN(buffer_list[i].size, - (1 << page_shift)) >> page_shift; - } - - page_list = vmalloc(sizeof(u64) * pbl_depth); - if (!page_list) { - pr_debug("couldn't vmalloc page_list of size %zd\n", - (sizeof(u64) * pbl_depth)); - return ERR_PTR(-ENOMEM); - } - - for (i = 0, j = 0; i < num_phys_buf; i++) { - - int naddrs; - - naddrs = ALIGN(buffer_list[i].size, - (1 << page_shift)) >> page_shift; - for (k = 0; k < naddrs; k++) - page_list[j++] = (buffer_list[i].addr + - (k << page_shift)); - } - - mr = kmalloc(sizeof(*mr), GFP_KERNEL); - if (!mr) - return ERR_PTR(-ENOMEM); - - mr->pd = to_c2pd(ib_pd); - pr_debug("%s - page shift %d, pbl_depth %d, total_len %u, " - "*iova_start %llx, first pa %llx, last pa %llx\n", - __FUNCTION__, page_shift, pbl_depth, total_len, - *iova_start, page_list[0], page_list[pbl_depth-1]); - err = c2_nsmr_register_phys_kern(to_c2dev(ib_pd->device), page_list, - (1 << page_shift), pbl_depth, - total_len, 0, iova_start, - c2_convert_access(acc), mr); - vfree(page_list); - if (err) { - kfree(mr); - return ERR_PTR(err); - } - - return &mr->ibmr; -} - -static struct ib_mr *c2_get_dma_mr(struct ib_pd *pd, int acc) -{ - struct ib_phys_buf bl; - u64 kva = 0; - - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - - /* AMSO1100 limit */ - bl.size = 0xffffffff; - bl.addr = 0; - return c2_reg_phys_mr(pd, &bl, 1, acc, &kva); -} - -static struct ib_mr *c2_reg_user_mr(struct ib_pd *pd, struct ib_umem *region, - int acc, struct ib_udata *udata) -{ - u64 *pages; - u64 kva = 0; - int shift, n, len; - int i, j, k; - int err = 0; - struct ib_umem_chunk *chunk; - struct c2_pd *c2pd = to_c2pd(pd); - struct c2_mr *c2mr; - - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - shift = ffs(region->page_size) - 1; - - c2mr = kmalloc(sizeof(*c2mr), GFP_KERNEL); - if (!c2mr) - return ERR_PTR(-ENOMEM); - c2mr->pd = c2pd; - - n = 0; - list_for_each_entry(chunk, ®ion->chunk_list, list) - n += chunk->nents; - - pages = kmalloc(n * sizeof(u64), GFP_KERNEL); - if (!pages) { - err = -ENOMEM; - goto err; - } - - i = 0; - list_for_each_entry(chunk, ®ion->chunk_list, list) { - for (j = 0; j < chunk->nmap; ++j) { - len = sg_dma_len(&chunk->page_list[j]) >> shift; - for (k = 0; k < len; ++k) { - pages[i++] = - sg_dma_address(&chunk->page_list[j]) + - (region->page_size * k); - } - } - } - - kva = (u64)region->virt_base; - err = c2_nsmr_register_phys_kern(to_c2dev(pd->device), - pages, - region->page_size, - i, - region->length, - region->offset, - &kva, - c2_convert_access(acc), - c2mr); - kfree(pages); - if (err) { - kfree(c2mr); - return ERR_PTR(err); - } - return &c2mr->ibmr; - -err: - kfree(c2mr); - return ERR_PTR(err); -} - -static int c2_dereg_mr(struct ib_mr *ib_mr) -{ - struct c2_mr *mr = to_c2mr(ib_mr); - int err; - - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - - err = c2_stag_dealloc(to_c2dev(ib_mr->device), ib_mr->lkey); - if (err) - pr_debug("c2_stag_dealloc failed: %d\n", err); - else - kfree(mr); - - return err; -} - -static ssize_t show_rev(struct class_device *cdev, char *buf) -{ - struct c2_dev *dev = container_of(cdev, struct c2_dev, ibdev.class_dev); - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - return sprintf(buf, "%x\n", dev->props.hw_ver); -} - -static ssize_t show_fw_ver(struct class_device *cdev, char *buf) -{ - struct c2_dev *dev = container_of(cdev, struct c2_dev, ibdev.class_dev); - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - return sprintf(buf, "%x.%x.%x\n", - (int) (dev->props.fw_ver >> 32), - (int) (dev->props.fw_ver >> 16) & 0xffff, - (int) (dev->props.fw_ver & 0xffff)); -} - -static ssize_t show_hca(struct class_device *cdev, char *buf) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - return sprintf(buf, "AMSO1100\n"); -} - -static ssize_t show_board(struct class_device *cdev, char *buf) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - return sprintf(buf, "%.*s\n", 32, "AMSO1100 Board ID"); -} - -static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL); -static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL); -static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL); -static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL); - -static struct class_device_attribute *c2_class_attributes[] = { - &class_device_attr_hw_rev, - &class_device_attr_fw_ver, - &class_device_attr_hca_type, - &class_device_attr_board_id -}; - -static int c2_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, - int attr_mask, struct ib_udata *udata) -{ - int err; - - err = - c2_qp_modify(to_c2dev(ibqp->device), to_c2qp(ibqp), attr, - attr_mask); - - return err; -} - -static int c2_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - return -ENOSYS; -} - -static int c2_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - return -ENOSYS; -} - -static int c2_process_mad(struct ib_device *ibdev, - int mad_flags, - u8 port_num, - struct ib_wc *in_wc, - struct ib_grh *in_grh, - struct ib_mad *in_mad, struct ib_mad *out_mad) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - return -ENOSYS; -} - -static int c2_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - - /* Request a connection */ - return c2_llp_connect(cm_id, iw_param); -} - -static int c2_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - - /* Accept the new connection */ - return c2_llp_accept(cm_id, iw_param); -} - -static int c2_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len) -{ - int err; - - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - - err = c2_llp_reject(cm_id, pdata, pdata_len); - return err; -} - -static int c2_service_create(struct iw_cm_id *cm_id, int backlog) -{ - int err; - - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - err = c2_llp_service_create(cm_id, backlog); - pr_debug("%s:%u err=%d\n", - __FUNCTION__, __LINE__, - err); - return err; -} - -static int c2_service_destroy(struct iw_cm_id *cm_id) -{ - int err; - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - - err = c2_llp_service_destroy(cm_id); - - return err; -} - -static int c2_pseudo_up(struct net_device *netdev) -{ - struct in_device *ind; - struct c2_dev *c2dev = netdev->priv; - - ind = in_dev_get(netdev); - if (!ind) - return 0; - - pr_debug("adding...\n"); - for_ifa(ind) { -#ifdef DEBUG - u8 *ip = (u8 *) & ifa->ifa_address; - - pr_debug("%s: %d.%d.%d.%d\n", - ifa->ifa_label, ip[0], ip[1], ip[2], ip[3]); -#endif - c2_add_addr(c2dev, ifa->ifa_address, ifa->ifa_mask); - } - endfor_ifa(ind); - in_dev_put(ind); - - return 0; -} - -static int c2_pseudo_down(struct net_device *netdev) -{ - struct in_device *ind; - struct c2_dev *c2dev = netdev->priv; - - ind = in_dev_get(netdev); - if (!ind) - return 0; - - pr_debug("deleting...\n"); - for_ifa(ind) { -#ifdef DEBUG - u8 *ip = (u8 *) & ifa->ifa_address; - - pr_debug("%s: %d.%d.%d.%d\n", - ifa->ifa_label, ip[0], ip[1], ip[2], ip[3]); -#endif - c2_del_addr(c2dev, ifa->ifa_address, ifa->ifa_mask); - } - endfor_ifa(ind); - in_dev_put(ind); - - return 0; -} - -static int c2_pseudo_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - kfree_skb(skb); - return NETDEV_TX_OK; -} - -static int c2_pseudo_change_mtu(struct net_device *netdev, int new_mtu) -{ - int ret = 0; - - if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) - return -EINVAL; - - netdev->mtu = new_mtu; - - /* TODO: Tell rnic about new rmda interface mtu */ - return ret; -} - -static void setup(struct net_device *netdev) -{ - SET_MODULE_OWNER(netdev); - netdev->open = c2_pseudo_up; - netdev->stop = c2_pseudo_down; - netdev->hard_start_xmit = c2_pseudo_xmit_frame; - netdev->get_stats = NULL; - netdev->tx_timeout = NULL; - netdev->set_mac_address = NULL; - netdev->change_mtu = c2_pseudo_change_mtu; - netdev->watchdog_timeo = 0; - netdev->type = ARPHRD_ETHER; - netdev->mtu = 1500; - netdev->hard_header_len = ETH_HLEN; - netdev->addr_len = ETH_ALEN; - netdev->tx_queue_len = 0; - netdev->flags |= IFF_NOARP; - return; -} - -static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev) -{ - char name[IFNAMSIZ]; - struct net_device *netdev; - - /* change ethxxx to iwxxx */ - strcpy(name, "iw"); - strcat(name, &c2dev->netdev->name[3]); - netdev = alloc_netdev(sizeof(*netdev), name, setup); - if (!netdev) { - printk(KERN_ERR PFX "%s - etherdev alloc failed", - __FUNCTION__); - return NULL; - } - - netdev->priv = c2dev; - - SET_NETDEV_DEV(netdev, &c2dev->pcidev->dev); - - memcpy_fromio(netdev->dev_addr, c2dev->kva + C2_REGS_RDMA_ENADDR, 6); - - /* Print out the MAC address */ - pr_debug("%s: MAC %02X:%02X:%02X:%02X:%02X:%02X\n", - netdev->name, - netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2], - netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]); - -#if 0 - /* Disable network packets */ - netif_stop_queue(netdev); -#endif - return netdev; -} - -int c2_register_device(struct c2_dev *dev) -{ - int ret; - int i; - - /* Register pseudo network device */ - dev->pseudo_netdev = c2_pseudo_netdev_init(dev); - if (dev->pseudo_netdev) { - ret = register_netdev(dev->pseudo_netdev); - if (ret) { - printk(KERN_ERR PFX - "Unable to register netdev, ret = %d\n", ret); - free_netdev(dev->pseudo_netdev); - return ret; - } - } - - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - strlcpy(dev->ibdev.name, "amso%d", IB_DEVICE_NAME_MAX); - dev->ibdev.owner = THIS_MODULE; - dev->ibdev.uverbs_cmd_mask = - (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | - (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | - (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | - (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_REG_MR) | - (1ull << IB_USER_VERBS_CMD_DEREG_MR) | - (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | - (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | - (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | - (1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) | - (1ull << IB_USER_VERBS_CMD_CREATE_QP) | - (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | - (1ull << IB_USER_VERBS_CMD_POLL_CQ) | - (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | - (1ull << IB_USER_VERBS_CMD_POST_SEND) | - (1ull << IB_USER_VERBS_CMD_POST_RECV); - - dev->ibdev.node_type = RDMA_NODE_RNIC; - memset(&dev->ibdev.node_guid, 0, sizeof(dev->ibdev.node_guid)); - memcpy(&dev->ibdev.node_guid, dev->pseudo_netdev->dev_addr, 6); - dev->ibdev.phys_port_cnt = 1; - dev->ibdev.dma_device = &dev->pcidev->dev; - dev->ibdev.class_dev.dev = &dev->pcidev->dev; - dev->ibdev.query_device = c2_query_device; - dev->ibdev.query_port = c2_query_port; - dev->ibdev.modify_port = c2_modify_port; - dev->ibdev.query_pkey = c2_query_pkey; - dev->ibdev.query_gid = c2_query_gid; - dev->ibdev.alloc_ucontext = c2_alloc_ucontext; - dev->ibdev.dealloc_ucontext = c2_dealloc_ucontext; - dev->ibdev.mmap = c2_mmap_uar; - dev->ibdev.alloc_pd = c2_alloc_pd; - dev->ibdev.dealloc_pd = c2_dealloc_pd; - dev->ibdev.create_ah = c2_ah_create; - dev->ibdev.destroy_ah = c2_ah_destroy; - dev->ibdev.create_qp = c2_create_qp; - dev->ibdev.modify_qp = c2_modify_qp; - dev->ibdev.destroy_qp = c2_destroy_qp; - dev->ibdev.create_cq = c2_create_cq; - dev->ibdev.destroy_cq = c2_destroy_cq; - dev->ibdev.poll_cq = c2_poll_cq; - dev->ibdev.get_dma_mr = c2_get_dma_mr; - dev->ibdev.reg_phys_mr = c2_reg_phys_mr; - dev->ibdev.reg_user_mr = c2_reg_user_mr; - dev->ibdev.dereg_mr = c2_dereg_mr; - - dev->ibdev.alloc_fmr = NULL; - dev->ibdev.unmap_fmr = NULL; - dev->ibdev.dealloc_fmr = NULL; - dev->ibdev.map_phys_fmr = NULL; - - dev->ibdev.attach_mcast = c2_multicast_attach; - dev->ibdev.detach_mcast = c2_multicast_detach; - dev->ibdev.process_mad = c2_process_mad; - - dev->ibdev.req_notify_cq = c2_arm_cq; - dev->ibdev.post_send = c2_post_send; - dev->ibdev.post_recv = c2_post_receive; - - dev->ibdev.iwcm = kmalloc(sizeof(*dev->ibdev.iwcm), GFP_KERNEL); - dev->ibdev.iwcm->add_ref = c2_add_ref; - dev->ibdev.iwcm->rem_ref = c2_rem_ref; - dev->ibdev.iwcm->get_qp = c2_get_qp; - dev->ibdev.iwcm->connect = c2_connect; - dev->ibdev.iwcm->accept = c2_accept; - dev->ibdev.iwcm->reject = c2_reject; - dev->ibdev.iwcm->create_listen = c2_service_create; - dev->ibdev.iwcm->destroy_listen = c2_service_destroy; - - ret = ib_register_device(&dev->ibdev); - if (ret) - return ret; - - for (i = 0; i < ARRAY_SIZE(c2_class_attributes); ++i) { - ret = class_device_create_file(&dev->ibdev.class_dev, - c2_class_attributes[i]); - if (ret) { - unregister_netdev(dev->pseudo_netdev); - free_netdev(dev->pseudo_netdev); - ib_unregister_device(&dev->ibdev); - return ret; - } - } - - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - return 0; -} - -void c2_unregister_device(struct c2_dev *dev) -{ - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - unregister_netdev(dev->pseudo_netdev); - free_netdev(dev->pseudo_netdev); - ib_unregister_device(&dev->ibdev); -} diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_provider.h b/trunk/drivers/infiniband/hw/amso1100/c2_provider.h deleted file mode 100644 index fc906223220f..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_provider.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef C2_PROVIDER_H -#define C2_PROVIDER_H -#include - -#include -#include - -#include "c2_mq.h" -#include - -#define C2_MPT_FLAG_ATOMIC (1 << 14) -#define C2_MPT_FLAG_REMOTE_WRITE (1 << 13) -#define C2_MPT_FLAG_REMOTE_READ (1 << 12) -#define C2_MPT_FLAG_LOCAL_WRITE (1 << 11) -#define C2_MPT_FLAG_LOCAL_READ (1 << 10) - -struct c2_buf_list { - void *buf; - DECLARE_PCI_UNMAP_ADDR(mapping) -}; - - -/* The user context keeps track of objects allocated for a - * particular user-mode client. */ -struct c2_ucontext { - struct ib_ucontext ibucontext; -}; - -struct c2_mtt; - -/* All objects associated with a PD are kept in the - * associated user context if present. - */ -struct c2_pd { - struct ib_pd ibpd; - u32 pd_id; -}; - -struct c2_mr { - struct ib_mr ibmr; - struct c2_pd *pd; -}; - -struct c2_av; - -enum c2_ah_type { - C2_AH_ON_HCA, - C2_AH_PCI_POOL, - C2_AH_KMALLOC -}; - -struct c2_ah { - struct ib_ah ibah; -}; - -struct c2_cq { - struct ib_cq ibcq; - spinlock_t lock; - atomic_t refcount; - int cqn; - int is_kernel; - wait_queue_head_t wait; - - u32 adapter_handle; - struct c2_mq mq; -}; - -struct c2_wq { - spinlock_t lock; -}; -struct iw_cm_id; -struct c2_qp { - struct ib_qp ibqp; - struct iw_cm_id *cm_id; - spinlock_t lock; - atomic_t refcount; - wait_queue_head_t wait; - int qpn; - - u32 adapter_handle; - u32 send_sgl_depth; - u32 recv_sgl_depth; - u32 rdma_write_sgl_depth; - u8 state; - - struct c2_mq sq_mq; - struct c2_mq rq_mq; -}; - -struct c2_cr_query_attrs { - u32 local_addr; - u32 remote_addr; - u16 local_port; - u16 remote_port; -}; - -static inline struct c2_pd *to_c2pd(struct ib_pd *ibpd) -{ - return container_of(ibpd, struct c2_pd, ibpd); -} - -static inline struct c2_ucontext *to_c2ucontext(struct ib_ucontext *ibucontext) -{ - return container_of(ibucontext, struct c2_ucontext, ibucontext); -} - -static inline struct c2_mr *to_c2mr(struct ib_mr *ibmr) -{ - return container_of(ibmr, struct c2_mr, ibmr); -} - - -static inline struct c2_ah *to_c2ah(struct ib_ah *ibah) -{ - return container_of(ibah, struct c2_ah, ibah); -} - -static inline struct c2_cq *to_c2cq(struct ib_cq *ibcq) -{ - return container_of(ibcq, struct c2_cq, ibcq); -} - -static inline struct c2_qp *to_c2qp(struct ib_qp *ibqp) -{ - return container_of(ibqp, struct c2_qp, ibqp); -} - -static inline int is_rnic_addr(struct net_device *netdev, u32 addr) -{ - struct in_device *ind; - int ret = 0; - - ind = in_dev_get(netdev); - if (!ind) - return 0; - - for_ifa(ind) { - if (ifa->ifa_address == addr) { - ret = 1; - break; - } - } - endfor_ifa(ind); - in_dev_put(ind); - return ret; -} -#endif /* C2_PROVIDER_H */ diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_qp.c b/trunk/drivers/infiniband/hw/amso1100/c2_qp.c deleted file mode 100644 index 12261132b077..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_qp.c +++ /dev/null @@ -1,975 +0,0 @@ -/* - * Copyright (c) 2004 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. - * Copyright (c) 2005 Mellanox Technologies. All rights reserved. - * Copyright (c) 2004 Voltaire, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#include "c2.h" -#include "c2_vq.h" -#include "c2_status.h" - -#define C2_MAX_ORD_PER_QP 128 -#define C2_MAX_IRD_PER_QP 128 - -#define C2_HINT_MAKE(q_index, hint_count) (((q_index) << 16) | hint_count) -#define C2_HINT_GET_INDEX(hint) (((hint) & 0x7FFF0000) >> 16) -#define C2_HINT_GET_COUNT(hint) ((hint) & 0x0000FFFF) - -#define NO_SUPPORT -1 -static const u8 c2_opcode[] = { - [IB_WR_SEND] = C2_WR_TYPE_SEND, - [IB_WR_SEND_WITH_IMM] = NO_SUPPORT, - [IB_WR_RDMA_WRITE] = C2_WR_TYPE_RDMA_WRITE, - [IB_WR_RDMA_WRITE_WITH_IMM] = NO_SUPPORT, - [IB_WR_RDMA_READ] = C2_WR_TYPE_RDMA_READ, - [IB_WR_ATOMIC_CMP_AND_SWP] = NO_SUPPORT, - [IB_WR_ATOMIC_FETCH_AND_ADD] = NO_SUPPORT, -}; - -static int to_c2_state(enum ib_qp_state ib_state) -{ - switch (ib_state) { - case IB_QPS_RESET: - return C2_QP_STATE_IDLE; - case IB_QPS_RTS: - return C2_QP_STATE_RTS; - case IB_QPS_SQD: - return C2_QP_STATE_CLOSING; - case IB_QPS_SQE: - return C2_QP_STATE_CLOSING; - case IB_QPS_ERR: - return C2_QP_STATE_ERROR; - default: - return -1; - } -} - -static int to_ib_state(enum c2_qp_state c2_state) -{ - switch (c2_state) { - case C2_QP_STATE_IDLE: - return IB_QPS_RESET; - case C2_QP_STATE_CONNECTING: - return IB_QPS_RTR; - case C2_QP_STATE_RTS: - return IB_QPS_RTS; - case C2_QP_STATE_CLOSING: - return IB_QPS_SQD; - case C2_QP_STATE_ERROR: - return IB_QPS_ERR; - case C2_QP_STATE_TERMINATE: - return IB_QPS_SQE; - default: - return -1; - } -} - -static const char *to_ib_state_str(int ib_state) -{ - static const char *state_str[] = { - "IB_QPS_RESET", - "IB_QPS_INIT", - "IB_QPS_RTR", - "IB_QPS_RTS", - "IB_QPS_SQD", - "IB_QPS_SQE", - "IB_QPS_ERR" - }; - if (ib_state < IB_QPS_RESET || - ib_state > IB_QPS_ERR) - return ""; - - ib_state -= IB_QPS_RESET; - return state_str[ib_state]; -} - -void c2_set_qp_state(struct c2_qp *qp, int c2_state) -{ - int new_state = to_ib_state(c2_state); - - pr_debug("%s: qp[%p] state modify %s --> %s\n", - __FUNCTION__, - qp, - to_ib_state_str(qp->state), - to_ib_state_str(new_state)); - qp->state = new_state; -} - -#define C2_QP_NO_ATTR_CHANGE 0xFFFFFFFF - -int c2_qp_modify(struct c2_dev *c2dev, struct c2_qp *qp, - struct ib_qp_attr *attr, int attr_mask) -{ - struct c2wr_qp_modify_req wr; - struct c2wr_qp_modify_rep *reply; - struct c2_vq_req *vq_req; - unsigned long flags; - u8 next_state; - int err; - - pr_debug("%s:%d qp=%p, %s --> %s\n", - __FUNCTION__, __LINE__, - qp, - to_ib_state_str(qp->state), - to_ib_state_str(attr->qp_state)); - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - c2_wr_set_id(&wr, CCWR_QP_MODIFY); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.qp_handle = qp->adapter_handle; - wr.ord = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - wr.ird = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - wr.sq_depth = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - wr.rq_depth = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - - if (attr_mask & IB_QP_STATE) { - /* Ensure the state is valid */ - if (attr->qp_state < 0 || attr->qp_state > IB_QPS_ERR) - return -EINVAL; - - wr.next_qp_state = cpu_to_be32(to_c2_state(attr->qp_state)); - - if (attr->qp_state == IB_QPS_ERR) { - spin_lock_irqsave(&qp->lock, flags); - if (qp->cm_id && qp->state == IB_QPS_RTS) { - pr_debug("Generating CLOSE event for QP-->ERR, " - "qp=%p, cm_id=%p\n",qp,qp->cm_id); - /* Generate an CLOSE event */ - vq_req->cm_id = qp->cm_id; - vq_req->event = IW_CM_EVENT_CLOSE; - } - spin_unlock_irqrestore(&qp->lock, flags); - } - next_state = attr->qp_state; - - } else if (attr_mask & IB_QP_CUR_STATE) { - - if (attr->cur_qp_state != IB_QPS_RTR && - attr->cur_qp_state != IB_QPS_RTS && - attr->cur_qp_state != IB_QPS_SQD && - attr->cur_qp_state != IB_QPS_SQE) - return -EINVAL; - else - wr.next_qp_state = - cpu_to_be32(to_c2_state(attr->cur_qp_state)); - - next_state = attr->cur_qp_state; - - } else { - err = 0; - goto bail0; - } - - /* reference the request struct */ - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail0; - - reply = (struct c2wr_qp_modify_rep *) (unsigned long) vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - err = c2_errno(reply); - if (!err) - qp->state = next_state; -#ifdef DEBUG - else - pr_debug("%s: c2_errno=%d\n", __FUNCTION__, err); -#endif - /* - * If we're going to error and generating the event here, then - * we need to remove the reference because there will be no - * close event generated by the adapter - */ - spin_lock_irqsave(&qp->lock, flags); - if (vq_req->event==IW_CM_EVENT_CLOSE && qp->cm_id) { - qp->cm_id->rem_ref(qp->cm_id); - qp->cm_id = NULL; - } - spin_unlock_irqrestore(&qp->lock, flags); - - vq_repbuf_free(c2dev, reply); - bail0: - vq_req_free(c2dev, vq_req); - - pr_debug("%s:%d qp=%p, cur_state=%s\n", - __FUNCTION__, __LINE__, - qp, - to_ib_state_str(qp->state)); - return err; -} - -int c2_qp_set_read_limits(struct c2_dev *c2dev, struct c2_qp *qp, - int ord, int ird) -{ - struct c2wr_qp_modify_req wr; - struct c2wr_qp_modify_rep *reply; - struct c2_vq_req *vq_req; - int err; - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - c2_wr_set_id(&wr, CCWR_QP_MODIFY); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.qp_handle = qp->adapter_handle; - wr.ord = cpu_to_be32(ord); - wr.ird = cpu_to_be32(ird); - wr.sq_depth = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - wr.rq_depth = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - wr.next_qp_state = cpu_to_be32(C2_QP_NO_ATTR_CHANGE); - - /* reference the request struct */ - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail0; - - reply = (struct c2wr_qp_modify_rep *) (unsigned long) - vq_req->reply_msg; - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - err = c2_errno(reply); - vq_repbuf_free(c2dev, reply); - bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -static int destroy_qp(struct c2_dev *c2dev, struct c2_qp *qp) -{ - struct c2_vq_req *vq_req; - struct c2wr_qp_destroy_req wr; - struct c2wr_qp_destroy_rep *reply; - unsigned long flags; - int err; - - /* - * Allocate a verb request message - */ - vq_req = vq_req_alloc(c2dev); - if (!vq_req) { - return -ENOMEM; - } - - /* - * Initialize the WR - */ - c2_wr_set_id(&wr, CCWR_QP_DESTROY); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.qp_handle = qp->adapter_handle; - - /* - * reference the request struct. dereferenced in the int handler. - */ - vq_req_get(c2dev, vq_req); - - spin_lock_irqsave(&qp->lock, flags); - if (qp->cm_id && qp->state == IB_QPS_RTS) { - pr_debug("destroy_qp: generating CLOSE event for QP-->ERR, " - "qp=%p, cm_id=%p\n",qp,qp->cm_id); - /* Generate an CLOSE event */ - vq_req->qp = qp; - vq_req->cm_id = qp->cm_id; - vq_req->event = IW_CM_EVENT_CLOSE; - } - spin_unlock_irqrestore(&qp->lock, flags); - - /* - * Send WR to adapter - */ - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - /* - * Wait for reply from adapter - */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail0; - } - - /* - * Process reply - */ - reply = (struct c2wr_qp_destroy_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - spin_lock_irqsave(&qp->lock, flags); - if (qp->cm_id) { - qp->cm_id->rem_ref(qp->cm_id); - qp->cm_id = NULL; - } - spin_unlock_irqrestore(&qp->lock, flags); - - vq_repbuf_free(c2dev, reply); - bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -static int c2_alloc_qpn(struct c2_dev *c2dev, struct c2_qp *qp) -{ - int ret; - - do { - spin_lock_irq(&c2dev->qp_table.lock); - ret = idr_get_new_above(&c2dev->qp_table.idr, qp, - c2dev->qp_table.last++, &qp->qpn); - spin_unlock_irq(&c2dev->qp_table.lock); - } while ((ret == -EAGAIN) && - idr_pre_get(&c2dev->qp_table.idr, GFP_KERNEL)); - return ret; -} - -static void c2_free_qpn(struct c2_dev *c2dev, int qpn) -{ - spin_lock_irq(&c2dev->qp_table.lock); - idr_remove(&c2dev->qp_table.idr, qpn); - spin_unlock_irq(&c2dev->qp_table.lock); -} - -struct c2_qp *c2_find_qpn(struct c2_dev *c2dev, int qpn) -{ - unsigned long flags; - struct c2_qp *qp; - - spin_lock_irqsave(&c2dev->qp_table.lock, flags); - qp = idr_find(&c2dev->qp_table.idr, qpn); - spin_unlock_irqrestore(&c2dev->qp_table.lock, flags); - return qp; -} - -int c2_alloc_qp(struct c2_dev *c2dev, - struct c2_pd *pd, - struct ib_qp_init_attr *qp_attrs, struct c2_qp *qp) -{ - struct c2wr_qp_create_req wr; - struct c2wr_qp_create_rep *reply; - struct c2_vq_req *vq_req; - struct c2_cq *send_cq = to_c2cq(qp_attrs->send_cq); - struct c2_cq *recv_cq = to_c2cq(qp_attrs->recv_cq); - unsigned long peer_pa; - u32 q_size, msg_size, mmap_size; - void __iomem *mmap; - int err; - - err = c2_alloc_qpn(c2dev, qp); - if (err) - return err; - qp->ibqp.qp_num = qp->qpn; - qp->ibqp.qp_type = IB_QPT_RC; - - /* Allocate the SQ and RQ shared pointers */ - qp->sq_mq.shared = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &qp->sq_mq.shared_dma, GFP_KERNEL); - if (!qp->sq_mq.shared) { - err = -ENOMEM; - goto bail0; - } - - qp->rq_mq.shared = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &qp->rq_mq.shared_dma, GFP_KERNEL); - if (!qp->rq_mq.shared) { - err = -ENOMEM; - goto bail1; - } - - /* Allocate the verbs request */ - vq_req = vq_req_alloc(c2dev); - if (vq_req == NULL) { - err = -ENOMEM; - goto bail2; - } - - /* Initialize the work request */ - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_QP_CREATE); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - wr.sq_cq_handle = send_cq->adapter_handle; - wr.rq_cq_handle = recv_cq->adapter_handle; - wr.sq_depth = cpu_to_be32(qp_attrs->cap.max_send_wr + 1); - wr.rq_depth = cpu_to_be32(qp_attrs->cap.max_recv_wr + 1); - wr.srq_handle = 0; - wr.flags = cpu_to_be32(QP_RDMA_READ | QP_RDMA_WRITE | QP_MW_BIND | - QP_ZERO_STAG | QP_RDMA_READ_RESPONSE); - wr.send_sgl_depth = cpu_to_be32(qp_attrs->cap.max_send_sge); - wr.recv_sgl_depth = cpu_to_be32(qp_attrs->cap.max_recv_sge); - wr.rdma_write_sgl_depth = cpu_to_be32(qp_attrs->cap.max_send_sge); - wr.shared_sq_ht = cpu_to_be64(qp->sq_mq.shared_dma); - wr.shared_rq_ht = cpu_to_be64(qp->rq_mq.shared_dma); - wr.ord = cpu_to_be32(C2_MAX_ORD_PER_QP); - wr.ird = cpu_to_be32(C2_MAX_IRD_PER_QP); - wr.pd_id = pd->pd_id; - wr.user_context = (unsigned long) qp; - - vq_req_get(c2dev, vq_req); - - /* Send the WR to the adapter */ - err = vq_send_wr(c2dev, (union c2wr *) & wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail3; - } - - /* Wait for the verb reply */ - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail3; - } - - /* Process the reply */ - reply = (struct c2wr_qp_create_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail3; - } - - if ((err = c2_wr_get_result(reply)) != 0) { - goto bail4; - } - - /* Fill in the kernel QP struct */ - atomic_set(&qp->refcount, 1); - qp->adapter_handle = reply->qp_handle; - qp->state = IB_QPS_RESET; - qp->send_sgl_depth = qp_attrs->cap.max_send_sge; - qp->rdma_write_sgl_depth = qp_attrs->cap.max_send_sge; - qp->recv_sgl_depth = qp_attrs->cap.max_recv_sge; - - /* Initialize the SQ MQ */ - q_size = be32_to_cpu(reply->sq_depth); - msg_size = be32_to_cpu(reply->sq_msg_size); - peer_pa = c2dev->pa + be32_to_cpu(reply->sq_mq_start); - mmap_size = PAGE_ALIGN(sizeof(struct c2_mq_shared) + msg_size * q_size); - mmap = ioremap_nocache(peer_pa, mmap_size); - if (!mmap) { - err = -ENOMEM; - goto bail5; - } - - c2_mq_req_init(&qp->sq_mq, - be32_to_cpu(reply->sq_mq_index), - q_size, - msg_size, - mmap + sizeof(struct c2_mq_shared), /* pool start */ - mmap, /* peer */ - C2_MQ_ADAPTER_TARGET); - - /* Initialize the RQ mq */ - q_size = be32_to_cpu(reply->rq_depth); - msg_size = be32_to_cpu(reply->rq_msg_size); - peer_pa = c2dev->pa + be32_to_cpu(reply->rq_mq_start); - mmap_size = PAGE_ALIGN(sizeof(struct c2_mq_shared) + msg_size * q_size); - mmap = ioremap_nocache(peer_pa, mmap_size); - if (!mmap) { - err = -ENOMEM; - goto bail6; - } - - c2_mq_req_init(&qp->rq_mq, - be32_to_cpu(reply->rq_mq_index), - q_size, - msg_size, - mmap + sizeof(struct c2_mq_shared), /* pool start */ - mmap, /* peer */ - C2_MQ_ADAPTER_TARGET); - - vq_repbuf_free(c2dev, reply); - vq_req_free(c2dev, vq_req); - - return 0; - - bail6: - iounmap(qp->sq_mq.peer); - bail5: - destroy_qp(c2dev, qp); - bail4: - vq_repbuf_free(c2dev, reply); - bail3: - vq_req_free(c2dev, vq_req); - bail2: - c2_free_mqsp(qp->rq_mq.shared); - bail1: - c2_free_mqsp(qp->sq_mq.shared); - bail0: - c2_free_qpn(c2dev, qp->qpn); - return err; -} - -void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp) -{ - struct c2_cq *send_cq; - struct c2_cq *recv_cq; - - send_cq = to_c2cq(qp->ibqp.send_cq); - recv_cq = to_c2cq(qp->ibqp.recv_cq); - - /* - * Lock CQs here, so that CQ polling code can do QP lookup - * without taking a lock. - */ - spin_lock_irq(&send_cq->lock); - if (send_cq != recv_cq) - spin_lock(&recv_cq->lock); - - c2_free_qpn(c2dev, qp->qpn); - - if (send_cq != recv_cq) - spin_unlock(&recv_cq->lock); - spin_unlock_irq(&send_cq->lock); - - /* - * Destory qp in the rnic... - */ - destroy_qp(c2dev, qp); - - /* - * Mark any unreaped CQEs as null and void. - */ - c2_cq_clean(c2dev, qp, send_cq->cqn); - if (send_cq != recv_cq) - c2_cq_clean(c2dev, qp, recv_cq->cqn); - /* - * Unmap the MQs and return the shared pointers - * to the message pool. - */ - iounmap(qp->sq_mq.peer); - iounmap(qp->rq_mq.peer); - c2_free_mqsp(qp->sq_mq.shared); - c2_free_mqsp(qp->rq_mq.shared); - - atomic_dec(&qp->refcount); - wait_event(qp->wait, !atomic_read(&qp->refcount)); -} - -/* - * Function: move_sgl - * - * Description: - * Move an SGL from the user's work request struct into a CCIL Work Request - * message, swapping to WR byte order and ensure the total length doesn't - * overflow. - * - * IN: - * dst - ptr to CCIL Work Request message SGL memory. - * src - ptr to the consumers SGL memory. - * - * OUT: none - * - * Return: - * CCIL status codes. - */ -static int -move_sgl(struct c2_data_addr * dst, struct ib_sge *src, int count, u32 * p_len, - u8 * actual_count) -{ - u32 tot = 0; /* running total */ - u8 acount = 0; /* running total non-0 len sge's */ - - while (count > 0) { - /* - * If the addition of this SGE causes the - * total SGL length to exceed 2^32-1, then - * fail-n-bail. - * - * If the current total plus the next element length - * wraps, then it will go negative and be less than the - * current total... - */ - if ((tot + src->length) < tot) { - return -EINVAL; - } - /* - * Bug: 1456 (as well as 1498 & 1643) - * Skip over any sge's supplied with len=0 - */ - if (src->length) { - tot += src->length; - dst->stag = cpu_to_be32(src->lkey); - dst->to = cpu_to_be64(src->addr); - dst->length = cpu_to_be32(src->length); - dst++; - acount++; - } - src++; - count--; - } - - if (acount == 0) { - /* - * Bug: 1476 (as well as 1498, 1456 and 1643) - * Setup the SGL in the WR to make it easier for the RNIC. - * This way, the FW doesn't have to deal with special cases. - * Setting length=0 should be sufficient. - */ - dst->stag = 0; - dst->to = 0; - dst->length = 0; - } - - *p_len = tot; - *actual_count = acount; - return 0; -} - -/* - * Function: c2_activity (private function) - * - * Description: - * Post an mq index to the host->adapter activity fifo. - * - * IN: - * c2dev - ptr to c2dev structure - * mq_index - mq index to post - * shared - value most recently written to shared - * - * OUT: - * - * Return: - * none - */ -static inline void c2_activity(struct c2_dev *c2dev, u32 mq_index, u16 shared) -{ - /* - * First read the register to see if the FIFO is full, and if so, - * spin until it's not. This isn't perfect -- there is no - * synchronization among the clients of the register, but in - * practice it prevents multiple CPU from hammering the bus - * with PCI RETRY. Note that when this does happen, the card - * cannot get on the bus and the card and system hang in a - * deadlock -- thus the need for this code. [TOT] - */ - while (readl(c2dev->regs + PCI_BAR0_ADAPTER_HINT) & 0x80000000) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(0); - } - - __raw_writel(C2_HINT_MAKE(mq_index, shared), - c2dev->regs + PCI_BAR0_ADAPTER_HINT); -} - -/* - * Function: qp_wr_post - * - * Description: - * This in-line function allocates a MQ msg, then moves the host-copy of - * the completed WR into msg. Then it posts the message. - * - * IN: - * q - ptr to user MQ. - * wr - ptr to host-copy of the WR. - * qp - ptr to user qp - * size - Number of bytes to post. Assumed to be divisible by 4. - * - * OUT: none - * - * Return: - * CCIL status codes. - */ -static int qp_wr_post(struct c2_mq *q, union c2wr * wr, struct c2_qp *qp, u32 size) -{ - union c2wr *msg; - - msg = c2_mq_alloc(q); - if (msg == NULL) { - return -EINVAL; - } -#ifdef CCMSGMAGIC - ((c2wr_hdr_t *) wr)->magic = cpu_to_be32(CCWR_MAGIC); -#endif - - /* - * Since all header fields in the WR are the same as the - * CQE, set the following so the adapter need not. - */ - c2_wr_set_result(wr, CCERR_PENDING); - - /* - * Copy the wr down to the adapter - */ - memcpy((void *) msg, (void *) wr, size); - - c2_mq_produce(q); - return 0; -} - - -int c2_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr, - struct ib_send_wr **bad_wr) -{ - struct c2_dev *c2dev = to_c2dev(ibqp->device); - struct c2_qp *qp = to_c2qp(ibqp); - union c2wr wr; - int err = 0; - - u32 flags; - u32 tot_len; - u8 actual_sge_count; - u32 msg_size; - - if (qp->state > IB_QPS_RTS) - return -EINVAL; - - while (ib_wr) { - - flags = 0; - wr.sqwr.sq_hdr.user_hdr.hdr.context = ib_wr->wr_id; - if (ib_wr->send_flags & IB_SEND_SIGNALED) { - flags |= SQ_SIGNALED; - } - - switch (ib_wr->opcode) { - case IB_WR_SEND: - if (ib_wr->send_flags & IB_SEND_SOLICITED) { - c2_wr_set_id(&wr, C2_WR_TYPE_SEND_SE); - msg_size = sizeof(struct c2wr_send_req); - } else { - c2_wr_set_id(&wr, C2_WR_TYPE_SEND); - msg_size = sizeof(struct c2wr_send_req); - } - - wr.sqwr.send.remote_stag = 0; - msg_size += sizeof(struct c2_data_addr) * ib_wr->num_sge; - if (ib_wr->num_sge > qp->send_sgl_depth) { - err = -EINVAL; - break; - } - if (ib_wr->send_flags & IB_SEND_FENCE) { - flags |= SQ_READ_FENCE; - } - err = move_sgl((struct c2_data_addr *) & (wr.sqwr.send.data), - ib_wr->sg_list, - ib_wr->num_sge, - &tot_len, &actual_sge_count); - wr.sqwr.send.sge_len = cpu_to_be32(tot_len); - c2_wr_set_sge_count(&wr, actual_sge_count); - break; - case IB_WR_RDMA_WRITE: - c2_wr_set_id(&wr, C2_WR_TYPE_RDMA_WRITE); - msg_size = sizeof(struct c2wr_rdma_write_req) + - (sizeof(struct c2_data_addr) * ib_wr->num_sge); - if (ib_wr->num_sge > qp->rdma_write_sgl_depth) { - err = -EINVAL; - break; - } - if (ib_wr->send_flags & IB_SEND_FENCE) { - flags |= SQ_READ_FENCE; - } - wr.sqwr.rdma_write.remote_stag = - cpu_to_be32(ib_wr->wr.rdma.rkey); - wr.sqwr.rdma_write.remote_to = - cpu_to_be64(ib_wr->wr.rdma.remote_addr); - err = move_sgl((struct c2_data_addr *) - & (wr.sqwr.rdma_write.data), - ib_wr->sg_list, - ib_wr->num_sge, - &tot_len, &actual_sge_count); - wr.sqwr.rdma_write.sge_len = cpu_to_be32(tot_len); - c2_wr_set_sge_count(&wr, actual_sge_count); - break; - case IB_WR_RDMA_READ: - c2_wr_set_id(&wr, C2_WR_TYPE_RDMA_READ); - msg_size = sizeof(struct c2wr_rdma_read_req); - - /* IWarp only suppots 1 sge for RDMA reads */ - if (ib_wr->num_sge > 1) { - err = -EINVAL; - break; - } - - /* - * Move the local and remote stag/to/len into the WR. - */ - wr.sqwr.rdma_read.local_stag = - cpu_to_be32(ib_wr->sg_list->lkey); - wr.sqwr.rdma_read.local_to = - cpu_to_be64(ib_wr->sg_list->addr); - wr.sqwr.rdma_read.remote_stag = - cpu_to_be32(ib_wr->wr.rdma.rkey); - wr.sqwr.rdma_read.remote_to = - cpu_to_be64(ib_wr->wr.rdma.remote_addr); - wr.sqwr.rdma_read.length = - cpu_to_be32(ib_wr->sg_list->length); - break; - default: - /* error */ - msg_size = 0; - err = -EINVAL; - break; - } - - /* - * If we had an error on the last wr build, then - * break out. Possible errors include bogus WR - * type, and a bogus SGL length... - */ - if (err) { - break; - } - - /* - * Store flags - */ - c2_wr_set_flags(&wr, flags); - - /* - * Post the puppy! - */ - err = qp_wr_post(&qp->sq_mq, &wr, qp, msg_size); - if (err) { - break; - } - - /* - * Enqueue mq index to activity FIFO. - */ - c2_activity(c2dev, qp->sq_mq.index, qp->sq_mq.hint_count); - - ib_wr = ib_wr->next; - } - - if (err) - *bad_wr = ib_wr; - return err; -} - -int c2_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr, - struct ib_recv_wr **bad_wr) -{ - struct c2_dev *c2dev = to_c2dev(ibqp->device); - struct c2_qp *qp = to_c2qp(ibqp); - union c2wr wr; - int err = 0; - - if (qp->state > IB_QPS_RTS) - return -EINVAL; - - /* - * Try and post each work request - */ - while (ib_wr) { - u32 tot_len; - u8 actual_sge_count; - - if (ib_wr->num_sge > qp->recv_sgl_depth) { - err = -EINVAL; - break; - } - - /* - * Create local host-copy of the WR - */ - wr.rqwr.rq_hdr.user_hdr.hdr.context = ib_wr->wr_id; - c2_wr_set_id(&wr, CCWR_RECV); - c2_wr_set_flags(&wr, 0); - - /* sge_count is limited to eight bits. */ - BUG_ON(ib_wr->num_sge >= 256); - err = move_sgl((struct c2_data_addr *) & (wr.rqwr.data), - ib_wr->sg_list, - ib_wr->num_sge, &tot_len, &actual_sge_count); - c2_wr_set_sge_count(&wr, actual_sge_count); - - /* - * If we had an error on the last wr build, then - * break out. Possible errors include bogus WR - * type, and a bogus SGL length... - */ - if (err) { - break; - } - - err = qp_wr_post(&qp->rq_mq, &wr, qp, qp->rq_mq.msg_size); - if (err) { - break; - } - - /* - * Enqueue mq index to activity FIFO - */ - c2_activity(c2dev, qp->rq_mq.index, qp->rq_mq.hint_count); - - ib_wr = ib_wr->next; - } - - if (err) - *bad_wr = ib_wr; - return err; -} - -void __devinit c2_init_qp_table(struct c2_dev *c2dev) -{ - spin_lock_init(&c2dev->qp_table.lock); - idr_init(&c2dev->qp_table.idr); -} - -void __devexit c2_cleanup_qp_table(struct c2_dev *c2dev) -{ - idr_destroy(&c2dev->qp_table.idr); -} diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_rnic.c b/trunk/drivers/infiniband/hw/amso1100/c2_rnic.c deleted file mode 100644 index f49a32b7a8f6..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_rnic.c +++ /dev/null @@ -1,664 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include "c2.h" -#include "c2_vq.h" - -/* Device capabilities */ -#define C2_MIN_PAGESIZE 1024 - -#define C2_MAX_MRS 32768 -#define C2_MAX_QPS 16000 -#define C2_MAX_WQE_SZ 256 -#define C2_MAX_QP_WR ((128*1024)/C2_MAX_WQE_SZ) -#define C2_MAX_SGES 4 -#define C2_MAX_SGE_RD 1 -#define C2_MAX_CQS 32768 -#define C2_MAX_CQES 4096 -#define C2_MAX_PDS 16384 - -/* - * Send the adapter INIT message to the amso1100 - */ -static int c2_adapter_init(struct c2_dev *c2dev) -{ - struct c2wr_init_req wr; - int err; - - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_INIT); - wr.hdr.context = 0; - wr.hint_count = cpu_to_be64(c2dev->hint_count_dma); - wr.q0_host_shared = cpu_to_be64(c2dev->req_vq.shared_dma); - wr.q1_host_shared = cpu_to_be64(c2dev->rep_vq.shared_dma); - wr.q1_host_msg_pool = cpu_to_be64(c2dev->rep_vq.host_dma); - wr.q2_host_shared = cpu_to_be64(c2dev->aeq.shared_dma); - wr.q2_host_msg_pool = cpu_to_be64(c2dev->aeq.host_dma); - - /* Post the init message */ - err = vq_send_wr(c2dev, (union c2wr *) & wr); - - return err; -} - -/* - * Send the adapter TERM message to the amso1100 - */ -static void c2_adapter_term(struct c2_dev *c2dev) -{ - struct c2wr_init_req wr; - - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_TERM); - wr.hdr.context = 0; - - /* Post the init message */ - vq_send_wr(c2dev, (union c2wr *) & wr); - c2dev->init = 0; - - return; -} - -/* - * Query the adapter - */ -static int c2_rnic_query(struct c2_dev *c2dev, struct ib_device_attr *props) -{ - struct c2_vq_req *vq_req; - struct c2wr_rnic_query_req wr; - struct c2wr_rnic_query_rep *reply; - int err; - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - c2_wr_set_id(&wr, CCWR_RNIC_QUERY); - wr.hdr.context = (unsigned long) vq_req; - wr.rnic_handle = c2dev->adapter_handle; - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) &wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail1; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail1; - - reply = - (struct c2wr_rnic_query_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) - err = -ENOMEM; - - err = c2_errno(reply); - if (err) - goto bail2; - - props->fw_ver = - ((u64)be32_to_cpu(reply->fw_ver_major) << 32) | - ((be32_to_cpu(reply->fw_ver_minor) && 0xFFFF) << 16) | - (be32_to_cpu(reply->fw_ver_patch) && 0xFFFF); - memcpy(&props->sys_image_guid, c2dev->netdev->dev_addr, 6); - props->max_mr_size = 0xFFFFFFFF; - props->page_size_cap = ~(C2_MIN_PAGESIZE-1); - props->vendor_id = be32_to_cpu(reply->vendor_id); - props->vendor_part_id = be32_to_cpu(reply->part_number); - props->hw_ver = be32_to_cpu(reply->hw_version); - props->max_qp = be32_to_cpu(reply->max_qps); - props->max_qp_wr = be32_to_cpu(reply->max_qp_depth); - props->device_cap_flags = c2dev->device_cap_flags; - props->max_sge = C2_MAX_SGES; - props->max_sge_rd = C2_MAX_SGE_RD; - props->max_cq = be32_to_cpu(reply->max_cqs); - props->max_cqe = be32_to_cpu(reply->max_cq_depth); - props->max_mr = be32_to_cpu(reply->max_mrs); - props->max_pd = be32_to_cpu(reply->max_pds); - props->max_qp_rd_atom = be32_to_cpu(reply->max_qp_ird); - props->max_ee_rd_atom = 0; - props->max_res_rd_atom = be32_to_cpu(reply->max_global_ird); - props->max_qp_init_rd_atom = be32_to_cpu(reply->max_qp_ord); - props->max_ee_init_rd_atom = 0; - props->atomic_cap = IB_ATOMIC_NONE; - props->max_ee = 0; - props->max_rdd = 0; - props->max_mw = be32_to_cpu(reply->max_mws); - props->max_raw_ipv6_qp = 0; - props->max_raw_ethy_qp = 0; - props->max_mcast_grp = 0; - props->max_mcast_qp_attach = 0; - props->max_total_mcast_qp_attach = 0; - props->max_ah = 0; - props->max_fmr = 0; - props->max_map_per_fmr = 0; - props->max_srq = 0; - props->max_srq_wr = 0; - props->max_srq_sge = 0; - props->max_pkeys = 0; - props->local_ca_ack_delay = 0; - - bail2: - vq_repbuf_free(c2dev, reply); - - bail1: - vq_req_free(c2dev, vq_req); - return err; -} - -/* - * Add an IP address to the RNIC interface - */ -int c2_add_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask) -{ - struct c2_vq_req *vq_req; - struct c2wr_rnic_setconfig_req *wr; - struct c2wr_rnic_setconfig_rep *reply; - struct c2_netaddr netaddr; - int err, len; - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - len = sizeof(struct c2_netaddr); - wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL); - if (!wr) { - err = -ENOMEM; - goto bail0; - } - - c2_wr_set_id(wr, CCWR_RNIC_SETCONFIG); - wr->hdr.context = (unsigned long) vq_req; - wr->rnic_handle = c2dev->adapter_handle; - wr->option = cpu_to_be32(C2_CFG_ADD_ADDR); - - netaddr.ip_addr = inaddr; - netaddr.netmask = inmask; - netaddr.mtu = 0; - - memcpy(wr->data, &netaddr, len); - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail1; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail1; - - reply = - (struct c2wr_rnic_setconfig_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail1; - } - - err = c2_errno(reply); - vq_repbuf_free(c2dev, reply); - - bail1: - kfree(wr); - bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -/* - * Delete an IP address from the RNIC interface - */ -int c2_del_addr(struct c2_dev *c2dev, u32 inaddr, u32 inmask) -{ - struct c2_vq_req *vq_req; - struct c2wr_rnic_setconfig_req *wr; - struct c2wr_rnic_setconfig_rep *reply; - struct c2_netaddr netaddr; - int err, len; - - vq_req = vq_req_alloc(c2dev); - if (!vq_req) - return -ENOMEM; - - len = sizeof(struct c2_netaddr); - wr = kmalloc(c2dev->req_vq.msg_size, GFP_KERNEL); - if (!wr) { - err = -ENOMEM; - goto bail0; - } - - c2_wr_set_id(wr, CCWR_RNIC_SETCONFIG); - wr->hdr.context = (unsigned long) vq_req; - wr->rnic_handle = c2dev->adapter_handle; - wr->option = cpu_to_be32(C2_CFG_DEL_ADDR); - - netaddr.ip_addr = inaddr; - netaddr.netmask = inmask; - netaddr.mtu = 0; - - memcpy(wr->data, &netaddr, len); - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, (union c2wr *) wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail1; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) - goto bail1; - - reply = - (struct c2wr_rnic_setconfig_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail1; - } - - err = c2_errno(reply); - vq_repbuf_free(c2dev, reply); - - bail1: - kfree(wr); - bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -/* - * Open a single RNIC instance to use with all - * low level openib calls - */ -static int c2_rnic_open(struct c2_dev *c2dev) -{ - struct c2_vq_req *vq_req; - union c2wr wr; - struct c2wr_rnic_open_rep *reply; - int err; - - vq_req = vq_req_alloc(c2dev); - if (vq_req == NULL) { - return -ENOMEM; - } - - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_RNIC_OPEN); - wr.rnic_open.req.hdr.context = (unsigned long) (vq_req); - wr.rnic_open.req.flags = cpu_to_be16(RNIC_PRIV_MODE); - wr.rnic_open.req.port_num = cpu_to_be16(0); - wr.rnic_open.req.user_context = (unsigned long) c2dev; - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, &wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail0; - } - - reply = (struct c2wr_rnic_open_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - if ((err = c2_errno(reply)) != 0) { - goto bail1; - } - - c2dev->adapter_handle = reply->rnic_handle; - - bail1: - vq_repbuf_free(c2dev, reply); - bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -/* - * Close the RNIC instance - */ -static int c2_rnic_close(struct c2_dev *c2dev) -{ - struct c2_vq_req *vq_req; - union c2wr wr; - struct c2wr_rnic_close_rep *reply; - int err; - - vq_req = vq_req_alloc(c2dev); - if (vq_req == NULL) { - return -ENOMEM; - } - - memset(&wr, 0, sizeof(wr)); - c2_wr_set_id(&wr, CCWR_RNIC_CLOSE); - wr.rnic_close.req.hdr.context = (unsigned long) vq_req; - wr.rnic_close.req.rnic_handle = c2dev->adapter_handle; - - vq_req_get(c2dev, vq_req); - - err = vq_send_wr(c2dev, &wr); - if (err) { - vq_req_put(c2dev, vq_req); - goto bail0; - } - - err = vq_wait_for_reply(c2dev, vq_req); - if (err) { - goto bail0; - } - - reply = (struct c2wr_rnic_close_rep *) (unsigned long) (vq_req->reply_msg); - if (!reply) { - err = -ENOMEM; - goto bail0; - } - - if ((err = c2_errno(reply)) != 0) { - goto bail1; - } - - c2dev->adapter_handle = 0; - - bail1: - vq_repbuf_free(c2dev, reply); - bail0: - vq_req_free(c2dev, vq_req); - return err; -} - -/* - * Called by c2_probe to initialize the RNIC. This principally - * involves initalizing the various limits and resouce pools that - * comprise the RNIC instance. - */ -int c2_rnic_init(struct c2_dev *c2dev) -{ - int err; - u32 qsize, msgsize; - void *q1_pages; - void *q2_pages; - void __iomem *mmio_regs; - - /* Device capabilities */ - c2dev->device_cap_flags = - (IB_DEVICE_RESIZE_MAX_WR | - IB_DEVICE_CURR_QP_STATE_MOD | - IB_DEVICE_SYS_IMAGE_GUID | - IB_DEVICE_ZERO_STAG | - IB_DEVICE_SEND_W_INV | IB_DEVICE_MEM_WINDOW); - - /* Allocate the qptr_array */ - c2dev->qptr_array = vmalloc(C2_MAX_CQS * sizeof(void *)); - if (!c2dev->qptr_array) { - return -ENOMEM; - } - - /* Inialize the qptr_array */ - memset(c2dev->qptr_array, 0, C2_MAX_CQS * sizeof(void *)); - c2dev->qptr_array[0] = (void *) &c2dev->req_vq; - c2dev->qptr_array[1] = (void *) &c2dev->rep_vq; - c2dev->qptr_array[2] = (void *) &c2dev->aeq; - - /* Initialize data structures */ - init_waitqueue_head(&c2dev->req_vq_wo); - spin_lock_init(&c2dev->vqlock); - spin_lock_init(&c2dev->lock); - - /* Allocate MQ shared pointer pool for kernel clients. User - * mode client pools are hung off the user context - */ - err = c2_init_mqsp_pool(c2dev, GFP_KERNEL, &c2dev->kern_mqsp_pool); - if (err) { - goto bail0; - } - - /* Allocate shared pointers for Q0, Q1, and Q2 from - * the shared pointer pool. - */ - - c2dev->hint_count = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &c2dev->hint_count_dma, - GFP_KERNEL); - c2dev->req_vq.shared = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &c2dev->req_vq.shared_dma, - GFP_KERNEL); - c2dev->rep_vq.shared = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &c2dev->rep_vq.shared_dma, - GFP_KERNEL); - c2dev->aeq.shared = c2_alloc_mqsp(c2dev, c2dev->kern_mqsp_pool, - &c2dev->aeq.shared_dma, GFP_KERNEL); - if (!c2dev->hint_count || !c2dev->req_vq.shared || - !c2dev->rep_vq.shared || !c2dev->aeq.shared) { - err = -ENOMEM; - goto bail1; - } - - mmio_regs = c2dev->kva; - /* Initialize the Verbs Request Queue */ - c2_mq_req_init(&c2dev->req_vq, 0, - be32_to_cpu(readl(mmio_regs + C2_REGS_Q0_QSIZE)), - be32_to_cpu(readl(mmio_regs + C2_REGS_Q0_MSGSIZE)), - mmio_regs + - be32_to_cpu(readl(mmio_regs + C2_REGS_Q0_POOLSTART)), - mmio_regs + - be32_to_cpu(readl(mmio_regs + C2_REGS_Q0_SHARED)), - C2_MQ_ADAPTER_TARGET); - - /* Initialize the Verbs Reply Queue */ - qsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q1_QSIZE)); - msgsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q1_MSGSIZE)); - q1_pages = kmalloc(qsize * msgsize, GFP_KERNEL); - if (!q1_pages) { - err = -ENOMEM; - goto bail1; - } - c2dev->rep_vq.host_dma = dma_map_single(c2dev->ibdev.dma_device, - (void *)q1_pages, qsize * msgsize, - DMA_FROM_DEVICE); - pci_unmap_addr_set(&c2dev->rep_vq, mapping, c2dev->rep_vq.host_dma); - pr_debug("%s rep_vq va %p dma %llx\n", __FUNCTION__, q1_pages, - (u64)c2dev->rep_vq.host_dma); - c2_mq_rep_init(&c2dev->rep_vq, - 1, - qsize, - msgsize, - q1_pages, - mmio_regs + - be32_to_cpu(readl(mmio_regs + C2_REGS_Q1_SHARED)), - C2_MQ_HOST_TARGET); - - /* Initialize the Asynchronus Event Queue */ - qsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q2_QSIZE)); - msgsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q2_MSGSIZE)); - q2_pages = kmalloc(qsize * msgsize, GFP_KERNEL); - if (!q2_pages) { - err = -ENOMEM; - goto bail2; - } - c2dev->aeq.host_dma = dma_map_single(c2dev->ibdev.dma_device, - (void *)q2_pages, qsize * msgsize, - DMA_FROM_DEVICE); - pci_unmap_addr_set(&c2dev->aeq, mapping, c2dev->aeq.host_dma); - pr_debug("%s aeq va %p dma %llx\n", __FUNCTION__, q1_pages, - (u64)c2dev->rep_vq.host_dma); - c2_mq_rep_init(&c2dev->aeq, - 2, - qsize, - msgsize, - q2_pages, - mmio_regs + - be32_to_cpu(readl(mmio_regs + C2_REGS_Q2_SHARED)), - C2_MQ_HOST_TARGET); - - /* Initialize the verbs request allocator */ - err = vq_init(c2dev); - if (err) - goto bail3; - - /* Enable interrupts on the adapter */ - writel(0, c2dev->regs + C2_IDIS); - - /* create the WR init message */ - err = c2_adapter_init(c2dev); - if (err) - goto bail4; - c2dev->init++; - - /* open an adapter instance */ - err = c2_rnic_open(c2dev); - if (err) - goto bail4; - - /* Initialize cached the adapter limits */ - if (c2_rnic_query(c2dev, &c2dev->props)) - goto bail5; - - /* Initialize the PD pool */ - err = c2_init_pd_table(c2dev); - if (err) - goto bail5; - - /* Initialize the QP pool */ - c2_init_qp_table(c2dev); - return 0; - - bail5: - c2_rnic_close(c2dev); - bail4: - vq_term(c2dev); - bail3: - dma_unmap_single(c2dev->ibdev.dma_device, - pci_unmap_addr(&c2dev->aeq, mapping), - c2dev->aeq.q_size * c2dev->aeq.msg_size, - DMA_FROM_DEVICE); - kfree(q2_pages); - bail2: - dma_unmap_single(c2dev->ibdev.dma_device, - pci_unmap_addr(&c2dev->rep_vq, mapping), - c2dev->rep_vq.q_size * c2dev->rep_vq.msg_size, - DMA_FROM_DEVICE); - kfree(q1_pages); - bail1: - c2_free_mqsp_pool(c2dev, c2dev->kern_mqsp_pool); - bail0: - vfree(c2dev->qptr_array); - - return err; -} - -/* - * Called by c2_remove to cleanup the RNIC resources. - */ -void c2_rnic_term(struct c2_dev *c2dev) -{ - - /* Close the open adapter instance */ - c2_rnic_close(c2dev); - - /* Send the TERM message to the adapter */ - c2_adapter_term(c2dev); - - /* Disable interrupts on the adapter */ - writel(1, c2dev->regs + C2_IDIS); - - /* Free the QP pool */ - c2_cleanup_qp_table(c2dev); - - /* Free the PD pool */ - c2_cleanup_pd_table(c2dev); - - /* Free the verbs request allocator */ - vq_term(c2dev); - - /* Unmap and free the asynchronus event queue */ - dma_unmap_single(c2dev->ibdev.dma_device, - pci_unmap_addr(&c2dev->aeq, mapping), - c2dev->aeq.q_size * c2dev->aeq.msg_size, - DMA_FROM_DEVICE); - kfree(c2dev->aeq.msg_pool.host); - - /* Unmap and free the verbs reply queue */ - dma_unmap_single(c2dev->ibdev.dma_device, - pci_unmap_addr(&c2dev->rep_vq, mapping), - c2dev->rep_vq.q_size * c2dev->rep_vq.msg_size, - DMA_FROM_DEVICE); - kfree(c2dev->rep_vq.msg_pool.host); - - /* Free the MQ shared pointer pool */ - c2_free_mqsp_pool(c2dev, c2dev->kern_mqsp_pool); - - /* Free the qptr_array */ - vfree(c2dev->qptr_array); - - return; -} diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_status.h b/trunk/drivers/infiniband/hw/amso1100/c2_status.h deleted file mode 100644 index 6ee4aa92d875..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_status.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _C2_STATUS_H_ -#define _C2_STATUS_H_ - -/* - * Verbs Status Codes - */ -enum c2_status { - C2_OK = 0, /* This must be zero */ - CCERR_INSUFFICIENT_RESOURCES = 1, - CCERR_INVALID_MODIFIER = 2, - CCERR_INVALID_MODE = 3, - CCERR_IN_USE = 4, - CCERR_INVALID_RNIC = 5, - CCERR_INTERRUPTED_OPERATION = 6, - CCERR_INVALID_EH = 7, - CCERR_INVALID_CQ = 8, - CCERR_CQ_EMPTY = 9, - CCERR_NOT_IMPLEMENTED = 10, - CCERR_CQ_DEPTH_TOO_SMALL = 11, - CCERR_PD_IN_USE = 12, - CCERR_INVALID_PD = 13, - CCERR_INVALID_SRQ = 14, - CCERR_INVALID_ADDRESS = 15, - CCERR_INVALID_NETMASK = 16, - CCERR_INVALID_QP = 17, - CCERR_INVALID_QP_STATE = 18, - CCERR_TOO_MANY_WRS_POSTED = 19, - CCERR_INVALID_WR_TYPE = 20, - CCERR_INVALID_SGL_LENGTH = 21, - CCERR_INVALID_SQ_DEPTH = 22, - CCERR_INVALID_RQ_DEPTH = 23, - CCERR_INVALID_ORD = 24, - CCERR_INVALID_IRD = 25, - CCERR_QP_ATTR_CANNOT_CHANGE = 26, - CCERR_INVALID_STAG = 27, - CCERR_QP_IN_USE = 28, - CCERR_OUTSTANDING_WRS = 29, - CCERR_STAG_IN_USE = 30, - CCERR_INVALID_STAG_INDEX = 31, - CCERR_INVALID_SGL_FORMAT = 32, - CCERR_ADAPTER_TIMEOUT = 33, - CCERR_INVALID_CQ_DEPTH = 34, - CCERR_INVALID_PRIVATE_DATA_LENGTH = 35, - CCERR_INVALID_EP = 36, - CCERR_MR_IN_USE = CCERR_STAG_IN_USE, - CCERR_FLUSHED = 38, - CCERR_INVALID_WQE = 39, - CCERR_LOCAL_QP_CATASTROPHIC_ERROR = 40, - CCERR_REMOTE_TERMINATION_ERROR = 41, - CCERR_BASE_AND_BOUNDS_VIOLATION = 42, - CCERR_ACCESS_VIOLATION = 43, - CCERR_INVALID_PD_ID = 44, - CCERR_WRAP_ERROR = 45, - CCERR_INV_STAG_ACCESS_ERROR = 46, - CCERR_ZERO_RDMA_READ_RESOURCES = 47, - CCERR_QP_NOT_PRIVILEGED = 48, - CCERR_STAG_STATE_NOT_INVALID = 49, - CCERR_INVALID_PAGE_SIZE = 50, - CCERR_INVALID_BUFFER_SIZE = 51, - CCERR_INVALID_PBE = 52, - CCERR_INVALID_FBO = 53, - CCERR_INVALID_LENGTH = 54, - CCERR_INVALID_ACCESS_RIGHTS = 55, - CCERR_PBL_TOO_BIG = 56, - CCERR_INVALID_VA = 57, - CCERR_INVALID_REGION = 58, - CCERR_INVALID_WINDOW = 59, - CCERR_TOTAL_LENGTH_TOO_BIG = 60, - CCERR_INVALID_QP_ID = 61, - CCERR_ADDR_IN_USE = 62, - CCERR_ADDR_NOT_AVAIL = 63, - CCERR_NET_DOWN = 64, - CCERR_NET_UNREACHABLE = 65, - CCERR_CONN_ABORTED = 66, - CCERR_CONN_RESET = 67, - CCERR_NO_BUFS = 68, - CCERR_CONN_TIMEDOUT = 69, - CCERR_CONN_REFUSED = 70, - CCERR_HOST_UNREACHABLE = 71, - CCERR_INVALID_SEND_SGL_DEPTH = 72, - CCERR_INVALID_RECV_SGL_DEPTH = 73, - CCERR_INVALID_RDMA_WRITE_SGL_DEPTH = 74, - CCERR_INSUFFICIENT_PRIVILEGES = 75, - CCERR_STACK_ERROR = 76, - CCERR_INVALID_VERSION = 77, - CCERR_INVALID_MTU = 78, - CCERR_INVALID_IMAGE = 79, - CCERR_PENDING = 98, /* not an error; user internally by adapter */ - CCERR_DEFER = 99, /* not an error; used internally by adapter */ - CCERR_FAILED_WRITE = 100, - CCERR_FAILED_ERASE = 101, - CCERR_FAILED_VERIFICATION = 102, - CCERR_NOT_FOUND = 103, - -}; - -/* - * CCAE_ACTIVE_CONNECT_RESULTS status result codes. - */ -enum c2_connect_status { - C2_CONN_STATUS_SUCCESS = C2_OK, - C2_CONN_STATUS_NO_MEM = CCERR_INSUFFICIENT_RESOURCES, - C2_CONN_STATUS_TIMEDOUT = CCERR_CONN_TIMEDOUT, - C2_CONN_STATUS_REFUSED = CCERR_CONN_REFUSED, - C2_CONN_STATUS_NETUNREACH = CCERR_NET_UNREACHABLE, - C2_CONN_STATUS_HOSTUNREACH = CCERR_HOST_UNREACHABLE, - C2_CONN_STATUS_INVALID_RNIC = CCERR_INVALID_RNIC, - C2_CONN_STATUS_INVALID_QP = CCERR_INVALID_QP, - C2_CONN_STATUS_INVALID_QP_STATE = CCERR_INVALID_QP_STATE, - C2_CONN_STATUS_REJECTED = CCERR_CONN_RESET, - C2_CONN_STATUS_ADDR_NOT_AVAIL = CCERR_ADDR_NOT_AVAIL, -}; - -/* - * Flash programming status codes. - */ -enum c2_flash_status { - C2_FLASH_STATUS_SUCCESS = 0x0000, - C2_FLASH_STATUS_VERIFY_ERR = 0x0002, - C2_FLASH_STATUS_IMAGE_ERR = 0x0004, - C2_FLASH_STATUS_ECLBS = 0x0400, - C2_FLASH_STATUS_PSLBS = 0x0800, - C2_FLASH_STATUS_VPENS = 0x1000, -}; - -#endif /* _C2_STATUS_H_ */ diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_user.h b/trunk/drivers/infiniband/hw/amso1100/c2_user.h deleted file mode 100644 index 7e9e7ad65467..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_user.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2005 Topspin Communications. All rights reserved. - * Copyright (c) 2005 Cisco Systems. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef C2_USER_H -#define C2_USER_H - -#include - -/* - * Make sure that all structs defined in this file remain laid out so - * that they pack the same way on 32-bit and 64-bit architectures (to - * avoid incompatibility between 32-bit userspace and 64-bit kernels). - * In particular do not use pointer types -- pass pointers in __u64 - * instead. - */ - -struct c2_alloc_ucontext_resp { - __u32 qp_tab_size; - __u32 uarc_size; -}; - -struct c2_alloc_pd_resp { - __u32 pdn; - __u32 reserved; -}; - -struct c2_create_cq { - __u32 lkey; - __u32 pdn; - __u64 arm_db_page; - __u64 set_db_page; - __u32 arm_db_index; - __u32 set_db_index; -}; - -struct c2_create_cq_resp { - __u32 cqn; - __u32 reserved; -}; - -struct c2_create_qp { - __u32 lkey; - __u32 reserved; - __u64 sq_db_page; - __u64 rq_db_page; - __u32 sq_db_index; - __u32 rq_db_index; -}; - -#endif /* C2_USER_H */ diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_vq.c b/trunk/drivers/infiniband/hw/amso1100/c2_vq.c deleted file mode 100644 index 40caeb5f41b4..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_vq.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include -#include - -#include "c2_vq.h" -#include "c2_provider.h" - -/* - * Verbs Request Objects: - * - * VQ Request Objects are allocated by the kernel verbs handlers. - * They contain a wait object, a refcnt, an atomic bool indicating that the - * adapter has replied, and a copy of the verb reply work request. - * A pointer to the VQ Request Object is passed down in the context - * field of the work request message, and reflected back by the adapter - * in the verbs reply message. The function handle_vq() in the interrupt - * path will use this pointer to: - * 1) append a copy of the verbs reply message - * 2) mark that the reply is ready - * 3) wake up the kernel verbs handler blocked awaiting the reply. - * - * - * The kernel verbs handlers do a "get" to put a 2nd reference on the - * VQ Request object. If the kernel verbs handler exits before the adapter - * can respond, this extra reference will keep the VQ Request object around - * until the adapter's reply can be processed. The reason we need this is - * because a pointer to this object is stuffed into the context field of - * the verbs work request message, and reflected back in the reply message. - * It is used in the interrupt handler (handle_vq()) to wake up the appropriate - * kernel verb handler that is blocked awaiting the verb reply. - * So handle_vq() will do a "put" on the object when it's done accessing it. - * NOTE: If we guarantee that the kernel verb handler will never bail before - * getting the reply, then we don't need these refcnts. - * - * - * VQ Request objects are freed by the kernel verbs handlers only - * after the verb has been processed, or when the adapter fails and - * does not reply. - * - * - * Verbs Reply Buffers: - * - * VQ Reply bufs are local host memory copies of a - * outstanding Verb Request reply - * message. The are always allocated by the kernel verbs handlers, and _may_ be - * freed by either the kernel verbs handler -or- the interrupt handler. The - * kernel verbs handler _must_ free the repbuf, then free the vq request object - * in that order. - */ - -int vq_init(struct c2_dev *c2dev) -{ - sprintf(c2dev->vq_cache_name, "c2-vq:dev%c", - (char) ('0' + c2dev->devnum)); - c2dev->host_msg_cache = - kmem_cache_create(c2dev->vq_cache_name, c2dev->rep_vq.msg_size, 0, - SLAB_HWCACHE_ALIGN, NULL, NULL); - if (c2dev->host_msg_cache == NULL) { - return -ENOMEM; - } - return 0; -} - -void vq_term(struct c2_dev *c2dev) -{ - kmem_cache_destroy(c2dev->host_msg_cache); -} - -/* vq_req_alloc - allocate a VQ Request Object and initialize it. - * The refcnt is set to 1. - */ -struct c2_vq_req *vq_req_alloc(struct c2_dev *c2dev) -{ - struct c2_vq_req *r; - - r = kmalloc(sizeof(struct c2_vq_req), GFP_KERNEL); - if (r) { - init_waitqueue_head(&r->wait_object); - r->reply_msg = (u64) NULL; - r->event = 0; - r->cm_id = NULL; - r->qp = NULL; - atomic_set(&r->refcnt, 1); - atomic_set(&r->reply_ready, 0); - } - return r; -} - - -/* vq_req_free - free the VQ Request Object. It is assumed the verbs handler - * has already free the VQ Reply Buffer if it existed. - */ -void vq_req_free(struct c2_dev *c2dev, struct c2_vq_req *r) -{ - r->reply_msg = (u64) NULL; - if (atomic_dec_and_test(&r->refcnt)) { - kfree(r); - } -} - -/* vq_req_get - reference a VQ Request Object. Done - * only in the kernel verbs handlers. - */ -void vq_req_get(struct c2_dev *c2dev, struct c2_vq_req *r) -{ - atomic_inc(&r->refcnt); -} - - -/* vq_req_put - dereference and potentially free a VQ Request Object. - * - * This is only called by handle_vq() on the - * interrupt when it is done processing - * a verb reply message. If the associated - * kernel verbs handler has already bailed, - * then this put will actually free the VQ - * Request object _and_ the VQ Reply Buffer - * if it exists. - */ -void vq_req_put(struct c2_dev *c2dev, struct c2_vq_req *r) -{ - if (atomic_dec_and_test(&r->refcnt)) { - if (r->reply_msg != (u64) NULL) - vq_repbuf_free(c2dev, - (void *) (unsigned long) r->reply_msg); - kfree(r); - } -} - - -/* - * vq_repbuf_alloc - allocate a VQ Reply Buffer. - */ -void *vq_repbuf_alloc(struct c2_dev *c2dev) -{ - return kmem_cache_alloc(c2dev->host_msg_cache, SLAB_ATOMIC); -} - -/* - * vq_send_wr - post a verbs request message to the Verbs Request Queue. - * If a message is not available in the MQ, then block until one is available. - * NOTE: handle_mq() on the interrupt context will wake up threads blocked here. - * When the adapter drains the Verbs Request Queue, - * it inserts MQ index 0 in to the - * adapter->host activity fifo and interrupts the host. - */ -int vq_send_wr(struct c2_dev *c2dev, union c2wr *wr) -{ - void *msg; - wait_queue_t __wait; - - /* - * grab adapter vq lock - */ - spin_lock(&c2dev->vqlock); - - /* - * allocate msg - */ - msg = c2_mq_alloc(&c2dev->req_vq); - - /* - * If we cannot get a msg, then we'll wait - * When a messages are available, the int handler will wake_up() - * any waiters. - */ - while (msg == NULL) { - pr_debug("%s:%d no available msg in VQ, waiting...\n", - __FUNCTION__, __LINE__); - init_waitqueue_entry(&__wait, current); - add_wait_queue(&c2dev->req_vq_wo, &__wait); - spin_unlock(&c2dev->vqlock); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (!c2_mq_full(&c2dev->req_vq)) { - break; - } - if (!signal_pending(current)) { - schedule_timeout(1 * HZ); /* 1 second... */ - continue; - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&c2dev->req_vq_wo, &__wait); - return -EINTR; - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&c2dev->req_vq_wo, &__wait); - spin_lock(&c2dev->vqlock); - msg = c2_mq_alloc(&c2dev->req_vq); - } - - /* - * copy wr into adapter msg - */ - memcpy(msg, wr, c2dev->req_vq.msg_size); - - /* - * post msg - */ - c2_mq_produce(&c2dev->req_vq); - - /* - * release adapter vq lock - */ - spin_unlock(&c2dev->vqlock); - return 0; -} - - -/* - * vq_wait_for_reply - block until the adapter posts a Verb Reply Message. - */ -int vq_wait_for_reply(struct c2_dev *c2dev, struct c2_vq_req *req) -{ - if (!wait_event_timeout(req->wait_object, - atomic_read(&req->reply_ready), - 60*HZ)) - return -ETIMEDOUT; - - return 0; -} - -/* - * vq_repbuf_free - Free a Verbs Reply Buffer. - */ -void vq_repbuf_free(struct c2_dev *c2dev, void *reply) -{ - kmem_cache_free(c2dev->host_msg_cache, reply); -} diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_vq.h b/trunk/drivers/infiniband/hw/amso1100/c2_vq.h deleted file mode 100644 index 33805627a607..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_vq.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _C2_VQ_H_ -#define _C2_VQ_H_ -#include -#include "c2.h" -#include "c2_wr.h" -#include "c2_provider.h" - -struct c2_vq_req { - u64 reply_msg; /* ptr to reply msg */ - wait_queue_head_t wait_object; /* wait object for vq reqs */ - atomic_t reply_ready; /* set when reply is ready */ - atomic_t refcnt; /* used to cancel WRs... */ - int event; - struct iw_cm_id *cm_id; - struct c2_qp *qp; -}; - -extern int vq_init(struct c2_dev *c2dev); -extern void vq_term(struct c2_dev *c2dev); - -extern struct c2_vq_req *vq_req_alloc(struct c2_dev *c2dev); -extern void vq_req_free(struct c2_dev *c2dev, struct c2_vq_req *req); -extern void vq_req_get(struct c2_dev *c2dev, struct c2_vq_req *req); -extern void vq_req_put(struct c2_dev *c2dev, struct c2_vq_req *req); -extern int vq_send_wr(struct c2_dev *c2dev, union c2wr * wr); - -extern void *vq_repbuf_alloc(struct c2_dev *c2dev); -extern void vq_repbuf_free(struct c2_dev *c2dev, void *reply); - -extern int vq_wait_for_reply(struct c2_dev *c2dev, struct c2_vq_req *req); -#endif /* _C2_VQ_H_ */ diff --git a/trunk/drivers/infiniband/hw/amso1100/c2_wr.h b/trunk/drivers/infiniband/hw/amso1100/c2_wr.h deleted file mode 100644 index 3ec6c43bb0ef..000000000000 --- a/trunk/drivers/infiniband/hw/amso1100/c2_wr.h +++ /dev/null @@ -1,1520 +0,0 @@ -/* - * Copyright (c) 2005 Ammasso, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _C2_WR_H_ -#define _C2_WR_H_ - -#ifdef CCDEBUG -#define CCWR_MAGIC 0xb07700b0 -#endif - -#define C2_QP_NO_ATTR_CHANGE 0xFFFFFFFF - -/* Maximum allowed size in bytes of private_data exchange - * on connect. - */ -#define C2_MAX_PRIVATE_DATA_SIZE 200 - -/* - * These types are shared among the adapter, host, and CCIL consumer. - */ -enum c2_cq_notification_type { - C2_CQ_NOTIFICATION_TYPE_NONE = 1, - C2_CQ_NOTIFICATION_TYPE_NEXT, - C2_CQ_NOTIFICATION_TYPE_NEXT_SE -}; - -enum c2_setconfig_cmd { - C2_CFG_ADD_ADDR = 1, - C2_CFG_DEL_ADDR = 2, - C2_CFG_ADD_ROUTE = 3, - C2_CFG_DEL_ROUTE = 4 -}; - -enum c2_getconfig_cmd { - C2_GETCONFIG_ROUTES = 1, - C2_GETCONFIG_ADDRS -}; - -/* - * CCIL Work Request Identifiers - */ -enum c2wr_ids { - CCWR_RNIC_OPEN = 1, - CCWR_RNIC_QUERY, - CCWR_RNIC_SETCONFIG, - CCWR_RNIC_GETCONFIG, - CCWR_RNIC_CLOSE, - CCWR_CQ_CREATE, - CCWR_CQ_QUERY, - CCWR_CQ_MODIFY, - CCWR_CQ_DESTROY, - CCWR_QP_CONNECT, - CCWR_PD_ALLOC, - CCWR_PD_DEALLOC, - CCWR_SRQ_CREATE, - CCWR_SRQ_QUERY, - CCWR_SRQ_MODIFY, - CCWR_SRQ_DESTROY, - CCWR_QP_CREATE, - CCWR_QP_QUERY, - CCWR_QP_MODIFY, - CCWR_QP_DESTROY, - CCWR_NSMR_STAG_ALLOC, - CCWR_NSMR_REGISTER, - CCWR_NSMR_PBL, - CCWR_STAG_DEALLOC, - CCWR_NSMR_REREGISTER, - CCWR_SMR_REGISTER, - CCWR_MR_QUERY, - CCWR_MW_ALLOC, - CCWR_MW_QUERY, - CCWR_EP_CREATE, - CCWR_EP_GETOPT, - CCWR_EP_SETOPT, - CCWR_EP_DESTROY, - CCWR_EP_BIND, - CCWR_EP_CONNECT, - CCWR_EP_LISTEN, - CCWR_EP_SHUTDOWN, - CCWR_EP_LISTEN_CREATE, - CCWR_EP_LISTEN_DESTROY, - CCWR_EP_QUERY, - CCWR_CR_ACCEPT, - CCWR_CR_REJECT, - CCWR_CONSOLE, - CCWR_TERM, - CCWR_FLASH_INIT, - CCWR_FLASH, - CCWR_BUF_ALLOC, - CCWR_BUF_FREE, - CCWR_FLASH_WRITE, - CCWR_INIT, /* WARNING: Don't move this ever again! */ - - - - /* Add new IDs here */ - - - - /* - * WARNING: CCWR_LAST must always be the last verbs id defined! - * All the preceding IDs are fixed, and must not change. - * You can add new IDs, but must not remove or reorder - * any IDs. If you do, YOU will ruin any hope of - * compatability between versions. - */ - CCWR_LAST, - - /* - * Start over at 1 so that arrays indexed by user wr id's - * begin at 1. This is OK since the verbs and user wr id's - * are always used on disjoint sets of queues. - */ - /* - * The order of the CCWR_SEND_XX verbs must - * match the order of the RDMA_OPs - */ - CCWR_SEND = 1, - CCWR_SEND_INV, - CCWR_SEND_SE, - CCWR_SEND_SE_INV, - CCWR_RDMA_WRITE, - CCWR_RDMA_READ, - CCWR_RDMA_READ_INV, - CCWR_MW_BIND, - CCWR_NSMR_FASTREG, - CCWR_STAG_INVALIDATE, - CCWR_RECV, - CCWR_NOP, - CCWR_UNIMPL, -/* WARNING: This must always be the last user wr id defined! */ -}; -#define RDMA_SEND_OPCODE_FROM_WR_ID(x) (x+2) - -/* - * SQ/RQ Work Request Types - */ -enum c2_wr_type { - C2_WR_TYPE_SEND = CCWR_SEND, - C2_WR_TYPE_SEND_SE = CCWR_SEND_SE, - C2_WR_TYPE_SEND_INV = CCWR_SEND_INV, - C2_WR_TYPE_SEND_SE_INV = CCWR_SEND_SE_INV, - C2_WR_TYPE_RDMA_WRITE = CCWR_RDMA_WRITE, - C2_WR_TYPE_RDMA_READ = CCWR_RDMA_READ, - C2_WR_TYPE_RDMA_READ_INV_STAG = CCWR_RDMA_READ_INV, - C2_WR_TYPE_BIND_MW = CCWR_MW_BIND, - C2_WR_TYPE_FASTREG_NSMR = CCWR_NSMR_FASTREG, - C2_WR_TYPE_INV_STAG = CCWR_STAG_INVALIDATE, - C2_WR_TYPE_RECV = CCWR_RECV, - C2_WR_TYPE_NOP = CCWR_NOP, -}; - -struct c2_netaddr { - u32 ip_addr; - u32 netmask; - u32 mtu; -}; - -struct c2_route { - u32 ip_addr; /* 0 indicates the default route */ - u32 netmask; /* netmask associated with dst */ - u32 flags; - union { - u32 ipaddr; /* address of the nexthop interface */ - u8 enaddr[6]; - } nexthop; -}; - -/* - * A Scatter Gather Entry. - */ -struct c2_data_addr { - u32 stag; - u32 length; - u64 to; -}; - -/* - * MR and MW flags used by the consumer, RI, and RNIC. - */ -enum c2_mm_flags { - MEM_REMOTE = 0x0001, /* allow mw binds with remote access. */ - MEM_VA_BASED = 0x0002, /* Not Zero-based */ - MEM_PBL_COMPLETE = 0x0004, /* PBL array is complete in this msg */ - MEM_LOCAL_READ = 0x0008, /* allow local reads */ - MEM_LOCAL_WRITE = 0x0010, /* allow local writes */ - MEM_REMOTE_READ = 0x0020, /* allow remote reads */ - MEM_REMOTE_WRITE = 0x0040, /* allow remote writes */ - MEM_WINDOW_BIND = 0x0080, /* binds allowed */ - MEM_SHARED = 0x0100, /* set if MR is shared */ - MEM_STAG_VALID = 0x0200 /* set if STAG is in valid state */ -}; - -/* - * CCIL API ACF flags defined in terms of the low level mem flags. - * This minimizes translation needed in the user API - */ -enum c2_acf { - C2_ACF_LOCAL_READ = MEM_LOCAL_READ, - C2_ACF_LOCAL_WRITE = MEM_LOCAL_WRITE, - C2_ACF_REMOTE_READ = MEM_REMOTE_READ, - C2_ACF_REMOTE_WRITE = MEM_REMOTE_WRITE, - C2_ACF_WINDOW_BIND = MEM_WINDOW_BIND -}; - -/* - * Image types of objects written to flash - */ -#define C2_FLASH_IMG_BITFILE 1 -#define C2_FLASH_IMG_OPTION_ROM 2 -#define C2_FLASH_IMG_VPD 3 - -/* - * to fix bug 1815 we define the max size allowable of the - * terminate message (per the IETF spec).Refer to the IETF - * protocal specification, section 12.1.6, page 64) - * The message is prefixed by 20 types of DDP info. - * - * Then the message has 6 bytes for the terminate control - * and DDP segment length info plus a DDP header (either - * 14 or 18 byts) plus 28 bytes for the RDMA header. - * Thus the max size in: - * 20 + (6 + 18 + 28) = 72 - */ -#define C2_MAX_TERMINATE_MESSAGE_SIZE (72) - -/* - * Build String Length. It must be the same as C2_BUILD_STR_LEN in ccil_api.h - */ -#define WR_BUILD_STR_LEN 64 - -/* - * WARNING: All of these structs need to align any 64bit types on - * 64 bit boundaries! 64bit types include u64 and u64. - */ - -/* - * Clustercore Work Request Header. Be sensitive to field layout - * and alignment. - */ -struct c2wr_hdr { - /* wqe_count is part of the cqe. It is put here so the - * adapter can write to it while the wr is pending without - * clobbering part of the wr. This word need not be dma'd - * from the host to adapter by libccil, but we copy it anyway - * to make the memcpy to the adapter better aligned. - */ - u32 wqe_count; - - /* Put these fields next so that later 32- and 64-bit - * quantities are naturally aligned. - */ - u8 id; - u8 result; /* adapter -> host */ - u8 sge_count; /* host -> adapter */ - u8 flags; /* host -> adapter */ - - u64 context; -#ifdef CCMSGMAGIC - u32 magic; - u32 pad; -#endif -} __attribute__((packed)); - -/* - *------------------------ RNIC ------------------------ - */ - -/* - * WR_RNIC_OPEN - */ - -/* - * Flags for the RNIC WRs - */ -enum c2_rnic_flags { - RNIC_IRD_STATIC = 0x0001, - RNIC_ORD_STATIC = 0x0002, - RNIC_QP_STATIC = 0x0004, - RNIC_SRQ_SUPPORTED = 0x0008, - RNIC_PBL_BLOCK_MODE = 0x0010, - RNIC_SRQ_MODEL_ARRIVAL = 0x0020, - RNIC_CQ_OVF_DETECTED = 0x0040, - RNIC_PRIV_MODE = 0x0080 -}; - -struct c2wr_rnic_open_req { - struct c2wr_hdr hdr; - u64 user_context; - u16 flags; /* See enum c2_rnic_flags */ - u16 port_num; -} __attribute__((packed)); - -struct c2wr_rnic_open_rep { - struct c2wr_hdr hdr; - u32 rnic_handle; -} __attribute__((packed)); - -union c2wr_rnic_open { - struct c2wr_rnic_open_req req; - struct c2wr_rnic_open_rep rep; -} __attribute__((packed)); - -struct c2wr_rnic_query_req { - struct c2wr_hdr hdr; - u32 rnic_handle; -} __attribute__((packed)); - -/* - * WR_RNIC_QUERY - */ -struct c2wr_rnic_query_rep { - struct c2wr_hdr hdr; - u64 user_context; - u32 vendor_id; - u32 part_number; - u32 hw_version; - u32 fw_ver_major; - u32 fw_ver_minor; - u32 fw_ver_patch; - char fw_ver_build_str[WR_BUILD_STR_LEN]; - u32 max_qps; - u32 max_qp_depth; - u32 max_srq_depth; - u32 max_send_sgl_depth; - u32 max_rdma_sgl_depth; - u32 max_cqs; - u32 max_cq_depth; - u32 max_cq_event_handlers; - u32 max_mrs; - u32 max_pbl_depth; - u32 max_pds; - u32 max_global_ird; - u32 max_global_ord; - u32 max_qp_ird; - u32 max_qp_ord; - u32 flags; - u32 max_mws; - u32 pbe_range_low; - u32 pbe_range_high; - u32 max_srqs; - u32 page_size; -} __attribute__((packed)); - -union c2wr_rnic_query { - struct c2wr_rnic_query_req req; - struct c2wr_rnic_query_rep rep; -} __attribute__((packed)); - -/* - * WR_RNIC_GETCONFIG - */ - -struct c2wr_rnic_getconfig_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 option; /* see c2_getconfig_cmd_t */ - u64 reply_buf; - u32 reply_buf_len; -} __attribute__((packed)) ; - -struct c2wr_rnic_getconfig_rep { - struct c2wr_hdr hdr; - u32 option; /* see c2_getconfig_cmd_t */ - u32 count_len; /* length of the number of addresses configured */ -} __attribute__((packed)) ; - -union c2wr_rnic_getconfig { - struct c2wr_rnic_getconfig_req req; - struct c2wr_rnic_getconfig_rep rep; -} __attribute__((packed)) ; - -/* - * WR_RNIC_SETCONFIG - */ -struct c2wr_rnic_setconfig_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 option; /* See c2_setconfig_cmd_t */ - /* variable data and pad. See c2_netaddr and c2_route */ - u8 data[0]; -} __attribute__((packed)) ; - -struct c2wr_rnic_setconfig_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_rnic_setconfig { - struct c2wr_rnic_setconfig_req req; - struct c2wr_rnic_setconfig_rep rep; -} __attribute__((packed)) ; - -/* - * WR_RNIC_CLOSE - */ -struct c2wr_rnic_close_req { - struct c2wr_hdr hdr; - u32 rnic_handle; -} __attribute__((packed)) ; - -struct c2wr_rnic_close_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_rnic_close { - struct c2wr_rnic_close_req req; - struct c2wr_rnic_close_rep rep; -} __attribute__((packed)) ; - -/* - *------------------------ CQ ------------------------ - */ -struct c2wr_cq_create_req { - struct c2wr_hdr hdr; - u64 shared_ht; - u64 user_context; - u64 msg_pool; - u32 rnic_handle; - u32 msg_size; - u32 depth; -} __attribute__((packed)) ; - -struct c2wr_cq_create_rep { - struct c2wr_hdr hdr; - u32 mq_index; - u32 adapter_shared; - u32 cq_handle; -} __attribute__((packed)) ; - -union c2wr_cq_create { - struct c2wr_cq_create_req req; - struct c2wr_cq_create_rep rep; -} __attribute__((packed)) ; - -struct c2wr_cq_modify_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 cq_handle; - u32 new_depth; - u64 new_msg_pool; -} __attribute__((packed)) ; - -struct c2wr_cq_modify_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_cq_modify { - struct c2wr_cq_modify_req req; - struct c2wr_cq_modify_rep rep; -} __attribute__((packed)) ; - -struct c2wr_cq_destroy_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 cq_handle; -} __attribute__((packed)) ; - -struct c2wr_cq_destroy_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_cq_destroy { - struct c2wr_cq_destroy_req req; - struct c2wr_cq_destroy_rep rep; -} __attribute__((packed)) ; - -/* - *------------------------ PD ------------------------ - */ -struct c2wr_pd_alloc_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 pd_id; -} __attribute__((packed)) ; - -struct c2wr_pd_alloc_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_pd_alloc { - struct c2wr_pd_alloc_req req; - struct c2wr_pd_alloc_rep rep; -} __attribute__((packed)) ; - -struct c2wr_pd_dealloc_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 pd_id; -} __attribute__((packed)) ; - -struct c2wr_pd_dealloc_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_pd_dealloc { - struct c2wr_pd_dealloc_req req; - struct c2wr_pd_dealloc_rep rep; -} __attribute__((packed)) ; - -/* - *------------------------ SRQ ------------------------ - */ -struct c2wr_srq_create_req { - struct c2wr_hdr hdr; - u64 shared_ht; - u64 user_context; - u32 rnic_handle; - u32 srq_depth; - u32 srq_limit; - u32 sgl_depth; - u32 pd_id; -} __attribute__((packed)) ; - -struct c2wr_srq_create_rep { - struct c2wr_hdr hdr; - u32 srq_depth; - u32 sgl_depth; - u32 msg_size; - u32 mq_index; - u32 mq_start; - u32 srq_handle; -} __attribute__((packed)) ; - -union c2wr_srq_create { - struct c2wr_srq_create_req req; - struct c2wr_srq_create_rep rep; -} __attribute__((packed)) ; - -struct c2wr_srq_destroy_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 srq_handle; -} __attribute__((packed)) ; - -struct c2wr_srq_destroy_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_srq_destroy { - struct c2wr_srq_destroy_req req; - struct c2wr_srq_destroy_rep rep; -} __attribute__((packed)) ; - -/* - *------------------------ QP ------------------------ - */ -enum c2wr_qp_flags { - QP_RDMA_READ = 0x00000001, /* RDMA read enabled? */ - QP_RDMA_WRITE = 0x00000002, /* RDMA write enabled? */ - QP_MW_BIND = 0x00000004, /* MWs enabled */ - QP_ZERO_STAG = 0x00000008, /* enabled? */ - QP_REMOTE_TERMINATION = 0x00000010, /* remote end terminated */ - QP_RDMA_READ_RESPONSE = 0x00000020 /* Remote RDMA read */ - /* enabled? */ -}; - -struct c2wr_qp_create_req { - struct c2wr_hdr hdr; - u64 shared_sq_ht; - u64 shared_rq_ht; - u64 user_context; - u32 rnic_handle; - u32 sq_cq_handle; - u32 rq_cq_handle; - u32 sq_depth; - u32 rq_depth; - u32 srq_handle; - u32 srq_limit; - u32 flags; /* see enum c2wr_qp_flags */ - u32 send_sgl_depth; - u32 recv_sgl_depth; - u32 rdma_write_sgl_depth; - u32 ord; - u32 ird; - u32 pd_id; -} __attribute__((packed)) ; - -struct c2wr_qp_create_rep { - struct c2wr_hdr hdr; - u32 sq_depth; - u32 rq_depth; - u32 send_sgl_depth; - u32 recv_sgl_depth; - u32 rdma_write_sgl_depth; - u32 ord; - u32 ird; - u32 sq_msg_size; - u32 sq_mq_index; - u32 sq_mq_start; - u32 rq_msg_size; - u32 rq_mq_index; - u32 rq_mq_start; - u32 qp_handle; -} __attribute__((packed)) ; - -union c2wr_qp_create { - struct c2wr_qp_create_req req; - struct c2wr_qp_create_rep rep; -} __attribute__((packed)) ; - -struct c2wr_qp_query_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 qp_handle; -} __attribute__((packed)) ; - -struct c2wr_qp_query_rep { - struct c2wr_hdr hdr; - u64 user_context; - u32 rnic_handle; - u32 sq_depth; - u32 rq_depth; - u32 send_sgl_depth; - u32 rdma_write_sgl_depth; - u32 recv_sgl_depth; - u32 ord; - u32 ird; - u16 qp_state; - u16 flags; /* see c2wr_qp_flags_t */ - u32 qp_id; - u32 local_addr; - u32 remote_addr; - u16 local_port; - u16 remote_port; - u32 terminate_msg_length; /* 0 if not present */ - u8 data[0]; - /* Terminate Message in-line here. */ -} __attribute__((packed)) ; - -union c2wr_qp_query { - struct c2wr_qp_query_req req; - struct c2wr_qp_query_rep rep; -} __attribute__((packed)) ; - -struct c2wr_qp_modify_req { - struct c2wr_hdr hdr; - u64 stream_msg; - u32 stream_msg_length; - u32 rnic_handle; - u32 qp_handle; - u32 next_qp_state; - u32 ord; - u32 ird; - u32 sq_depth; - u32 rq_depth; - u32 llp_ep_handle; -} __attribute__((packed)) ; - -struct c2wr_qp_modify_rep { - struct c2wr_hdr hdr; - u32 ord; - u32 ird; - u32 sq_depth; - u32 rq_depth; - u32 sq_msg_size; - u32 sq_mq_index; - u32 sq_mq_start; - u32 rq_msg_size; - u32 rq_mq_index; - u32 rq_mq_start; -} __attribute__((packed)) ; - -union c2wr_qp_modify { - struct c2wr_qp_modify_req req; - struct c2wr_qp_modify_rep rep; -} __attribute__((packed)) ; - -struct c2wr_qp_destroy_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 qp_handle; -} __attribute__((packed)) ; - -struct c2wr_qp_destroy_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_qp_destroy { - struct c2wr_qp_destroy_req req; - struct c2wr_qp_destroy_rep rep; -} __attribute__((packed)) ; - -/* - * The CCWR_QP_CONNECT msg is posted on the verbs request queue. It can - * only be posted when a QP is in IDLE state. After the connect request is - * submitted to the LLP, the adapter moves the QP to CONNECT_PENDING state. - * No synchronous reply from adapter to this WR. The results of - * connection are passed back in an async event CCAE_ACTIVE_CONNECT_RESULTS - * See c2wr_ae_active_connect_results_t - */ -struct c2wr_qp_connect_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 qp_handle; - u32 remote_addr; - u16 remote_port; - u16 pad; - u32 private_data_length; - u8 private_data[0]; /* Private data in-line. */ -} __attribute__((packed)) ; - -struct c2wr_qp_connect { - struct c2wr_qp_connect_req req; - /* no synchronous reply. */ -} __attribute__((packed)) ; - - -/* - *------------------------ MM ------------------------ - */ - -struct c2wr_nsmr_stag_alloc_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 pbl_depth; - u32 pd_id; - u32 flags; -} __attribute__((packed)) ; - -struct c2wr_nsmr_stag_alloc_rep { - struct c2wr_hdr hdr; - u32 pbl_depth; - u32 stag_index; -} __attribute__((packed)) ; - -union c2wr_nsmr_stag_alloc { - struct c2wr_nsmr_stag_alloc_req req; - struct c2wr_nsmr_stag_alloc_rep rep; -} __attribute__((packed)) ; - -struct c2wr_nsmr_register_req { - struct c2wr_hdr hdr; - u64 va; - u32 rnic_handle; - u16 flags; - u8 stag_key; - u8 pad; - u32 pd_id; - u32 pbl_depth; - u32 pbe_size; - u32 fbo; - u32 length; - u32 addrs_length; - /* array of paddrs (must be aligned on a 64bit boundary) */ - u64 paddrs[0]; -} __attribute__((packed)) ; - -struct c2wr_nsmr_register_rep { - struct c2wr_hdr hdr; - u32 pbl_depth; - u32 stag_index; -} __attribute__((packed)) ; - -union c2wr_nsmr_register { - struct c2wr_nsmr_register_req req; - struct c2wr_nsmr_register_rep rep; -} __attribute__((packed)) ; - -struct c2wr_nsmr_pbl_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 flags; - u32 stag_index; - u32 addrs_length; - /* array of paddrs (must be aligned on a 64bit boundary) */ - u64 paddrs[0]; -} __attribute__((packed)) ; - -struct c2wr_nsmr_pbl_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_nsmr_pbl { - struct c2wr_nsmr_pbl_req req; - struct c2wr_nsmr_pbl_rep rep; -} __attribute__((packed)) ; - -struct c2wr_mr_query_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 stag_index; -} __attribute__((packed)) ; - -struct c2wr_mr_query_rep { - struct c2wr_hdr hdr; - u8 stag_key; - u8 pad[3]; - u32 pd_id; - u32 flags; - u32 pbl_depth; -} __attribute__((packed)) ; - -union c2wr_mr_query { - struct c2wr_mr_query_req req; - struct c2wr_mr_query_rep rep; -} __attribute__((packed)) ; - -struct c2wr_mw_query_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 stag_index; -} __attribute__((packed)) ; - -struct c2wr_mw_query_rep { - struct c2wr_hdr hdr; - u8 stag_key; - u8 pad[3]; - u32 pd_id; - u32 flags; -} __attribute__((packed)) ; - -union c2wr_mw_query { - struct c2wr_mw_query_req req; - struct c2wr_mw_query_rep rep; -} __attribute__((packed)) ; - - -struct c2wr_stag_dealloc_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 stag_index; -} __attribute__((packed)) ; - -struct c2wr_stag_dealloc_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)) ; - -union c2wr_stag_dealloc { - struct c2wr_stag_dealloc_req req; - struct c2wr_stag_dealloc_rep rep; -} __attribute__((packed)) ; - -struct c2wr_nsmr_reregister_req { - struct c2wr_hdr hdr; - u64 va; - u32 rnic_handle; - u16 flags; - u8 stag_key; - u8 pad; - u32 stag_index; - u32 pd_id; - u32 pbl_depth; - u32 pbe_size; - u32 fbo; - u32 length; - u32 addrs_length; - u32 pad1; - /* array of paddrs (must be aligned on a 64bit boundary) */ - u64 paddrs[0]; -} __attribute__((packed)) ; - -struct c2wr_nsmr_reregister_rep { - struct c2wr_hdr hdr; - u32 pbl_depth; - u32 stag_index; -} __attribute__((packed)) ; - -union c2wr_nsmr_reregister { - struct c2wr_nsmr_reregister_req req; - struct c2wr_nsmr_reregister_rep rep; -} __attribute__((packed)) ; - -struct c2wr_smr_register_req { - struct c2wr_hdr hdr; - u64 va; - u32 rnic_handle; - u16 flags; - u8 stag_key; - u8 pad; - u32 stag_index; - u32 pd_id; -} __attribute__((packed)) ; - -struct c2wr_smr_register_rep { - struct c2wr_hdr hdr; - u32 stag_index; -} __attribute__((packed)) ; - -union c2wr_smr_register { - struct c2wr_smr_register_req req; - struct c2wr_smr_register_rep rep; -} __attribute__((packed)) ; - -struct c2wr_mw_alloc_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 pd_id; -} __attribute__((packed)) ; - -struct c2wr_mw_alloc_rep { - struct c2wr_hdr hdr; - u32 stag_index; -} __attribute__((packed)) ; - -union c2wr_mw_alloc { - struct c2wr_mw_alloc_req req; - struct c2wr_mw_alloc_rep rep; -} __attribute__((packed)) ; - -/* - *------------------------ WRs ----------------------- - */ - -struct c2wr_user_hdr { - struct c2wr_hdr hdr; /* Has status and WR Type */ -} __attribute__((packed)) ; - -enum c2_qp_state { - C2_QP_STATE_IDLE = 0x01, - C2_QP_STATE_CONNECTING = 0x02, - C2_QP_STATE_RTS = 0x04, - C2_QP_STATE_CLOSING = 0x08, - C2_QP_STATE_TERMINATE = 0x10, - C2_QP_STATE_ERROR = 0x20, -}; - -/* Completion queue entry. */ -struct c2wr_ce { - struct c2wr_hdr hdr; /* Has status and WR Type */ - u64 qp_user_context; /* c2_user_qp_t * */ - u32 qp_state; /* Current QP State */ - u32 handle; /* QPID or EP Handle */ - u32 bytes_rcvd; /* valid for RECV WCs */ - u32 stag; -} __attribute__((packed)) ; - - -/* - * Flags used for all post-sq WRs. These must fit in the flags - * field of the struct c2wr_hdr (eight bits). - */ -enum { - SQ_SIGNALED = 0x01, - SQ_READ_FENCE = 0x02, - SQ_FENCE = 0x04, -}; - -/* - * Common fields for all post-sq WRs. Namely the standard header and a - * secondary header with fields common to all post-sq WRs. - */ -struct c2_sq_hdr { - struct c2wr_user_hdr user_hdr; -} __attribute__((packed)); - -/* - * Same as above but for post-rq WRs. - */ -struct c2_rq_hdr { - struct c2wr_user_hdr user_hdr; -} __attribute__((packed)); - -/* - * use the same struct for all sends. - */ -struct c2wr_send_req { - struct c2_sq_hdr sq_hdr; - u32 sge_len; - u32 remote_stag; - u8 data[0]; /* SGE array */ -} __attribute__((packed)); - -union c2wr_send { - struct c2wr_send_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -struct c2wr_rdma_write_req { - struct c2_sq_hdr sq_hdr; - u64 remote_to; - u32 remote_stag; - u32 sge_len; - u8 data[0]; /* SGE array */ -} __attribute__((packed)); - -union c2wr_rdma_write { - struct c2wr_rdma_write_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -struct c2wr_rdma_read_req { - struct c2_sq_hdr sq_hdr; - u64 local_to; - u64 remote_to; - u32 local_stag; - u32 remote_stag; - u32 length; -} __attribute__((packed)); - -union c2wr_rdma_read { - struct c2wr_rdma_read_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -struct c2wr_mw_bind_req { - struct c2_sq_hdr sq_hdr; - u64 va; - u8 stag_key; - u8 pad[3]; - u32 mw_stag_index; - u32 mr_stag_index; - u32 length; - u32 flags; -} __attribute__((packed)); - -union c2wr_mw_bind { - struct c2wr_mw_bind_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -struct c2wr_nsmr_fastreg_req { - struct c2_sq_hdr sq_hdr; - u64 va; - u8 stag_key; - u8 pad[3]; - u32 stag_index; - u32 pbe_size; - u32 fbo; - u32 length; - u32 addrs_length; - /* array of paddrs (must be aligned on a 64bit boundary) */ - u64 paddrs[0]; -} __attribute__((packed)); - -union c2wr_nsmr_fastreg { - struct c2wr_nsmr_fastreg_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -struct c2wr_stag_invalidate_req { - struct c2_sq_hdr sq_hdr; - u8 stag_key; - u8 pad[3]; - u32 stag_index; -} __attribute__((packed)); - -union c2wr_stag_invalidate { - struct c2wr_stag_invalidate_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -union c2wr_sqwr { - struct c2_sq_hdr sq_hdr; - struct c2wr_send_req send; - struct c2wr_send_req send_se; - struct c2wr_send_req send_inv; - struct c2wr_send_req send_se_inv; - struct c2wr_rdma_write_req rdma_write; - struct c2wr_rdma_read_req rdma_read; - struct c2wr_mw_bind_req mw_bind; - struct c2wr_nsmr_fastreg_req nsmr_fastreg; - struct c2wr_stag_invalidate_req stag_inv; -} __attribute__((packed)); - - -/* - * RQ WRs - */ -struct c2wr_rqwr { - struct c2_rq_hdr rq_hdr; - u8 data[0]; /* array of SGEs */ -} __attribute__((packed)); - -union c2wr_recv { - struct c2wr_rqwr req; - struct c2wr_ce rep; -} __attribute__((packed)); - -/* - * All AEs start with this header. Most AEs only need to convey the - * information in the header. Some, like LLP connection events, need - * more info. The union typdef c2wr_ae_t has all the possible AEs. - * - * hdr.context is the user_context from the rnic_open WR. NULL If this - * is not affiliated with an rnic - * - * hdr.id is the AE identifier (eg; CCAE_REMOTE_SHUTDOWN, - * CCAE_LLP_CLOSE_COMPLETE) - * - * resource_type is one of: C2_RES_IND_QP, C2_RES_IND_CQ, C2_RES_IND_SRQ - * - * user_context is the context passed down when the host created the resource. - */ -struct c2wr_ae_hdr { - struct c2wr_hdr hdr; - u64 user_context; /* user context for this res. */ - u32 resource_type; /* see enum c2_resource_indicator */ - u32 resource; /* handle for resource */ - u32 qp_state; /* current QP State */ -} __attribute__((packed)); - -/* - * After submitting the CCAE_ACTIVE_CONNECT_RESULTS message on the AEQ, - * the adapter moves the QP into RTS state - */ -struct c2wr_ae_active_connect_results { - struct c2wr_ae_hdr ae_hdr; - u32 laddr; - u32 raddr; - u16 lport; - u16 rport; - u32 private_data_length; - u8 private_data[0]; /* data is in-line in the msg. */ -} __attribute__((packed)); - -/* - * When connections are established by the stack (and the private data - * MPA frame is received), the adapter will generate an event to the host. - * The details of the connection, any private data, and the new connection - * request handle is passed up via the CCAE_CONNECTION_REQUEST msg on the - * AE queue: - */ -struct c2wr_ae_connection_request { - struct c2wr_ae_hdr ae_hdr; - u32 cr_handle; /* connreq handle (sock ptr) */ - u32 laddr; - u32 raddr; - u16 lport; - u16 rport; - u32 private_data_length; - u8 private_data[0]; /* data is in-line in the msg. */ -} __attribute__((packed)); - -union c2wr_ae { - struct c2wr_ae_hdr ae_generic; - struct c2wr_ae_active_connect_results ae_active_connect_results; - struct c2wr_ae_connection_request ae_connection_request; -} __attribute__((packed)); - -struct c2wr_init_req { - struct c2wr_hdr hdr; - u64 hint_count; - u64 q0_host_shared; - u64 q1_host_shared; - u64 q1_host_msg_pool; - u64 q2_host_shared; - u64 q2_host_msg_pool; -} __attribute__((packed)); - -struct c2wr_init_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)); - -union c2wr_init { - struct c2wr_init_req req; - struct c2wr_init_rep rep; -} __attribute__((packed)); - -/* - * For upgrading flash. - */ - -struct c2wr_flash_init_req { - struct c2wr_hdr hdr; - u32 rnic_handle; -} __attribute__((packed)); - -struct c2wr_flash_init_rep { - struct c2wr_hdr hdr; - u32 adapter_flash_buf_offset; - u32 adapter_flash_len; -} __attribute__((packed)); - -union c2wr_flash_init { - struct c2wr_flash_init_req req; - struct c2wr_flash_init_rep rep; -} __attribute__((packed)); - -struct c2wr_flash_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 len; -} __attribute__((packed)); - -struct c2wr_flash_rep { - struct c2wr_hdr hdr; - u32 status; -} __attribute__((packed)); - -union c2wr_flash { - struct c2wr_flash_req req; - struct c2wr_flash_rep rep; -} __attribute__((packed)); - -struct c2wr_buf_alloc_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 size; -} __attribute__((packed)); - -struct c2wr_buf_alloc_rep { - struct c2wr_hdr hdr; - u32 offset; /* 0 if mem not available */ - u32 size; /* 0 if mem not available */ -} __attribute__((packed)); - -union c2wr_buf_alloc { - struct c2wr_buf_alloc_req req; - struct c2wr_buf_alloc_rep rep; -} __attribute__((packed)); - -struct c2wr_buf_free_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 offset; /* Must match value from alloc */ - u32 size; /* Must match value from alloc */ -} __attribute__((packed)); - -struct c2wr_buf_free_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)); - -union c2wr_buf_free { - struct c2wr_buf_free_req req; - struct c2wr_ce rep; -} __attribute__((packed)); - -struct c2wr_flash_write_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 offset; - u32 size; - u32 type; - u32 flags; -} __attribute__((packed)); - -struct c2wr_flash_write_rep { - struct c2wr_hdr hdr; - u32 status; -} __attribute__((packed)); - -union c2wr_flash_write { - struct c2wr_flash_write_req req; - struct c2wr_flash_write_rep rep; -} __attribute__((packed)); - -/* - * Messages for LLP connection setup. - */ - -/* - * Listen Request. This allocates a listening endpoint to allow passive - * connection setup. Newly established LLP connections are passed up - * via an AE. See c2wr_ae_connection_request_t - */ -struct c2wr_ep_listen_create_req { - struct c2wr_hdr hdr; - u64 user_context; /* returned in AEs. */ - u32 rnic_handle; - u32 local_addr; /* local addr, or 0 */ - u16 local_port; /* 0 means "pick one" */ - u16 pad; - u32 backlog; /* tradional tcp listen bl */ -} __attribute__((packed)); - -struct c2wr_ep_listen_create_rep { - struct c2wr_hdr hdr; - u32 ep_handle; /* handle to new listening ep */ - u16 local_port; /* resulting port... */ - u16 pad; -} __attribute__((packed)); - -union c2wr_ep_listen_create { - struct c2wr_ep_listen_create_req req; - struct c2wr_ep_listen_create_rep rep; -} __attribute__((packed)); - -struct c2wr_ep_listen_destroy_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 ep_handle; -} __attribute__((packed)); - -struct c2wr_ep_listen_destroy_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)); - -union c2wr_ep_listen_destroy { - struct c2wr_ep_listen_destroy_req req; - struct c2wr_ep_listen_destroy_rep rep; -} __attribute__((packed)); - -struct c2wr_ep_query_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 ep_handle; -} __attribute__((packed)); - -struct c2wr_ep_query_rep { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 local_addr; - u32 remote_addr; - u16 local_port; - u16 remote_port; -} __attribute__((packed)); - -union c2wr_ep_query { - struct c2wr_ep_query_req req; - struct c2wr_ep_query_rep rep; -} __attribute__((packed)); - - -/* - * The host passes this down to indicate acceptance of a pending iWARP - * connection. The cr_handle was obtained from the CONNECTION_REQUEST - * AE passed up by the adapter. See c2wr_ae_connection_request_t. - */ -struct c2wr_cr_accept_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 qp_handle; /* QP to bind to this LLP conn */ - u32 ep_handle; /* LLP handle to accept */ - u32 private_data_length; - u8 private_data[0]; /* data in-line in msg. */ -} __attribute__((packed)); - -/* - * adapter sends reply when private data is successfully submitted to - * the LLP. - */ -struct c2wr_cr_accept_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)); - -union c2wr_cr_accept { - struct c2wr_cr_accept_req req; - struct c2wr_cr_accept_rep rep; -} __attribute__((packed)); - -/* - * The host sends this down if a given iWARP connection request was - * rejected by the consumer. The cr_handle was obtained from a - * previous c2wr_ae_connection_request_t AE sent by the adapter. - */ -struct c2wr_cr_reject_req { - struct c2wr_hdr hdr; - u32 rnic_handle; - u32 ep_handle; /* LLP handle to reject */ -} __attribute__((packed)); - -/* - * Dunno if this is needed, but we'll add it for now. The adapter will - * send the reject_reply after the LLP endpoint has been destroyed. - */ -struct c2wr_cr_reject_rep { - struct c2wr_hdr hdr; -} __attribute__((packed)); - -union c2wr_cr_reject { - struct c2wr_cr_reject_req req; - struct c2wr_cr_reject_rep rep; -} __attribute__((packed)); - -/* - * console command. Used to implement a debug console over the verbs - * request and reply queues. - */ - -/* - * Console request message. It contains: - * - message hdr with id = CCWR_CONSOLE - * - the physaddr/len of host memory to be used for the reply. - * - the command string. eg: "netstat -s" or "zoneinfo" - */ -struct c2wr_console_req { - struct c2wr_hdr hdr; /* id = CCWR_CONSOLE */ - u64 reply_buf; /* pinned host buf for reply */ - u32 reply_buf_len; /* length of reply buffer */ - u8 command[0]; /* NUL terminated ascii string */ - /* containing the command req */ -} __attribute__((packed)); - -/* - * flags used in the console reply. - */ -enum c2_console_flags { - CONS_REPLY_TRUNCATED = 0x00000001 /* reply was truncated */ -} __attribute__((packed)); - -/* - * Console reply message. - * hdr.result contains the c2_status_t error if the reply was _not_ generated, - * or C2_OK if the reply was generated. - */ -struct c2wr_console_rep { - struct c2wr_hdr hdr; /* id = CCWR_CONSOLE */ - u32 flags; -} __attribute__((packed)); - -union c2wr_console { - struct c2wr_console_req req; - struct c2wr_console_rep rep; -} __attribute__((packed)); - - -/* - * Giant union with all WRs. Makes life easier... - */ -union c2wr { - struct c2wr_hdr hdr; - struct c2wr_user_hdr user_hdr; - union c2wr_rnic_open rnic_open; - union c2wr_rnic_query rnic_query; - union c2wr_rnic_getconfig rnic_getconfig; - union c2wr_rnic_setconfig rnic_setconfig; - union c2wr_rnic_close rnic_close; - union c2wr_cq_create cq_create; - union c2wr_cq_modify cq_modify; - union c2wr_cq_destroy cq_destroy; - union c2wr_pd_alloc pd_alloc; - union c2wr_pd_dealloc pd_dealloc; - union c2wr_srq_create srq_create; - union c2wr_srq_destroy srq_destroy; - union c2wr_qp_create qp_create; - union c2wr_qp_query qp_query; - union c2wr_qp_modify qp_modify; - union c2wr_qp_destroy qp_destroy; - struct c2wr_qp_connect qp_connect; - union c2wr_nsmr_stag_alloc nsmr_stag_alloc; - union c2wr_nsmr_register nsmr_register; - union c2wr_nsmr_pbl nsmr_pbl; - union c2wr_mr_query mr_query; - union c2wr_mw_query mw_query; - union c2wr_stag_dealloc stag_dealloc; - union c2wr_sqwr sqwr; - struct c2wr_rqwr rqwr; - struct c2wr_ce ce; - union c2wr_ae ae; - union c2wr_init init; - union c2wr_ep_listen_create ep_listen_create; - union c2wr_ep_listen_destroy ep_listen_destroy; - union c2wr_cr_accept cr_accept; - union c2wr_cr_reject cr_reject; - union c2wr_console console; - union c2wr_flash_init flash_init; - union c2wr_flash flash; - union c2wr_buf_alloc buf_alloc; - union c2wr_buf_free buf_free; - union c2wr_flash_write flash_write; -} __attribute__((packed)); - - -/* - * Accessors for the wr fields that are packed together tightly to - * reduce the wr message size. The wr arguments are void* so that - * either a struct c2wr*, a struct c2wr_hdr*, or a pointer to any of the types - * in the struct c2wr union can be passed in. - */ -static __inline__ u8 c2_wr_get_id(void *wr) -{ - return ((struct c2wr_hdr *) wr)->id; -} -static __inline__ void c2_wr_set_id(void *wr, u8 id) -{ - ((struct c2wr_hdr *) wr)->id = id; -} -static __inline__ u8 c2_wr_get_result(void *wr) -{ - return ((struct c2wr_hdr *) wr)->result; -} -static __inline__ void c2_wr_set_result(void *wr, u8 result) -{ - ((struct c2wr_hdr *) wr)->result = result; -} -static __inline__ u8 c2_wr_get_flags(void *wr) -{ - return ((struct c2wr_hdr *) wr)->flags; -} -static __inline__ void c2_wr_set_flags(void *wr, u8 flags) -{ - ((struct c2wr_hdr *) wr)->flags = flags; -} -static __inline__ u8 c2_wr_get_sge_count(void *wr) -{ - return ((struct c2wr_hdr *) wr)->sge_count; -} -static __inline__ void c2_wr_set_sge_count(void *wr, u8 sge_count) -{ - ((struct c2wr_hdr *) wr)->sge_count = sge_count; -} -static __inline__ u32 c2_wr_get_wqe_count(void *wr) -{ - return ((struct c2wr_hdr *) wr)->wqe_count; -} -static __inline__ void c2_wr_set_wqe_count(void *wr, u32 wqe_count) -{ - ((struct c2wr_hdr *) wr)->wqe_count = wqe_count; -} - -#endif /* _C2_WR_H_ */ diff --git a/trunk/drivers/infiniband/hw/ehca/Kconfig b/trunk/drivers/infiniband/hw/ehca/Kconfig deleted file mode 100644 index 922389b64394..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -config INFINIBAND_EHCA - tristate "eHCA support" - depends on IBMEBUS && INFINIBAND - ---help--- - This driver supports the IBM pSeries eHCA InfiniBand adapter. - - To compile the driver as a module, choose M here. The module - will be called ib_ehca. - -config INFINIBAND_EHCA_SCALING - bool "Scaling support (EXPERIMENTAL)" - depends on IBMEBUS && INFINIBAND_EHCA && HOTPLUG_CPU && EXPERIMENTAL - ---help--- - eHCA scaling support schedules the CQ callbacks to different CPUs. - - To enable this feature choose Y here. diff --git a/trunk/drivers/infiniband/hw/ehca/Makefile b/trunk/drivers/infiniband/hw/ehca/Makefile deleted file mode 100644 index 74d284e46a40..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# Authors: Heiko J Schick -# Christoph Raisch -# Joachim Fenkes -# -# Copyright (c) 2005 IBM Corporation -# -# All rights reserved. -# -# This source code is distributed under a dual license of GPL v2.0 and OpenIB BSD. - -obj-$(CONFIG_INFINIBAND_EHCA) += ib_ehca.o - -ib_ehca-objs = ehca_main.o ehca_hca.o ehca_mcast.o ehca_pd.o ehca_av.o ehca_eq.o \ - ehca_cq.o ehca_qp.o ehca_sqp.o ehca_mrmw.o ehca_reqs.o ehca_irq.o \ - ehca_uverbs.o ipz_pt_fn.o hcp_if.o hcp_phyp.o - diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_av.c b/trunk/drivers/infiniband/hw/ehca/ehca_av.c deleted file mode 100644 index 3bac197f9014..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_av.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * adress vector functions - * - * Authors: Hoang-Nam Nguyen - * Khadija Souissi - * Reinhard Ernst - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#include - -#include "ehca_tools.h" -#include "ehca_iverbs.h" -#include "hcp_if.h" - -static struct kmem_cache *av_cache; - -struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) -{ - int ret; - struct ehca_av *av; - struct ehca_shca *shca = container_of(pd->device, struct ehca_shca, - ib_device); - - av = kmem_cache_alloc(av_cache, SLAB_KERNEL); - if (!av) { - ehca_err(pd->device, "Out of memory pd=%p ah_attr=%p", - pd, ah_attr); - return ERR_PTR(-ENOMEM); - } - - av->av.sl = ah_attr->sl; - av->av.dlid = ah_attr->dlid; - av->av.slid_path_bits = ah_attr->src_path_bits; - - if (ehca_static_rate < 0) { - int ah_mult = ib_rate_to_mult(ah_attr->static_rate); - int ehca_mult = - ib_rate_to_mult(shca->sport[ah_attr->port_num].rate ); - - if (ah_mult >= ehca_mult) - av->av.ipd = 0; - else - av->av.ipd = (ah_mult > 0) ? - ((ehca_mult - 1) / ah_mult) : 0; - } else - av->av.ipd = ehca_static_rate; - - av->av.lnh = ah_attr->ah_flags; - av->av.grh.word_0 = EHCA_BMASK_SET(GRH_IPVERSION_MASK, 6); - av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_TCLASS_MASK, - ah_attr->grh.traffic_class); - av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_FLOWLABEL_MASK, - ah_attr->grh.flow_label); - av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_HOPLIMIT_MASK, - ah_attr->grh.hop_limit); - av->av.grh.word_0 |= EHCA_BMASK_SET(GRH_NEXTHEADER_MASK, 0x1B); - /* set sgid in grh.word_1 */ - if (ah_attr->ah_flags & IB_AH_GRH) { - int rc; - struct ib_port_attr port_attr; - union ib_gid gid; - memset(&port_attr, 0, sizeof(port_attr)); - rc = ehca_query_port(pd->device, ah_attr->port_num, - &port_attr); - if (rc) { /* invalid port number */ - ret = -EINVAL; - ehca_err(pd->device, "Invalid port number " - "ehca_query_port() returned %x " - "pd=%p ah_attr=%p", rc, pd, ah_attr); - goto create_ah_exit1; - } - memset(&gid, 0, sizeof(gid)); - rc = ehca_query_gid(pd->device, - ah_attr->port_num, - ah_attr->grh.sgid_index, &gid); - if (rc) { - ret = -EINVAL; - ehca_err(pd->device, "Failed to retrieve sgid " - "ehca_query_gid() returned %x " - "pd=%p ah_attr=%p", rc, pd, ah_attr); - goto create_ah_exit1; - } - memcpy(&av->av.grh.word_1, &gid, sizeof(gid)); - } - /* for the time being we use a hard coded PMTU of 2048 Bytes */ - av->av.pmtu = 4; - - /* dgid comes in grh.word_3 */ - memcpy(&av->av.grh.word_3, &ah_attr->grh.dgid, - sizeof(ah_attr->grh.dgid)); - - return &av->ib_ah; - -create_ah_exit1: - kmem_cache_free(av_cache, av); - - return ERR_PTR(ret); -} - -int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) -{ - struct ehca_av *av; - struct ehca_ud_av new_ehca_av; - struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd); - u32 cur_pid = current->tgid; - - if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && - my_pd->ownpid != cur_pid) { - ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x", - cur_pid, my_pd->ownpid); - return -EINVAL; - } - - memset(&new_ehca_av, 0, sizeof(new_ehca_av)); - new_ehca_av.sl = ah_attr->sl; - new_ehca_av.dlid = ah_attr->dlid; - new_ehca_av.slid_path_bits = ah_attr->src_path_bits; - new_ehca_av.ipd = ah_attr->static_rate; - new_ehca_av.lnh = EHCA_BMASK_SET(GRH_FLAG_MASK, - (ah_attr->ah_flags & IB_AH_GRH) > 0); - new_ehca_av.grh.word_0 = EHCA_BMASK_SET(GRH_TCLASS_MASK, - ah_attr->grh.traffic_class); - new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_FLOWLABEL_MASK, - ah_attr->grh.flow_label); - new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_HOPLIMIT_MASK, - ah_attr->grh.hop_limit); - new_ehca_av.grh.word_0 |= EHCA_BMASK_SET(GRH_NEXTHEADER_MASK, 0x1b); - - /* set sgid in grh.word_1 */ - if (ah_attr->ah_flags & IB_AH_GRH) { - int rc; - struct ib_port_attr port_attr; - union ib_gid gid; - memset(&port_attr, 0, sizeof(port_attr)); - rc = ehca_query_port(ah->device, ah_attr->port_num, - &port_attr); - if (rc) { /* invalid port number */ - ehca_err(ah->device, "Invalid port number " - "ehca_query_port() returned %x " - "ah=%p ah_attr=%p port_num=%x", - rc, ah, ah_attr, ah_attr->port_num); - return -EINVAL; - } - memset(&gid, 0, sizeof(gid)); - rc = ehca_query_gid(ah->device, - ah_attr->port_num, - ah_attr->grh.sgid_index, &gid); - if (rc) { - ehca_err(ah->device, "Failed to retrieve sgid " - "ehca_query_gid() returned %x " - "ah=%p ah_attr=%p port_num=%x " - "sgid_index=%x", - rc, ah, ah_attr, ah_attr->port_num, - ah_attr->grh.sgid_index); - return -EINVAL; - } - memcpy(&new_ehca_av.grh.word_1, &gid, sizeof(gid)); - } - - new_ehca_av.pmtu = 4; /* see also comment in create_ah() */ - - memcpy(&new_ehca_av.grh.word_3, &ah_attr->grh.dgid, - sizeof(ah_attr->grh.dgid)); - - av = container_of(ah, struct ehca_av, ib_ah); - av->av = new_ehca_av; - - return 0; -} - -int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) -{ - struct ehca_av *av = container_of(ah, struct ehca_av, ib_ah); - struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd); - u32 cur_pid = current->tgid; - - if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && - my_pd->ownpid != cur_pid) { - ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x", - cur_pid, my_pd->ownpid); - return -EINVAL; - } - - memcpy(&ah_attr->grh.dgid, &av->av.grh.word_3, - sizeof(ah_attr->grh.dgid)); - ah_attr->sl = av->av.sl; - - ah_attr->dlid = av->av.dlid; - - ah_attr->src_path_bits = av->av.slid_path_bits; - ah_attr->static_rate = av->av.ipd; - ah_attr->ah_flags = EHCA_BMASK_GET(GRH_FLAG_MASK, av->av.lnh); - ah_attr->grh.traffic_class = EHCA_BMASK_GET(GRH_TCLASS_MASK, - av->av.grh.word_0); - ah_attr->grh.hop_limit = EHCA_BMASK_GET(GRH_HOPLIMIT_MASK, - av->av.grh.word_0); - ah_attr->grh.flow_label = EHCA_BMASK_GET(GRH_FLOWLABEL_MASK, - av->av.grh.word_0); - - return 0; -} - -int ehca_destroy_ah(struct ib_ah *ah) -{ - struct ehca_pd *my_pd = container_of(ah->pd, struct ehca_pd, ib_pd); - u32 cur_pid = current->tgid; - - if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && - my_pd->ownpid != cur_pid) { - ehca_err(ah->device, "Invalid caller pid=%x ownpid=%x", - cur_pid, my_pd->ownpid); - return -EINVAL; - } - - kmem_cache_free(av_cache, container_of(ah, struct ehca_av, ib_ah)); - - return 0; -} - -int ehca_init_av_cache(void) -{ - av_cache = kmem_cache_create("ehca_cache_av", - sizeof(struct ehca_av), 0, - SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (!av_cache) - return -ENOMEM; - return 0; -} - -void ehca_cleanup_av_cache(void) -{ - if (av_cache) - kmem_cache_destroy(av_cache); -} diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h b/trunk/drivers/infiniband/hw/ehca/ehca_classes.h deleted file mode 100644 index 1c722032319c..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_classes.h +++ /dev/null @@ -1,346 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Struct definition for eHCA internal structures - * - * Authors: Heiko J Schick - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __EHCA_CLASSES_H__ -#define __EHCA_CLASSES_H__ - -#include "ehca_classes.h" -#include "ipz_pt_fn.h" - -struct ehca_module; -struct ehca_qp; -struct ehca_cq; -struct ehca_eq; -struct ehca_mr; -struct ehca_mw; -struct ehca_pd; -struct ehca_av; - -#ifdef CONFIG_PPC64 -#include "ehca_classes_pSeries.h" -#endif - -#include -#include - -#include "ehca_irq.h" - -struct ehca_eq { - u32 length; - struct ipz_queue ipz_queue; - struct ipz_eq_handle ipz_eq_handle; - struct work_struct work; - struct h_galpas galpas; - int is_initialized; - struct ehca_pfeq pf; - spinlock_t spinlock; - struct tasklet_struct interrupt_task; - u32 ist; -}; - -struct ehca_sport { - struct ib_cq *ibcq_aqp1; - struct ib_qp *ibqp_aqp1; - enum ib_rate rate; - enum ib_port_state port_state; -}; - -struct ehca_shca { - struct ib_device ib_device; - struct ibmebus_dev *ibmebus_dev; - u8 num_ports; - int hw_level; - struct list_head shca_list; - struct ipz_adapter_handle ipz_hca_handle; - struct ehca_sport sport[2]; - struct ehca_eq eq; - struct ehca_eq neq; - struct ehca_mr *maxmr; - struct ehca_pd *pd; - struct h_galpas galpas; -}; - -struct ehca_pd { - struct ib_pd ib_pd; - struct ipz_pd fw_pd; - u32 ownpid; -}; - -struct ehca_qp { - struct ib_qp ib_qp; - u32 qp_type; - struct ipz_queue ipz_squeue; - struct ipz_queue ipz_rqueue; - struct h_galpas galpas; - u32 qkey; - u32 real_qp_num; - u32 token; - spinlock_t spinlock_s; - spinlock_t spinlock_r; - u32 sq_max_inline_data_size; - struct ipz_qp_handle ipz_qp_handle; - struct ehca_pfqp pf; - struct ib_qp_init_attr init_attr; - u64 uspace_squeue; - u64 uspace_rqueue; - u64 uspace_fwh; - struct ehca_cq *send_cq; - struct ehca_cq *recv_cq; - unsigned int sqerr_purgeflag; - struct hlist_node list_entries; -}; - -/* must be power of 2 */ -#define QP_HASHTAB_LEN 8 - -struct ehca_cq { - struct ib_cq ib_cq; - struct ipz_queue ipz_queue; - struct h_galpas galpas; - spinlock_t spinlock; - u32 cq_number; - u32 token; - u32 nr_of_entries; - struct ipz_cq_handle ipz_cq_handle; - struct ehca_pfcq pf; - spinlock_t cb_lock; - u64 uspace_queue; - u64 uspace_fwh; - struct hlist_head qp_hashtab[QP_HASHTAB_LEN]; - struct list_head entry; - u32 nr_callbacks; - spinlock_t task_lock; - u32 ownpid; -}; - -enum ehca_mr_flag { - EHCA_MR_FLAG_FMR = 0x80000000, /* FMR, created with ehca_alloc_fmr */ - EHCA_MR_FLAG_MAXMR = 0x40000000, /* max-MR */ -}; - -struct ehca_mr { - union { - struct ib_mr ib_mr; /* must always be first in ehca_mr */ - struct ib_fmr ib_fmr; /* must always be first in ehca_mr */ - } ib; - spinlock_t mrlock; - - enum ehca_mr_flag flags; - u32 num_pages; /* number of MR pages */ - u32 num_4k; /* number of 4k "page" portions to form MR */ - int acl; /* ACL (stored here for usage in reregister) */ - u64 *start; /* virtual start address (stored here for */ - /* usage in reregister) */ - u64 size; /* size (stored here for usage in reregister) */ - u32 fmr_page_size; /* page size for FMR */ - u32 fmr_max_pages; /* max pages for FMR */ - u32 fmr_max_maps; /* max outstanding maps for FMR */ - u32 fmr_map_cnt; /* map counter for FMR */ - /* fw specific data */ - struct ipz_mrmw_handle ipz_mr_handle; /* MR handle for h-calls */ - struct h_galpas galpas; - /* data for userspace bridge */ - u32 nr_of_pages; - void *pagearray; -}; - -struct ehca_mw { - struct ib_mw ib_mw; /* gen2 mw, must always be first in ehca_mw */ - spinlock_t mwlock; - - u8 never_bound; /* indication MW was never bound */ - struct ipz_mrmw_handle ipz_mw_handle; /* MW handle for h-calls */ - struct h_galpas galpas; -}; - -enum ehca_mr_pgi_type { - EHCA_MR_PGI_PHYS = 1, /* type of ehca_reg_phys_mr, - * ehca_rereg_phys_mr, - * ehca_reg_internal_maxmr */ - EHCA_MR_PGI_USER = 2, /* type of ehca_reg_user_mr */ - EHCA_MR_PGI_FMR = 3 /* type of ehca_map_phys_fmr */ -}; - -struct ehca_mr_pginfo { - enum ehca_mr_pgi_type type; - u64 num_pages; - u64 page_cnt; - u64 num_4k; /* number of 4k "page" portions */ - u64 page_4k_cnt; /* counter for 4k "page" portions */ - u64 next_4k; /* next 4k "page" portion in buffer/chunk/listelem */ - - /* type EHCA_MR_PGI_PHYS section */ - int num_phys_buf; - struct ib_phys_buf *phys_buf_array; - u64 next_buf; - - /* type EHCA_MR_PGI_USER section */ - struct ib_umem *region; - struct ib_umem_chunk *next_chunk; - u64 next_nmap; - - /* type EHCA_MR_PGI_FMR section */ - u64 *page_list; - u64 next_listelem; - /* next_4k also used within EHCA_MR_PGI_FMR */ -}; - -/* output parameters for MR/FMR hipz calls */ -struct ehca_mr_hipzout_parms { - struct ipz_mrmw_handle handle; - u32 lkey; - u32 rkey; - u64 len; - u64 vaddr; - u32 acl; -}; - -/* output parameters for MW hipz calls */ -struct ehca_mw_hipzout_parms { - struct ipz_mrmw_handle handle; - u32 rkey; -}; - -struct ehca_av { - struct ib_ah ib_ah; - struct ehca_ud_av av; -}; - -struct ehca_ucontext { - struct ib_ucontext ib_ucontext; -}; - -struct ehca_module *ehca_module_new(void); - -int ehca_module_delete(struct ehca_module *me); - -int ehca_eq_ctor(struct ehca_eq *eq); - -int ehca_eq_dtor(struct ehca_eq *eq); - -struct ehca_shca *ehca_shca_new(void); - -int ehca_shca_delete(struct ehca_shca *me); - -struct ehca_sport *ehca_sport_new(struct ehca_shca *anchor); - -int ehca_init_pd_cache(void); -void ehca_cleanup_pd_cache(void); -int ehca_init_cq_cache(void); -void ehca_cleanup_cq_cache(void); -int ehca_init_qp_cache(void); -void ehca_cleanup_qp_cache(void); -int ehca_init_av_cache(void); -void ehca_cleanup_av_cache(void); -int ehca_init_mrmw_cache(void); -void ehca_cleanup_mrmw_cache(void); - -extern spinlock_t ehca_qp_idr_lock; -extern spinlock_t ehca_cq_idr_lock; -extern struct idr ehca_qp_idr; -extern struct idr ehca_cq_idr; - -extern int ehca_static_rate; -extern int ehca_port_act_time; -extern int ehca_use_hp_mr; - -struct ipzu_queue_resp { - u64 queue; /* points to first queue entry */ - u32 qe_size; /* queue entry size */ - u32 act_nr_of_sg; - u32 queue_length; /* queue length allocated in bytes */ - u32 pagesize; - u32 toggle_state; - u32 dummy; /* padding for 8 byte alignment */ -}; - -struct ehca_create_cq_resp { - u32 cq_number; - u32 token; - struct ipzu_queue_resp ipz_queue; - struct h_galpas galpas; -}; - -struct ehca_create_qp_resp { - u32 qp_num; - u32 token; - u32 qp_type; - u32 qkey; - /* qp_num assigned by ehca: sqp0/1 may have got different numbers */ - u32 real_qp_num; - u32 dummy; /* padding for 8 byte alignment */ - struct ipzu_queue_resp ipz_squeue; - struct ipzu_queue_resp ipz_rqueue; - struct h_galpas galpas; -}; - -struct ehca_alloc_cq_parms { - u32 nr_cqe; - u32 act_nr_of_entries; - u32 act_pages; - struct ipz_eq_handle eq_handle; -}; - -struct ehca_alloc_qp_parms { - int servicetype; - int sigtype; - int daqp_ctrl; - int max_send_sge; - int max_recv_sge; - int ud_av_l_key_ctl; - - u16 act_nr_send_wqes; - u16 act_nr_recv_wqes; - u8 act_nr_recv_sges; - u8 act_nr_send_sges; - - u32 nr_rq_pages; - u32 nr_sq_pages; - - struct ipz_eq_handle ipz_eq_handle; - struct ipz_pd pd; -}; - -int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp); -int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int qp_num); -struct ehca_qp* ehca_cq_get_qp(struct ehca_cq *cq, int qp_num); - -#endif diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h b/trunk/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h deleted file mode 100644 index 5665f213b81a..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_classes_pSeries.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * pSeries interface definitions - * - * Authors: Waleri Fomin - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __EHCA_CLASSES_PSERIES_H__ -#define __EHCA_CLASSES_PSERIES_H__ - -#include "hcp_phyp.h" -#include "ipz_pt_fn.h" - - -struct ehca_pfqp { - struct ipz_qpt sqpt; - struct ipz_qpt rqpt; -}; - -struct ehca_pfcq { - struct ipz_qpt qpt; - u32 cqnr; -}; - -struct ehca_pfeq { - struct ipz_qpt qpt; - struct h_galpa galpa; - u32 eqnr; -}; - -struct ipz_adapter_handle { - u64 handle; -}; - -struct ipz_cq_handle { - u64 handle; -}; - -struct ipz_eq_handle { - u64 handle; -}; - -struct ipz_qp_handle { - u64 handle; -}; -struct ipz_mrmw_handle { - u64 handle; -}; - -struct ipz_pd { - u32 value; -}; - -struct hcp_modify_qp_control_block { - u32 qkey; /* 00 */ - u32 rdd; /* reliable datagram domain */ - u32 send_psn; /* 02 */ - u32 receive_psn; /* 03 */ - u32 prim_phys_port; /* 04 */ - u32 alt_phys_port; /* 05 */ - u32 prim_p_key_idx; /* 06 */ - u32 alt_p_key_idx; /* 07 */ - u32 rdma_atomic_ctrl; /* 08 */ - u32 qp_state; /* 09 */ - u32 reserved_10; /* 10 */ - u32 rdma_nr_atomic_resp_res; /* 11 */ - u32 path_migration_state; /* 12 */ - u32 rdma_atomic_outst_dest_qp; /* 13 */ - u32 dest_qp_nr; /* 14 */ - u32 min_rnr_nak_timer_field; /* 15 */ - u32 service_level; /* 16 */ - u32 send_grh_flag; /* 17 */ - u32 retry_count; /* 18 */ - u32 timeout; /* 19 */ - u32 path_mtu; /* 20 */ - u32 max_static_rate; /* 21 */ - u32 dlid; /* 22 */ - u32 rnr_retry_count; /* 23 */ - u32 source_path_bits; /* 24 */ - u32 traffic_class; /* 25 */ - u32 hop_limit; /* 26 */ - u32 source_gid_idx; /* 27 */ - u32 flow_label; /* 28 */ - u32 reserved_29; /* 29 */ - union { /* 30 */ - u64 dw[2]; - u8 byte[16]; - } dest_gid; - u32 service_level_al; /* 34 */ - u32 send_grh_flag_al; /* 35 */ - u32 retry_count_al; /* 36 */ - u32 timeout_al; /* 37 */ - u32 max_static_rate_al; /* 38 */ - u32 dlid_al; /* 39 */ - u32 rnr_retry_count_al; /* 40 */ - u32 source_path_bits_al; /* 41 */ - u32 traffic_class_al; /* 42 */ - u32 hop_limit_al; /* 43 */ - u32 source_gid_idx_al; /* 44 */ - u32 flow_label_al; /* 45 */ - u32 reserved_46; /* 46 */ - u32 reserved_47; /* 47 */ - union { /* 48 */ - u64 dw[2]; - u8 byte[16]; - } dest_gid_al; - u32 max_nr_outst_send_wr; /* 52 */ - u32 max_nr_outst_recv_wr; /* 53 */ - u32 disable_ete_credit_check; /* 54 */ - u32 qp_number; /* 55 */ - u64 send_queue_handle; /* 56 */ - u64 recv_queue_handle; /* 58 */ - u32 actual_nr_sges_in_sq_wqe; /* 60 */ - u32 actual_nr_sges_in_rq_wqe; /* 61 */ - u32 qp_enable; /* 62 */ - u32 curr_srq_limit; /* 63 */ - u64 qp_aff_asyn_ev_log_reg; /* 64 */ - u64 shared_rq_hndl; /* 66 */ - u64 trigg_doorbell_qp_hndl; /* 68 */ - u32 reserved_70_127[58]; /* 70 */ -}; - -#define MQPCB_MASK_QKEY EHCA_BMASK_IBM(0,0) -#define MQPCB_MASK_SEND_PSN EHCA_BMASK_IBM(2,2) -#define MQPCB_MASK_RECEIVE_PSN EHCA_BMASK_IBM(3,3) -#define MQPCB_MASK_PRIM_PHYS_PORT EHCA_BMASK_IBM(4,4) -#define MQPCB_PRIM_PHYS_PORT EHCA_BMASK_IBM(24,31) -#define MQPCB_MASK_ALT_PHYS_PORT EHCA_BMASK_IBM(5,5) -#define MQPCB_MASK_PRIM_P_KEY_IDX EHCA_BMASK_IBM(6,6) -#define MQPCB_PRIM_P_KEY_IDX EHCA_BMASK_IBM(24,31) -#define MQPCB_MASK_ALT_P_KEY_IDX EHCA_BMASK_IBM(7,7) -#define MQPCB_MASK_RDMA_ATOMIC_CTRL EHCA_BMASK_IBM(8,8) -#define MQPCB_MASK_QP_STATE EHCA_BMASK_IBM(9,9) -#define MQPCB_QP_STATE EHCA_BMASK_IBM(24,31) -#define MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES EHCA_BMASK_IBM(11,11) -#define MQPCB_MASK_PATH_MIGRATION_STATE EHCA_BMASK_IBM(12,12) -#define MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP EHCA_BMASK_IBM(13,13) -#define MQPCB_MASK_DEST_QP_NR EHCA_BMASK_IBM(14,14) -#define MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD EHCA_BMASK_IBM(15,15) -#define MQPCB_MASK_SERVICE_LEVEL EHCA_BMASK_IBM(16,16) -#define MQPCB_MASK_SEND_GRH_FLAG EHCA_BMASK_IBM(17,17) -#define MQPCB_MASK_RETRY_COUNT EHCA_BMASK_IBM(18,18) -#define MQPCB_MASK_TIMEOUT EHCA_BMASK_IBM(19,19) -#define MQPCB_MASK_PATH_MTU EHCA_BMASK_IBM(20,20) -#define MQPCB_PATH_MTU EHCA_BMASK_IBM(24,31) -#define MQPCB_MASK_MAX_STATIC_RATE EHCA_BMASK_IBM(21,21) -#define MQPCB_MAX_STATIC_RATE EHCA_BMASK_IBM(24,31) -#define MQPCB_MASK_DLID EHCA_BMASK_IBM(22,22) -#define MQPCB_DLID EHCA_BMASK_IBM(16,31) -#define MQPCB_MASK_RNR_RETRY_COUNT EHCA_BMASK_IBM(23,23) -#define MQPCB_RNR_RETRY_COUNT EHCA_BMASK_IBM(29,31) -#define MQPCB_MASK_SOURCE_PATH_BITS EHCA_BMASK_IBM(24,24) -#define MQPCB_SOURCE_PATH_BITS EHCA_BMASK_IBM(25,31) -#define MQPCB_MASK_TRAFFIC_CLASS EHCA_BMASK_IBM(25,25) -#define MQPCB_TRAFFIC_CLASS EHCA_BMASK_IBM(24,31) -#define MQPCB_MASK_HOP_LIMIT EHCA_BMASK_IBM(26,26) -#define MQPCB_HOP_LIMIT EHCA_BMASK_IBM(24,31) -#define MQPCB_MASK_SOURCE_GID_IDX EHCA_BMASK_IBM(27,27) -#define MQPCB_SOURCE_GID_IDX EHCA_BMASK_IBM(24,31) -#define MQPCB_MASK_FLOW_LABEL EHCA_BMASK_IBM(28,28) -#define MQPCB_FLOW_LABEL EHCA_BMASK_IBM(12,31) -#define MQPCB_MASK_DEST_GID EHCA_BMASK_IBM(30,30) -#define MQPCB_MASK_SERVICE_LEVEL_AL EHCA_BMASK_IBM(31,31) -#define MQPCB_SERVICE_LEVEL_AL EHCA_BMASK_IBM(28,31) -#define MQPCB_MASK_SEND_GRH_FLAG_AL EHCA_BMASK_IBM(32,32) -#define MQPCB_SEND_GRH_FLAG_AL EHCA_BMASK_IBM(31,31) -#define MQPCB_MASK_RETRY_COUNT_AL EHCA_BMASK_IBM(33,33) -#define MQPCB_RETRY_COUNT_AL EHCA_BMASK_IBM(29,31) -#define MQPCB_MASK_TIMEOUT_AL EHCA_BMASK_IBM(34,34) -#define MQPCB_TIMEOUT_AL EHCA_BMASK_IBM(27,31) -#define MQPCB_MASK_MAX_STATIC_RATE_AL EHCA_BMASK_IBM(35,35) -#define MQPCB_MAX_STATIC_RATE_AL EHCA_BMASK_IBM(24,31) -#define MQPCB_MASK_DLID_AL EHCA_BMASK_IBM(36,36) -#define MQPCB_DLID_AL EHCA_BMASK_IBM(16,31) -#define MQPCB_MASK_RNR_RETRY_COUNT_AL EHCA_BMASK_IBM(37,37) -#define MQPCB_RNR_RETRY_COUNT_AL EHCA_BMASK_IBM(29,31) -#define MQPCB_MASK_SOURCE_PATH_BITS_AL EHCA_BMASK_IBM(38,38) -#define MQPCB_SOURCE_PATH_BITS_AL EHCA_BMASK_IBM(25,31) -#define MQPCB_MASK_TRAFFIC_CLASS_AL EHCA_BMASK_IBM(39,39) -#define MQPCB_TRAFFIC_CLASS_AL EHCA_BMASK_IBM(24,31) -#define MQPCB_MASK_HOP_LIMIT_AL EHCA_BMASK_IBM(40,40) -#define MQPCB_HOP_LIMIT_AL EHCA_BMASK_IBM(24,31) -#define MQPCB_MASK_SOURCE_GID_IDX_AL EHCA_BMASK_IBM(41,41) -#define MQPCB_SOURCE_GID_IDX_AL EHCA_BMASK_IBM(24,31) -#define MQPCB_MASK_FLOW_LABEL_AL EHCA_BMASK_IBM(42,42) -#define MQPCB_FLOW_LABEL_AL EHCA_BMASK_IBM(12,31) -#define MQPCB_MASK_DEST_GID_AL EHCA_BMASK_IBM(44,44) -#define MQPCB_MASK_MAX_NR_OUTST_SEND_WR EHCA_BMASK_IBM(45,45) -#define MQPCB_MAX_NR_OUTST_SEND_WR EHCA_BMASK_IBM(16,31) -#define MQPCB_MASK_MAX_NR_OUTST_RECV_WR EHCA_BMASK_IBM(46,46) -#define MQPCB_MAX_NR_OUTST_RECV_WR EHCA_BMASK_IBM(16,31) -#define MQPCB_MASK_DISABLE_ETE_CREDIT_CHECK EHCA_BMASK_IBM(47,47) -#define MQPCB_DISABLE_ETE_CREDIT_CHECK EHCA_BMASK_IBM(31,31) -#define MQPCB_QP_NUMBER EHCA_BMASK_IBM(8,31) -#define MQPCB_MASK_QP_ENABLE EHCA_BMASK_IBM(48,48) -#define MQPCB_QP_ENABLE EHCA_BMASK_IBM(31,31) -#define MQPCB_MASK_CURR_SQR_LIMIT EHCA_BMASK_IBM(49,49) -#define MQPCB_CURR_SQR_LIMIT EHCA_BMASK_IBM(15,31) -#define MQPCB_MASK_QP_AFF_ASYN_EV_LOG_REG EHCA_BMASK_IBM(50,50) -#define MQPCB_MASK_SHARED_RQ_HNDL EHCA_BMASK_IBM(51,51) - -#endif /* __EHCA_CLASSES_PSERIES_H__ */ diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_cq.c b/trunk/drivers/infiniband/hw/ehca/ehca_cq.c deleted file mode 100644 index 458fe19648a1..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_cq.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Completion queue handling - * - * Authors: Waleri Fomin - * Khadija Souissi - * Reinhard Ernst - * Heiko J Schick - * Hoang-Nam Nguyen - * - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "ehca_iverbs.h" -#include "ehca_classes.h" -#include "ehca_irq.h" -#include "hcp_if.h" - -static struct kmem_cache *cq_cache; - -int ehca_cq_assign_qp(struct ehca_cq *cq, struct ehca_qp *qp) -{ - unsigned int qp_num = qp->real_qp_num; - unsigned int key = qp_num & (QP_HASHTAB_LEN-1); - unsigned long spl_flags; - - spin_lock_irqsave(&cq->spinlock, spl_flags); - hlist_add_head(&qp->list_entries, &cq->qp_hashtab[key]); - spin_unlock_irqrestore(&cq->spinlock, spl_flags); - - ehca_dbg(cq->ib_cq.device, "cq_num=%x real_qp_num=%x", - cq->cq_number, qp_num); - - return 0; -} - -int ehca_cq_unassign_qp(struct ehca_cq *cq, unsigned int real_qp_num) -{ - int ret = -EINVAL; - unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1); - struct hlist_node *iter; - struct ehca_qp *qp; - unsigned long spl_flags; - - spin_lock_irqsave(&cq->spinlock, spl_flags); - hlist_for_each(iter, &cq->qp_hashtab[key]) { - qp = hlist_entry(iter, struct ehca_qp, list_entries); - if (qp->real_qp_num == real_qp_num) { - hlist_del(iter); - ehca_dbg(cq->ib_cq.device, - "removed qp from cq .cq_num=%x real_qp_num=%x", - cq->cq_number, real_qp_num); - ret = 0; - break; - } - } - spin_unlock_irqrestore(&cq->spinlock, spl_flags); - if (ret) - ehca_err(cq->ib_cq.device, - "qp not found cq_num=%x real_qp_num=%x", - cq->cq_number, real_qp_num); - - return ret; -} - -struct ehca_qp* ehca_cq_get_qp(struct ehca_cq *cq, int real_qp_num) -{ - struct ehca_qp *ret = NULL; - unsigned int key = real_qp_num & (QP_HASHTAB_LEN-1); - struct hlist_node *iter; - struct ehca_qp *qp; - hlist_for_each(iter, &cq->qp_hashtab[key]) { - qp = hlist_entry(iter, struct ehca_qp, list_entries); - if (qp->real_qp_num == real_qp_num) { - ret = qp; - break; - } - } - return ret; -} - -struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, - struct ib_ucontext *context, - struct ib_udata *udata) -{ - static const u32 additional_cqe = 20; - struct ib_cq *cq; - struct ehca_cq *my_cq; - struct ehca_shca *shca = - container_of(device, struct ehca_shca, ib_device); - struct ipz_adapter_handle adapter_handle; - struct ehca_alloc_cq_parms param; /* h_call's out parameters */ - struct h_galpa gal; - void *vpage; - u32 counter; - u64 rpage, cqx_fec, h_ret; - int ipz_rc, ret, i; - unsigned long flags; - - if (cqe >= 0xFFFFFFFF - 64 - additional_cqe) - return ERR_PTR(-EINVAL); - - my_cq = kmem_cache_alloc(cq_cache, SLAB_KERNEL); - if (!my_cq) { - ehca_err(device, "Out of memory for ehca_cq struct device=%p", - device); - return ERR_PTR(-ENOMEM); - } - - memset(my_cq, 0, sizeof(struct ehca_cq)); - memset(¶m, 0, sizeof(struct ehca_alloc_cq_parms)); - - spin_lock_init(&my_cq->spinlock); - spin_lock_init(&my_cq->cb_lock); - spin_lock_init(&my_cq->task_lock); - my_cq->ownpid = current->tgid; - - cq = &my_cq->ib_cq; - - adapter_handle = shca->ipz_hca_handle; - param.eq_handle = shca->eq.ipz_eq_handle; - - do { - if (!idr_pre_get(&ehca_cq_idr, GFP_KERNEL)) { - cq = ERR_PTR(-ENOMEM); - ehca_err(device, "Can't reserve idr nr. device=%p", - device); - goto create_cq_exit1; - } - - spin_lock_irqsave(&ehca_cq_idr_lock, flags); - ret = idr_get_new(&ehca_cq_idr, my_cq, &my_cq->token); - spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); - - } while (ret == -EAGAIN); - - if (ret) { - cq = ERR_PTR(-ENOMEM); - ehca_err(device, "Can't allocate new idr entry. device=%p", - device); - goto create_cq_exit1; - } - - /* - * CQs maximum depth is 4GB-64, but we need additional 20 as buffer - * for receiving errors CQEs. - */ - param.nr_cqe = cqe + additional_cqe; - h_ret = hipz_h_alloc_resource_cq(adapter_handle, my_cq, ¶m); - - if (h_ret != H_SUCCESS) { - ehca_err(device, "hipz_h_alloc_resource_cq() failed " - "h_ret=%lx device=%p", h_ret, device); - cq = ERR_PTR(ehca2ib_return_code(h_ret)); - goto create_cq_exit2; - } - - ipz_rc = ipz_queue_ctor(&my_cq->ipz_queue, param.act_pages, - EHCA_PAGESIZE, sizeof(struct ehca_cqe), 0); - if (!ipz_rc) { - ehca_err(device, "ipz_queue_ctor() failed ipz_rc=%x device=%p", - ipz_rc, device); - cq = ERR_PTR(-EINVAL); - goto create_cq_exit3; - } - - for (counter = 0; counter < param.act_pages; counter++) { - vpage = ipz_qpageit_get_inc(&my_cq->ipz_queue); - if (!vpage) { - ehca_err(device, "ipz_qpageit_get_inc() " - "returns NULL device=%p", device); - cq = ERR_PTR(-EAGAIN); - goto create_cq_exit4; - } - rpage = virt_to_abs(vpage); - - h_ret = hipz_h_register_rpage_cq(adapter_handle, - my_cq->ipz_cq_handle, - &my_cq->pf, - 0, - 0, - rpage, - 1, - my_cq->galpas. - kernel); - - if (h_ret < H_SUCCESS) { - ehca_err(device, "hipz_h_register_rpage_cq() failed " - "ehca_cq=%p cq_num=%x h_ret=%lx counter=%i " - "act_pages=%i", my_cq, my_cq->cq_number, - h_ret, counter, param.act_pages); - cq = ERR_PTR(-EINVAL); - goto create_cq_exit4; - } - - if (counter == (param.act_pages - 1)) { - vpage = ipz_qpageit_get_inc(&my_cq->ipz_queue); - if ((h_ret != H_SUCCESS) || vpage) { - ehca_err(device, "Registration of pages not " - "complete ehca_cq=%p cq_num=%x " - "h_ret=%lx", my_cq, my_cq->cq_number, - h_ret); - cq = ERR_PTR(-EAGAIN); - goto create_cq_exit4; - } - } else { - if (h_ret != H_PAGE_REGISTERED) { - ehca_err(device, "Registration of page failed " - "ehca_cq=%p cq_num=%x h_ret=%lx" - "counter=%i act_pages=%i", - my_cq, my_cq->cq_number, - h_ret, counter, param.act_pages); - cq = ERR_PTR(-ENOMEM); - goto create_cq_exit4; - } - } - } - - ipz_qeit_reset(&my_cq->ipz_queue); - - gal = my_cq->galpas.kernel; - cqx_fec = hipz_galpa_load(gal, CQTEMM_OFFSET(cqx_fec)); - ehca_dbg(device, "ehca_cq=%p cq_num=%x CQX_FEC=%lx", - my_cq, my_cq->cq_number, cqx_fec); - - my_cq->ib_cq.cqe = my_cq->nr_of_entries = - param.act_nr_of_entries - additional_cqe; - my_cq->cq_number = (my_cq->ipz_cq_handle.handle) & 0xffff; - - for (i = 0; i < QP_HASHTAB_LEN; i++) - INIT_HLIST_HEAD(&my_cq->qp_hashtab[i]); - - if (context) { - struct ipz_queue *ipz_queue = &my_cq->ipz_queue; - struct ehca_create_cq_resp resp; - struct vm_area_struct *vma; - memset(&resp, 0, sizeof(resp)); - resp.cq_number = my_cq->cq_number; - resp.token = my_cq->token; - resp.ipz_queue.qe_size = ipz_queue->qe_size; - resp.ipz_queue.act_nr_of_sg = ipz_queue->act_nr_of_sg; - resp.ipz_queue.queue_length = ipz_queue->queue_length; - resp.ipz_queue.pagesize = ipz_queue->pagesize; - resp.ipz_queue.toggle_state = ipz_queue->toggle_state; - ret = ehca_mmap_nopage(((u64)(my_cq->token) << 32) | 0x12000000, - ipz_queue->queue_length, - (void**)&resp.ipz_queue.queue, - &vma); - if (ret) { - ehca_err(device, "Could not mmap queue pages"); - cq = ERR_PTR(ret); - goto create_cq_exit4; - } - my_cq->uspace_queue = resp.ipz_queue.queue; - resp.galpas = my_cq->galpas; - ret = ehca_mmap_register(my_cq->galpas.user.fw_handle, - (void**)&resp.galpas.kernel.fw_handle, - &vma); - if (ret) { - ehca_err(device, "Could not mmap fw_handle"); - cq = ERR_PTR(ret); - goto create_cq_exit5; - } - my_cq->uspace_fwh = (u64)resp.galpas.kernel.fw_handle; - if (ib_copy_to_udata(udata, &resp, sizeof(resp))) { - ehca_err(device, "Copy to udata failed."); - goto create_cq_exit6; - } - } - - return cq; - -create_cq_exit6: - ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE); - -create_cq_exit5: - ehca_munmap(my_cq->uspace_queue, my_cq->ipz_queue.queue_length); - -create_cq_exit4: - ipz_queue_dtor(&my_cq->ipz_queue); - -create_cq_exit3: - h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 1); - if (h_ret != H_SUCCESS) - ehca_err(device, "hipz_h_destroy_cq() failed ehca_cq=%p " - "cq_num=%x h_ret=%lx", my_cq, my_cq->cq_number, h_ret); - -create_cq_exit2: - spin_lock_irqsave(&ehca_cq_idr_lock, flags); - idr_remove(&ehca_cq_idr, my_cq->token); - spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); - -create_cq_exit1: - kmem_cache_free(cq_cache, my_cq); - - return cq; -} - -int ehca_destroy_cq(struct ib_cq *cq) -{ - u64 h_ret; - int ret; - struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); - int cq_num = my_cq->cq_number; - struct ib_device *device = cq->device; - struct ehca_shca *shca = container_of(device, struct ehca_shca, - ib_device); - struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle; - u32 cur_pid = current->tgid; - unsigned long flags; - - spin_lock_irqsave(&ehca_cq_idr_lock, flags); - while (my_cq->nr_callbacks) - yield(); - - idr_remove(&ehca_cq_idr, my_cq->token); - spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); - - if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) { - ehca_err(device, "Invalid caller pid=%x ownpid=%x", - cur_pid, my_cq->ownpid); - return -EINVAL; - } - - /* un-mmap if vma alloc */ - if (my_cq->uspace_queue ) { - ret = ehca_munmap(my_cq->uspace_queue, - my_cq->ipz_queue.queue_length); - if (ret) - ehca_err(device, "Could not munmap queue ehca_cq=%p " - "cq_num=%x", my_cq, cq_num); - ret = ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE); - if (ret) - ehca_err(device, "Could not munmap fwh ehca_cq=%p " - "cq_num=%x", my_cq, cq_num); - } - - h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0); - if (h_ret == H_R_STATE) { - /* cq in err: read err data and destroy it forcibly */ - ehca_dbg(device, "ehca_cq=%p cq_num=%x ressource=%lx in err " - "state. Try to delete it forcibly.", - my_cq, cq_num, my_cq->ipz_cq_handle.handle); - ehca_error_data(shca, my_cq, my_cq->ipz_cq_handle.handle); - h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 1); - if (h_ret == H_SUCCESS) - ehca_dbg(device, "cq_num=%x deleted successfully.", - cq_num); - } - if (h_ret != H_SUCCESS) { - ehca_err(device, "hipz_h_destroy_cq() failed h_ret=%lx " - "ehca_cq=%p cq_num=%x", h_ret, my_cq, cq_num); - return ehca2ib_return_code(h_ret); - } - ipz_queue_dtor(&my_cq->ipz_queue); - kmem_cache_free(cq_cache, my_cq); - - return 0; -} - -int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata) -{ - struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); - u32 cur_pid = current->tgid; - - if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) { - ehca_err(cq->device, "Invalid caller pid=%x ownpid=%x", - cur_pid, my_cq->ownpid); - return -EINVAL; - } - - /* TODO: proper resize needs to be done */ - ehca_err(cq->device, "not implemented yet"); - - return -EFAULT; -} - -int ehca_init_cq_cache(void) -{ - cq_cache = kmem_cache_create("ehca_cache_cq", - sizeof(struct ehca_cq), 0, - SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (!cq_cache) - return -ENOMEM; - return 0; -} - -void ehca_cleanup_cq_cache(void) -{ - if (cq_cache) - kmem_cache_destroy(cq_cache); -} diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_eq.c b/trunk/drivers/infiniband/hw/ehca/ehca_eq.c deleted file mode 100644 index 5281dec66f12..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_eq.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Event queue handling - * - * Authors: Waleri Fomin - * Khadija Souissi - * Reinhard Ernst - * Heiko J Schick - * Hoang-Nam Nguyen - * - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ehca_classes.h" -#include "ehca_irq.h" -#include "ehca_iverbs.h" -#include "ehca_qes.h" -#include "hcp_if.h" -#include "ipz_pt_fn.h" - -int ehca_create_eq(struct ehca_shca *shca, - struct ehca_eq *eq, - const enum ehca_eq_type type, const u32 length) -{ - u64 ret; - u32 nr_pages; - u32 i; - void *vpage; - struct ib_device *ib_dev = &shca->ib_device; - - spin_lock_init(&eq->spinlock); - eq->is_initialized = 0; - - if (type != EHCA_EQ && type != EHCA_NEQ) { - ehca_err(ib_dev, "Invalid EQ type %x. eq=%p", type, eq); - return -EINVAL; - } - if (!length) { - ehca_err(ib_dev, "EQ length must not be zero. eq=%p", eq); - return -EINVAL; - } - - ret = hipz_h_alloc_resource_eq(shca->ipz_hca_handle, - &eq->pf, - type, - length, - &eq->ipz_eq_handle, - &eq->length, - &nr_pages, &eq->ist); - - if (ret != H_SUCCESS) { - ehca_err(ib_dev, "Can't allocate EQ/NEQ. eq=%p", eq); - return -EINVAL; - } - - ret = ipz_queue_ctor(&eq->ipz_queue, nr_pages, - EHCA_PAGESIZE, sizeof(struct ehca_eqe), 0); - if (!ret) { - ehca_err(ib_dev, "Can't allocate EQ pages eq=%p", eq); - goto create_eq_exit1; - } - - for (i = 0; i < nr_pages; i++) { - u64 rpage; - - if (!(vpage = ipz_qpageit_get_inc(&eq->ipz_queue))) { - ret = H_RESOURCE; - goto create_eq_exit2; - } - - rpage = virt_to_abs(vpage); - ret = hipz_h_register_rpage_eq(shca->ipz_hca_handle, - eq->ipz_eq_handle, - &eq->pf, - 0, 0, rpage, 1); - - if (i == (nr_pages - 1)) { - /* last page */ - vpage = ipz_qpageit_get_inc(&eq->ipz_queue); - if (ret != H_SUCCESS || vpage) - goto create_eq_exit2; - } else { - if (ret != H_PAGE_REGISTERED || !vpage) - goto create_eq_exit2; - } - } - - ipz_qeit_reset(&eq->ipz_queue); - - /* register interrupt handlers and initialize work queues */ - if (type == EHCA_EQ) { - ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_eq, - SA_INTERRUPT, "ehca_eq", - (void *)shca); - if (ret < 0) - ehca_err(ib_dev, "Can't map interrupt handler."); - - tasklet_init(&eq->interrupt_task, ehca_tasklet_eq, (long)shca); - } else if (type == EHCA_NEQ) { - ret = ibmebus_request_irq(NULL, eq->ist, ehca_interrupt_neq, - SA_INTERRUPT, "ehca_neq", - (void *)shca); - if (ret < 0) - ehca_err(ib_dev, "Can't map interrupt handler."); - - tasklet_init(&eq->interrupt_task, ehca_tasklet_neq, (long)shca); - } - - eq->is_initialized = 1; - - return 0; - -create_eq_exit2: - ipz_queue_dtor(&eq->ipz_queue); - -create_eq_exit1: - hipz_h_destroy_eq(shca->ipz_hca_handle, eq); - - return -EINVAL; -} - -void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq) -{ - unsigned long flags; - void *eqe; - - spin_lock_irqsave(&eq->spinlock, flags); - eqe = ipz_eqit_eq_get_inc_valid(&eq->ipz_queue); - spin_unlock_irqrestore(&eq->spinlock, flags); - - return eqe; -} - -int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq) -{ - unsigned long flags; - u64 h_ret; - - spin_lock_irqsave(&eq->spinlock, flags); - ibmebus_free_irq(NULL, eq->ist, (void *)shca); - - h_ret = hipz_h_destroy_eq(shca->ipz_hca_handle, eq); - - spin_unlock_irqrestore(&eq->spinlock, flags); - - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't free EQ resources."); - return -EINVAL; - } - ipz_queue_dtor(&eq->ipz_queue); - - return 0; -} diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_hca.c b/trunk/drivers/infiniband/hw/ehca/ehca_hca.c deleted file mode 100644 index 5eae6ac48425..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_hca.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * HCA query functions - * - * Authors: Heiko J Schick - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ehca_tools.h" -#include "hcp_if.h" - -int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) -{ - int ret = 0; - struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, - ib_device); - struct hipz_query_hca *rblock; - - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); - if (!rblock) { - ehca_err(&shca->ib_device, "Can't allocate rblock memory."); - return -ENOMEM; - } - - if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't query device properties"); - ret = -EINVAL; - goto query_device1; - } - - memset(props, 0, sizeof(struct ib_device_attr)); - props->fw_ver = rblock->hw_ver; - props->max_mr_size = rblock->max_mr_size; - props->vendor_id = rblock->vendor_id >> 8; - props->vendor_part_id = rblock->vendor_part_id >> 16; - props->hw_ver = rblock->hw_ver; - props->max_qp = min_t(int, rblock->max_qp, INT_MAX); - props->max_qp_wr = min_t(int, rblock->max_wqes_wq, INT_MAX); - props->max_sge = min_t(int, rblock->max_sge, INT_MAX); - props->max_sge_rd = min_t(int, rblock->max_sge_rd, INT_MAX); - props->max_cq = min_t(int, rblock->max_cq, INT_MAX); - props->max_cqe = min_t(int, rblock->max_cqe, INT_MAX); - props->max_mr = min_t(int, rblock->max_mr, INT_MAX); - props->max_mw = min_t(int, rblock->max_mw, INT_MAX); - props->max_pd = min_t(int, rblock->max_pd, INT_MAX); - props->max_ah = min_t(int, rblock->max_ah, INT_MAX); - props->max_fmr = min_t(int, rblock->max_mr, INT_MAX); - props->max_srq = 0; - props->max_srq_wr = 0; - props->max_srq_sge = 0; - props->max_pkeys = 16; - props->local_ca_ack_delay - = rblock->local_ca_ack_delay; - props->max_raw_ipv6_qp - = min_t(int, rblock->max_raw_ipv6_qp, INT_MAX); - props->max_raw_ethy_qp - = min_t(int, rblock->max_raw_ethy_qp, INT_MAX); - props->max_mcast_grp - = min_t(int, rblock->max_mcast_grp, INT_MAX); - props->max_mcast_qp_attach - = min_t(int, rblock->max_mcast_qp_attach, INT_MAX); - props->max_total_mcast_qp_attach - = min_t(int, rblock->max_total_mcast_qp_attach, INT_MAX); - -query_device1: - kfree(rblock); - - return ret; -} - -int ehca_query_port(struct ib_device *ibdev, - u8 port, struct ib_port_attr *props) -{ - int ret = 0; - struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, - ib_device); - struct hipz_query_port *rblock; - - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); - if (!rblock) { - ehca_err(&shca->ib_device, "Can't allocate rblock memory."); - return -ENOMEM; - } - - if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't query port properties"); - ret = -EINVAL; - goto query_port1; - } - - memset(props, 0, sizeof(struct ib_port_attr)); - props->state = rblock->state; - - switch (rblock->max_mtu) { - case 0x1: - props->active_mtu = props->max_mtu = IB_MTU_256; - break; - case 0x2: - props->active_mtu = props->max_mtu = IB_MTU_512; - break; - case 0x3: - props->active_mtu = props->max_mtu = IB_MTU_1024; - break; - case 0x4: - props->active_mtu = props->max_mtu = IB_MTU_2048; - break; - case 0x5: - props->active_mtu = props->max_mtu = IB_MTU_4096; - break; - default: - ehca_err(&shca->ib_device, "Unknown MTU size: %x.", - rblock->max_mtu); - break; - } - - props->gid_tbl_len = rblock->gid_tbl_len; - props->max_msg_sz = rblock->max_msg_sz; - props->bad_pkey_cntr = rblock->bad_pkey_cntr; - props->qkey_viol_cntr = rblock->qkey_viol_cntr; - props->pkey_tbl_len = rblock->pkey_tbl_len; - props->lid = rblock->lid; - props->sm_lid = rblock->sm_lid; - props->lmc = rblock->lmc; - props->sm_sl = rblock->sm_sl; - props->subnet_timeout = rblock->subnet_timeout; - props->init_type_reply = rblock->init_type_reply; - - props->active_width = IB_WIDTH_12X; - props->active_speed = 0x1; - -query_port1: - kfree(rblock); - - return ret; -} - -int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) -{ - int ret = 0; - struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, ib_device); - struct hipz_query_port *rblock; - - if (index > 16) { - ehca_err(&shca->ib_device, "Invalid index: %x.", index); - return -EINVAL; - } - - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); - if (!rblock) { - ehca_err(&shca->ib_device, "Can't allocate rblock memory."); - return -ENOMEM; - } - - if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't query port properties"); - ret = -EINVAL; - goto query_pkey1; - } - - memcpy(pkey, &rblock->pkey_entries + index, sizeof(u16)); - -query_pkey1: - kfree(rblock); - - return ret; -} - -int ehca_query_gid(struct ib_device *ibdev, u8 port, - int index, union ib_gid *gid) -{ - int ret = 0; - struct ehca_shca *shca = container_of(ibdev, struct ehca_shca, - ib_device); - struct hipz_query_port *rblock; - - if (index > 255) { - ehca_err(&shca->ib_device, "Invalid index: %x.", index); - return -EINVAL; - } - - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); - if (!rblock) { - ehca_err(&shca->ib_device, "Can't allocate rblock memory."); - return -ENOMEM; - } - - if (hipz_h_query_port(shca->ipz_hca_handle, port, rblock) != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't query port properties"); - ret = -EINVAL; - goto query_gid1; - } - - memcpy(&gid->raw[0], &rblock->gid_prefix, sizeof(u64)); - memcpy(&gid->raw[8], &rblock->guid_entries[index], sizeof(u64)); - -query_gid1: - kfree(rblock); - - return ret; -} - -int ehca_modify_port(struct ib_device *ibdev, - u8 port, int port_modify_mask, - struct ib_port_modify *props) -{ - /* Not implemented yet */ - return -EFAULT; -} diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_irq.c b/trunk/drivers/infiniband/hw/ehca/ehca_irq.c deleted file mode 100644 index 2a65b5be1979..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_irq.c +++ /dev/null @@ -1,762 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Functions for EQs, NEQs and interrupts - * - * Authors: Heiko J Schick - * Khadija Souissi - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ehca_classes.h" -#include "ehca_irq.h" -#include "ehca_iverbs.h" -#include "ehca_tools.h" -#include "hcp_if.h" -#include "hipz_fns.h" - -#define EQE_COMPLETION_EVENT EHCA_BMASK_IBM(1,1) -#define EQE_CQ_QP_NUMBER EHCA_BMASK_IBM(8,31) -#define EQE_EE_IDENTIFIER EHCA_BMASK_IBM(2,7) -#define EQE_CQ_NUMBER EHCA_BMASK_IBM(8,31) -#define EQE_QP_NUMBER EHCA_BMASK_IBM(8,31) -#define EQE_QP_TOKEN EHCA_BMASK_IBM(32,63) -#define EQE_CQ_TOKEN EHCA_BMASK_IBM(32,63) - -#define NEQE_COMPLETION_EVENT EHCA_BMASK_IBM(1,1) -#define NEQE_EVENT_CODE EHCA_BMASK_IBM(2,7) -#define NEQE_PORT_NUMBER EHCA_BMASK_IBM(8,15) -#define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16,16) - -#define ERROR_DATA_LENGTH EHCA_BMASK_IBM(52,63) -#define ERROR_DATA_TYPE EHCA_BMASK_IBM(0,7) - -#ifdef CONFIG_INFINIBAND_EHCA_SCALING - -static void queue_comp_task(struct ehca_cq *__cq); - -static struct ehca_comp_pool* pool; -static struct notifier_block comp_pool_callback_nb; - -#endif - -static inline void comp_event_callback(struct ehca_cq *cq) -{ - if (!cq->ib_cq.comp_handler) - return; - - spin_lock(&cq->cb_lock); - cq->ib_cq.comp_handler(&cq->ib_cq, cq->ib_cq.cq_context); - spin_unlock(&cq->cb_lock); - - return; -} - -static void print_error_data(struct ehca_shca * shca, void* data, - u64* rblock, int length) -{ - u64 type = EHCA_BMASK_GET(ERROR_DATA_TYPE, rblock[2]); - u64 resource = rblock[1]; - - switch (type) { - case 0x1: /* Queue Pair */ - { - struct ehca_qp *qp = (struct ehca_qp*)data; - - /* only print error data if AER is set */ - if (rblock[6] == 0) - return; - - ehca_err(&shca->ib_device, - "QP 0x%x (resource=%lx) has errors.", - qp->ib_qp.qp_num, resource); - break; - } - case 0x4: /* Completion Queue */ - { - struct ehca_cq *cq = (struct ehca_cq*)data; - - ehca_err(&shca->ib_device, - "CQ 0x%x (resource=%lx) has errors.", - cq->cq_number, resource); - break; - } - default: - ehca_err(&shca->ib_device, - "Unknown errror type: %lx on %s.", - type, shca->ib_device.name); - break; - } - - ehca_err(&shca->ib_device, "Error data is available: %lx.", resource); - ehca_err(&shca->ib_device, "EHCA ----- error data begin " - "---------------------------------------------------"); - ehca_dmp(rblock, length, "resource=%lx", resource); - ehca_err(&shca->ib_device, "EHCA ----- error data end " - "----------------------------------------------------"); - - return; -} - -int ehca_error_data(struct ehca_shca *shca, void *data, - u64 resource) -{ - - unsigned long ret; - u64 *rblock; - unsigned long block_count; - - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); - if (!rblock) { - ehca_err(&shca->ib_device, "Cannot allocate rblock memory."); - ret = -ENOMEM; - goto error_data1; - } - - ret = hipz_h_error_data(shca->ipz_hca_handle, - resource, - rblock, - &block_count); - - if (ret == H_R_STATE) { - ehca_err(&shca->ib_device, - "No error data is available: %lx.", resource); - } - else if (ret == H_SUCCESS) { - int length; - - length = EHCA_BMASK_GET(ERROR_DATA_LENGTH, rblock[0]); - - if (length > PAGE_SIZE) - length = PAGE_SIZE; - - print_error_data(shca, data, rblock, length); - } - else { - ehca_err(&shca->ib_device, - "Error data could not be fetched: %lx", resource); - } - - kfree(rblock); - -error_data1: - return ret; - -} - -static void qp_event_callback(struct ehca_shca *shca, - u64 eqe, - enum ib_event_type event_type) -{ - struct ib_event event; - struct ehca_qp *qp; - unsigned long flags; - u32 token = EHCA_BMASK_GET(EQE_QP_TOKEN, eqe); - - spin_lock_irqsave(&ehca_qp_idr_lock, flags); - qp = idr_find(&ehca_qp_idr, token); - spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); - - - if (!qp) - return; - - ehca_error_data(shca, qp, qp->ipz_qp_handle.handle); - - if (!qp->ib_qp.event_handler) - return; - - event.device = &shca->ib_device; - event.event = event_type; - event.element.qp = &qp->ib_qp; - - qp->ib_qp.event_handler(&event, qp->ib_qp.qp_context); - - return; -} - -static void cq_event_callback(struct ehca_shca *shca, - u64 eqe) -{ - struct ehca_cq *cq; - unsigned long flags; - u32 token = EHCA_BMASK_GET(EQE_CQ_TOKEN, eqe); - - spin_lock_irqsave(&ehca_cq_idr_lock, flags); - cq = idr_find(&ehca_cq_idr, token); - spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); - - if (!cq) - return; - - ehca_error_data(shca, cq, cq->ipz_cq_handle.handle); - - return; -} - -static void parse_identifier(struct ehca_shca *shca, u64 eqe) -{ - u8 identifier = EHCA_BMASK_GET(EQE_EE_IDENTIFIER, eqe); - - switch (identifier) { - case 0x02: /* path migrated */ - qp_event_callback(shca, eqe, IB_EVENT_PATH_MIG); - break; - case 0x03: /* communication established */ - qp_event_callback(shca, eqe, IB_EVENT_COMM_EST); - break; - case 0x04: /* send queue drained */ - qp_event_callback(shca, eqe, IB_EVENT_SQ_DRAINED); - break; - case 0x05: /* QP error */ - case 0x06: /* QP error */ - qp_event_callback(shca, eqe, IB_EVENT_QP_FATAL); - break; - case 0x07: /* CQ error */ - case 0x08: /* CQ error */ - cq_event_callback(shca, eqe); - break; - case 0x09: /* MRMWPTE error */ - ehca_err(&shca->ib_device, "MRMWPTE error."); - break; - case 0x0A: /* port event */ - ehca_err(&shca->ib_device, "Port event."); - break; - case 0x0B: /* MR access error */ - ehca_err(&shca->ib_device, "MR access error."); - break; - case 0x0C: /* EQ error */ - ehca_err(&shca->ib_device, "EQ error."); - break; - case 0x0D: /* P/Q_Key mismatch */ - ehca_err(&shca->ib_device, "P/Q_Key mismatch."); - break; - case 0x10: /* sampling complete */ - ehca_err(&shca->ib_device, "Sampling complete."); - break; - case 0x11: /* unaffiliated access error */ - ehca_err(&shca->ib_device, "Unaffiliated access error."); - break; - case 0x12: /* path migrating error */ - ehca_err(&shca->ib_device, "Path migration error."); - break; - case 0x13: /* interface trace stopped */ - ehca_err(&shca->ib_device, "Interface trace stopped."); - break; - case 0x14: /* first error capture info available */ - default: - ehca_err(&shca->ib_device, "Unknown identifier: %x on %s.", - identifier, shca->ib_device.name); - break; - } - - return; -} - -static void parse_ec(struct ehca_shca *shca, u64 eqe) -{ - struct ib_event event; - u8 ec = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe); - u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe); - - switch (ec) { - case 0x30: /* port availability change */ - if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) { - ehca_info(&shca->ib_device, - "port %x is active.", port); - event.device = &shca->ib_device; - event.event = IB_EVENT_PORT_ACTIVE; - event.element.port_num = port; - shca->sport[port - 1].port_state = IB_PORT_ACTIVE; - ib_dispatch_event(&event); - } else { - ehca_info(&shca->ib_device, - "port %x is inactive.", port); - event.device = &shca->ib_device; - event.event = IB_EVENT_PORT_ERR; - event.element.port_num = port; - shca->sport[port - 1].port_state = IB_PORT_DOWN; - ib_dispatch_event(&event); - } - break; - case 0x31: - /* port configuration change - * disruptive change is caused by - * LID, PKEY or SM change - */ - ehca_warn(&shca->ib_device, - "disruptive port %x configuration change", port); - - ehca_info(&shca->ib_device, - "port %x is inactive.", port); - event.device = &shca->ib_device; - event.event = IB_EVENT_PORT_ERR; - event.element.port_num = port; - shca->sport[port - 1].port_state = IB_PORT_DOWN; - ib_dispatch_event(&event); - - ehca_info(&shca->ib_device, - "port %x is active.", port); - event.device = &shca->ib_device; - event.event = IB_EVENT_PORT_ACTIVE; - event.element.port_num = port; - shca->sport[port - 1].port_state = IB_PORT_ACTIVE; - ib_dispatch_event(&event); - break; - case 0x32: /* adapter malfunction */ - ehca_err(&shca->ib_device, "Adapter malfunction."); - break; - case 0x33: /* trace stopped */ - ehca_err(&shca->ib_device, "Traced stopped."); - break; - default: - ehca_err(&shca->ib_device, "Unknown event code: %x on %s.", - ec, shca->ib_device.name); - break; - } - - return; -} - -static inline void reset_eq_pending(struct ehca_cq *cq) -{ - u64 CQx_EP; - struct h_galpa gal = cq->galpas.kernel; - - hipz_galpa_store_cq(gal, cqx_ep, 0x0); - CQx_EP = hipz_galpa_load(gal, CQTEMM_OFFSET(cqx_ep)); - - return; -} - -irqreturn_t ehca_interrupt_neq(int irq, void *dev_id, struct pt_regs *regs) -{ - struct ehca_shca *shca = (struct ehca_shca*)dev_id; - - tasklet_hi_schedule(&shca->neq.interrupt_task); - - return IRQ_HANDLED; -} - -void ehca_tasklet_neq(unsigned long data) -{ - struct ehca_shca *shca = (struct ehca_shca*)data; - struct ehca_eqe *eqe; - u64 ret; - - eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->neq); - - while (eqe) { - if (!EHCA_BMASK_GET(NEQE_COMPLETION_EVENT, eqe->entry)) - parse_ec(shca, eqe->entry); - - eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->neq); - } - - ret = hipz_h_reset_event(shca->ipz_hca_handle, - shca->neq.ipz_eq_handle, 0xFFFFFFFFFFFFFFFFL); - - if (ret != H_SUCCESS) - ehca_err(&shca->ib_device, "Can't clear notification events."); - - return; -} - -irqreturn_t ehca_interrupt_eq(int irq, void *dev_id, struct pt_regs *regs) -{ - struct ehca_shca *shca = (struct ehca_shca*)dev_id; - - tasklet_hi_schedule(&shca->eq.interrupt_task); - - return IRQ_HANDLED; -} - -void ehca_tasklet_eq(unsigned long data) -{ - struct ehca_shca *shca = (struct ehca_shca*)data; - struct ehca_eqe *eqe; - int int_state; - int query_cnt = 0; - - do { - eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq); - - if ((shca->hw_level >= 2) && eqe) - int_state = 1; - else - int_state = 0; - - while ((int_state == 1) || eqe) { - while (eqe) { - u64 eqe_value = eqe->entry; - - ehca_dbg(&shca->ib_device, - "eqe_value=%lx", eqe_value); - - /* TODO: better structure */ - if (EHCA_BMASK_GET(EQE_COMPLETION_EVENT, - eqe_value)) { - unsigned long flags; - u32 token; - struct ehca_cq *cq; - - ehca_dbg(&shca->ib_device, - "... completion event"); - token = - EHCA_BMASK_GET(EQE_CQ_TOKEN, - eqe_value); - spin_lock_irqsave(&ehca_cq_idr_lock, - flags); - cq = idr_find(&ehca_cq_idr, token); - - if (cq == NULL) { - spin_unlock(&ehca_cq_idr_lock); - break; - } - - reset_eq_pending(cq); -#ifdef CONFIG_INFINIBAND_EHCA_SCALING - queue_comp_task(cq); - spin_unlock_irqrestore(&ehca_cq_idr_lock, - flags); -#else - spin_unlock_irqrestore(&ehca_cq_idr_lock, - flags); - comp_event_callback(cq); -#endif - } else { - ehca_dbg(&shca->ib_device, - "... non completion event"); - parse_identifier(shca, eqe_value); - } - eqe = - (struct ehca_eqe *)ehca_poll_eq(shca, - &shca->eq); - } - - if (shca->hw_level >= 2) { - int_state = - hipz_h_query_int_state(shca->ipz_hca_handle, - shca->eq.ist); - query_cnt++; - iosync(); - if (query_cnt >= 100) { - query_cnt = 0; - int_state = 0; - } - } - eqe = (struct ehca_eqe *)ehca_poll_eq(shca, &shca->eq); - - } - } while (int_state != 0); - - return; -} - -#ifdef CONFIG_INFINIBAND_EHCA_SCALING - -static inline int find_next_online_cpu(struct ehca_comp_pool* pool) -{ - unsigned long flags_last_cpu; - - if (ehca_debug_level) - ehca_dmp(&cpu_online_map, sizeof(cpumask_t), ""); - - spin_lock_irqsave(&pool->last_cpu_lock, flags_last_cpu); - pool->last_cpu = next_cpu(pool->last_cpu, cpu_online_map); - if (pool->last_cpu == NR_CPUS) - pool->last_cpu = first_cpu(cpu_online_map); - spin_unlock_irqrestore(&pool->last_cpu_lock, flags_last_cpu); - - return pool->last_cpu; -} - -static void __queue_comp_task(struct ehca_cq *__cq, - struct ehca_cpu_comp_task *cct) -{ - unsigned long flags_cct; - unsigned long flags_cq; - - spin_lock_irqsave(&cct->task_lock, flags_cct); - spin_lock_irqsave(&__cq->task_lock, flags_cq); - - if (__cq->nr_callbacks == 0) { - __cq->nr_callbacks++; - list_add_tail(&__cq->entry, &cct->cq_list); - cct->cq_jobs++; - wake_up(&cct->wait_queue); - } - else - __cq->nr_callbacks++; - - spin_unlock_irqrestore(&__cq->task_lock, flags_cq); - spin_unlock_irqrestore(&cct->task_lock, flags_cct); -} - -static void queue_comp_task(struct ehca_cq *__cq) -{ - int cpu; - int cpu_id; - struct ehca_cpu_comp_task *cct; - - cpu = get_cpu(); - cpu_id = find_next_online_cpu(pool); - - BUG_ON(!cpu_online(cpu_id)); - - cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id); - - if (cct->cq_jobs > 0) { - cpu_id = find_next_online_cpu(pool); - cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu_id); - } - - __queue_comp_task(__cq, cct); - - put_cpu(); - - return; -} - -static void run_comp_task(struct ehca_cpu_comp_task* cct) -{ - struct ehca_cq *cq; - unsigned long flags_cct; - unsigned long flags_cq; - - spin_lock_irqsave(&cct->task_lock, flags_cct); - - while (!list_empty(&cct->cq_list)) { - cq = list_entry(cct->cq_list.next, struct ehca_cq, entry); - spin_unlock_irqrestore(&cct->task_lock, flags_cct); - comp_event_callback(cq); - spin_lock_irqsave(&cct->task_lock, flags_cct); - - spin_lock_irqsave(&cq->task_lock, flags_cq); - cq->nr_callbacks--; - if (cq->nr_callbacks == 0) { - list_del_init(cct->cq_list.next); - cct->cq_jobs--; - } - spin_unlock_irqrestore(&cq->task_lock, flags_cq); - - } - - spin_unlock_irqrestore(&cct->task_lock, flags_cct); - - return; -} - -static int comp_task(void *__cct) -{ - struct ehca_cpu_comp_task* cct = __cct; - DECLARE_WAITQUEUE(wait, current); - - set_current_state(TASK_INTERRUPTIBLE); - while(!kthread_should_stop()) { - add_wait_queue(&cct->wait_queue, &wait); - - if (list_empty(&cct->cq_list)) - schedule(); - else - __set_current_state(TASK_RUNNING); - - remove_wait_queue(&cct->wait_queue, &wait); - - if (!list_empty(&cct->cq_list)) - run_comp_task(__cct); - - set_current_state(TASK_INTERRUPTIBLE); - } - __set_current_state(TASK_RUNNING); - - return 0; -} - -static struct task_struct *create_comp_task(struct ehca_comp_pool *pool, - int cpu) -{ - struct ehca_cpu_comp_task *cct; - - cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); - spin_lock_init(&cct->task_lock); - INIT_LIST_HEAD(&cct->cq_list); - init_waitqueue_head(&cct->wait_queue); - cct->task = kthread_create(comp_task, cct, "ehca_comp/%d", cpu); - - return cct->task; -} - -static void destroy_comp_task(struct ehca_comp_pool *pool, - int cpu) -{ - struct ehca_cpu_comp_task *cct; - struct task_struct *task; - unsigned long flags_cct; - - cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); - - spin_lock_irqsave(&cct->task_lock, flags_cct); - - task = cct->task; - cct->task = NULL; - cct->cq_jobs = 0; - - spin_unlock_irqrestore(&cct->task_lock, flags_cct); - - if (task) - kthread_stop(task); - - return; -} - -static void take_over_work(struct ehca_comp_pool *pool, - int cpu) -{ - struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); - LIST_HEAD(list); - struct ehca_cq *cq; - unsigned long flags_cct; - - spin_lock_irqsave(&cct->task_lock, flags_cct); - - list_splice_init(&cct->cq_list, &list); - - while(!list_empty(&list)) { - cq = list_entry(cct->cq_list.next, struct ehca_cq, entry); - - list_del(&cq->entry); - __queue_comp_task(cq, per_cpu_ptr(pool->cpu_comp_tasks, - smp_processor_id())); - } - - spin_unlock_irqrestore(&cct->task_lock, flags_cct); - -} - -static int comp_pool_callback(struct notifier_block *nfb, - unsigned long action, - void *hcpu) -{ - unsigned int cpu = (unsigned long)hcpu; - struct ehca_cpu_comp_task *cct; - - switch (action) { - case CPU_UP_PREPARE: - ehca_gen_dbg("CPU: %x (CPU_PREPARE)", cpu); - if(!create_comp_task(pool, cpu)) { - ehca_gen_err("Can't create comp_task for cpu: %x", cpu); - return NOTIFY_BAD; - } - break; - case CPU_UP_CANCELED: - ehca_gen_dbg("CPU: %x (CPU_CANCELED)", cpu); - cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); - kthread_bind(cct->task, any_online_cpu(cpu_online_map)); - destroy_comp_task(pool, cpu); - break; - case CPU_ONLINE: - ehca_gen_dbg("CPU: %x (CPU_ONLINE)", cpu); - cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); - kthread_bind(cct->task, cpu); - wake_up_process(cct->task); - break; - case CPU_DOWN_PREPARE: - ehca_gen_dbg("CPU: %x (CPU_DOWN_PREPARE)", cpu); - break; - case CPU_DOWN_FAILED: - ehca_gen_dbg("CPU: %x (CPU_DOWN_FAILED)", cpu); - break; - case CPU_DEAD: - ehca_gen_dbg("CPU: %x (CPU_DEAD)", cpu); - destroy_comp_task(pool, cpu); - take_over_work(pool, cpu); - break; - } - - return NOTIFY_OK; -} - -#endif - -int ehca_create_comp_pool(void) -{ -#ifdef CONFIG_INFINIBAND_EHCA_SCALING - int cpu; - struct task_struct *task; - - pool = kzalloc(sizeof(struct ehca_comp_pool), GFP_KERNEL); - if (pool == NULL) - return -ENOMEM; - - spin_lock_init(&pool->last_cpu_lock); - pool->last_cpu = any_online_cpu(cpu_online_map); - - pool->cpu_comp_tasks = alloc_percpu(struct ehca_cpu_comp_task); - if (pool->cpu_comp_tasks == NULL) { - kfree(pool); - return -EINVAL; - } - - for_each_online_cpu(cpu) { - task = create_comp_task(pool, cpu); - if (task) { - kthread_bind(task, cpu); - wake_up_process(task); - } - } - - comp_pool_callback_nb.notifier_call = comp_pool_callback; - comp_pool_callback_nb.priority =0; - register_cpu_notifier(&comp_pool_callback_nb); -#endif - - return 0; -} - -void ehca_destroy_comp_pool(void) -{ -#ifdef CONFIG_INFINIBAND_EHCA_SCALING - int i; - - unregister_cpu_notifier(&comp_pool_callback_nb); - - for (i = 0; i < NR_CPUS; i++) { - if (cpu_online(i)) - destroy_comp_task(pool, i); - } -#endif - - return; -} diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_irq.h b/trunk/drivers/infiniband/hw/ehca/ehca_irq.h deleted file mode 100644 index 85bf1fe16fe4..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_irq.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Function definitions and structs for EQs, NEQs and interrupts - * - * Authors: Heiko J Schick - * Khadija Souissi - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __EHCA_IRQ_H -#define __EHCA_IRQ_H - - -struct ehca_shca; - -#include -#include -#include - -int ehca_error_data(struct ehca_shca *shca, void *data, u64 resource); - -irqreturn_t ehca_interrupt_neq(int irq, void *dev_id, struct pt_regs *regs); -void ehca_tasklet_neq(unsigned long data); - -irqreturn_t ehca_interrupt_eq(int irq, void *dev_id, struct pt_regs *regs); -void ehca_tasklet_eq(unsigned long data); - -struct ehca_cpu_comp_task { - wait_queue_head_t wait_queue; - struct list_head cq_list; - struct task_struct *task; - spinlock_t task_lock; - int cq_jobs; -}; - -struct ehca_comp_pool { - struct ehca_cpu_comp_task *cpu_comp_tasks; - int last_cpu; - spinlock_t last_cpu_lock; -}; - -int ehca_create_comp_pool(void); -void ehca_destroy_comp_pool(void); - -#endif diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h b/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h deleted file mode 100644 index 319c39d47f3a..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_iverbs.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Function definitions for internal functions - * - * Authors: Heiko J Schick - * Dietmar Decker - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __EHCA_IVERBS_H__ -#define __EHCA_IVERBS_H__ - -#include "ehca_classes.h" - -int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props); - -int ehca_query_port(struct ib_device *ibdev, u8 port, - struct ib_port_attr *props); - -int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 * pkey); - -int ehca_query_gid(struct ib_device *ibdev, u8 port, int index, - union ib_gid *gid); - -int ehca_modify_port(struct ib_device *ibdev, u8 port, int port_modify_mask, - struct ib_port_modify *props); - -struct ib_pd *ehca_alloc_pd(struct ib_device *device, - struct ib_ucontext *context, - struct ib_udata *udata); - -int ehca_dealloc_pd(struct ib_pd *pd); - -struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr); - -int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr); - -int ehca_query_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr); - -int ehca_destroy_ah(struct ib_ah *ah); - -struct ib_mr *ehca_get_dma_mr(struct ib_pd *pd, int mr_access_flags); - -struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd, - struct ib_phys_buf *phys_buf_array, - int num_phys_buf, - int mr_access_flags, u64 *iova_start); - -struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, - struct ib_umem *region, - int mr_access_flags, struct ib_udata *udata); - -int ehca_rereg_phys_mr(struct ib_mr *mr, - int mr_rereg_mask, - struct ib_pd *pd, - struct ib_phys_buf *phys_buf_array, - int num_phys_buf, int mr_access_flags, u64 *iova_start); - -int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr); - -int ehca_dereg_mr(struct ib_mr *mr); - -struct ib_mw *ehca_alloc_mw(struct ib_pd *pd); - -int ehca_bind_mw(struct ib_qp *qp, struct ib_mw *mw, - struct ib_mw_bind *mw_bind); - -int ehca_dealloc_mw(struct ib_mw *mw); - -struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd, - int mr_access_flags, - struct ib_fmr_attr *fmr_attr); - -int ehca_map_phys_fmr(struct ib_fmr *fmr, - u64 *page_list, int list_len, u64 iova); - -int ehca_unmap_fmr(struct list_head *fmr_list); - -int ehca_dealloc_fmr(struct ib_fmr *fmr); - -enum ehca_eq_type { - EHCA_EQ = 0, /* Event Queue */ - EHCA_NEQ /* Notification Event Queue */ -}; - -int ehca_create_eq(struct ehca_shca *shca, struct ehca_eq *eq, - enum ehca_eq_type type, const u32 length); - -int ehca_destroy_eq(struct ehca_shca *shca, struct ehca_eq *eq); - -void *ehca_poll_eq(struct ehca_shca *shca, struct ehca_eq *eq); - - -struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, - struct ib_ucontext *context, - struct ib_udata *udata); - -int ehca_destroy_cq(struct ib_cq *cq); - -int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata); - -int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc); - -int ehca_peek_cq(struct ib_cq *cq, int wc_cnt); - -int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify cq_notify); - -struct ib_qp *ehca_create_qp(struct ib_pd *pd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata); - -int ehca_destroy_qp(struct ib_qp *qp); - -int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, - struct ib_udata *udata); - -int ehca_query_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr, - int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr); - -int ehca_post_send(struct ib_qp *qp, struct ib_send_wr *send_wr, - struct ib_send_wr **bad_send_wr); - -int ehca_post_recv(struct ib_qp *qp, struct ib_recv_wr *recv_wr, - struct ib_recv_wr **bad_recv_wr); - -u64 ehca_define_sqp(struct ehca_shca *shca, struct ehca_qp *ibqp, - struct ib_qp_init_attr *qp_init_attr); - -int ehca_attach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid); - -int ehca_detach_mcast(struct ib_qp *qp, union ib_gid *gid, u16 lid); - -struct ib_ucontext *ehca_alloc_ucontext(struct ib_device *device, - struct ib_udata *udata); - -int ehca_dealloc_ucontext(struct ib_ucontext *context); - -int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); - -void ehca_poll_eqs(unsigned long data); - -int ehca_mmap_nopage(u64 foffset,u64 length,void **mapped, - struct vm_area_struct **vma); - -int ehca_mmap_register(u64 physical,void **mapped, - struct vm_area_struct **vma); - -int ehca_munmap(unsigned long addr, size_t len); - -#endif diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_main.c b/trunk/drivers/infiniband/hw/ehca/ehca_main.c deleted file mode 100644 index 2380994418a5..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_main.c +++ /dev/null @@ -1,818 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * module start stop, hca detection - * - * Authors: Heiko J Schick - * Hoang-Nam Nguyen - * Joachim Fenkes - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ehca_classes.h" -#include "ehca_iverbs.h" -#include "ehca_mrmw.h" -#include "ehca_tools.h" -#include "hcp_if.h" - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_AUTHOR("Christoph Raisch "); -MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); -MODULE_VERSION("SVNEHCA_0016"); - -int ehca_open_aqp1 = 0; -int ehca_debug_level = 0; -int ehca_hw_level = 0; -int ehca_nr_ports = 2; -int ehca_use_hp_mr = 0; -int ehca_port_act_time = 30; -int ehca_poll_all_eqs = 1; -int ehca_static_rate = -1; - -module_param_named(open_aqp1, ehca_open_aqp1, int, 0); -module_param_named(debug_level, ehca_debug_level, int, 0); -module_param_named(hw_level, ehca_hw_level, int, 0); -module_param_named(nr_ports, ehca_nr_ports, int, 0); -module_param_named(use_hp_mr, ehca_use_hp_mr, int, 0); -module_param_named(port_act_time, ehca_port_act_time, int, 0); -module_param_named(poll_all_eqs, ehca_poll_all_eqs, int, 0); -module_param_named(static_rate, ehca_static_rate, int, 0); - -MODULE_PARM_DESC(open_aqp1, - "AQP1 on startup (0: no (default), 1: yes)"); -MODULE_PARM_DESC(debug_level, - "debug level" - " (0: no debug traces (default), 1: with debug traces)"); -MODULE_PARM_DESC(hw_level, - "hardware level" - " (0: autosensing (default), 1: v. 0.20, 2: v. 0.21)"); -MODULE_PARM_DESC(nr_ports, - "number of connected ports (default: 2)"); -MODULE_PARM_DESC(use_hp_mr, - "high performance MRs (0: no (default), 1: yes)"); -MODULE_PARM_DESC(port_act_time, - "time to wait for port activation (default: 30 sec)"); -MODULE_PARM_DESC(poll_all_eqs, - "polls all event queues periodically" - " (0: no, 1: yes (default))"); -MODULE_PARM_DESC(static_rate, - "set permanent static rate (default: disabled)"); - -spinlock_t ehca_qp_idr_lock; -spinlock_t ehca_cq_idr_lock; -DEFINE_IDR(ehca_qp_idr); -DEFINE_IDR(ehca_cq_idr); - -static struct list_head shca_list; /* list of all registered ehcas */ -static spinlock_t shca_list_lock; - -static struct timer_list poll_eqs_timer; - -static int ehca_create_slab_caches(void) -{ - int ret; - - ret = ehca_init_pd_cache(); - if (ret) { - ehca_gen_err("Cannot create PD SLAB cache."); - return ret; - } - - ret = ehca_init_cq_cache(); - if (ret) { - ehca_gen_err("Cannot create CQ SLAB cache."); - goto create_slab_caches2; - } - - ret = ehca_init_qp_cache(); - if (ret) { - ehca_gen_err("Cannot create QP SLAB cache."); - goto create_slab_caches3; - } - - ret = ehca_init_av_cache(); - if (ret) { - ehca_gen_err("Cannot create AV SLAB cache."); - goto create_slab_caches4; - } - - ret = ehca_init_mrmw_cache(); - if (ret) { - ehca_gen_err("Cannot create MR&MW SLAB cache."); - goto create_slab_caches5; - } - - return 0; - -create_slab_caches5: - ehca_cleanup_av_cache(); - -create_slab_caches4: - ehca_cleanup_qp_cache(); - -create_slab_caches3: - ehca_cleanup_cq_cache(); - -create_slab_caches2: - ehca_cleanup_pd_cache(); - - return ret; -} - -static void ehca_destroy_slab_caches(void) -{ - ehca_cleanup_mrmw_cache(); - ehca_cleanup_av_cache(); - ehca_cleanup_qp_cache(); - ehca_cleanup_cq_cache(); - ehca_cleanup_pd_cache(); -} - -#define EHCA_HCAAVER EHCA_BMASK_IBM(32,39) -#define EHCA_REVID EHCA_BMASK_IBM(40,63) - -int ehca_sense_attributes(struct ehca_shca *shca) -{ - int ret = 0; - u64 h_ret; - struct hipz_query_hca *rblock; - - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); - if (!rblock) { - ehca_gen_err("Cannot allocate rblock memory."); - return -ENOMEM; - } - - h_ret = hipz_h_query_hca(shca->ipz_hca_handle, rblock); - if (h_ret != H_SUCCESS) { - ehca_gen_err("Cannot query device properties. h_ret=%lx", - h_ret); - ret = -EPERM; - goto num_ports1; - } - - if (ehca_nr_ports == 1) - shca->num_ports = 1; - else - shca->num_ports = (u8)rblock->num_ports; - - ehca_gen_dbg(" ... found %x ports", rblock->num_ports); - - if (ehca_hw_level == 0) { - u32 hcaaver; - u32 revid; - - hcaaver = EHCA_BMASK_GET(EHCA_HCAAVER, rblock->hw_ver); - revid = EHCA_BMASK_GET(EHCA_REVID, rblock->hw_ver); - - ehca_gen_dbg(" ... hardware version=%x:%x", hcaaver, revid); - - if ((hcaaver == 1) && (revid == 0)) - shca->hw_level = 0; - else if ((hcaaver == 1) && (revid == 1)) - shca->hw_level = 1; - else if ((hcaaver == 1) && (revid == 2)) - shca->hw_level = 2; - } - ehca_gen_dbg(" ... hardware level=%x", shca->hw_level); - - shca->sport[0].rate = IB_RATE_30_GBPS; - shca->sport[1].rate = IB_RATE_30_GBPS; - -num_ports1: - kfree(rblock); - return ret; -} - -static int init_node_guid(struct ehca_shca *shca) -{ - int ret = 0; - struct hipz_query_hca *rblock; - - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); - if (!rblock) { - ehca_err(&shca->ib_device, "Can't allocate rblock memory."); - return -ENOMEM; - } - - if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { - ehca_err(&shca->ib_device, "Can't query device properties"); - ret = -EINVAL; - goto init_node_guid1; - } - - memcpy(&shca->ib_device.node_guid, &rblock->node_guid, sizeof(u64)); - -init_node_guid1: - kfree(rblock); - return ret; -} - -int ehca_register_device(struct ehca_shca *shca) -{ - int ret; - - ret = init_node_guid(shca); - if (ret) - return ret; - - strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX); - shca->ib_device.owner = THIS_MODULE; - - shca->ib_device.uverbs_abi_ver = 5; - shca->ib_device.uverbs_cmd_mask = - (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | - (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | - (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | - (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | - (1ull << IB_USER_VERBS_CMD_REG_MR) | - (1ull << IB_USER_VERBS_CMD_DEREG_MR) | - (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | - (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | - (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | - (1ull << IB_USER_VERBS_CMD_CREATE_QP) | - (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | - (1ull << IB_USER_VERBS_CMD_QUERY_QP) | - (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | - (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | - (1ull << IB_USER_VERBS_CMD_DETACH_MCAST); - - shca->ib_device.node_type = RDMA_NODE_IB_CA; - shca->ib_device.phys_port_cnt = shca->num_ports; - shca->ib_device.dma_device = &shca->ibmebus_dev->ofdev.dev; - shca->ib_device.query_device = ehca_query_device; - shca->ib_device.query_port = ehca_query_port; - shca->ib_device.query_gid = ehca_query_gid; - shca->ib_device.query_pkey = ehca_query_pkey; - /* shca->in_device.modify_device = ehca_modify_device */ - shca->ib_device.modify_port = ehca_modify_port; - shca->ib_device.alloc_ucontext = ehca_alloc_ucontext; - shca->ib_device.dealloc_ucontext = ehca_dealloc_ucontext; - shca->ib_device.alloc_pd = ehca_alloc_pd; - shca->ib_device.dealloc_pd = ehca_dealloc_pd; - shca->ib_device.create_ah = ehca_create_ah; - /* shca->ib_device.modify_ah = ehca_modify_ah; */ - shca->ib_device.query_ah = ehca_query_ah; - shca->ib_device.destroy_ah = ehca_destroy_ah; - shca->ib_device.create_qp = ehca_create_qp; - shca->ib_device.modify_qp = ehca_modify_qp; - shca->ib_device.query_qp = ehca_query_qp; - shca->ib_device.destroy_qp = ehca_destroy_qp; - shca->ib_device.post_send = ehca_post_send; - shca->ib_device.post_recv = ehca_post_recv; - shca->ib_device.create_cq = ehca_create_cq; - shca->ib_device.destroy_cq = ehca_destroy_cq; - shca->ib_device.resize_cq = ehca_resize_cq; - shca->ib_device.poll_cq = ehca_poll_cq; - /* shca->ib_device.peek_cq = ehca_peek_cq; */ - shca->ib_device.req_notify_cq = ehca_req_notify_cq; - /* shca->ib_device.req_ncomp_notif = ehca_req_ncomp_notif; */ - shca->ib_device.get_dma_mr = ehca_get_dma_mr; - shca->ib_device.reg_phys_mr = ehca_reg_phys_mr; - shca->ib_device.reg_user_mr = ehca_reg_user_mr; - shca->ib_device.query_mr = ehca_query_mr; - shca->ib_device.dereg_mr = ehca_dereg_mr; - shca->ib_device.rereg_phys_mr = ehca_rereg_phys_mr; - shca->ib_device.alloc_mw = ehca_alloc_mw; - shca->ib_device.bind_mw = ehca_bind_mw; - shca->ib_device.dealloc_mw = ehca_dealloc_mw; - shca->ib_device.alloc_fmr = ehca_alloc_fmr; - shca->ib_device.map_phys_fmr = ehca_map_phys_fmr; - shca->ib_device.unmap_fmr = ehca_unmap_fmr; - shca->ib_device.dealloc_fmr = ehca_dealloc_fmr; - shca->ib_device.attach_mcast = ehca_attach_mcast; - shca->ib_device.detach_mcast = ehca_detach_mcast; - /* shca->ib_device.process_mad = ehca_process_mad; */ - shca->ib_device.mmap = ehca_mmap; - - ret = ib_register_device(&shca->ib_device); - if (ret) - ehca_err(&shca->ib_device, - "ib_register_device() failed ret=%x", ret); - - return ret; -} - -static int ehca_create_aqp1(struct ehca_shca *shca, u32 port) -{ - struct ehca_sport *sport = &shca->sport[port - 1]; - struct ib_cq *ibcq; - struct ib_qp *ibqp; - struct ib_qp_init_attr qp_init_attr; - int ret; - - if (sport->ibcq_aqp1) { - ehca_err(&shca->ib_device, "AQP1 CQ is already created."); - return -EPERM; - } - - ibcq = ib_create_cq(&shca->ib_device, NULL, NULL, (void*)(-1), 10); - if (IS_ERR(ibcq)) { - ehca_err(&shca->ib_device, "Cannot create AQP1 CQ."); - return PTR_ERR(ibcq); - } - sport->ibcq_aqp1 = ibcq; - - if (sport->ibqp_aqp1) { - ehca_err(&shca->ib_device, "AQP1 QP is already created."); - ret = -EPERM; - goto create_aqp1; - } - - memset(&qp_init_attr, 0, sizeof(struct ib_qp_init_attr)); - qp_init_attr.send_cq = ibcq; - qp_init_attr.recv_cq = ibcq; - qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR; - qp_init_attr.cap.max_send_wr = 100; - qp_init_attr.cap.max_recv_wr = 100; - qp_init_attr.cap.max_send_sge = 2; - qp_init_attr.cap.max_recv_sge = 1; - qp_init_attr.qp_type = IB_QPT_GSI; - qp_init_attr.port_num = port; - qp_init_attr.qp_context = NULL; - qp_init_attr.event_handler = NULL; - qp_init_attr.srq = NULL; - - ibqp = ib_create_qp(&shca->pd->ib_pd, &qp_init_attr); - if (IS_ERR(ibqp)) { - ehca_err(&shca->ib_device, "Cannot create AQP1 QP."); - ret = PTR_ERR(ibqp); - goto create_aqp1; - } - sport->ibqp_aqp1 = ibqp; - - return 0; - -create_aqp1: - ib_destroy_cq(sport->ibcq_aqp1); - return ret; -} - -static int ehca_destroy_aqp1(struct ehca_sport *sport) -{ - int ret; - - ret = ib_destroy_qp(sport->ibqp_aqp1); - if (ret) { - ehca_gen_err("Cannot destroy AQP1 QP. ret=%x", ret); - return ret; - } - - ret = ib_destroy_cq(sport->ibcq_aqp1); - if (ret) - ehca_gen_err("Cannot destroy AQP1 CQ. ret=%x", ret); - - return ret; -} - -static ssize_t ehca_show_debug_level(struct device_driver *ddp, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", - ehca_debug_level); -} - -static ssize_t ehca_store_debug_level(struct device_driver *ddp, - const char *buf, size_t count) -{ - int value = (*buf) - '0'; - if (value >= 0 && value <= 9) - ehca_debug_level = value; - return 1; -} - -DRIVER_ATTR(debug_level, S_IRUSR | S_IWUSR, - ehca_show_debug_level, ehca_store_debug_level); - -void ehca_create_driver_sysfs(struct ibmebus_driver *drv) -{ - driver_create_file(&drv->driver, &driver_attr_debug_level); -} - -void ehca_remove_driver_sysfs(struct ibmebus_driver *drv) -{ - driver_remove_file(&drv->driver, &driver_attr_debug_level); -} - -#define EHCA_RESOURCE_ATTR(name) \ -static ssize_t ehca_show_##name(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct ehca_shca *shca; \ - struct hipz_query_hca *rblock; \ - int data; \ - \ - shca = dev->driver_data; \ - \ - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); \ - if (!rblock) { \ - dev_err(dev, "Can't allocate rblock memory."); \ - return 0; \ - } \ - \ - if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { \ - dev_err(dev, "Can't query device properties"); \ - kfree(rblock); \ - return 0; \ - } \ - \ - data = rblock->name; \ - kfree(rblock); \ - \ - if ((strcmp(#name, "num_ports") == 0) && (ehca_nr_ports == 1)) \ - return snprintf(buf, 256, "1\n"); \ - else \ - return snprintf(buf, 256, "%d\n", data); \ - \ -} \ -static DEVICE_ATTR(name, S_IRUGO, ehca_show_##name, NULL); - -EHCA_RESOURCE_ATTR(num_ports); -EHCA_RESOURCE_ATTR(hw_ver); -EHCA_RESOURCE_ATTR(max_eq); -EHCA_RESOURCE_ATTR(cur_eq); -EHCA_RESOURCE_ATTR(max_cq); -EHCA_RESOURCE_ATTR(cur_cq); -EHCA_RESOURCE_ATTR(max_qp); -EHCA_RESOURCE_ATTR(cur_qp); -EHCA_RESOURCE_ATTR(max_mr); -EHCA_RESOURCE_ATTR(cur_mr); -EHCA_RESOURCE_ATTR(max_mw); -EHCA_RESOURCE_ATTR(cur_mw); -EHCA_RESOURCE_ATTR(max_pd); -EHCA_RESOURCE_ATTR(max_ah); - -static ssize_t ehca_show_adapter_handle(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ehca_shca *shca = dev->driver_data; - - return sprintf(buf, "%lx\n", shca->ipz_hca_handle.handle); - -} -static DEVICE_ATTR(adapter_handle, S_IRUGO, ehca_show_adapter_handle, NULL); - - -void ehca_create_device_sysfs(struct ibmebus_dev *dev) -{ - device_create_file(&dev->ofdev.dev, &dev_attr_adapter_handle); - device_create_file(&dev->ofdev.dev, &dev_attr_num_ports); - device_create_file(&dev->ofdev.dev, &dev_attr_hw_ver); - device_create_file(&dev->ofdev.dev, &dev_attr_max_eq); - device_create_file(&dev->ofdev.dev, &dev_attr_cur_eq); - device_create_file(&dev->ofdev.dev, &dev_attr_max_cq); - device_create_file(&dev->ofdev.dev, &dev_attr_cur_cq); - device_create_file(&dev->ofdev.dev, &dev_attr_max_qp); - device_create_file(&dev->ofdev.dev, &dev_attr_cur_qp); - device_create_file(&dev->ofdev.dev, &dev_attr_max_mr); - device_create_file(&dev->ofdev.dev, &dev_attr_cur_mr); - device_create_file(&dev->ofdev.dev, &dev_attr_max_mw); - device_create_file(&dev->ofdev.dev, &dev_attr_cur_mw); - device_create_file(&dev->ofdev.dev, &dev_attr_max_pd); - device_create_file(&dev->ofdev.dev, &dev_attr_max_ah); -} - -void ehca_remove_device_sysfs(struct ibmebus_dev *dev) -{ - device_remove_file(&dev->ofdev.dev, &dev_attr_adapter_handle); - device_remove_file(&dev->ofdev.dev, &dev_attr_num_ports); - device_remove_file(&dev->ofdev.dev, &dev_attr_hw_ver); - device_remove_file(&dev->ofdev.dev, &dev_attr_max_eq); - device_remove_file(&dev->ofdev.dev, &dev_attr_cur_eq); - device_remove_file(&dev->ofdev.dev, &dev_attr_max_cq); - device_remove_file(&dev->ofdev.dev, &dev_attr_cur_cq); - device_remove_file(&dev->ofdev.dev, &dev_attr_max_qp); - device_remove_file(&dev->ofdev.dev, &dev_attr_cur_qp); - device_remove_file(&dev->ofdev.dev, &dev_attr_max_mr); - device_remove_file(&dev->ofdev.dev, &dev_attr_cur_mr); - device_remove_file(&dev->ofdev.dev, &dev_attr_max_mw); - device_remove_file(&dev->ofdev.dev, &dev_attr_cur_mw); - device_remove_file(&dev->ofdev.dev, &dev_attr_max_pd); - device_remove_file(&dev->ofdev.dev, &dev_attr_max_ah); -} - -static int __devinit ehca_probe(struct ibmebus_dev *dev, - const struct of_device_id *id) -{ - struct ehca_shca *shca; - u64 *handle; - struct ib_pd *ibpd; - int ret; - - handle = (u64 *)get_property(dev->ofdev.node, "ibm,hca-handle", NULL); - if (!handle) { - ehca_gen_err("Cannot get eHCA handle for adapter: %s.", - dev->ofdev.node->full_name); - return -ENODEV; - } - - if (!(*handle)) { - ehca_gen_err("Wrong eHCA handle for adapter: %s.", - dev->ofdev.node->full_name); - return -ENODEV; - } - - shca = (struct ehca_shca *)ib_alloc_device(sizeof(*shca)); - if (!shca) { - ehca_gen_err("Cannot allocate shca memory."); - return -ENOMEM; - } - - shca->ibmebus_dev = dev; - shca->ipz_hca_handle.handle = *handle; - dev->ofdev.dev.driver_data = shca; - - ret = ehca_sense_attributes(shca); - if (ret < 0) { - ehca_gen_err("Cannot sense eHCA attributes."); - goto probe1; - } - - ret = ehca_register_device(shca); - if (ret) { - ehca_gen_err("Cannot register Infiniband device"); - goto probe1; - } - - /* create event queues */ - ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, 2048); - if (ret) { - ehca_err(&shca->ib_device, "Cannot create EQ."); - goto probe2; - } - - ret = ehca_create_eq(shca, &shca->neq, EHCA_NEQ, 513); - if (ret) { - ehca_err(&shca->ib_device, "Cannot create NEQ."); - goto probe3; - } - - /* create internal protection domain */ - ibpd = ehca_alloc_pd(&shca->ib_device, (void*)(-1), NULL); - if (IS_ERR(ibpd)) { - ehca_err(&shca->ib_device, "Cannot create internal PD."); - ret = PTR_ERR(ibpd); - goto probe4; - } - - shca->pd = container_of(ibpd, struct ehca_pd, ib_pd); - shca->pd->ib_pd.device = &shca->ib_device; - - /* create internal max MR */ - ret = ehca_reg_internal_maxmr(shca, shca->pd, &shca->maxmr); - - if (ret) { - ehca_err(&shca->ib_device, "Cannot create internal MR ret=%x", - ret); - goto probe5; - } - - /* create AQP1 for port 1 */ - if (ehca_open_aqp1 == 1) { - shca->sport[0].port_state = IB_PORT_DOWN; - ret = ehca_create_aqp1(shca, 1); - if (ret) { - ehca_err(&shca->ib_device, - "Cannot create AQP1 for port 1."); - goto probe6; - } - } - - /* create AQP1 for port 2 */ - if ((ehca_open_aqp1 == 1) && (shca->num_ports == 2)) { - shca->sport[1].port_state = IB_PORT_DOWN; - ret = ehca_create_aqp1(shca, 2); - if (ret) { - ehca_err(&shca->ib_device, - "Cannot create AQP1 for port 2."); - goto probe7; - } - } - - ehca_create_device_sysfs(dev); - - spin_lock(&shca_list_lock); - list_add(&shca->shca_list, &shca_list); - spin_unlock(&shca_list_lock); - - return 0; - -probe7: - ret = ehca_destroy_aqp1(&shca->sport[0]); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy AQP1 for port 1. ret=%x", ret); - -probe6: - ret = ehca_dereg_internal_maxmr(shca); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy internal MR. ret=%x", ret); - -probe5: - ret = ehca_dealloc_pd(&shca->pd->ib_pd); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy internal PD. ret=%x", ret); - -probe4: - ret = ehca_destroy_eq(shca, &shca->neq); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy NEQ. ret=%x", ret); - -probe3: - ret = ehca_destroy_eq(shca, &shca->eq); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy EQ. ret=%x", ret); - -probe2: - ib_unregister_device(&shca->ib_device); - -probe1: - ib_dealloc_device(&shca->ib_device); - - return -EINVAL; -} - -static int __devexit ehca_remove(struct ibmebus_dev *dev) -{ - struct ehca_shca *shca = dev->ofdev.dev.driver_data; - int ret; - - ehca_remove_device_sysfs(dev); - - if (ehca_open_aqp1 == 1) { - int i; - for (i = 0; i < shca->num_ports; i++) { - ret = ehca_destroy_aqp1(&shca->sport[i]); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy AQP1 for port %x " - "ret=%x", ret, i); - } - } - - ib_unregister_device(&shca->ib_device); - - ret = ehca_dereg_internal_maxmr(shca); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy internal MR. ret=%x", ret); - - ret = ehca_dealloc_pd(&shca->pd->ib_pd); - if (ret) - ehca_err(&shca->ib_device, - "Cannot destroy internal PD. ret=%x", ret); - - ret = ehca_destroy_eq(shca, &shca->eq); - if (ret) - ehca_err(&shca->ib_device, "Cannot destroy EQ. ret=%x", ret); - - ret = ehca_destroy_eq(shca, &shca->neq); - if (ret) - ehca_err(&shca->ib_device, "Canot destroy NEQ. ret=%x", ret); - - ib_dealloc_device(&shca->ib_device); - - spin_lock(&shca_list_lock); - list_del(&shca->shca_list); - spin_unlock(&shca_list_lock); - - return ret; -} - -static struct of_device_id ehca_device_table[] = -{ - { - .name = "lhca", - .compatible = "IBM,lhca", - }, - {}, -}; - -static struct ibmebus_driver ehca_driver = { - .name = "ehca", - .id_table = ehca_device_table, - .probe = ehca_probe, - .remove = ehca_remove, -}; - -void ehca_poll_eqs(unsigned long data) -{ - struct ehca_shca *shca; - - spin_lock(&shca_list_lock); - list_for_each_entry(shca, &shca_list, shca_list) { - if (shca->eq.is_initialized) - ehca_tasklet_eq((unsigned long)(void*)shca); - } - mod_timer(&poll_eqs_timer, jiffies + HZ); - spin_unlock(&shca_list_lock); -} - -int __init ehca_module_init(void) -{ - int ret; - - printk(KERN_INFO "eHCA Infiniband Device Driver " - "(Rel.: SVNEHCA_0016)\n"); - idr_init(&ehca_qp_idr); - idr_init(&ehca_cq_idr); - spin_lock_init(&ehca_qp_idr_lock); - spin_lock_init(&ehca_cq_idr_lock); - - INIT_LIST_HEAD(&shca_list); - spin_lock_init(&shca_list_lock); - - if ((ret = ehca_create_comp_pool())) { - ehca_gen_err("Cannot create comp pool."); - return ret; - } - - if ((ret = ehca_create_slab_caches())) { - ehca_gen_err("Cannot create SLAB caches"); - ret = -ENOMEM; - goto module_init1; - } - - if ((ret = ibmebus_register_driver(&ehca_driver))) { - ehca_gen_err("Cannot register eHCA device driver"); - ret = -EINVAL; - goto module_init2; - } - - ehca_create_driver_sysfs(&ehca_driver); - - if (ehca_poll_all_eqs != 1) { - ehca_gen_err("WARNING!!!"); - ehca_gen_err("It is possible to lose interrupts."); - } else { - init_timer(&poll_eqs_timer); - poll_eqs_timer.function = ehca_poll_eqs; - poll_eqs_timer.expires = jiffies + HZ; - add_timer(&poll_eqs_timer); - } - - return 0; - -module_init2: - ehca_destroy_slab_caches(); - -module_init1: - ehca_destroy_comp_pool(); - return ret; -}; - -void __exit ehca_module_exit(void) -{ - if (ehca_poll_all_eqs == 1) - del_timer_sync(&poll_eqs_timer); - - ehca_remove_driver_sysfs(&ehca_driver); - ibmebus_unregister_driver(&ehca_driver); - - ehca_destroy_slab_caches(); - - ehca_destroy_comp_pool(); - - idr_destroy(&ehca_cq_idr); - idr_destroy(&ehca_qp_idr); -}; - -module_init(ehca_module_init); -module_exit(ehca_module_exit); diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_mcast.c b/trunk/drivers/infiniband/hw/ehca/ehca_mcast.c deleted file mode 100644 index 32a870660bfe..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_mcast.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * mcast functions - * - * Authors: Khadija Souissi - * Waleri Fomin - * Reinhard Ernst - * Hoang-Nam Nguyen - * Heiko J Schick - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include "ehca_classes.h" -#include "ehca_tools.h" -#include "ehca_qes.h" -#include "ehca_iverbs.h" -#include "hcp_if.h" - -#define MAX_MC_LID 0xFFFE -#define MIN_MC_LID 0xC000 /* Multicast limits */ -#define EHCA_VALID_MULTICAST_GID(gid) ((gid)[0] == 0xFF) -#define EHCA_VALID_MULTICAST_LID(lid) \ - (((lid) >= MIN_MC_LID) && ((lid) <= MAX_MC_LID)) - -int ehca_attach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); - struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca, - ib_device); - union ib_gid my_gid; - u64 subnet_prefix, interface_id, h_ret; - - if (ibqp->qp_type != IB_QPT_UD) { - ehca_err(ibqp->device, "invalid qp_type=%x", ibqp->qp_type); - return -EINVAL; - } - - if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) { - ehca_err(ibqp->device, "invalid mulitcast gid"); - return -EINVAL; - } else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) { - ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid); - return -EINVAL; - } - - memcpy(&my_gid.raw, gid->raw, sizeof(union ib_gid)); - - subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix); - interface_id = be64_to_cpu(my_gid.global.interface_id); - h_ret = hipz_h_attach_mcqp(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, - my_qp->galpas.kernel, - lid, subnet_prefix, interface_id); - if (h_ret != H_SUCCESS) - ehca_err(ibqp->device, - "ehca_qp=%p qp_num=%x hipz_h_attach_mcqp() failed " - "h_ret=%lx", my_qp, ibqp->qp_num, h_ret); - - return ehca2ib_return_code(h_ret); -} - -int ehca_detach_mcast(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) -{ - struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); - struct ehca_shca *shca = container_of(ibqp->pd->device, - struct ehca_shca, ib_device); - union ib_gid my_gid; - u64 subnet_prefix, interface_id, h_ret; - - if (ibqp->qp_type != IB_QPT_UD) { - ehca_err(ibqp->device, "invalid qp_type %x", ibqp->qp_type); - return -EINVAL; - } - - if (!(EHCA_VALID_MULTICAST_GID(gid->raw))) { - ehca_err(ibqp->device, "invalid mulitcast gid"); - return -EINVAL; - } else if ((lid < MIN_MC_LID) || (lid > MAX_MC_LID)) { - ehca_err(ibqp->device, "invalid mulitcast lid=%x", lid); - return -EINVAL; - } - - memcpy(&my_gid.raw, gid->raw, sizeof(union ib_gid)); - - subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix); - interface_id = be64_to_cpu(my_gid.global.interface_id); - h_ret = hipz_h_detach_mcqp(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, - my_qp->galpas.kernel, - lid, subnet_prefix, interface_id); - if (h_ret != H_SUCCESS) - ehca_err(ibqp->device, - "ehca_qp=%p qp_num=%x hipz_h_detach_mcqp() failed " - "h_ret=%lx", my_qp, ibqp->qp_num, h_ret); - - return ehca2ib_return_code(h_ret); -} diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c b/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c deleted file mode 100644 index 5ca65441e1da..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c +++ /dev/null @@ -1,2261 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * MR/MW functions - * - * Authors: Dietmar Decker - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "ehca_iverbs.h" -#include "ehca_mrmw.h" -#include "hcp_if.h" -#include "hipz_hw.h" - -static struct kmem_cache *mr_cache; -static struct kmem_cache *mw_cache; - -static struct ehca_mr *ehca_mr_new(void) -{ - struct ehca_mr *me; - - me = kmem_cache_alloc(mr_cache, SLAB_KERNEL); - if (me) { - memset(me, 0, sizeof(struct ehca_mr)); - spin_lock_init(&me->mrlock); - } else - ehca_gen_err("alloc failed"); - - return me; -} - -static void ehca_mr_delete(struct ehca_mr *me) -{ - kmem_cache_free(mr_cache, me); -} - -static struct ehca_mw *ehca_mw_new(void) -{ - struct ehca_mw *me; - - me = kmem_cache_alloc(mw_cache, SLAB_KERNEL); - if (me) { - memset(me, 0, sizeof(struct ehca_mw)); - spin_lock_init(&me->mwlock); - } else - ehca_gen_err("alloc failed"); - - return me; -} - -static void ehca_mw_delete(struct ehca_mw *me) -{ - kmem_cache_free(mw_cache, me); -} - -/*----------------------------------------------------------------------*/ - -struct ib_mr *ehca_get_dma_mr(struct ib_pd *pd, int mr_access_flags) -{ - struct ib_mr *ib_mr; - int ret; - struct ehca_mr *e_maxmr; - struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); - struct ehca_shca *shca = - container_of(pd->device, struct ehca_shca, ib_device); - - if (shca->maxmr) { - e_maxmr = ehca_mr_new(); - if (!e_maxmr) { - ehca_err(&shca->ib_device, "out of memory"); - ib_mr = ERR_PTR(-ENOMEM); - goto get_dma_mr_exit0; - } - - ret = ehca_reg_maxmr(shca, e_maxmr, (u64*)KERNELBASE, - mr_access_flags, e_pd, - &e_maxmr->ib.ib_mr.lkey, - &e_maxmr->ib.ib_mr.rkey); - if (ret) { - ib_mr = ERR_PTR(ret); - goto get_dma_mr_exit0; - } - ib_mr = &e_maxmr->ib.ib_mr; - } else { - ehca_err(&shca->ib_device, "no internal max-MR exist!"); - ib_mr = ERR_PTR(-EINVAL); - goto get_dma_mr_exit0; - } - -get_dma_mr_exit0: - if (IS_ERR(ib_mr)) - ehca_err(&shca->ib_device, "rc=%lx pd=%p mr_access_flags=%x ", - PTR_ERR(ib_mr), pd, mr_access_flags); - return ib_mr; -} /* end ehca_get_dma_mr() */ - -/*----------------------------------------------------------------------*/ - -struct ib_mr *ehca_reg_phys_mr(struct ib_pd *pd, - struct ib_phys_buf *phys_buf_array, - int num_phys_buf, - int mr_access_flags, - u64 *iova_start) -{ - struct ib_mr *ib_mr; - int ret; - struct ehca_mr *e_mr; - struct ehca_shca *shca = - container_of(pd->device, struct ehca_shca, ib_device); - struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); - - u64 size; - struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; - u32 num_pages_mr; - u32 num_pages_4k; /* 4k portion "pages" */ - - if ((num_phys_buf <= 0) || !phys_buf_array) { - ehca_err(pd->device, "bad input values: num_phys_buf=%x " - "phys_buf_array=%p", num_phys_buf, phys_buf_array); - ib_mr = ERR_PTR(-EINVAL); - goto reg_phys_mr_exit0; - } - if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) && - !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) || - ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) && - !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) { - /* - * Remote Write Access requires Local Write Access - * Remote Atomic Access requires Local Write Access - */ - ehca_err(pd->device, "bad input values: mr_access_flags=%x", - mr_access_flags); - ib_mr = ERR_PTR(-EINVAL); - goto reg_phys_mr_exit0; - } - - /* check physical buffer list and calculate size */ - ret = ehca_mr_chk_buf_and_calc_size(phys_buf_array, num_phys_buf, - iova_start, &size); - if (ret) { - ib_mr = ERR_PTR(ret); - goto reg_phys_mr_exit0; - } - if ((size == 0) || - (((u64)iova_start + size) < (u64)iova_start)) { - ehca_err(pd->device, "bad input values: size=%lx iova_start=%p", - size, iova_start); - ib_mr = ERR_PTR(-EINVAL); - goto reg_phys_mr_exit0; - } - - e_mr = ehca_mr_new(); - if (!e_mr) { - ehca_err(pd->device, "out of memory"); - ib_mr = ERR_PTR(-ENOMEM); - goto reg_phys_mr_exit0; - } - - /* determine number of MR pages */ - num_pages_mr = ((((u64)iova_start % PAGE_SIZE) + size + - PAGE_SIZE - 1) / PAGE_SIZE); - num_pages_4k = ((((u64)iova_start % EHCA_PAGESIZE) + size + - EHCA_PAGESIZE - 1) / EHCA_PAGESIZE); - - /* register MR on HCA */ - if (ehca_mr_is_maxmr(size, iova_start)) { - e_mr->flags |= EHCA_MR_FLAG_MAXMR; - ret = ehca_reg_maxmr(shca, e_mr, iova_start, mr_access_flags, - e_pd, &e_mr->ib.ib_mr.lkey, - &e_mr->ib.ib_mr.rkey); - if (ret) { - ib_mr = ERR_PTR(ret); - goto reg_phys_mr_exit1; - } - } else { - pginfo.type = EHCA_MR_PGI_PHYS; - pginfo.num_pages = num_pages_mr; - pginfo.num_4k = num_pages_4k; - pginfo.num_phys_buf = num_phys_buf; - pginfo.phys_buf_array = phys_buf_array; - pginfo.next_4k = (((u64)iova_start & ~PAGE_MASK) / - EHCA_PAGESIZE); - - ret = ehca_reg_mr(shca, e_mr, iova_start, size, mr_access_flags, - e_pd, &pginfo, &e_mr->ib.ib_mr.lkey, - &e_mr->ib.ib_mr.rkey); - if (ret) { - ib_mr = ERR_PTR(ret); - goto reg_phys_mr_exit1; - } - } - - /* successful registration of all pages */ - return &e_mr->ib.ib_mr; - -reg_phys_mr_exit1: - ehca_mr_delete(e_mr); -reg_phys_mr_exit0: - if (IS_ERR(ib_mr)) - ehca_err(pd->device, "rc=%lx pd=%p phys_buf_array=%p " - "num_phys_buf=%x mr_access_flags=%x iova_start=%p", - PTR_ERR(ib_mr), pd, phys_buf_array, - num_phys_buf, mr_access_flags, iova_start); - return ib_mr; -} /* end ehca_reg_phys_mr() */ - -/*----------------------------------------------------------------------*/ - -struct ib_mr *ehca_reg_user_mr(struct ib_pd *pd, - struct ib_umem *region, - int mr_access_flags, - struct ib_udata *udata) -{ - struct ib_mr *ib_mr; - struct ehca_mr *e_mr; - struct ehca_shca *shca = - container_of(pd->device, struct ehca_shca, ib_device); - struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); - struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; - int ret; - u32 num_pages_mr; - u32 num_pages_4k; /* 4k portion "pages" */ - - if (!pd) { - ehca_gen_err("bad pd=%p", pd); - return ERR_PTR(-EFAULT); - } - if (!region) { - ehca_err(pd->device, "bad input values: region=%p", region); - ib_mr = ERR_PTR(-EINVAL); - goto reg_user_mr_exit0; - } - if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) && - !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) || - ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) && - !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) { - /* - * Remote Write Access requires Local Write Access - * Remote Atomic Access requires Local Write Access - */ - ehca_err(pd->device, "bad input values: mr_access_flags=%x", - mr_access_flags); - ib_mr = ERR_PTR(-EINVAL); - goto reg_user_mr_exit0; - } - if (region->page_size != PAGE_SIZE) { - ehca_err(pd->device, "page size not supported, " - "region->page_size=%x", region->page_size); - ib_mr = ERR_PTR(-EINVAL); - goto reg_user_mr_exit0; - } - - if ((region->length == 0) || - ((region->virt_base + region->length) < region->virt_base)) { - ehca_err(pd->device, "bad input values: length=%lx " - "virt_base=%lx", region->length, region->virt_base); - ib_mr = ERR_PTR(-EINVAL); - goto reg_user_mr_exit0; - } - - e_mr = ehca_mr_new(); - if (!e_mr) { - ehca_err(pd->device, "out of memory"); - ib_mr = ERR_PTR(-ENOMEM); - goto reg_user_mr_exit0; - } - - /* determine number of MR pages */ - num_pages_mr = (((region->virt_base % PAGE_SIZE) + region->length + - PAGE_SIZE - 1) / PAGE_SIZE); - num_pages_4k = (((region->virt_base % EHCA_PAGESIZE) + region->length + - EHCA_PAGESIZE - 1) / EHCA_PAGESIZE); - - /* register MR on HCA */ - pginfo.type = EHCA_MR_PGI_USER; - pginfo.num_pages = num_pages_mr; - pginfo.num_4k = num_pages_4k; - pginfo.region = region; - pginfo.next_4k = region->offset / EHCA_PAGESIZE; - pginfo.next_chunk = list_prepare_entry(pginfo.next_chunk, - (®ion->chunk_list), - list); - - ret = ehca_reg_mr(shca, e_mr, (u64*)region->virt_base, - region->length, mr_access_flags, e_pd, &pginfo, - &e_mr->ib.ib_mr.lkey, &e_mr->ib.ib_mr.rkey); - if (ret) { - ib_mr = ERR_PTR(ret); - goto reg_user_mr_exit1; - } - - /* successful registration of all pages */ - return &e_mr->ib.ib_mr; - -reg_user_mr_exit1: - ehca_mr_delete(e_mr); -reg_user_mr_exit0: - if (IS_ERR(ib_mr)) - ehca_err(pd->device, "rc=%lx pd=%p region=%p mr_access_flags=%x" - " udata=%p", - PTR_ERR(ib_mr), pd, region, mr_access_flags, udata); - return ib_mr; -} /* end ehca_reg_user_mr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_rereg_phys_mr(struct ib_mr *mr, - int mr_rereg_mask, - struct ib_pd *pd, - struct ib_phys_buf *phys_buf_array, - int num_phys_buf, - int mr_access_flags, - u64 *iova_start) -{ - int ret; - - struct ehca_shca *shca = - container_of(mr->device, struct ehca_shca, ib_device); - struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr); - struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd); - u64 new_size; - u64 *new_start; - u32 new_acl; - struct ehca_pd *new_pd; - u32 tmp_lkey, tmp_rkey; - unsigned long sl_flags; - u32 num_pages_mr = 0; - u32 num_pages_4k = 0; /* 4k portion "pages" */ - struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; - u32 cur_pid = current->tgid; - - if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && - (my_pd->ownpid != cur_pid)) { - ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x", - cur_pid, my_pd->ownpid); - ret = -EINVAL; - goto rereg_phys_mr_exit0; - } - - if (!(mr_rereg_mask & IB_MR_REREG_TRANS)) { - /* TODO not supported, because PHYP rereg hCall needs pages */ - ehca_err(mr->device, "rereg without IB_MR_REREG_TRANS not " - "supported yet, mr_rereg_mask=%x", mr_rereg_mask); - ret = -EINVAL; - goto rereg_phys_mr_exit0; - } - - if (mr_rereg_mask & IB_MR_REREG_PD) { - if (!pd) { - ehca_err(mr->device, "rereg with bad pd, pd=%p " - "mr_rereg_mask=%x", pd, mr_rereg_mask); - ret = -EINVAL; - goto rereg_phys_mr_exit0; - } - } - - if ((mr_rereg_mask & - ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS)) || - (mr_rereg_mask == 0)) { - ret = -EINVAL; - goto rereg_phys_mr_exit0; - } - - /* check other parameters */ - if (e_mr == shca->maxmr) { - /* should be impossible, however reject to be sure */ - ehca_err(mr->device, "rereg internal max-MR impossible, mr=%p " - "shca->maxmr=%p mr->lkey=%x", - mr, shca->maxmr, mr->lkey); - ret = -EINVAL; - goto rereg_phys_mr_exit0; - } - if (mr_rereg_mask & IB_MR_REREG_TRANS) { /* transl., i.e. addr/size */ - if (e_mr->flags & EHCA_MR_FLAG_FMR) { - ehca_err(mr->device, "not supported for FMR, mr=%p " - "flags=%x", mr, e_mr->flags); - ret = -EINVAL; - goto rereg_phys_mr_exit0; - } - if (!phys_buf_array || num_phys_buf <= 0) { - ehca_err(mr->device, "bad input values: mr_rereg_mask=%x" - " phys_buf_array=%p num_phys_buf=%x", - mr_rereg_mask, phys_buf_array, num_phys_buf); - ret = -EINVAL; - goto rereg_phys_mr_exit0; - } - } - if ((mr_rereg_mask & IB_MR_REREG_ACCESS) && /* change ACL */ - (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) && - !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) || - ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) && - !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)))) { - /* - * Remote Write Access requires Local Write Access - * Remote Atomic Access requires Local Write Access - */ - ehca_err(mr->device, "bad input values: mr_rereg_mask=%x " - "mr_access_flags=%x", mr_rereg_mask, mr_access_flags); - ret = -EINVAL; - goto rereg_phys_mr_exit0; - } - - /* set requested values dependent on rereg request */ - spin_lock_irqsave(&e_mr->mrlock, sl_flags); - new_start = e_mr->start; /* new == old address */ - new_size = e_mr->size; /* new == old length */ - new_acl = e_mr->acl; /* new == old access control */ - new_pd = container_of(mr->pd,struct ehca_pd,ib_pd); /*new == old PD*/ - - if (mr_rereg_mask & IB_MR_REREG_TRANS) { - new_start = iova_start; /* change address */ - /* check physical buffer list and calculate size */ - ret = ehca_mr_chk_buf_and_calc_size(phys_buf_array, - num_phys_buf, iova_start, - &new_size); - if (ret) - goto rereg_phys_mr_exit1; - if ((new_size == 0) || - (((u64)iova_start + new_size) < (u64)iova_start)) { - ehca_err(mr->device, "bad input values: new_size=%lx " - "iova_start=%p", new_size, iova_start); - ret = -EINVAL; - goto rereg_phys_mr_exit1; - } - num_pages_mr = ((((u64)new_start % PAGE_SIZE) + new_size + - PAGE_SIZE - 1) / PAGE_SIZE); - num_pages_4k = ((((u64)new_start % EHCA_PAGESIZE) + new_size + - EHCA_PAGESIZE - 1) / EHCA_PAGESIZE); - pginfo.type = EHCA_MR_PGI_PHYS; - pginfo.num_pages = num_pages_mr; - pginfo.num_4k = num_pages_4k; - pginfo.num_phys_buf = num_phys_buf; - pginfo.phys_buf_array = phys_buf_array; - pginfo.next_4k = (((u64)iova_start & ~PAGE_MASK) / - EHCA_PAGESIZE); - } - if (mr_rereg_mask & IB_MR_REREG_ACCESS) - new_acl = mr_access_flags; - if (mr_rereg_mask & IB_MR_REREG_PD) - new_pd = container_of(pd, struct ehca_pd, ib_pd); - - ret = ehca_rereg_mr(shca, e_mr, new_start, new_size, new_acl, - new_pd, &pginfo, &tmp_lkey, &tmp_rkey); - if (ret) - goto rereg_phys_mr_exit1; - - /* successful reregistration */ - if (mr_rereg_mask & IB_MR_REREG_PD) - mr->pd = pd; - mr->lkey = tmp_lkey; - mr->rkey = tmp_rkey; - -rereg_phys_mr_exit1: - spin_unlock_irqrestore(&e_mr->mrlock, sl_flags); -rereg_phys_mr_exit0: - if (ret) - ehca_err(mr->device, "ret=%x mr=%p mr_rereg_mask=%x pd=%p " - "phys_buf_array=%p num_phys_buf=%x mr_access_flags=%x " - "iova_start=%p", - ret, mr, mr_rereg_mask, pd, phys_buf_array, - num_phys_buf, mr_access_flags, iova_start); - return ret; -} /* end ehca_rereg_phys_mr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_query_mr(struct ib_mr *mr, struct ib_mr_attr *mr_attr) -{ - int ret = 0; - u64 h_ret; - struct ehca_shca *shca = - container_of(mr->device, struct ehca_shca, ib_device); - struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr); - struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd); - u32 cur_pid = current->tgid; - unsigned long sl_flags; - struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0}; - - if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && - (my_pd->ownpid != cur_pid)) { - ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x", - cur_pid, my_pd->ownpid); - ret = -EINVAL; - goto query_mr_exit0; - } - - if ((e_mr->flags & EHCA_MR_FLAG_FMR)) { - ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p " - "e_mr->flags=%x", mr, e_mr, e_mr->flags); - ret = -EINVAL; - goto query_mr_exit0; - } - - memset(mr_attr, 0, sizeof(struct ib_mr_attr)); - spin_lock_irqsave(&e_mr->mrlock, sl_flags); - - h_ret = hipz_h_query_mr(shca->ipz_hca_handle, e_mr, &hipzout); - if (h_ret != H_SUCCESS) { - ehca_err(mr->device, "hipz_mr_query failed, h_ret=%lx mr=%p " - "hca_hndl=%lx mr_hndl=%lx lkey=%x", - h_ret, mr, shca->ipz_hca_handle.handle, - e_mr->ipz_mr_handle.handle, mr->lkey); - ret = ehca_mrmw_map_hrc_query_mr(h_ret); - goto query_mr_exit1; - } - mr_attr->pd = mr->pd; - mr_attr->device_virt_addr = hipzout.vaddr; - mr_attr->size = hipzout.len; - mr_attr->lkey = hipzout.lkey; - mr_attr->rkey = hipzout.rkey; - ehca_mrmw_reverse_map_acl(&hipzout.acl, &mr_attr->mr_access_flags); - -query_mr_exit1: - spin_unlock_irqrestore(&e_mr->mrlock, sl_flags); -query_mr_exit0: - if (ret) - ehca_err(mr->device, "ret=%x mr=%p mr_attr=%p", - ret, mr, mr_attr); - return ret; -} /* end ehca_query_mr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_dereg_mr(struct ib_mr *mr) -{ - int ret = 0; - u64 h_ret; - struct ehca_shca *shca = - container_of(mr->device, struct ehca_shca, ib_device); - struct ehca_mr *e_mr = container_of(mr, struct ehca_mr, ib.ib_mr); - struct ehca_pd *my_pd = container_of(mr->pd, struct ehca_pd, ib_pd); - u32 cur_pid = current->tgid; - - if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && - (my_pd->ownpid != cur_pid)) { - ehca_err(mr->device, "Invalid caller pid=%x ownpid=%x", - cur_pid, my_pd->ownpid); - ret = -EINVAL; - goto dereg_mr_exit0; - } - - if ((e_mr->flags & EHCA_MR_FLAG_FMR)) { - ehca_err(mr->device, "not supported for FMR, mr=%p e_mr=%p " - "e_mr->flags=%x", mr, e_mr, e_mr->flags); - ret = -EINVAL; - goto dereg_mr_exit0; - } else if (e_mr == shca->maxmr) { - /* should be impossible, however reject to be sure */ - ehca_err(mr->device, "dereg internal max-MR impossible, mr=%p " - "shca->maxmr=%p mr->lkey=%x", - mr, shca->maxmr, mr->lkey); - ret = -EINVAL; - goto dereg_mr_exit0; - } - - /* TODO: BUSY: MR still has bound window(s) */ - h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr); - if (h_ret != H_SUCCESS) { - ehca_err(mr->device, "hipz_free_mr failed, h_ret=%lx shca=%p " - "e_mr=%p hca_hndl=%lx mr_hndl=%lx mr->lkey=%x", - h_ret, shca, e_mr, shca->ipz_hca_handle.handle, - e_mr->ipz_mr_handle.handle, mr->lkey); - ret = ehca_mrmw_map_hrc_free_mr(h_ret); - goto dereg_mr_exit0; - } - - /* successful deregistration */ - ehca_mr_delete(e_mr); - -dereg_mr_exit0: - if (ret) - ehca_err(mr->device, "ret=%x mr=%p", ret, mr); - return ret; -} /* end ehca_dereg_mr() */ - -/*----------------------------------------------------------------------*/ - -struct ib_mw *ehca_alloc_mw(struct ib_pd *pd) -{ - struct ib_mw *ib_mw; - u64 h_ret; - struct ehca_mw *e_mw; - struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); - struct ehca_shca *shca = - container_of(pd->device, struct ehca_shca, ib_device); - struct ehca_mw_hipzout_parms hipzout = {{0},0}; - - e_mw = ehca_mw_new(); - if (!e_mw) { - ib_mw = ERR_PTR(-ENOMEM); - goto alloc_mw_exit0; - } - - h_ret = hipz_h_alloc_resource_mw(shca->ipz_hca_handle, e_mw, - e_pd->fw_pd, &hipzout); - if (h_ret != H_SUCCESS) { - ehca_err(pd->device, "hipz_mw_allocate failed, h_ret=%lx " - "shca=%p hca_hndl=%lx mw=%p", - h_ret, shca, shca->ipz_hca_handle.handle, e_mw); - ib_mw = ERR_PTR(ehca_mrmw_map_hrc_alloc(h_ret)); - goto alloc_mw_exit1; - } - /* successful MW allocation */ - e_mw->ipz_mw_handle = hipzout.handle; - e_mw->ib_mw.rkey = hipzout.rkey; - return &e_mw->ib_mw; - -alloc_mw_exit1: - ehca_mw_delete(e_mw); -alloc_mw_exit0: - if (IS_ERR(ib_mw)) - ehca_err(pd->device, "rc=%lx pd=%p", PTR_ERR(ib_mw), pd); - return ib_mw; -} /* end ehca_alloc_mw() */ - -/*----------------------------------------------------------------------*/ - -int ehca_bind_mw(struct ib_qp *qp, - struct ib_mw *mw, - struct ib_mw_bind *mw_bind) -{ - /* TODO: not supported up to now */ - ehca_gen_err("bind MW currently not supported by HCAD"); - - return -EPERM; -} /* end ehca_bind_mw() */ - -/*----------------------------------------------------------------------*/ - -int ehca_dealloc_mw(struct ib_mw *mw) -{ - u64 h_ret; - struct ehca_shca *shca = - container_of(mw->device, struct ehca_shca, ib_device); - struct ehca_mw *e_mw = container_of(mw, struct ehca_mw, ib_mw); - - h_ret = hipz_h_free_resource_mw(shca->ipz_hca_handle, e_mw); - if (h_ret != H_SUCCESS) { - ehca_err(mw->device, "hipz_free_mw failed, h_ret=%lx shca=%p " - "mw=%p rkey=%x hca_hndl=%lx mw_hndl=%lx", - h_ret, shca, mw, mw->rkey, shca->ipz_hca_handle.handle, - e_mw->ipz_mw_handle.handle); - return ehca_mrmw_map_hrc_free_mw(h_ret); - } - /* successful deallocation */ - ehca_mw_delete(e_mw); - return 0; -} /* end ehca_dealloc_mw() */ - -/*----------------------------------------------------------------------*/ - -struct ib_fmr *ehca_alloc_fmr(struct ib_pd *pd, - int mr_access_flags, - struct ib_fmr_attr *fmr_attr) -{ - struct ib_fmr *ib_fmr; - struct ehca_shca *shca = - container_of(pd->device, struct ehca_shca, ib_device); - struct ehca_pd *e_pd = container_of(pd, struct ehca_pd, ib_pd); - struct ehca_mr *e_fmr; - int ret; - u32 tmp_lkey, tmp_rkey; - struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; - - /* check other parameters */ - if (((mr_access_flags & IB_ACCESS_REMOTE_WRITE) && - !(mr_access_flags & IB_ACCESS_LOCAL_WRITE)) || - ((mr_access_flags & IB_ACCESS_REMOTE_ATOMIC) && - !(mr_access_flags & IB_ACCESS_LOCAL_WRITE))) { - /* - * Remote Write Access requires Local Write Access - * Remote Atomic Access requires Local Write Access - */ - ehca_err(pd->device, "bad input values: mr_access_flags=%x", - mr_access_flags); - ib_fmr = ERR_PTR(-EINVAL); - goto alloc_fmr_exit0; - } - if (mr_access_flags & IB_ACCESS_MW_BIND) { - ehca_err(pd->device, "bad input values: mr_access_flags=%x", - mr_access_flags); - ib_fmr = ERR_PTR(-EINVAL); - goto alloc_fmr_exit0; - } - if ((fmr_attr->max_pages == 0) || (fmr_attr->max_maps == 0)) { - ehca_err(pd->device, "bad input values: fmr_attr->max_pages=%x " - "fmr_attr->max_maps=%x fmr_attr->page_shift=%x", - fmr_attr->max_pages, fmr_attr->max_maps, - fmr_attr->page_shift); - ib_fmr = ERR_PTR(-EINVAL); - goto alloc_fmr_exit0; - } - if (((1 << fmr_attr->page_shift) != EHCA_PAGESIZE) && - ((1 << fmr_attr->page_shift) != PAGE_SIZE)) { - ehca_err(pd->device, "unsupported fmr_attr->page_shift=%x", - fmr_attr->page_shift); - ib_fmr = ERR_PTR(-EINVAL); - goto alloc_fmr_exit0; - } - - e_fmr = ehca_mr_new(); - if (!e_fmr) { - ib_fmr = ERR_PTR(-ENOMEM); - goto alloc_fmr_exit0; - } - e_fmr->flags |= EHCA_MR_FLAG_FMR; - - /* register MR on HCA */ - ret = ehca_reg_mr(shca, e_fmr, NULL, - fmr_attr->max_pages * (1 << fmr_attr->page_shift), - mr_access_flags, e_pd, &pginfo, - &tmp_lkey, &tmp_rkey); - if (ret) { - ib_fmr = ERR_PTR(ret); - goto alloc_fmr_exit1; - } - - /* successful */ - e_fmr->fmr_page_size = 1 << fmr_attr->page_shift; - e_fmr->fmr_max_pages = fmr_attr->max_pages; - e_fmr->fmr_max_maps = fmr_attr->max_maps; - e_fmr->fmr_map_cnt = 0; - return &e_fmr->ib.ib_fmr; - -alloc_fmr_exit1: - ehca_mr_delete(e_fmr); -alloc_fmr_exit0: - if (IS_ERR(ib_fmr)) - ehca_err(pd->device, "rc=%lx pd=%p mr_access_flags=%x " - "fmr_attr=%p", PTR_ERR(ib_fmr), pd, - mr_access_flags, fmr_attr); - return ib_fmr; -} /* end ehca_alloc_fmr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_map_phys_fmr(struct ib_fmr *fmr, - u64 *page_list, - int list_len, - u64 iova) -{ - int ret; - struct ehca_shca *shca = - container_of(fmr->device, struct ehca_shca, ib_device); - struct ehca_mr *e_fmr = container_of(fmr, struct ehca_mr, ib.ib_fmr); - struct ehca_pd *e_pd = container_of(fmr->pd, struct ehca_pd, ib_pd); - struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; - u32 tmp_lkey, tmp_rkey; - - if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) { - ehca_err(fmr->device, "not a FMR, e_fmr=%p e_fmr->flags=%x", - e_fmr, e_fmr->flags); - ret = -EINVAL; - goto map_phys_fmr_exit0; - } - ret = ehca_fmr_check_page_list(e_fmr, page_list, list_len); - if (ret) - goto map_phys_fmr_exit0; - if (iova % e_fmr->fmr_page_size) { - /* only whole-numbered pages */ - ehca_err(fmr->device, "bad iova, iova=%lx fmr_page_size=%x", - iova, e_fmr->fmr_page_size); - ret = -EINVAL; - goto map_phys_fmr_exit0; - } - if (e_fmr->fmr_map_cnt >= e_fmr->fmr_max_maps) { - /* HCAD does not limit the maps, however trace this anyway */ - ehca_info(fmr->device, "map limit exceeded, fmr=%p " - "e_fmr->fmr_map_cnt=%x e_fmr->fmr_max_maps=%x", - fmr, e_fmr->fmr_map_cnt, e_fmr->fmr_max_maps); - } - - pginfo.type = EHCA_MR_PGI_FMR; - pginfo.num_pages = list_len; - pginfo.num_4k = list_len * (e_fmr->fmr_page_size / EHCA_PAGESIZE); - pginfo.page_list = page_list; - pginfo.next_4k = ((iova & (e_fmr->fmr_page_size-1)) / - EHCA_PAGESIZE); - - ret = ehca_rereg_mr(shca, e_fmr, (u64*)iova, - list_len * e_fmr->fmr_page_size, - e_fmr->acl, e_pd, &pginfo, &tmp_lkey, &tmp_rkey); - if (ret) - goto map_phys_fmr_exit0; - - /* successful reregistration */ - e_fmr->fmr_map_cnt++; - e_fmr->ib.ib_fmr.lkey = tmp_lkey; - e_fmr->ib.ib_fmr.rkey = tmp_rkey; - return 0; - -map_phys_fmr_exit0: - if (ret) - ehca_err(fmr->device, "ret=%x fmr=%p page_list=%p list_len=%x " - "iova=%lx", - ret, fmr, page_list, list_len, iova); - return ret; -} /* end ehca_map_phys_fmr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_unmap_fmr(struct list_head *fmr_list) -{ - int ret = 0; - struct ib_fmr *ib_fmr; - struct ehca_shca *shca = NULL; - struct ehca_shca *prev_shca; - struct ehca_mr *e_fmr; - u32 num_fmr = 0; - u32 unmap_fmr_cnt = 0; - - /* check all FMR belong to same SHCA, and check internal flag */ - list_for_each_entry(ib_fmr, fmr_list, list) { - prev_shca = shca; - if (!ib_fmr) { - ehca_gen_err("bad fmr=%p in list", ib_fmr); - ret = -EINVAL; - goto unmap_fmr_exit0; - } - shca = container_of(ib_fmr->device, struct ehca_shca, - ib_device); - e_fmr = container_of(ib_fmr, struct ehca_mr, ib.ib_fmr); - if ((shca != prev_shca) && prev_shca) { - ehca_err(&shca->ib_device, "SHCA mismatch, shca=%p " - "prev_shca=%p e_fmr=%p", - shca, prev_shca, e_fmr); - ret = -EINVAL; - goto unmap_fmr_exit0; - } - if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) { - ehca_err(&shca->ib_device, "not a FMR, e_fmr=%p " - "e_fmr->flags=%x", e_fmr, e_fmr->flags); - ret = -EINVAL; - goto unmap_fmr_exit0; - } - num_fmr++; - } - - /* loop over all FMRs to unmap */ - list_for_each_entry(ib_fmr, fmr_list, list) { - unmap_fmr_cnt++; - e_fmr = container_of(ib_fmr, struct ehca_mr, ib.ib_fmr); - shca = container_of(ib_fmr->device, struct ehca_shca, - ib_device); - ret = ehca_unmap_one_fmr(shca, e_fmr); - if (ret) { - /* unmap failed, stop unmapping of rest of FMRs */ - ehca_err(&shca->ib_device, "unmap of one FMR failed, " - "stop rest, e_fmr=%p num_fmr=%x " - "unmap_fmr_cnt=%x lkey=%x", e_fmr, num_fmr, - unmap_fmr_cnt, e_fmr->ib.ib_fmr.lkey); - goto unmap_fmr_exit0; - } - } - -unmap_fmr_exit0: - if (ret) - ehca_gen_err("ret=%x fmr_list=%p num_fmr=%x unmap_fmr_cnt=%x", - ret, fmr_list, num_fmr, unmap_fmr_cnt); - return ret; -} /* end ehca_unmap_fmr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_dealloc_fmr(struct ib_fmr *fmr) -{ - int ret; - u64 h_ret; - struct ehca_shca *shca = - container_of(fmr->device, struct ehca_shca, ib_device); - struct ehca_mr *e_fmr = container_of(fmr, struct ehca_mr, ib.ib_fmr); - - if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) { - ehca_err(fmr->device, "not a FMR, e_fmr=%p e_fmr->flags=%x", - e_fmr, e_fmr->flags); - ret = -EINVAL; - goto free_fmr_exit0; - } - - h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr); - if (h_ret != H_SUCCESS) { - ehca_err(fmr->device, "hipz_free_mr failed, h_ret=%lx e_fmr=%p " - "hca_hndl=%lx fmr_hndl=%lx fmr->lkey=%x", - h_ret, e_fmr, shca->ipz_hca_handle.handle, - e_fmr->ipz_mr_handle.handle, fmr->lkey); - ret = ehca_mrmw_map_hrc_free_mr(h_ret); - goto free_fmr_exit0; - } - /* successful deregistration */ - ehca_mr_delete(e_fmr); - return 0; - -free_fmr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%x fmr=%p", ret, fmr); - return ret; -} /* end ehca_dealloc_fmr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_reg_mr(struct ehca_shca *shca, - struct ehca_mr *e_mr, - u64 *iova_start, - u64 size, - int acl, - struct ehca_pd *e_pd, - struct ehca_mr_pginfo *pginfo, - u32 *lkey, /*OUT*/ - u32 *rkey) /*OUT*/ -{ - int ret; - u64 h_ret; - u32 hipz_acl; - struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0}; - - ehca_mrmw_map_acl(acl, &hipz_acl); - ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl); - if (ehca_use_hp_mr == 1) - hipz_acl |= 0x00000001; - - h_ret = hipz_h_alloc_resource_mr(shca->ipz_hca_handle, e_mr, - (u64)iova_start, size, hipz_acl, - e_pd->fw_pd, &hipzout); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "hipz_alloc_mr failed, h_ret=%lx " - "hca_hndl=%lx", h_ret, shca->ipz_hca_handle.handle); - ret = ehca_mrmw_map_hrc_alloc(h_ret); - goto ehca_reg_mr_exit0; - } - - e_mr->ipz_mr_handle = hipzout.handle; - - ret = ehca_reg_mr_rpages(shca, e_mr, pginfo); - if (ret) - goto ehca_reg_mr_exit1; - - /* successful registration */ - e_mr->num_pages = pginfo->num_pages; - e_mr->num_4k = pginfo->num_4k; - e_mr->start = iova_start; - e_mr->size = size; - e_mr->acl = acl; - *lkey = hipzout.lkey; - *rkey = hipzout.rkey; - return 0; - -ehca_reg_mr_exit1: - h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "h_ret=%lx shca=%p e_mr=%p " - "iova_start=%p size=%lx acl=%x e_pd=%p lkey=%x " - "pginfo=%p num_pages=%lx num_4k=%lx ret=%x", - h_ret, shca, e_mr, iova_start, size, acl, e_pd, - hipzout.lkey, pginfo, pginfo->num_pages, - pginfo->num_4k, ret); - ehca_err(&shca->ib_device, "internal error in ehca_reg_mr, " - "not recoverable"); - } -ehca_reg_mr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%x shca=%p e_mr=%p " - "iova_start=%p size=%lx acl=%x e_pd=%p pginfo=%p " - "num_pages=%lx num_4k=%lx", - ret, shca, e_mr, iova_start, size, acl, e_pd, pginfo, - pginfo->num_pages, pginfo->num_4k); - return ret; -} /* end ehca_reg_mr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_reg_mr_rpages(struct ehca_shca *shca, - struct ehca_mr *e_mr, - struct ehca_mr_pginfo *pginfo) -{ - int ret = 0; - u64 h_ret; - u32 rnum; - u64 rpage; - u32 i; - u64 *kpage; - - kpage = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); - if (!kpage) { - ehca_err(&shca->ib_device, "kpage alloc failed"); - ret = -ENOMEM; - goto ehca_reg_mr_rpages_exit0; - } - - /* max 512 pages per shot */ - for (i = 0; i < ((pginfo->num_4k + 512 - 1) / 512); i++) { - - if (i == ((pginfo->num_4k + 512 - 1) / 512) - 1) { - rnum = pginfo->num_4k % 512; /* last shot */ - if (rnum == 0) - rnum = 512; /* last shot is full */ - } else - rnum = 512; - - if (rnum > 1) { - ret = ehca_set_pagebuf(e_mr, pginfo, rnum, kpage); - if (ret) { - ehca_err(&shca->ib_device, "ehca_set_pagebuf " - "bad rc, ret=%x rnum=%x kpage=%p", - ret, rnum, kpage); - ret = -EFAULT; - goto ehca_reg_mr_rpages_exit1; - } - rpage = virt_to_abs(kpage); - if (!rpage) { - ehca_err(&shca->ib_device, "kpage=%p i=%x", - kpage, i); - ret = -EFAULT; - goto ehca_reg_mr_rpages_exit1; - } - } else { /* rnum==1 */ - ret = ehca_set_pagebuf_1(e_mr, pginfo, &rpage); - if (ret) { - ehca_err(&shca->ib_device, "ehca_set_pagebuf_1 " - "bad rc, ret=%x i=%x", ret, i); - ret = -EFAULT; - goto ehca_reg_mr_rpages_exit1; - } - } - - h_ret = hipz_h_register_rpage_mr(shca->ipz_hca_handle, e_mr, - 0, /* pagesize 4k */ - 0, rpage, rnum); - - if (i == ((pginfo->num_4k + 512 - 1) / 512) - 1) { - /* - * check for 'registration complete'==H_SUCCESS - * and for 'page registered'==H_PAGE_REGISTERED - */ - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "last " - "hipz_reg_rpage_mr failed, h_ret=%lx " - "e_mr=%p i=%x hca_hndl=%lx mr_hndl=%lx" - " lkey=%x", h_ret, e_mr, i, - shca->ipz_hca_handle.handle, - e_mr->ipz_mr_handle.handle, - e_mr->ib.ib_mr.lkey); - ret = ehca_mrmw_map_hrc_rrpg_last(h_ret); - break; - } else - ret = 0; - } else if (h_ret != H_PAGE_REGISTERED) { - ehca_err(&shca->ib_device, "hipz_reg_rpage_mr failed, " - "h_ret=%lx e_mr=%p i=%x lkey=%x hca_hndl=%lx " - "mr_hndl=%lx", h_ret, e_mr, i, - e_mr->ib.ib_mr.lkey, - shca->ipz_hca_handle.handle, - e_mr->ipz_mr_handle.handle); - ret = ehca_mrmw_map_hrc_rrpg_notlast(h_ret); - break; - } else - ret = 0; - } /* end for(i) */ - - -ehca_reg_mr_rpages_exit1: - kfree(kpage); -ehca_reg_mr_rpages_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%x shca=%p e_mr=%p pginfo=%p " - "num_pages=%lx num_4k=%lx", ret, shca, e_mr, pginfo, - pginfo->num_pages, pginfo->num_4k); - return ret; -} /* end ehca_reg_mr_rpages() */ - -/*----------------------------------------------------------------------*/ - -inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca, - struct ehca_mr *e_mr, - u64 *iova_start, - u64 size, - u32 acl, - struct ehca_pd *e_pd, - struct ehca_mr_pginfo *pginfo, - u32 *lkey, /*OUT*/ - u32 *rkey) /*OUT*/ -{ - int ret; - u64 h_ret; - u32 hipz_acl; - u64 *kpage; - u64 rpage; - struct ehca_mr_pginfo pginfo_save; - struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0}; - - ehca_mrmw_map_acl(acl, &hipz_acl); - ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl); - - kpage = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); - if (!kpage) { - ehca_err(&shca->ib_device, "kpage alloc failed"); - ret = -ENOMEM; - goto ehca_rereg_mr_rereg1_exit0; - } - - pginfo_save = *pginfo; - ret = ehca_set_pagebuf(e_mr, pginfo, pginfo->num_4k, kpage); - if (ret) { - ehca_err(&shca->ib_device, "set pagebuf failed, e_mr=%p " - "pginfo=%p type=%x num_pages=%lx num_4k=%lx kpage=%p", - e_mr, pginfo, pginfo->type, pginfo->num_pages, - pginfo->num_4k,kpage); - goto ehca_rereg_mr_rereg1_exit1; - } - rpage = virt_to_abs(kpage); - if (!rpage) { - ehca_err(&shca->ib_device, "kpage=%p", kpage); - ret = -EFAULT; - goto ehca_rereg_mr_rereg1_exit1; - } - h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_mr, - (u64)iova_start, size, hipz_acl, - e_pd->fw_pd, rpage, &hipzout); - if (h_ret != H_SUCCESS) { - /* - * reregistration unsuccessful, try it again with the 3 hCalls, - * e.g. this is required in case H_MR_CONDITION - * (MW bound or MR is shared) - */ - ehca_warn(&shca->ib_device, "hipz_h_reregister_pmr failed " - "(Rereg1), h_ret=%lx e_mr=%p", h_ret, e_mr); - *pginfo = pginfo_save; - ret = -EAGAIN; - } else if ((u64*)hipzout.vaddr != iova_start) { - ehca_err(&shca->ib_device, "PHYP changed iova_start in " - "rereg_pmr, iova_start=%p iova_start_out=%lx e_mr=%p " - "mr_handle=%lx lkey=%x lkey_out=%x", iova_start, - hipzout.vaddr, e_mr, e_mr->ipz_mr_handle.handle, - e_mr->ib.ib_mr.lkey, hipzout.lkey); - ret = -EFAULT; - } else { - /* - * successful reregistration - * note: start and start_out are identical for eServer HCAs - */ - e_mr->num_pages = pginfo->num_pages; - e_mr->num_4k = pginfo->num_4k; - e_mr->start = iova_start; - e_mr->size = size; - e_mr->acl = acl; - *lkey = hipzout.lkey; - *rkey = hipzout.rkey; - } - -ehca_rereg_mr_rereg1_exit1: - kfree(kpage); -ehca_rereg_mr_rereg1_exit0: - if ( ret && (ret != -EAGAIN) ) - ehca_err(&shca->ib_device, "ret=%x lkey=%x rkey=%x " - "pginfo=%p num_pages=%lx num_4k=%lx", - ret, *lkey, *rkey, pginfo, pginfo->num_pages, - pginfo->num_4k); - return ret; -} /* end ehca_rereg_mr_rereg1() */ - -/*----------------------------------------------------------------------*/ - -int ehca_rereg_mr(struct ehca_shca *shca, - struct ehca_mr *e_mr, - u64 *iova_start, - u64 size, - int acl, - struct ehca_pd *e_pd, - struct ehca_mr_pginfo *pginfo, - u32 *lkey, - u32 *rkey) -{ - int ret = 0; - u64 h_ret; - int rereg_1_hcall = 1; /* 1: use hipz_h_reregister_pmr directly */ - int rereg_3_hcall = 0; /* 1: use 3 hipz calls for reregistration */ - - /* first determine reregistration hCall(s) */ - if ((pginfo->num_4k > 512) || (e_mr->num_4k > 512) || - (pginfo->num_4k > e_mr->num_4k)) { - ehca_dbg(&shca->ib_device, "Rereg3 case, pginfo->num_4k=%lx " - "e_mr->num_4k=%x", pginfo->num_4k, e_mr->num_4k); - rereg_1_hcall = 0; - rereg_3_hcall = 1; - } - - if (e_mr->flags & EHCA_MR_FLAG_MAXMR) { /* check for max-MR */ - rereg_1_hcall = 0; - rereg_3_hcall = 1; - e_mr->flags &= ~EHCA_MR_FLAG_MAXMR; - ehca_err(&shca->ib_device, "Rereg MR for max-MR! e_mr=%p", - e_mr); - } - - if (rereg_1_hcall) { - ret = ehca_rereg_mr_rereg1(shca, e_mr, iova_start, size, - acl, e_pd, pginfo, lkey, rkey); - if (ret) { - if (ret == -EAGAIN) - rereg_3_hcall = 1; - else - goto ehca_rereg_mr_exit0; - } - } - - if (rereg_3_hcall) { - struct ehca_mr save_mr; - - /* first deregister old MR */ - h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "hipz_free_mr failed, " - "h_ret=%lx e_mr=%p hca_hndl=%lx mr_hndl=%lx " - "mr->lkey=%x", - h_ret, e_mr, shca->ipz_hca_handle.handle, - e_mr->ipz_mr_handle.handle, - e_mr->ib.ib_mr.lkey); - ret = ehca_mrmw_map_hrc_free_mr(h_ret); - goto ehca_rereg_mr_exit0; - } - /* clean ehca_mr_t, without changing struct ib_mr and lock */ - save_mr = *e_mr; - ehca_mr_deletenew(e_mr); - - /* set some MR values */ - e_mr->flags = save_mr.flags; - e_mr->fmr_page_size = save_mr.fmr_page_size; - e_mr->fmr_max_pages = save_mr.fmr_max_pages; - e_mr->fmr_max_maps = save_mr.fmr_max_maps; - e_mr->fmr_map_cnt = save_mr.fmr_map_cnt; - - ret = ehca_reg_mr(shca, e_mr, iova_start, size, acl, - e_pd, pginfo, lkey, rkey); - if (ret) { - u32 offset = (u64)(&e_mr->flags) - (u64)e_mr; - memcpy(&e_mr->flags, &(save_mr.flags), - sizeof(struct ehca_mr) - offset); - goto ehca_rereg_mr_exit0; - } - } - -ehca_rereg_mr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%x shca=%p e_mr=%p " - "iova_start=%p size=%lx acl=%x e_pd=%p pginfo=%p " - "num_pages=%lx lkey=%x rkey=%x rereg_1_hcall=%x " - "rereg_3_hcall=%x", ret, shca, e_mr, iova_start, size, - acl, e_pd, pginfo, pginfo->num_pages, *lkey, *rkey, - rereg_1_hcall, rereg_3_hcall); - return ret; -} /* end ehca_rereg_mr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_unmap_one_fmr(struct ehca_shca *shca, - struct ehca_mr *e_fmr) -{ - int ret = 0; - u64 h_ret; - int rereg_1_hcall = 1; /* 1: use hipz_mr_reregister directly */ - int rereg_3_hcall = 0; /* 1: use 3 hipz calls for unmapping */ - struct ehca_pd *e_pd = - container_of(e_fmr->ib.ib_fmr.pd, struct ehca_pd, ib_pd); - struct ehca_mr save_fmr; - u32 tmp_lkey, tmp_rkey; - struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; - struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0}; - - /* first check if reregistration hCall can be used for unmap */ - if (e_fmr->fmr_max_pages > 512) { - rereg_1_hcall = 0; - rereg_3_hcall = 1; - } - - if (rereg_1_hcall) { - /* - * note: after using rereg hcall with len=0, - * rereg hcall must be used again for registering pages - */ - h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_fmr, 0, - 0, 0, e_pd->fw_pd, 0, &hipzout); - if (h_ret != H_SUCCESS) { - /* - * should not happen, because length checked above, - * FMRs are not shared and no MW bound to FMRs - */ - ehca_err(&shca->ib_device, "hipz_reregister_pmr failed " - "(Rereg1), h_ret=%lx e_fmr=%p hca_hndl=%lx " - "mr_hndl=%lx lkey=%x lkey_out=%x", - h_ret, e_fmr, shca->ipz_hca_handle.handle, - e_fmr->ipz_mr_handle.handle, - e_fmr->ib.ib_fmr.lkey, hipzout.lkey); - rereg_3_hcall = 1; - } else { - /* successful reregistration */ - e_fmr->start = NULL; - e_fmr->size = 0; - tmp_lkey = hipzout.lkey; - tmp_rkey = hipzout.rkey; - } - } - - if (rereg_3_hcall) { - struct ehca_mr save_mr; - - /* first free old FMR */ - h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "hipz_free_mr failed, " - "h_ret=%lx e_fmr=%p hca_hndl=%lx mr_hndl=%lx " - "lkey=%x", - h_ret, e_fmr, shca->ipz_hca_handle.handle, - e_fmr->ipz_mr_handle.handle, - e_fmr->ib.ib_fmr.lkey); - ret = ehca_mrmw_map_hrc_free_mr(h_ret); - goto ehca_unmap_one_fmr_exit0; - } - /* clean ehca_mr_t, without changing lock */ - save_fmr = *e_fmr; - ehca_mr_deletenew(e_fmr); - - /* set some MR values */ - e_fmr->flags = save_fmr.flags; - e_fmr->fmr_page_size = save_fmr.fmr_page_size; - e_fmr->fmr_max_pages = save_fmr.fmr_max_pages; - e_fmr->fmr_max_maps = save_fmr.fmr_max_maps; - e_fmr->fmr_map_cnt = save_fmr.fmr_map_cnt; - e_fmr->acl = save_fmr.acl; - - pginfo.type = EHCA_MR_PGI_FMR; - pginfo.num_pages = 0; - pginfo.num_4k = 0; - ret = ehca_reg_mr(shca, e_fmr, NULL, - (e_fmr->fmr_max_pages * e_fmr->fmr_page_size), - e_fmr->acl, e_pd, &pginfo, &tmp_lkey, - &tmp_rkey); - if (ret) { - u32 offset = (u64)(&e_fmr->flags) - (u64)e_fmr; - memcpy(&e_fmr->flags, &(save_mr.flags), - sizeof(struct ehca_mr) - offset); - goto ehca_unmap_one_fmr_exit0; - } - } - -ehca_unmap_one_fmr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%x tmp_lkey=%x tmp_rkey=%x " - "fmr_max_pages=%x rereg_1_hcall=%x rereg_3_hcall=%x", - ret, tmp_lkey, tmp_rkey, e_fmr->fmr_max_pages, - rereg_1_hcall, rereg_3_hcall); - return ret; -} /* end ehca_unmap_one_fmr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_reg_smr(struct ehca_shca *shca, - struct ehca_mr *e_origmr, - struct ehca_mr *e_newmr, - u64 *iova_start, - int acl, - struct ehca_pd *e_pd, - u32 *lkey, /*OUT*/ - u32 *rkey) /*OUT*/ -{ - int ret = 0; - u64 h_ret; - u32 hipz_acl; - struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0}; - - ehca_mrmw_map_acl(acl, &hipz_acl); - ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl); - - h_ret = hipz_h_register_smr(shca->ipz_hca_handle, e_newmr, e_origmr, - (u64)iova_start, hipz_acl, e_pd->fw_pd, - &hipzout); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%lx " - "shca=%p e_origmr=%p e_newmr=%p iova_start=%p acl=%x " - "e_pd=%p hca_hndl=%lx mr_hndl=%lx lkey=%x", - h_ret, shca, e_origmr, e_newmr, iova_start, acl, e_pd, - shca->ipz_hca_handle.handle, - e_origmr->ipz_mr_handle.handle, - e_origmr->ib.ib_mr.lkey); - ret = ehca_mrmw_map_hrc_reg_smr(h_ret); - goto ehca_reg_smr_exit0; - } - /* successful registration */ - e_newmr->num_pages = e_origmr->num_pages; - e_newmr->num_4k = e_origmr->num_4k; - e_newmr->start = iova_start; - e_newmr->size = e_origmr->size; - e_newmr->acl = acl; - e_newmr->ipz_mr_handle = hipzout.handle; - *lkey = hipzout.lkey; - *rkey = hipzout.rkey; - return 0; - -ehca_reg_smr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%x shca=%p e_origmr=%p " - "e_newmr=%p iova_start=%p acl=%x e_pd=%p", - ret, shca, e_origmr, e_newmr, iova_start, acl, e_pd); - return ret; -} /* end ehca_reg_smr() */ - -/*----------------------------------------------------------------------*/ - -/* register internal max-MR to internal SHCA */ -int ehca_reg_internal_maxmr( - struct ehca_shca *shca, - struct ehca_pd *e_pd, - struct ehca_mr **e_maxmr) /*OUT*/ -{ - int ret; - struct ehca_mr *e_mr; - u64 *iova_start; - u64 size_maxmr; - struct ehca_mr_pginfo pginfo={0,0,0,0,0,0,0,NULL,0,NULL,NULL,0,NULL,0}; - struct ib_phys_buf ib_pbuf; - u32 num_pages_mr; - u32 num_pages_4k; /* 4k portion "pages" */ - - e_mr = ehca_mr_new(); - if (!e_mr) { - ehca_err(&shca->ib_device, "out of memory"); - ret = -ENOMEM; - goto ehca_reg_internal_maxmr_exit0; - } - e_mr->flags |= EHCA_MR_FLAG_MAXMR; - - /* register internal max-MR on HCA */ - size_maxmr = (u64)high_memory - PAGE_OFFSET; - iova_start = (u64*)KERNELBASE; - ib_pbuf.addr = 0; - ib_pbuf.size = size_maxmr; - num_pages_mr = ((((u64)iova_start % PAGE_SIZE) + size_maxmr + - PAGE_SIZE - 1) / PAGE_SIZE); - num_pages_4k = ((((u64)iova_start % EHCA_PAGESIZE) + size_maxmr + - EHCA_PAGESIZE - 1) / EHCA_PAGESIZE); - - pginfo.type = EHCA_MR_PGI_PHYS; - pginfo.num_pages = num_pages_mr; - pginfo.num_4k = num_pages_4k; - pginfo.num_phys_buf = 1; - pginfo.phys_buf_array = &ib_pbuf; - - ret = ehca_reg_mr(shca, e_mr, iova_start, size_maxmr, 0, e_pd, - &pginfo, &e_mr->ib.ib_mr.lkey, - &e_mr->ib.ib_mr.rkey); - if (ret) { - ehca_err(&shca->ib_device, "reg of internal max MR failed, " - "e_mr=%p iova_start=%p size_maxmr=%lx num_pages_mr=%x " - "num_pages_4k=%x", e_mr, iova_start, size_maxmr, - num_pages_mr, num_pages_4k); - goto ehca_reg_internal_maxmr_exit1; - } - - /* successful registration of all pages */ - e_mr->ib.ib_mr.device = e_pd->ib_pd.device; - e_mr->ib.ib_mr.pd = &e_pd->ib_pd; - e_mr->ib.ib_mr.uobject = NULL; - atomic_inc(&(e_pd->ib_pd.usecnt)); - atomic_set(&(e_mr->ib.ib_mr.usecnt), 0); - *e_maxmr = e_mr; - return 0; - -ehca_reg_internal_maxmr_exit1: - ehca_mr_delete(e_mr); -ehca_reg_internal_maxmr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%x shca=%p e_pd=%p e_maxmr=%p", - ret, shca, e_pd, e_maxmr); - return ret; -} /* end ehca_reg_internal_maxmr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_reg_maxmr(struct ehca_shca *shca, - struct ehca_mr *e_newmr, - u64 *iova_start, - int acl, - struct ehca_pd *e_pd, - u32 *lkey, - u32 *rkey) -{ - u64 h_ret; - struct ehca_mr *e_origmr = shca->maxmr; - u32 hipz_acl; - struct ehca_mr_hipzout_parms hipzout = {{0},0,0,0,0,0}; - - ehca_mrmw_map_acl(acl, &hipz_acl); - ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl); - - h_ret = hipz_h_register_smr(shca->ipz_hca_handle, e_newmr, e_origmr, - (u64)iova_start, hipz_acl, e_pd->fw_pd, - &hipzout); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "hipz_reg_smr failed, h_ret=%lx " - "e_origmr=%p hca_hndl=%lx mr_hndl=%lx lkey=%x", - h_ret, e_origmr, shca->ipz_hca_handle.handle, - e_origmr->ipz_mr_handle.handle, - e_origmr->ib.ib_mr.lkey); - return ehca_mrmw_map_hrc_reg_smr(h_ret); - } - /* successful registration */ - e_newmr->num_pages = e_origmr->num_pages; - e_newmr->num_4k = e_origmr->num_4k; - e_newmr->start = iova_start; - e_newmr->size = e_origmr->size; - e_newmr->acl = acl; - e_newmr->ipz_mr_handle = hipzout.handle; - *lkey = hipzout.lkey; - *rkey = hipzout.rkey; - return 0; -} /* end ehca_reg_maxmr() */ - -/*----------------------------------------------------------------------*/ - -int ehca_dereg_internal_maxmr(struct ehca_shca *shca) -{ - int ret; - struct ehca_mr *e_maxmr; - struct ib_pd *ib_pd; - - if (!shca->maxmr) { - ehca_err(&shca->ib_device, "bad call, shca=%p", shca); - ret = -EINVAL; - goto ehca_dereg_internal_maxmr_exit0; - } - - e_maxmr = shca->maxmr; - ib_pd = e_maxmr->ib.ib_mr.pd; - shca->maxmr = NULL; /* remove internal max-MR indication from SHCA */ - - ret = ehca_dereg_mr(&e_maxmr->ib.ib_mr); - if (ret) { - ehca_err(&shca->ib_device, "dereg internal max-MR failed, " - "ret=%x e_maxmr=%p shca=%p lkey=%x", - ret, e_maxmr, shca, e_maxmr->ib.ib_mr.lkey); - shca->maxmr = e_maxmr; - goto ehca_dereg_internal_maxmr_exit0; - } - - atomic_dec(&ib_pd->usecnt); - -ehca_dereg_internal_maxmr_exit0: - if (ret) - ehca_err(&shca->ib_device, "ret=%x shca=%p shca->maxmr=%p", - ret, shca, shca->maxmr); - return ret; -} /* end ehca_dereg_internal_maxmr() */ - -/*----------------------------------------------------------------------*/ - -/* - * check physical buffer array of MR verbs for validness and - * calculates MR size - */ -int ehca_mr_chk_buf_and_calc_size(struct ib_phys_buf *phys_buf_array, - int num_phys_buf, - u64 *iova_start, - u64 *size) -{ - struct ib_phys_buf *pbuf = phys_buf_array; - u64 size_count = 0; - u32 i; - - if (num_phys_buf == 0) { - ehca_gen_err("bad phys buf array len, num_phys_buf=0"); - return -EINVAL; - } - /* check first buffer */ - if (((u64)iova_start & ~PAGE_MASK) != (pbuf->addr & ~PAGE_MASK)) { - ehca_gen_err("iova_start/addr mismatch, iova_start=%p " - "pbuf->addr=%lx pbuf->size=%lx", - iova_start, pbuf->addr, pbuf->size); - return -EINVAL; - } - if (((pbuf->addr + pbuf->size) % PAGE_SIZE) && - (num_phys_buf > 1)) { - ehca_gen_err("addr/size mismatch in 1st buf, pbuf->addr=%lx " - "pbuf->size=%lx", pbuf->addr, pbuf->size); - return -EINVAL; - } - - for (i = 0; i < num_phys_buf; i++) { - if ((i > 0) && (pbuf->addr % PAGE_SIZE)) { - ehca_gen_err("bad address, i=%x pbuf->addr=%lx " - "pbuf->size=%lx", - i, pbuf->addr, pbuf->size); - return -EINVAL; - } - if (((i > 0) && /* not 1st */ - (i < (num_phys_buf - 1)) && /* not last */ - (pbuf->size % PAGE_SIZE)) || (pbuf->size == 0)) { - ehca_gen_err("bad size, i=%x pbuf->size=%lx", - i, pbuf->size); - return -EINVAL; - } - size_count += pbuf->size; - pbuf++; - } - - *size = size_count; - return 0; -} /* end ehca_mr_chk_buf_and_calc_size() */ - -/*----------------------------------------------------------------------*/ - -/* check page list of map FMR verb for validness */ -int ehca_fmr_check_page_list(struct ehca_mr *e_fmr, - u64 *page_list, - int list_len) -{ - u32 i; - u64 *page; - - if ((list_len == 0) || (list_len > e_fmr->fmr_max_pages)) { - ehca_gen_err("bad list_len, list_len=%x " - "e_fmr->fmr_max_pages=%x fmr=%p", - list_len, e_fmr->fmr_max_pages, e_fmr); - return -EINVAL; - } - - /* each page must be aligned */ - page = page_list; - for (i = 0; i < list_len; i++) { - if (*page % e_fmr->fmr_page_size) { - ehca_gen_err("bad page, i=%x *page=%lx page=%p fmr=%p " - "fmr_page_size=%x", i, *page, page, e_fmr, - e_fmr->fmr_page_size); - return -EINVAL; - } - page++; - } - - return 0; -} /* end ehca_fmr_check_page_list() */ - -/*----------------------------------------------------------------------*/ - -/* setup page buffer from page info */ -int ehca_set_pagebuf(struct ehca_mr *e_mr, - struct ehca_mr_pginfo *pginfo, - u32 number, - u64 *kpage) -{ - int ret = 0; - struct ib_umem_chunk *prev_chunk; - struct ib_umem_chunk *chunk; - struct ib_phys_buf *pbuf; - u64 *fmrlist; - u64 num4k, pgaddr, offs4k; - u32 i = 0; - u32 j = 0; - - if (pginfo->type == EHCA_MR_PGI_PHYS) { - /* loop over desired phys_buf_array entries */ - while (i < number) { - pbuf = pginfo->phys_buf_array + pginfo->next_buf; - num4k = ((pbuf->addr % EHCA_PAGESIZE) + pbuf->size + - EHCA_PAGESIZE - 1) / EHCA_PAGESIZE; - offs4k = (pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE; - while (pginfo->next_4k < offs4k + num4k) { - /* sanity check */ - if ((pginfo->page_cnt >= pginfo->num_pages) || - (pginfo->page_4k_cnt >= pginfo->num_4k)) { - ehca_gen_err("page_cnt >= num_pages, " - "page_cnt=%lx " - "num_pages=%lx " - "page_4k_cnt=%lx " - "num_4k=%lx i=%x", - pginfo->page_cnt, - pginfo->num_pages, - pginfo->page_4k_cnt, - pginfo->num_4k, i); - ret = -EFAULT; - goto ehca_set_pagebuf_exit0; - } - *kpage = phys_to_abs( - (pbuf->addr & EHCA_PAGEMASK) - + (pginfo->next_4k * EHCA_PAGESIZE)); - if ( !(*kpage) && pbuf->addr ) { - ehca_gen_err("pbuf->addr=%lx " - "pbuf->size=%lx " - "next_4k=%lx", pbuf->addr, - pbuf->size, - pginfo->next_4k); - ret = -EFAULT; - goto ehca_set_pagebuf_exit0; - } - (pginfo->page_4k_cnt)++; - (pginfo->next_4k)++; - if (pginfo->next_4k % - (PAGE_SIZE / EHCA_PAGESIZE) == 0) - (pginfo->page_cnt)++; - kpage++; - i++; - if (i >= number) break; - } - if (pginfo->next_4k >= offs4k + num4k) { - (pginfo->next_buf)++; - pginfo->next_4k = 0; - } - } - } else if (pginfo->type == EHCA_MR_PGI_USER) { - /* loop over desired chunk entries */ - chunk = pginfo->next_chunk; - prev_chunk = pginfo->next_chunk; - list_for_each_entry_continue(chunk, - (&(pginfo->region->chunk_list)), - list) { - for (i = pginfo->next_nmap; i < chunk->nmap; ) { - pgaddr = ( page_to_pfn(chunk->page_list[i].page) - << PAGE_SHIFT ); - *kpage = phys_to_abs(pgaddr + - (pginfo->next_4k * - EHCA_PAGESIZE)); - if ( !(*kpage) ) { - ehca_gen_err("pgaddr=%lx " - "chunk->page_list[i]=%lx " - "i=%x next_4k=%lx mr=%p", - pgaddr, - (u64)sg_dma_address( - &chunk-> - page_list[i]), - i, pginfo->next_4k, e_mr); - ret = -EFAULT; - goto ehca_set_pagebuf_exit0; - } - (pginfo->page_4k_cnt)++; - (pginfo->next_4k)++; - kpage++; - if (pginfo->next_4k % - (PAGE_SIZE / EHCA_PAGESIZE) == 0) { - (pginfo->page_cnt)++; - (pginfo->next_nmap)++; - pginfo->next_4k = 0; - i++; - } - j++; - if (j >= number) break; - } - if ((pginfo->next_nmap >= chunk->nmap) && - (j >= number)) { - pginfo->next_nmap = 0; - prev_chunk = chunk; - break; - } else if (pginfo->next_nmap >= chunk->nmap) { - pginfo->next_nmap = 0; - prev_chunk = chunk; - } else if (j >= number) - break; - else - prev_chunk = chunk; - } - pginfo->next_chunk = - list_prepare_entry(prev_chunk, - (&(pginfo->region->chunk_list)), - list); - } else if (pginfo->type == EHCA_MR_PGI_FMR) { - /* loop over desired page_list entries */ - fmrlist = pginfo->page_list + pginfo->next_listelem; - for (i = 0; i < number; i++) { - *kpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) + - pginfo->next_4k * EHCA_PAGESIZE); - if ( !(*kpage) ) { - ehca_gen_err("*fmrlist=%lx fmrlist=%p " - "next_listelem=%lx next_4k=%lx", - *fmrlist, fmrlist, - pginfo->next_listelem, - pginfo->next_4k); - ret = -EFAULT; - goto ehca_set_pagebuf_exit0; - } - (pginfo->page_4k_cnt)++; - (pginfo->next_4k)++; - kpage++; - if (pginfo->next_4k % - (e_mr->fmr_page_size / EHCA_PAGESIZE) == 0) { - (pginfo->page_cnt)++; - (pginfo->next_listelem)++; - fmrlist++; - pginfo->next_4k = 0; - } - } - } else { - ehca_gen_err("bad pginfo->type=%x", pginfo->type); - ret = -EFAULT; - goto ehca_set_pagebuf_exit0; - } - -ehca_set_pagebuf_exit0: - if (ret) - ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_pages=%lx " - "num_4k=%lx next_buf=%lx next_4k=%lx number=%x " - "kpage=%p page_cnt=%lx page_4k_cnt=%lx i=%x " - "next_listelem=%lx region=%p next_chunk=%p " - "next_nmap=%lx", ret, e_mr, pginfo, pginfo->type, - pginfo->num_pages, pginfo->num_4k, - pginfo->next_buf, pginfo->next_4k, number, kpage, - pginfo->page_cnt, pginfo->page_4k_cnt, i, - pginfo->next_listelem, pginfo->region, - pginfo->next_chunk, pginfo->next_nmap); - return ret; -} /* end ehca_set_pagebuf() */ - -/*----------------------------------------------------------------------*/ - -/* setup 1 page from page info page buffer */ -int ehca_set_pagebuf_1(struct ehca_mr *e_mr, - struct ehca_mr_pginfo *pginfo, - u64 *rpage) -{ - int ret = 0; - struct ib_phys_buf *tmp_pbuf; - u64 *fmrlist; - struct ib_umem_chunk *chunk; - struct ib_umem_chunk *prev_chunk; - u64 pgaddr, num4k, offs4k; - - if (pginfo->type == EHCA_MR_PGI_PHYS) { - /* sanity check */ - if ((pginfo->page_cnt >= pginfo->num_pages) || - (pginfo->page_4k_cnt >= pginfo->num_4k)) { - ehca_gen_err("page_cnt >= num_pages, page_cnt=%lx " - "num_pages=%lx page_4k_cnt=%lx num_4k=%lx", - pginfo->page_cnt, pginfo->num_pages, - pginfo->page_4k_cnt, pginfo->num_4k); - ret = -EFAULT; - goto ehca_set_pagebuf_1_exit0; - } - tmp_pbuf = pginfo->phys_buf_array + pginfo->next_buf; - num4k = ((tmp_pbuf->addr % EHCA_PAGESIZE) + tmp_pbuf->size + - EHCA_PAGESIZE - 1) / EHCA_PAGESIZE; - offs4k = (tmp_pbuf->addr & ~PAGE_MASK) / EHCA_PAGESIZE; - *rpage = phys_to_abs((tmp_pbuf->addr & EHCA_PAGEMASK) + - (pginfo->next_4k * EHCA_PAGESIZE)); - if ( !(*rpage) && tmp_pbuf->addr ) { - ehca_gen_err("tmp_pbuf->addr=%lx" - " tmp_pbuf->size=%lx next_4k=%lx", - tmp_pbuf->addr, tmp_pbuf->size, - pginfo->next_4k); - ret = -EFAULT; - goto ehca_set_pagebuf_1_exit0; - } - (pginfo->page_4k_cnt)++; - (pginfo->next_4k)++; - if (pginfo->next_4k % (PAGE_SIZE / EHCA_PAGESIZE) == 0) - (pginfo->page_cnt)++; - if (pginfo->next_4k >= offs4k + num4k) { - (pginfo->next_buf)++; - pginfo->next_4k = 0; - } - } else if (pginfo->type == EHCA_MR_PGI_USER) { - chunk = pginfo->next_chunk; - prev_chunk = pginfo->next_chunk; - list_for_each_entry_continue(chunk, - (&(pginfo->region->chunk_list)), - list) { - pgaddr = ( page_to_pfn(chunk->page_list[ - pginfo->next_nmap].page) - << PAGE_SHIFT); - *rpage = phys_to_abs(pgaddr + - (pginfo->next_4k * EHCA_PAGESIZE)); - if ( !(*rpage) ) { - ehca_gen_err("pgaddr=%lx chunk->page_list[]=%lx" - " next_nmap=%lx next_4k=%lx mr=%p", - pgaddr, (u64)sg_dma_address( - &chunk->page_list[ - pginfo-> - next_nmap]), - pginfo->next_nmap, pginfo->next_4k, - e_mr); - ret = -EFAULT; - goto ehca_set_pagebuf_1_exit0; - } - (pginfo->page_4k_cnt)++; - (pginfo->next_4k)++; - if (pginfo->next_4k % - (PAGE_SIZE / EHCA_PAGESIZE) == 0) { - (pginfo->page_cnt)++; - (pginfo->next_nmap)++; - pginfo->next_4k = 0; - } - if (pginfo->next_nmap >= chunk->nmap) { - pginfo->next_nmap = 0; - prev_chunk = chunk; - } - break; - } - pginfo->next_chunk = - list_prepare_entry(prev_chunk, - (&(pginfo->region->chunk_list)), - list); - } else if (pginfo->type == EHCA_MR_PGI_FMR) { - fmrlist = pginfo->page_list + pginfo->next_listelem; - *rpage = phys_to_abs((*fmrlist & EHCA_PAGEMASK) + - pginfo->next_4k * EHCA_PAGESIZE); - if ( !(*rpage) ) { - ehca_gen_err("*fmrlist=%lx fmrlist=%p " - "next_listelem=%lx next_4k=%lx", - *fmrlist, fmrlist, pginfo->next_listelem, - pginfo->next_4k); - ret = -EFAULT; - goto ehca_set_pagebuf_1_exit0; - } - (pginfo->page_4k_cnt)++; - (pginfo->next_4k)++; - if (pginfo->next_4k % - (e_mr->fmr_page_size / EHCA_PAGESIZE) == 0) { - (pginfo->page_cnt)++; - (pginfo->next_listelem)++; - pginfo->next_4k = 0; - } - } else { - ehca_gen_err("bad pginfo->type=%x", pginfo->type); - ret = -EFAULT; - goto ehca_set_pagebuf_1_exit0; - } - -ehca_set_pagebuf_1_exit0: - if (ret) - ehca_gen_err("ret=%x e_mr=%p pginfo=%p type=%x num_pages=%lx " - "num_4k=%lx next_buf=%lx next_4k=%lx rpage=%p " - "page_cnt=%lx page_4k_cnt=%lx next_listelem=%lx " - "region=%p next_chunk=%p next_nmap=%lx", ret, e_mr, - pginfo, pginfo->type, pginfo->num_pages, - pginfo->num_4k, pginfo->next_buf, pginfo->next_4k, - rpage, pginfo->page_cnt, pginfo->page_4k_cnt, - pginfo->next_listelem, pginfo->region, - pginfo->next_chunk, pginfo->next_nmap); - return ret; -} /* end ehca_set_pagebuf_1() */ - -/*----------------------------------------------------------------------*/ - -/* - * check MR if it is a max-MR, i.e. uses whole memory - * in case it's a max-MR 1 is returned, else 0 - */ -int ehca_mr_is_maxmr(u64 size, - u64 *iova_start) -{ - /* a MR is treated as max-MR only if it fits following: */ - if ((size == ((u64)high_memory - PAGE_OFFSET)) && - (iova_start == (void*)KERNELBASE)) { - ehca_gen_dbg("this is a max-MR"); - return 1; - } else - return 0; -} /* end ehca_mr_is_maxmr() */ - -/*----------------------------------------------------------------------*/ - -/* map access control for MR/MW. This routine is used for MR and MW. */ -void ehca_mrmw_map_acl(int ib_acl, - u32 *hipz_acl) -{ - *hipz_acl = 0; - if (ib_acl & IB_ACCESS_REMOTE_READ) - *hipz_acl |= HIPZ_ACCESSCTRL_R_READ; - if (ib_acl & IB_ACCESS_REMOTE_WRITE) - *hipz_acl |= HIPZ_ACCESSCTRL_R_WRITE; - if (ib_acl & IB_ACCESS_REMOTE_ATOMIC) - *hipz_acl |= HIPZ_ACCESSCTRL_R_ATOMIC; - if (ib_acl & IB_ACCESS_LOCAL_WRITE) - *hipz_acl |= HIPZ_ACCESSCTRL_L_WRITE; - if (ib_acl & IB_ACCESS_MW_BIND) - *hipz_acl |= HIPZ_ACCESSCTRL_MW_BIND; -} /* end ehca_mrmw_map_acl() */ - -/*----------------------------------------------------------------------*/ - -/* sets page size in hipz access control for MR/MW. */ -void ehca_mrmw_set_pgsize_hipz_acl(u32 *hipz_acl) /*INOUT*/ -{ - return; /* HCA supports only 4k */ -} /* end ehca_mrmw_set_pgsize_hipz_acl() */ - -/*----------------------------------------------------------------------*/ - -/* - * reverse map access control for MR/MW. - * This routine is used for MR and MW. - */ -void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl, - int *ib_acl) /*OUT*/ -{ - *ib_acl = 0; - if (*hipz_acl & HIPZ_ACCESSCTRL_R_READ) - *ib_acl |= IB_ACCESS_REMOTE_READ; - if (*hipz_acl & HIPZ_ACCESSCTRL_R_WRITE) - *ib_acl |= IB_ACCESS_REMOTE_WRITE; - if (*hipz_acl & HIPZ_ACCESSCTRL_R_ATOMIC) - *ib_acl |= IB_ACCESS_REMOTE_ATOMIC; - if (*hipz_acl & HIPZ_ACCESSCTRL_L_WRITE) - *ib_acl |= IB_ACCESS_LOCAL_WRITE; - if (*hipz_acl & HIPZ_ACCESSCTRL_MW_BIND) - *ib_acl |= IB_ACCESS_MW_BIND; -} /* end ehca_mrmw_reverse_map_acl() */ - - -/*----------------------------------------------------------------------*/ - -/* - * map HIPZ rc to IB retcodes for MR/MW allocations - * Used for hipz_mr_reg_alloc and hipz_mw_alloc. - */ -int ehca_mrmw_map_hrc_alloc(const u64 hipz_rc) -{ - switch (hipz_rc) { - case H_SUCCESS: /* successful completion */ - return 0; - case H_ADAPTER_PARM: /* invalid adapter handle */ - case H_RT_PARM: /* invalid resource type */ - case H_NOT_ENOUGH_RESOURCES: /* insufficient resources */ - case H_MLENGTH_PARM: /* invalid memory length */ - case H_MEM_ACCESS_PARM: /* invalid access controls */ - case H_CONSTRAINED: /* resource constraint */ - return -EINVAL; - case H_BUSY: /* long busy */ - return -EBUSY; - default: - return -EINVAL; - } -} /* end ehca_mrmw_map_hrc_alloc() */ - -/*----------------------------------------------------------------------*/ - -/* - * map HIPZ rc to IB retcodes for MR register rpage - * Used for hipz_h_register_rpage_mr at registering last page - */ -int ehca_mrmw_map_hrc_rrpg_last(const u64 hipz_rc) -{ - switch (hipz_rc) { - case H_SUCCESS: /* registration complete */ - return 0; - case H_PAGE_REGISTERED: /* page registered */ - case H_ADAPTER_PARM: /* invalid adapter handle */ - case H_RH_PARM: /* invalid resource handle */ -/* case H_QT_PARM: invalid queue type */ - case H_PARAMETER: /* - * invalid logical address, - * or count zero or greater 512 - */ - case H_TABLE_FULL: /* page table full */ - case H_HARDWARE: /* HCA not operational */ - return -EINVAL; - case H_BUSY: /* long busy */ - return -EBUSY; - default: - return -EINVAL; - } -} /* end ehca_mrmw_map_hrc_rrpg_last() */ - -/*----------------------------------------------------------------------*/ - -/* - * map HIPZ rc to IB retcodes for MR register rpage - * Used for hipz_h_register_rpage_mr at registering one page, but not last page - */ -int ehca_mrmw_map_hrc_rrpg_notlast(const u64 hipz_rc) -{ - switch (hipz_rc) { - case H_PAGE_REGISTERED: /* page registered */ - return 0; - case H_SUCCESS: /* registration complete */ - case H_ADAPTER_PARM: /* invalid adapter handle */ - case H_RH_PARM: /* invalid resource handle */ -/* case H_QT_PARM: invalid queue type */ - case H_PARAMETER: /* - * invalid logical address, - * or count zero or greater 512 - */ - case H_TABLE_FULL: /* page table full */ - case H_HARDWARE: /* HCA not operational */ - return -EINVAL; - case H_BUSY: /* long busy */ - return -EBUSY; - default: - return -EINVAL; - } -} /* end ehca_mrmw_map_hrc_rrpg_notlast() */ - -/*----------------------------------------------------------------------*/ - -/* map HIPZ rc to IB retcodes for MR query. Used for hipz_mr_query. */ -int ehca_mrmw_map_hrc_query_mr(const u64 hipz_rc) -{ - switch (hipz_rc) { - case H_SUCCESS: /* successful completion */ - return 0; - case H_ADAPTER_PARM: /* invalid adapter handle */ - case H_RH_PARM: /* invalid resource handle */ - return -EINVAL; - case H_BUSY: /* long busy */ - return -EBUSY; - default: - return -EINVAL; - } -} /* end ehca_mrmw_map_hrc_query_mr() */ - -/*----------------------------------------------------------------------*/ -/*----------------------------------------------------------------------*/ - -/* - * map HIPZ rc to IB retcodes for freeing MR resource - * Used for hipz_h_free_resource_mr - */ -int ehca_mrmw_map_hrc_free_mr(const u64 hipz_rc) -{ - switch (hipz_rc) { - case H_SUCCESS: /* resource freed */ - return 0; - case H_ADAPTER_PARM: /* invalid adapter handle */ - case H_RH_PARM: /* invalid resource handle */ - case H_R_STATE: /* invalid resource state */ - case H_HARDWARE: /* HCA not operational */ - return -EINVAL; - case H_RESOURCE: /* Resource in use */ - case H_BUSY: /* long busy */ - return -EBUSY; - default: - return -EINVAL; - } -} /* end ehca_mrmw_map_hrc_free_mr() */ - -/*----------------------------------------------------------------------*/ - -/* - * map HIPZ rc to IB retcodes for freeing MW resource - * Used for hipz_h_free_resource_mw - */ -int ehca_mrmw_map_hrc_free_mw(const u64 hipz_rc) -{ - switch (hipz_rc) { - case H_SUCCESS: /* resource freed */ - return 0; - case H_ADAPTER_PARM: /* invalid adapter handle */ - case H_RH_PARM: /* invalid resource handle */ - case H_R_STATE: /* invalid resource state */ - case H_HARDWARE: /* HCA not operational */ - return -EINVAL; - case H_RESOURCE: /* Resource in use */ - case H_BUSY: /* long busy */ - return -EBUSY; - default: - return -EINVAL; - } -} /* end ehca_mrmw_map_hrc_free_mw() */ - -/*----------------------------------------------------------------------*/ - -/* - * map HIPZ rc to IB retcodes for SMR registrations - * Used for hipz_h_register_smr. - */ -int ehca_mrmw_map_hrc_reg_smr(const u64 hipz_rc) -{ - switch (hipz_rc) { - case H_SUCCESS: /* successful completion */ - return 0; - case H_ADAPTER_PARM: /* invalid adapter handle */ - case H_RH_PARM: /* invalid resource handle */ - case H_MEM_PARM: /* invalid MR virtual address */ - case H_MEM_ACCESS_PARM: /* invalid access controls */ - case H_NOT_ENOUGH_RESOURCES: /* insufficient resources */ - return -EINVAL; - case H_BUSY: /* long busy */ - return -EBUSY; - default: - return -EINVAL; - } -} /* end ehca_mrmw_map_hrc_reg_smr() */ - -/*----------------------------------------------------------------------*/ - -/* - * MR destructor and constructor - * used in Reregister MR verb, sets all fields in ehca_mr_t to 0, - * except struct ib_mr and spinlock - */ -void ehca_mr_deletenew(struct ehca_mr *mr) -{ - mr->flags = 0; - mr->num_pages = 0; - mr->num_4k = 0; - mr->acl = 0; - mr->start = NULL; - mr->fmr_page_size = 0; - mr->fmr_max_pages = 0; - mr->fmr_max_maps = 0; - mr->fmr_map_cnt = 0; - memset(&mr->ipz_mr_handle, 0, sizeof(mr->ipz_mr_handle)); - memset(&mr->galpas, 0, sizeof(mr->galpas)); - mr->nr_of_pages = 0; - mr->pagearray = NULL; -} /* end ehca_mr_deletenew() */ - -int ehca_init_mrmw_cache(void) -{ - mr_cache = kmem_cache_create("ehca_cache_mr", - sizeof(struct ehca_mr), 0, - SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (!mr_cache) - return -ENOMEM; - mw_cache = kmem_cache_create("ehca_cache_mw", - sizeof(struct ehca_mw), 0, - SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (!mw_cache) { - kmem_cache_destroy(mr_cache); - mr_cache = NULL; - return -ENOMEM; - } - return 0; -} - -void ehca_cleanup_mrmw_cache(void) -{ - if (mr_cache) - kmem_cache_destroy(mr_cache); - if (mw_cache) - kmem_cache_destroy(mw_cache); -} diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.h b/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.h deleted file mode 100644 index d936e40a5748..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * MR/MW declarations and inline functions - * - * Authors: Dietmar Decker - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _EHCA_MRMW_H_ -#define _EHCA_MRMW_H_ - -int ehca_reg_mr(struct ehca_shca *shca, - struct ehca_mr *e_mr, - u64 *iova_start, - u64 size, - int acl, - struct ehca_pd *e_pd, - struct ehca_mr_pginfo *pginfo, - u32 *lkey, - u32 *rkey); - -int ehca_reg_mr_rpages(struct ehca_shca *shca, - struct ehca_mr *e_mr, - struct ehca_mr_pginfo *pginfo); - -int ehca_rereg_mr(struct ehca_shca *shca, - struct ehca_mr *e_mr, - u64 *iova_start, - u64 size, - int mr_access_flags, - struct ehca_pd *e_pd, - struct ehca_mr_pginfo *pginfo, - u32 *lkey, - u32 *rkey); - -int ehca_unmap_one_fmr(struct ehca_shca *shca, - struct ehca_mr *e_fmr); - -int ehca_reg_smr(struct ehca_shca *shca, - struct ehca_mr *e_origmr, - struct ehca_mr *e_newmr, - u64 *iova_start, - int acl, - struct ehca_pd *e_pd, - u32 *lkey, - u32 *rkey); - -int ehca_reg_internal_maxmr(struct ehca_shca *shca, - struct ehca_pd *e_pd, - struct ehca_mr **maxmr); - -int ehca_reg_maxmr(struct ehca_shca *shca, - struct ehca_mr *e_newmr, - u64 *iova_start, - int acl, - struct ehca_pd *e_pd, - u32 *lkey, - u32 *rkey); - -int ehca_dereg_internal_maxmr(struct ehca_shca *shca); - -int ehca_mr_chk_buf_and_calc_size(struct ib_phys_buf *phys_buf_array, - int num_phys_buf, - u64 *iova_start, - u64 *size); - -int ehca_fmr_check_page_list(struct ehca_mr *e_fmr, - u64 *page_list, - int list_len); - -int ehca_set_pagebuf(struct ehca_mr *e_mr, - struct ehca_mr_pginfo *pginfo, - u32 number, - u64 *kpage); - -int ehca_set_pagebuf_1(struct ehca_mr *e_mr, - struct ehca_mr_pginfo *pginfo, - u64 *rpage); - -int ehca_mr_is_maxmr(u64 size, - u64 *iova_start); - -void ehca_mrmw_map_acl(int ib_acl, - u32 *hipz_acl); - -void ehca_mrmw_set_pgsize_hipz_acl(u32 *hipz_acl); - -void ehca_mrmw_reverse_map_acl(const u32 *hipz_acl, - int *ib_acl); - -int ehca_mrmw_map_hrc_alloc(const u64 hipz_rc); - -int ehca_mrmw_map_hrc_rrpg_last(const u64 hipz_rc); - -int ehca_mrmw_map_hrc_rrpg_notlast(const u64 hipz_rc); - -int ehca_mrmw_map_hrc_query_mr(const u64 hipz_rc); - -int ehca_mrmw_map_hrc_free_mr(const u64 hipz_rc); - -int ehca_mrmw_map_hrc_free_mw(const u64 hipz_rc); - -int ehca_mrmw_map_hrc_reg_smr(const u64 hipz_rc); - -void ehca_mr_deletenew(struct ehca_mr *mr); - -#endif /*_EHCA_MRMW_H_*/ diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_pd.c b/trunk/drivers/infiniband/hw/ehca/ehca_pd.c deleted file mode 100644 index 2c3cdc6f7b39..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_pd.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * PD functions - * - * Authors: Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "ehca_tools.h" -#include "ehca_iverbs.h" - -static struct kmem_cache *pd_cache; - -struct ib_pd *ehca_alloc_pd(struct ib_device *device, - struct ib_ucontext *context, struct ib_udata *udata) -{ - struct ehca_pd *pd; - - pd = kmem_cache_alloc(pd_cache, SLAB_KERNEL); - if (!pd) { - ehca_err(device, "device=%p context=%p out of memory", - device, context); - return ERR_PTR(-ENOMEM); - } - - memset(pd, 0, sizeof(struct ehca_pd)); - pd->ownpid = current->tgid; - - /* - * Kernel PD: when device = -1, 0 - * User PD: when context != -1 - */ - if (!context) { - /* - * Kernel PDs after init reuses always - * the one created in ehca_shca_reopen() - */ - struct ehca_shca *shca = container_of(device, struct ehca_shca, - ib_device); - pd->fw_pd.value = shca->pd->fw_pd.value; - } else - pd->fw_pd.value = (u64)pd; - - return &pd->ib_pd; -} - -int ehca_dealloc_pd(struct ib_pd *pd) -{ - u32 cur_pid = current->tgid; - struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd); - - if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && - my_pd->ownpid != cur_pid) { - ehca_err(pd->device, "Invalid caller pid=%x ownpid=%x", - cur_pid, my_pd->ownpid); - return -EINVAL; - } - - kmem_cache_free(pd_cache, - container_of(pd, struct ehca_pd, ib_pd)); - - return 0; -} - -int ehca_init_pd_cache(void) -{ - pd_cache = kmem_cache_create("ehca_cache_pd", - sizeof(struct ehca_pd), 0, - SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (!pd_cache) - return -ENOMEM; - return 0; -} - -void ehca_cleanup_pd_cache(void) -{ - if (pd_cache) - kmem_cache_destroy(pd_cache); -} diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_qes.h b/trunk/drivers/infiniband/hw/ehca/ehca_qes.h deleted file mode 100644 index 8707d297ce4c..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_qes.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Hardware request structures - * - * Authors: Waleri Fomin - * Reinhard Ernst - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef _EHCA_QES_H_ -#define _EHCA_QES_H_ - -#include "ehca_tools.h" - -/* virtual scatter gather entry to specify remote adresses with length */ -struct ehca_vsgentry { - u64 vaddr; - u32 lkey; - u32 length; -}; - -#define GRH_FLAG_MASK EHCA_BMASK_IBM(7,7) -#define GRH_IPVERSION_MASK EHCA_BMASK_IBM(0,3) -#define GRH_TCLASS_MASK EHCA_BMASK_IBM(4,12) -#define GRH_FLOWLABEL_MASK EHCA_BMASK_IBM(13,31) -#define GRH_PAYLEN_MASK EHCA_BMASK_IBM(32,47) -#define GRH_NEXTHEADER_MASK EHCA_BMASK_IBM(48,55) -#define GRH_HOPLIMIT_MASK EHCA_BMASK_IBM(56,63) - -/* - * Unreliable Datagram Address Vector Format - * see IBTA Vol1 chapter 8.3 Global Routing Header - */ -struct ehca_ud_av { - u8 sl; - u8 lnh; - u16 dlid; - u8 reserved1; - u8 reserved2; - u8 reserved3; - u8 slid_path_bits; - u8 reserved4; - u8 ipd; - u8 reserved5; - u8 pmtu; - u32 reserved6; - u64 reserved7; - union { - struct { - u64 word_0; /* always set to 6 */ - /*should be 0x1B for IB transport */ - u64 word_1; - u64 word_2; - u64 word_3; - u64 word_4; - } grh; - struct { - u32 wd_0; - u32 wd_1; - /* DWord_1 --> SGID */ - - u32 sgid_wd3; - u32 sgid_wd2; - - u32 sgid_wd1; - u32 sgid_wd0; - /* DWord_3 --> DGID */ - - u32 dgid_wd3; - u32 dgid_wd2; - - u32 dgid_wd1; - u32 dgid_wd0; - } grh_l; - }; -}; - -/* maximum number of sg entries allowed in a WQE */ -#define MAX_WQE_SG_ENTRIES 252 - -#define WQE_OPTYPE_SEND 0x80 -#define WQE_OPTYPE_RDMAREAD 0x40 -#define WQE_OPTYPE_RDMAWRITE 0x20 -#define WQE_OPTYPE_CMPSWAP 0x10 -#define WQE_OPTYPE_FETCHADD 0x08 -#define WQE_OPTYPE_BIND 0x04 - -#define WQE_WRFLAG_REQ_SIGNAL_COM 0x80 -#define WQE_WRFLAG_FENCE 0x40 -#define WQE_WRFLAG_IMM_DATA_PRESENT 0x20 -#define WQE_WRFLAG_SOLIC_EVENT 0x10 - -#define WQEF_CACHE_HINT 0x80 -#define WQEF_CACHE_HINT_RD_WR 0x40 -#define WQEF_TIMED_WQE 0x20 -#define WQEF_PURGE 0x08 -#define WQEF_HIGH_NIBBLE 0xF0 - -#define MW_BIND_ACCESSCTRL_R_WRITE 0x40 -#define MW_BIND_ACCESSCTRL_R_READ 0x20 -#define MW_BIND_ACCESSCTRL_R_ATOMIC 0x10 - -struct ehca_wqe { - u64 work_request_id; - u8 optype; - u8 wr_flag; - u16 pkeyi; - u8 wqef; - u8 nr_of_data_seg; - u16 wqe_provided_slid; - u32 destination_qp_number; - u32 resync_psn_sqp; - u32 local_ee_context_qkey; - u32 immediate_data; - union { - struct { - u64 remote_virtual_adress; - u32 rkey; - u32 reserved; - u64 atomic_1st_op_dma_len; - u64 atomic_2nd_op; - struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES]; - - } nud; - struct { - u64 ehca_ud_av_ptr; - u64 reserved1; - u64 reserved2; - u64 reserved3; - struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES]; - } ud_avp; - struct { - struct ehca_ud_av ud_av; - struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES - - 2]; - } ud_av; - struct { - u64 reserved0; - u64 reserved1; - u64 reserved2; - u64 reserved3; - struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES]; - } all_rcv; - - struct { - u64 reserved; - u32 rkey; - u32 old_rkey; - u64 reserved1; - u64 reserved2; - u64 virtual_address; - u32 reserved3; - u32 length; - u32 reserved4; - u16 reserved5; - u8 reserved6; - u8 lr_ctl; - u32 lkey; - u32 reserved7; - u64 reserved8; - u64 reserved9; - u64 reserved10; - u64 reserved11; - } bind; - struct { - u64 reserved12; - u64 reserved13; - u32 size; - u32 start; - } inline_data; - } u; - -}; - -#define WC_SEND_RECEIVE EHCA_BMASK_IBM(0,0) -#define WC_IMM_DATA EHCA_BMASK_IBM(1,1) -#define WC_GRH_PRESENT EHCA_BMASK_IBM(2,2) -#define WC_SE_BIT EHCA_BMASK_IBM(3,3) -#define WC_STATUS_ERROR_BIT 0x80000000 -#define WC_STATUS_REMOTE_ERROR_FLAGS 0x0000F800 -#define WC_STATUS_PURGE_BIT 0x10 - -struct ehca_cqe { - u64 work_request_id; - u8 optype; - u8 w_completion_flags; - u16 reserved1; - u32 nr_bytes_transferred; - u32 immediate_data; - u32 local_qp_number; - u8 freed_resource_count; - u8 service_level; - u16 wqe_count; - u32 qp_token; - u32 qkey_ee_token; - u32 remote_qp_number; - u16 dlid; - u16 rlid; - u16 reserved2; - u16 pkey_index; - u32 cqe_timestamp; - u32 wqe_timestamp; - u8 wqe_timestamp_valid; - u8 reserved3; - u8 reserved4; - u8 cqe_flags; - u32 status; -}; - -struct ehca_eqe { - u64 entry; -}; - -struct ehca_mrte { - u64 starting_va; - u64 length; /* length of memory region in bytes*/ - u32 pd; - u8 key_instance; - u8 pagesize; - u8 mr_control; - u8 local_remote_access_ctrl; - u8 reserved[0x20 - 0x18]; - u64 at_pointer[4]; -}; -#endif /*_EHCA_QES_H_*/ diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_qp.c b/trunk/drivers/infiniband/hw/ehca/ehca_qp.c deleted file mode 100644 index 4394123cdbd7..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_qp.c +++ /dev/null @@ -1,1507 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * QP functions - * - * Authors: Waleri Fomin - * Hoang-Nam Nguyen - * Reinhard Ernst - * Heiko J Schick - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#include - -#include "ehca_classes.h" -#include "ehca_tools.h" -#include "ehca_qes.h" -#include "ehca_iverbs.h" -#include "hcp_if.h" -#include "hipz_fns.h" - -static struct kmem_cache *qp_cache; - -/* - * attributes not supported by query qp - */ -#define QP_ATTR_QUERY_NOT_SUPPORTED (IB_QP_MAX_DEST_RD_ATOMIC | \ - IB_QP_MAX_QP_RD_ATOMIC | \ - IB_QP_ACCESS_FLAGS | \ - IB_QP_EN_SQD_ASYNC_NOTIFY) - -/* - * ehca (internal) qp state values - */ -enum ehca_qp_state { - EHCA_QPS_RESET = 1, - EHCA_QPS_INIT = 2, - EHCA_QPS_RTR = 3, - EHCA_QPS_RTS = 5, - EHCA_QPS_SQD = 6, - EHCA_QPS_SQE = 8, - EHCA_QPS_ERR = 128 -}; - -/* - * qp state transitions as defined by IB Arch Rel 1.1 page 431 - */ -enum ib_qp_statetrans { - IB_QPST_ANY2RESET, - IB_QPST_ANY2ERR, - IB_QPST_RESET2INIT, - IB_QPST_INIT2RTR, - IB_QPST_INIT2INIT, - IB_QPST_RTR2RTS, - IB_QPST_RTS2SQD, - IB_QPST_RTS2RTS, - IB_QPST_SQD2RTS, - IB_QPST_SQE2RTS, - IB_QPST_SQD2SQD, - IB_QPST_MAX /* nr of transitions, this must be last!!! */ -}; - -/* - * ib2ehca_qp_state maps IB to ehca qp_state - * returns ehca qp state corresponding to given ib qp state - */ -static inline enum ehca_qp_state ib2ehca_qp_state(enum ib_qp_state ib_qp_state) -{ - switch (ib_qp_state) { - case IB_QPS_RESET: - return EHCA_QPS_RESET; - case IB_QPS_INIT: - return EHCA_QPS_INIT; - case IB_QPS_RTR: - return EHCA_QPS_RTR; - case IB_QPS_RTS: - return EHCA_QPS_RTS; - case IB_QPS_SQD: - return EHCA_QPS_SQD; - case IB_QPS_SQE: - return EHCA_QPS_SQE; - case IB_QPS_ERR: - return EHCA_QPS_ERR; - default: - ehca_gen_err("invalid ib_qp_state=%x", ib_qp_state); - return -EINVAL; - } -} - -/* - * ehca2ib_qp_state maps ehca to IB qp_state - * returns ib qp state corresponding to given ehca qp state - */ -static inline enum ib_qp_state ehca2ib_qp_state(enum ehca_qp_state - ehca_qp_state) -{ - switch (ehca_qp_state) { - case EHCA_QPS_RESET: - return IB_QPS_RESET; - case EHCA_QPS_INIT: - return IB_QPS_INIT; - case EHCA_QPS_RTR: - return IB_QPS_RTR; - case EHCA_QPS_RTS: - return IB_QPS_RTS; - case EHCA_QPS_SQD: - return IB_QPS_SQD; - case EHCA_QPS_SQE: - return IB_QPS_SQE; - case EHCA_QPS_ERR: - return IB_QPS_ERR; - default: - ehca_gen_err("invalid ehca_qp_state=%x", ehca_qp_state); - return -EINVAL; - } -} - -/* - * ehca_qp_type used as index for req_attr and opt_attr of - * struct ehca_modqp_statetrans - */ -enum ehca_qp_type { - QPT_RC = 0, - QPT_UC = 1, - QPT_UD = 2, - QPT_SQP = 3, - QPT_MAX -}; - -/* - * ib2ehcaqptype maps Ib to ehca qp_type - * returns ehca qp type corresponding to ib qp type - */ -static inline enum ehca_qp_type ib2ehcaqptype(enum ib_qp_type ibqptype) -{ - switch (ibqptype) { - case IB_QPT_SMI: - case IB_QPT_GSI: - return QPT_SQP; - case IB_QPT_RC: - return QPT_RC; - case IB_QPT_UC: - return QPT_UC; - case IB_QPT_UD: - return QPT_UD; - default: - ehca_gen_err("Invalid ibqptype=%x", ibqptype); - return -EINVAL; - } -} - -static inline enum ib_qp_statetrans get_modqp_statetrans(int ib_fromstate, - int ib_tostate) -{ - int index = -EINVAL; - switch (ib_tostate) { - case IB_QPS_RESET: - index = IB_QPST_ANY2RESET; - break; - case IB_QPS_INIT: - switch (ib_fromstate) { - case IB_QPS_RESET: - index = IB_QPST_RESET2INIT; - break; - case IB_QPS_INIT: - index = IB_QPST_INIT2INIT; - break; - } - break; - case IB_QPS_RTR: - if (ib_fromstate == IB_QPS_INIT) - index = IB_QPST_INIT2RTR; - break; - case IB_QPS_RTS: - switch (ib_fromstate) { - case IB_QPS_RTR: - index = IB_QPST_RTR2RTS; - break; - case IB_QPS_RTS: - index = IB_QPST_RTS2RTS; - break; - case IB_QPS_SQD: - index = IB_QPST_SQD2RTS; - break; - case IB_QPS_SQE: - index = IB_QPST_SQE2RTS; - break; - } - break; - case IB_QPS_SQD: - if (ib_fromstate == IB_QPS_RTS) - index = IB_QPST_RTS2SQD; - break; - case IB_QPS_SQE: - break; - case IB_QPS_ERR: - index = IB_QPST_ANY2ERR; - break; - default: - break; - } - return index; -} - -enum ehca_service_type { - ST_RC = 0, - ST_UC = 1, - ST_RD = 2, - ST_UD = 3 -}; - -/* - * ibqptype2servicetype returns hcp service type corresponding to given - * ib qp type used by create_qp() - */ -static inline int ibqptype2servicetype(enum ib_qp_type ibqptype) -{ - switch (ibqptype) { - case IB_QPT_SMI: - case IB_QPT_GSI: - return ST_UD; - case IB_QPT_RC: - return ST_RC; - case IB_QPT_UC: - return ST_UC; - case IB_QPT_UD: - return ST_UD; - case IB_QPT_RAW_IPV6: - return -EINVAL; - case IB_QPT_RAW_ETY: - return -EINVAL; - default: - ehca_gen_err("Invalid ibqptype=%x", ibqptype); - return -EINVAL; - } -} - -/* - * init_qp_queues initializes/constructs r/squeue and registers queue pages. - */ -static inline int init_qp_queues(struct ehca_shca *shca, - struct ehca_qp *my_qp, - int nr_sq_pages, - int nr_rq_pages, - int swqe_size, - int rwqe_size, - int nr_send_sges, int nr_receive_sges) -{ - int ret, cnt, ipz_rc; - void *vpage; - u64 rpage, h_ret; - struct ib_device *ib_dev = &shca->ib_device; - struct ipz_adapter_handle ipz_hca_handle = shca->ipz_hca_handle; - - ipz_rc = ipz_queue_ctor(&my_qp->ipz_squeue, - nr_sq_pages, - EHCA_PAGESIZE, swqe_size, nr_send_sges); - if (!ipz_rc) { - ehca_err(ib_dev,"Cannot allocate page for squeue. ipz_rc=%x", - ipz_rc); - return -EBUSY; - } - - ipz_rc = ipz_queue_ctor(&my_qp->ipz_rqueue, - nr_rq_pages, - EHCA_PAGESIZE, rwqe_size, nr_receive_sges); - if (!ipz_rc) { - ehca_err(ib_dev, "Cannot allocate page for rqueue. ipz_rc=%x", - ipz_rc); - ret = -EBUSY; - goto init_qp_queues0; - } - /* register SQ pages */ - for (cnt = 0; cnt < nr_sq_pages; cnt++) { - vpage = ipz_qpageit_get_inc(&my_qp->ipz_squeue); - if (!vpage) { - ehca_err(ib_dev, "SQ ipz_qpageit_get_inc() " - "failed p_vpage= %p", vpage); - ret = -EINVAL; - goto init_qp_queues1; - } - rpage = virt_to_abs(vpage); - - h_ret = hipz_h_register_rpage_qp(ipz_hca_handle, - my_qp->ipz_qp_handle, - &my_qp->pf, 0, 0, - rpage, 1, - my_qp->galpas.kernel); - if (h_ret < H_SUCCESS) { - ehca_err(ib_dev, "SQ hipz_qp_register_rpage()" - " failed rc=%lx", h_ret); - ret = ehca2ib_return_code(h_ret); - goto init_qp_queues1; - } - } - - ipz_qeit_reset(&my_qp->ipz_squeue); - - /* register RQ pages */ - for (cnt = 0; cnt < nr_rq_pages; cnt++) { - vpage = ipz_qpageit_get_inc(&my_qp->ipz_rqueue); - if (!vpage) { - ehca_err(ib_dev, "RQ ipz_qpageit_get_inc() " - "failed p_vpage = %p", vpage); - ret = -EINVAL; - goto init_qp_queues1; - } - - rpage = virt_to_abs(vpage); - - h_ret = hipz_h_register_rpage_qp(ipz_hca_handle, - my_qp->ipz_qp_handle, - &my_qp->pf, 0, 1, - rpage, 1,my_qp->galpas.kernel); - if (h_ret < H_SUCCESS) { - ehca_err(ib_dev, "RQ hipz_qp_register_rpage() failed " - "rc=%lx", h_ret); - ret = ehca2ib_return_code(h_ret); - goto init_qp_queues1; - } - if (cnt == (nr_rq_pages - 1)) { /* last page! */ - if (h_ret != H_SUCCESS) { - ehca_err(ib_dev, "RQ hipz_qp_register_rpage() " - "h_ret= %lx ", h_ret); - ret = ehca2ib_return_code(h_ret); - goto init_qp_queues1; - } - vpage = ipz_qpageit_get_inc(&my_qp->ipz_rqueue); - if (vpage) { - ehca_err(ib_dev, "ipz_qpageit_get_inc() " - "should not succeed vpage=%p", vpage); - ret = -EINVAL; - goto init_qp_queues1; - } - } else { - if (h_ret != H_PAGE_REGISTERED) { - ehca_err(ib_dev, "RQ hipz_qp_register_rpage() " - "h_ret= %lx ", h_ret); - ret = ehca2ib_return_code(h_ret); - goto init_qp_queues1; - } - } - } - - ipz_qeit_reset(&my_qp->ipz_rqueue); - - return 0; - -init_qp_queues1: - ipz_queue_dtor(&my_qp->ipz_rqueue); -init_qp_queues0: - ipz_queue_dtor(&my_qp->ipz_squeue); - return ret; -} - -struct ib_qp *ehca_create_qp(struct ib_pd *pd, - struct ib_qp_init_attr *init_attr, - struct ib_udata *udata) -{ - static int da_rc_msg_size[]={ 128, 256, 512, 1024, 2048, 4096 }; - static int da_ud_sq_msg_size[]={ 128, 384, 896, 1920, 3968 }; - struct ehca_qp *my_qp; - struct ehca_pd *my_pd = container_of(pd, struct ehca_pd, ib_pd); - struct ehca_shca *shca = container_of(pd->device, struct ehca_shca, - ib_device); - struct ib_ucontext *context = NULL; - u64 h_ret; - int max_send_sge, max_recv_sge, ret; - - /* h_call's out parameters */ - struct ehca_alloc_qp_parms parms; - u32 swqe_size = 0, rwqe_size = 0; - u8 daqp_completion, isdaqp; - unsigned long flags; - - if (init_attr->sq_sig_type != IB_SIGNAL_REQ_WR && - init_attr->sq_sig_type != IB_SIGNAL_ALL_WR) { - ehca_err(pd->device, "init_attr->sg_sig_type=%x not allowed", - init_attr->sq_sig_type); - return ERR_PTR(-EINVAL); - } - - /* save daqp completion bits */ - daqp_completion = init_attr->qp_type & 0x60; - /* save daqp bit */ - isdaqp = (init_attr->qp_type & 0x80) ? 1 : 0; - init_attr->qp_type = init_attr->qp_type & 0x1F; - - if (init_attr->qp_type != IB_QPT_UD && - init_attr->qp_type != IB_QPT_SMI && - init_attr->qp_type != IB_QPT_GSI && - init_attr->qp_type != IB_QPT_UC && - init_attr->qp_type != IB_QPT_RC) { - ehca_err(pd->device, "wrong QP Type=%x", init_attr->qp_type); - return ERR_PTR(-EINVAL); - } - if ((init_attr->qp_type != IB_QPT_RC && init_attr->qp_type != IB_QPT_UD) - && isdaqp) { - ehca_err(pd->device, "unsupported LL QP Type=%x", - init_attr->qp_type); - return ERR_PTR(-EINVAL); - } else if (init_attr->qp_type == IB_QPT_RC && isdaqp && - (init_attr->cap.max_send_wr > 255 || - init_attr->cap.max_recv_wr > 255 )) { - ehca_err(pd->device, "Invalid Number of max_sq_wr =%x " - "or max_rq_wr=%x for QP Type=%x", - init_attr->cap.max_send_wr, - init_attr->cap.max_recv_wr,init_attr->qp_type); - return ERR_PTR(-EINVAL); - } else if (init_attr->qp_type == IB_QPT_UD && isdaqp && - init_attr->cap.max_send_wr > 255) { - ehca_err(pd->device, - "Invalid Number of max_send_wr=%x for UD QP_TYPE=%x", - init_attr->cap.max_send_wr, init_attr->qp_type); - return ERR_PTR(-EINVAL); - } - - if (pd->uobject && udata) - context = pd->uobject->context; - - my_qp = kmem_cache_alloc(qp_cache, SLAB_KERNEL); - if (!my_qp) { - ehca_err(pd->device, "pd=%p not enough memory to alloc qp", pd); - return ERR_PTR(-ENOMEM); - } - - memset(my_qp, 0, sizeof(struct ehca_qp)); - memset (&parms, 0, sizeof(struct ehca_alloc_qp_parms)); - spin_lock_init(&my_qp->spinlock_s); - spin_lock_init(&my_qp->spinlock_r); - - my_qp->recv_cq = - container_of(init_attr->recv_cq, struct ehca_cq, ib_cq); - my_qp->send_cq = - container_of(init_attr->send_cq, struct ehca_cq, ib_cq); - - my_qp->init_attr = *init_attr; - - do { - if (!idr_pre_get(&ehca_qp_idr, GFP_KERNEL)) { - ret = -ENOMEM; - ehca_err(pd->device, "Can't reserve idr resources."); - goto create_qp_exit0; - } - - spin_lock_irqsave(&ehca_qp_idr_lock, flags); - ret = idr_get_new(&ehca_qp_idr, my_qp, &my_qp->token); - spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); - - } while (ret == -EAGAIN); - - if (ret) { - ret = -ENOMEM; - ehca_err(pd->device, "Can't allocate new idr entry."); - goto create_qp_exit0; - } - - parms.servicetype = ibqptype2servicetype(init_attr->qp_type); - if (parms.servicetype < 0) { - ret = -EINVAL; - ehca_err(pd->device, "Invalid qp_type=%x", init_attr->qp_type); - goto create_qp_exit0; - } - - if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) - parms.sigtype = HCALL_SIGT_EVERY; - else - parms.sigtype = HCALL_SIGT_BY_WQE; - - /* UD_AV CIRCUMVENTION */ - max_send_sge = init_attr->cap.max_send_sge; - max_recv_sge = init_attr->cap.max_recv_sge; - if (IB_QPT_UD == init_attr->qp_type || - IB_QPT_GSI == init_attr->qp_type || - IB_QPT_SMI == init_attr->qp_type) { - max_send_sge += 2; - max_recv_sge += 2; - } - - parms.ipz_eq_handle = shca->eq.ipz_eq_handle; - parms.daqp_ctrl = isdaqp | daqp_completion; - parms.pd = my_pd->fw_pd; - parms.max_recv_sge = max_recv_sge; - parms.max_send_sge = max_send_sge; - - h_ret = hipz_h_alloc_resource_qp(shca->ipz_hca_handle, my_qp, &parms); - - if (h_ret != H_SUCCESS) { - ehca_err(pd->device, "h_alloc_resource_qp() failed h_ret=%lx", - h_ret); - ret = ehca2ib_return_code(h_ret); - goto create_qp_exit1; - } - - switch (init_attr->qp_type) { - case IB_QPT_RC: - if (isdaqp == 0) { - swqe_size = offsetof(struct ehca_wqe, u.nud.sg_list[ - (parms.act_nr_send_sges)]); - rwqe_size = offsetof(struct ehca_wqe, u.nud.sg_list[ - (parms.act_nr_recv_sges)]); - } else { /* for daqp we need to use msg size, not wqe size */ - swqe_size = da_rc_msg_size[max_send_sge]; - rwqe_size = da_rc_msg_size[max_recv_sge]; - parms.act_nr_send_sges = 1; - parms.act_nr_recv_sges = 1; - } - break; - case IB_QPT_UC: - swqe_size = offsetof(struct ehca_wqe, - u.nud.sg_list[parms.act_nr_send_sges]); - rwqe_size = offsetof(struct ehca_wqe, - u.nud.sg_list[parms.act_nr_recv_sges]); - break; - - case IB_QPT_UD: - case IB_QPT_GSI: - case IB_QPT_SMI: - /* UD circumvention */ - parms.act_nr_recv_sges -= 2; - parms.act_nr_send_sges -= 2; - if (isdaqp) { - swqe_size = da_ud_sq_msg_size[max_send_sge]; - rwqe_size = da_rc_msg_size[max_recv_sge]; - parms.act_nr_send_sges = 1; - parms.act_nr_recv_sges = 1; - } else { - swqe_size = offsetof(struct ehca_wqe, - u.ud_av.sg_list[parms.act_nr_send_sges]); - rwqe_size = offsetof(struct ehca_wqe, - u.ud_av.sg_list[parms.act_nr_recv_sges]); - } - - if (IB_QPT_GSI == init_attr->qp_type || - IB_QPT_SMI == init_attr->qp_type) { - parms.act_nr_send_wqes = init_attr->cap.max_send_wr; - parms.act_nr_recv_wqes = init_attr->cap.max_recv_wr; - parms.act_nr_send_sges = init_attr->cap.max_send_sge; - parms.act_nr_recv_sges = init_attr->cap.max_recv_sge; - my_qp->real_qp_num = - (init_attr->qp_type == IB_QPT_SMI) ? 0 : 1; - } - - break; - - default: - break; - } - - /* initializes r/squeue and registers queue pages */ - ret = init_qp_queues(shca, my_qp, - parms.nr_sq_pages, parms.nr_rq_pages, - swqe_size, rwqe_size, - parms.act_nr_send_sges, parms.act_nr_recv_sges); - if (ret) { - ehca_err(pd->device, - "Couldn't initialize r/squeue and pages ret=%x", ret); - goto create_qp_exit2; - } - - my_qp->ib_qp.pd = &my_pd->ib_pd; - my_qp->ib_qp.device = my_pd->ib_pd.device; - - my_qp->ib_qp.recv_cq = init_attr->recv_cq; - my_qp->ib_qp.send_cq = init_attr->send_cq; - - my_qp->ib_qp.qp_num = my_qp->real_qp_num; - my_qp->ib_qp.qp_type = init_attr->qp_type; - - my_qp->qp_type = init_attr->qp_type; - my_qp->ib_qp.srq = init_attr->srq; - - my_qp->ib_qp.qp_context = init_attr->qp_context; - my_qp->ib_qp.event_handler = init_attr->event_handler; - - init_attr->cap.max_inline_data = 0; /* not supported yet */ - init_attr->cap.max_recv_sge = parms.act_nr_recv_sges; - init_attr->cap.max_recv_wr = parms.act_nr_recv_wqes; - init_attr->cap.max_send_sge = parms.act_nr_send_sges; - init_attr->cap.max_send_wr = parms.act_nr_send_wqes; - - /* NOTE: define_apq0() not supported yet */ - if (init_attr->qp_type == IB_QPT_GSI) { - h_ret = ehca_define_sqp(shca, my_qp, init_attr); - if (h_ret != H_SUCCESS) { - ehca_err(pd->device, "ehca_define_sqp() failed rc=%lx", - h_ret); - ret = ehca2ib_return_code(h_ret); - goto create_qp_exit3; - } - } - if (init_attr->send_cq) { - struct ehca_cq *cq = container_of(init_attr->send_cq, - struct ehca_cq, ib_cq); - ret = ehca_cq_assign_qp(cq, my_qp); - if (ret) { - ehca_err(pd->device, "Couldn't assign qp to send_cq ret=%x", - ret); - goto create_qp_exit3; - } - my_qp->send_cq = cq; - } - /* copy queues, galpa data to user space */ - if (context && udata) { - struct ipz_queue *ipz_rqueue = &my_qp->ipz_rqueue; - struct ipz_queue *ipz_squeue = &my_qp->ipz_squeue; - struct ehca_create_qp_resp resp; - struct vm_area_struct * vma; - memset(&resp, 0, sizeof(resp)); - - resp.qp_num = my_qp->real_qp_num; - resp.token = my_qp->token; - resp.qp_type = my_qp->qp_type; - resp.qkey = my_qp->qkey; - resp.real_qp_num = my_qp->real_qp_num; - /* rqueue properties */ - resp.ipz_rqueue.qe_size = ipz_rqueue->qe_size; - resp.ipz_rqueue.act_nr_of_sg = ipz_rqueue->act_nr_of_sg; - resp.ipz_rqueue.queue_length = ipz_rqueue->queue_length; - resp.ipz_rqueue.pagesize = ipz_rqueue->pagesize; - resp.ipz_rqueue.toggle_state = ipz_rqueue->toggle_state; - ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x22000000, - ipz_rqueue->queue_length, - (void**)&resp.ipz_rqueue.queue, - &vma); - if (ret) { - ehca_err(pd->device, "Could not mmap rqueue pages"); - goto create_qp_exit3; - } - my_qp->uspace_rqueue = resp.ipz_rqueue.queue; - /* squeue properties */ - resp.ipz_squeue.qe_size = ipz_squeue->qe_size; - resp.ipz_squeue.act_nr_of_sg = ipz_squeue->act_nr_of_sg; - resp.ipz_squeue.queue_length = ipz_squeue->queue_length; - resp.ipz_squeue.pagesize = ipz_squeue->pagesize; - resp.ipz_squeue.toggle_state = ipz_squeue->toggle_state; - ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x23000000, - ipz_squeue->queue_length, - (void**)&resp.ipz_squeue.queue, - &vma); - if (ret) { - ehca_err(pd->device, "Could not mmap squeue pages"); - goto create_qp_exit4; - } - my_qp->uspace_squeue = resp.ipz_squeue.queue; - /* fw_handle */ - resp.galpas = my_qp->galpas; - ret = ehca_mmap_register(my_qp->galpas.user.fw_handle, - (void**)&resp.galpas.kernel.fw_handle, - &vma); - if (ret) { - ehca_err(pd->device, "Could not mmap fw_handle"); - goto create_qp_exit5; - } - my_qp->uspace_fwh = (u64)resp.galpas.kernel.fw_handle; - - if (ib_copy_to_udata(udata, &resp, sizeof resp)) { - ehca_err(pd->device, "Copy to udata failed"); - ret = -EINVAL; - goto create_qp_exit6; - } - } - - return &my_qp->ib_qp; - -create_qp_exit6: - ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE); - -create_qp_exit5: - ehca_munmap(my_qp->uspace_squeue, my_qp->ipz_squeue.queue_length); - -create_qp_exit4: - ehca_munmap(my_qp->uspace_rqueue, my_qp->ipz_rqueue.queue_length); - -create_qp_exit3: - ipz_queue_dtor(&my_qp->ipz_rqueue); - ipz_queue_dtor(&my_qp->ipz_squeue); - -create_qp_exit2: - hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp); - -create_qp_exit1: - spin_lock_irqsave(&ehca_qp_idr_lock, flags); - idr_remove(&ehca_qp_idr, my_qp->token); - spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); - -create_qp_exit0: - kmem_cache_free(qp_cache, my_qp); - return ERR_PTR(ret); -} - -/* - * prepare_sqe_rts called by internal_modify_qp() at trans sqe -> rts - * set purge bit of bad wqe and subsequent wqes to avoid reentering sqe - * returns total number of bad wqes in bad_wqe_cnt - */ -static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca, - int *bad_wqe_cnt) -{ - u64 h_ret; - struct ipz_queue *squeue; - void *bad_send_wqe_p, *bad_send_wqe_v; - void *squeue_start_p, *squeue_end_p; - void *squeue_start_v, *squeue_end_v; - struct ehca_wqe *wqe; - int qp_num = my_qp->ib_qp.qp_num; - - /* get send wqe pointer */ - h_ret = hipz_h_disable_and_get_wqe(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, &my_qp->pf, - &bad_send_wqe_p, NULL, 2); - if (h_ret != H_SUCCESS) { - ehca_err(&shca->ib_device, "hipz_h_disable_and_get_wqe() failed" - " ehca_qp=%p qp_num=%x h_ret=%lx", - my_qp, qp_num, h_ret); - return ehca2ib_return_code(h_ret); - } - bad_send_wqe_p = (void*)((u64)bad_send_wqe_p & (~(1L<<63))); - ehca_dbg(&shca->ib_device, "qp_num=%x bad_send_wqe_p=%p", - qp_num, bad_send_wqe_p); - /* convert wqe pointer to vadr */ - bad_send_wqe_v = abs_to_virt((u64)bad_send_wqe_p); - if (ehca_debug_level) - ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num); - squeue = &my_qp->ipz_squeue; - squeue_start_p = (void*)virt_to_abs(ipz_qeit_calc(squeue, 0L)); - squeue_end_p = squeue_start_p+squeue->queue_length; - squeue_start_v = abs_to_virt((u64)squeue_start_p); - squeue_end_v = abs_to_virt((u64)squeue_end_p); - ehca_dbg(&shca->ib_device, "qp_num=%x squeue_start_v=%p squeue_end_v=%p", - qp_num, squeue_start_v, squeue_end_v); - - /* loop sets wqe's purge bit */ - wqe = (struct ehca_wqe*)bad_send_wqe_v; - *bad_wqe_cnt = 0; - while (wqe->optype != 0xff && wqe->wqef != 0xff) { - if (ehca_debug_level) - ehca_dmp(wqe, 32, "qp_num=%x wqe", qp_num); - wqe->nr_of_data_seg = 0; /* suppress data access */ - wqe->wqef = WQEF_PURGE; /* WQE to be purged */ - wqe = (struct ehca_wqe*)((u8*)wqe+squeue->qe_size); - *bad_wqe_cnt = (*bad_wqe_cnt)+1; - if ((void*)wqe >= squeue_end_v) { - wqe = squeue_start_v; - } - } - /* - * bad wqe will be reprocessed and ignored when pol_cq() is called, - * i.e. nr of wqes with flush error status is one less - */ - ehca_dbg(&shca->ib_device, "qp_num=%x flusherr_wqe_cnt=%x", - qp_num, (*bad_wqe_cnt)-1); - wqe->wqef = 0; - - return 0; -} - -/* - * internal_modify_qp with circumvention to handle aqp0 properly - * smi_reset2init indicates if this is an internal reset-to-init-call for - * smi. This flag must always be zero if called from ehca_modify_qp()! - * This internal func was intorduced to avoid recursion of ehca_modify_qp()! - */ -static int internal_modify_qp(struct ib_qp *ibqp, - struct ib_qp_attr *attr, - int attr_mask, int smi_reset2init) -{ - enum ib_qp_state qp_cur_state, qp_new_state; - int cnt, qp_attr_idx, ret = 0; - enum ib_qp_statetrans statetrans; - struct hcp_modify_qp_control_block *mqpcb; - struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); - struct ehca_shca *shca = - container_of(ibqp->pd->device, struct ehca_shca, ib_device); - u64 update_mask; - u64 h_ret; - int bad_wqe_cnt = 0; - int squeue_locked = 0; - unsigned long spl_flags = 0; - - /* do query_qp to obtain current attr values */ - mqpcb = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); - if (mqpcb == NULL) { - ehca_err(ibqp->device, "Could not get zeroed page for mqpcb " - "ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num); - return -ENOMEM; - } - - h_ret = hipz_h_query_qp(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, - &my_qp->pf, - mqpcb, my_qp->galpas.kernel); - if (h_ret != H_SUCCESS) { - ehca_err(ibqp->device, "hipz_h_query_qp() failed " - "ehca_qp=%p qp_num=%x h_ret=%lx", - my_qp, ibqp->qp_num, h_ret); - ret = ehca2ib_return_code(h_ret); - goto modify_qp_exit1; - } - - qp_cur_state = ehca2ib_qp_state(mqpcb->qp_state); - - if (qp_cur_state == -EINVAL) { /* invalid qp state */ - ret = -EINVAL; - ehca_err(ibqp->device, "Invalid current ehca_qp_state=%x " - "ehca_qp=%p qp_num=%x", - mqpcb->qp_state, my_qp, ibqp->qp_num); - goto modify_qp_exit1; - } - /* - * circumvention to set aqp0 initial state to init - * as expected by IB spec - */ - if (smi_reset2init == 0 && - ibqp->qp_type == IB_QPT_SMI && - qp_cur_state == IB_QPS_RESET && - (attr_mask & IB_QP_STATE) && - attr->qp_state == IB_QPS_INIT) { /* RESET -> INIT */ - struct ib_qp_attr smiqp_attr = { - .qp_state = IB_QPS_INIT, - .port_num = my_qp->init_attr.port_num, - .pkey_index = 0, - .qkey = 0 - }; - int smiqp_attr_mask = IB_QP_STATE | IB_QP_PORT | - IB_QP_PKEY_INDEX | IB_QP_QKEY; - int smirc = internal_modify_qp( - ibqp, &smiqp_attr, smiqp_attr_mask, 1); - if (smirc) { - ehca_err(ibqp->device, "SMI RESET -> INIT failed. " - "ehca_modify_qp() rc=%x", smirc); - ret = H_PARAMETER; - goto modify_qp_exit1; - } - qp_cur_state = IB_QPS_INIT; - ehca_dbg(ibqp->device, "SMI RESET -> INIT succeeded"); - } - /* is transmitted current state equal to "real" current state */ - if ((attr_mask & IB_QP_CUR_STATE) && - qp_cur_state != attr->cur_qp_state) { - ret = -EINVAL; - ehca_err(ibqp->device, - "Invalid IB_QP_CUR_STATE attr->curr_qp_state=%x <>" - " actual cur_qp_state=%x. ehca_qp=%p qp_num=%x", - attr->cur_qp_state, qp_cur_state, my_qp, ibqp->qp_num); - goto modify_qp_exit1; - } - - ehca_dbg(ibqp->device,"ehca_qp=%p qp_num=%x current qp_state=%x " - "new qp_state=%x attribute_mask=%x", - my_qp, ibqp->qp_num, qp_cur_state, attr->qp_state, attr_mask); - - qp_new_state = attr_mask & IB_QP_STATE ? attr->qp_state : qp_cur_state; - if (!smi_reset2init && - !ib_modify_qp_is_ok(qp_cur_state, qp_new_state, ibqp->qp_type, - attr_mask)) { - ret = -EINVAL; - ehca_err(ibqp->device, - "Invalid qp transition new_state=%x cur_state=%x " - "ehca_qp=%p qp_num=%x attr_mask=%x", qp_new_state, - qp_cur_state, my_qp, ibqp->qp_num, attr_mask); - goto modify_qp_exit1; - } - - if ((mqpcb->qp_state = ib2ehca_qp_state(qp_new_state))) - update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_STATE, 1); - else { - ret = -EINVAL; - ehca_err(ibqp->device, "Invalid new qp state=%x " - "ehca_qp=%p qp_num=%x", - qp_new_state, my_qp, ibqp->qp_num); - goto modify_qp_exit1; - } - - /* retrieve state transition struct to get req and opt attrs */ - statetrans = get_modqp_statetrans(qp_cur_state, qp_new_state); - if (statetrans < 0) { - ret = -EINVAL; - ehca_err(ibqp->device, " qp_cur_state=%x " - "new_qp_state=%x State_xsition=%x ehca_qp=%p " - "qp_num=%x", qp_cur_state, qp_new_state, - statetrans, my_qp, ibqp->qp_num); - goto modify_qp_exit1; - } - - qp_attr_idx = ib2ehcaqptype(ibqp->qp_type); - - if (qp_attr_idx < 0) { - ret = qp_attr_idx; - ehca_err(ibqp->device, - "Invalid QP type=%x ehca_qp=%p qp_num=%x", - ibqp->qp_type, my_qp, ibqp->qp_num); - goto modify_qp_exit1; - } - - ehca_dbg(ibqp->device, - "ehca_qp=%p qp_num=%x qp_state_xsit=%x", - my_qp, ibqp->qp_num, statetrans); - - /* sqe -> rts: set purge bit of bad wqe before actual trans */ - if ((my_qp->qp_type == IB_QPT_UD || - my_qp->qp_type == IB_QPT_GSI || - my_qp->qp_type == IB_QPT_SMI) && - statetrans == IB_QPST_SQE2RTS) { - /* mark next free wqe if kernel */ - if (my_qp->uspace_squeue == 0) { - struct ehca_wqe *wqe; - /* lock send queue */ - spin_lock_irqsave(&my_qp->spinlock_s, spl_flags); - squeue_locked = 1; - /* mark next free wqe */ - wqe = (struct ehca_wqe*) - ipz_qeit_get(&my_qp->ipz_squeue); - wqe->optype = wqe->wqef = 0xff; - ehca_dbg(ibqp->device, "qp_num=%x next_free_wqe=%p", - ibqp->qp_num, wqe); - } - ret = prepare_sqe_rts(my_qp, shca, &bad_wqe_cnt); - if (ret) { - ehca_err(ibqp->device, "prepare_sqe_rts() failed " - "ehca_qp=%p qp_num=%x ret=%x", - my_qp, ibqp->qp_num, ret); - goto modify_qp_exit2; - } - } - - /* - * enable RDMA_Atomic_Control if reset->init und reliable con - * this is necessary since gen2 does not provide that flag, - * but pHyp requires it - */ - if (statetrans == IB_QPST_RESET2INIT && - (ibqp->qp_type == IB_QPT_RC || ibqp->qp_type == IB_QPT_UC)) { - mqpcb->rdma_atomic_ctrl = 3; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RDMA_ATOMIC_CTRL, 1); - } - /* circ. pHyp requires #RDMA/Atomic Resp Res for UC INIT -> RTR */ - if (statetrans == IB_QPST_INIT2RTR && - (ibqp->qp_type == IB_QPT_UC) && - !(attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)) { - mqpcb->rdma_nr_atomic_resp_res = 1; /* default to 1 */ - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1); - } - - if (attr_mask & IB_QP_PKEY_INDEX) { - mqpcb->prim_p_key_idx = attr->pkey_index; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_P_KEY_IDX, 1); - } - if (attr_mask & IB_QP_PORT) { - if (attr->port_num < 1 || attr->port_num > shca->num_ports) { - ret = -EINVAL; - ehca_err(ibqp->device, "Invalid port=%x. " - "ehca_qp=%p qp_num=%x num_ports=%x", - attr->port_num, my_qp, ibqp->qp_num, - shca->num_ports); - goto modify_qp_exit2; - } - mqpcb->prim_phys_port = attr->port_num; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_PHYS_PORT, 1); - } - if (attr_mask & IB_QP_QKEY) { - mqpcb->qkey = attr->qkey; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_QKEY, 1); - } - if (attr_mask & IB_QP_AV) { - int ah_mult = ib_rate_to_mult(attr->ah_attr.static_rate); - int ehca_mult = ib_rate_to_mult(shca->sport[my_qp-> - init_attr.port_num].rate); - - mqpcb->dlid = attr->ah_attr.dlid; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID, 1); - mqpcb->source_path_bits = attr->ah_attr.src_path_bits; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS, 1); - mqpcb->service_level = attr->ah_attr.sl; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL, 1); - - if (ah_mult < ehca_mult) - mqpcb->max_static_rate = (ah_mult > 0) ? - ((ehca_mult - 1) / ah_mult) : 0; - else - mqpcb->max_static_rate = 0; - - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE, 1); - - /* - * only if GRH is TRUE we might consider SOURCE_GID_IDX - * and DEST_GID otherwise phype will return H_ATTR_PARM!!! - */ - if (attr->ah_attr.ah_flags == IB_AH_GRH) { - mqpcb->send_grh_flag = 1 << 31; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG, 1); - mqpcb->source_gid_idx = attr->ah_attr.grh.sgid_index; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX, 1); - - for (cnt = 0; cnt < 16; cnt++) - mqpcb->dest_gid.byte[cnt] = - attr->ah_attr.grh.dgid.raw[cnt]; - - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_GID, 1); - mqpcb->flow_label = attr->ah_attr.grh.flow_label; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL, 1); - mqpcb->hop_limit = attr->ah_attr.grh.hop_limit; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT, 1); - mqpcb->traffic_class = attr->ah_attr.grh.traffic_class; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS, 1); - } - } - - if (attr_mask & IB_QP_PATH_MTU) { - mqpcb->path_mtu = attr->path_mtu; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PATH_MTU, 1); - } - if (attr_mask & IB_QP_TIMEOUT) { - mqpcb->timeout = attr->timeout; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_TIMEOUT, 1); - } - if (attr_mask & IB_QP_RETRY_CNT) { - mqpcb->retry_count = attr->retry_cnt; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RETRY_COUNT, 1); - } - if (attr_mask & IB_QP_RNR_RETRY) { - mqpcb->rnr_retry_count = attr->rnr_retry; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RNR_RETRY_COUNT, 1); - } - if (attr_mask & IB_QP_RQ_PSN) { - mqpcb->receive_psn = attr->rq_psn; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_RECEIVE_PSN, 1); - } - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { - mqpcb->rdma_nr_atomic_resp_res = attr->max_dest_rd_atomic < 3 ? - attr->max_dest_rd_atomic : 2; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_RDMA_NR_ATOMIC_RESP_RES, 1); - } - if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { - mqpcb->rdma_atomic_outst_dest_qp = attr->max_rd_atomic < 3 ? - attr->max_rd_atomic : 2; - update_mask |= - EHCA_BMASK_SET - (MQPCB_MASK_RDMA_ATOMIC_OUTST_DEST_QP, 1); - } - if (attr_mask & IB_QP_ALT_PATH) { - int ah_mult = ib_rate_to_mult(attr->alt_ah_attr.static_rate); - int ehca_mult = ib_rate_to_mult( - shca->sport[my_qp->init_attr.port_num].rate); - - mqpcb->dlid_al = attr->alt_ah_attr.dlid; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DLID_AL, 1); - mqpcb->source_path_bits_al = attr->alt_ah_attr.src_path_bits; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_SOURCE_PATH_BITS_AL, 1); - mqpcb->service_level_al = attr->alt_ah_attr.sl; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SERVICE_LEVEL_AL, 1); - - if (ah_mult < ehca_mult) - mqpcb->max_static_rate = (ah_mult > 0) ? - ((ehca_mult - 1) / ah_mult) : 0; - else - mqpcb->max_static_rate_al = 0; - - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_MAX_STATIC_RATE_AL, 1); - - /* - * only if GRH is TRUE we might consider SOURCE_GID_IDX - * and DEST_GID otherwise phype will return H_ATTR_PARM!!! - */ - if (attr->alt_ah_attr.ah_flags == IB_AH_GRH) { - mqpcb->send_grh_flag_al = 1 << 31; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_SEND_GRH_FLAG_AL, 1); - mqpcb->source_gid_idx_al = - attr->alt_ah_attr.grh.sgid_index; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_SOURCE_GID_IDX_AL, 1); - - for (cnt = 0; cnt < 16; cnt++) - mqpcb->dest_gid_al.byte[cnt] = - attr->alt_ah_attr.grh.dgid.raw[cnt]; - - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_DEST_GID_AL, 1); - mqpcb->flow_label_al = attr->alt_ah_attr.grh.flow_label; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_FLOW_LABEL_AL, 1); - mqpcb->hop_limit_al = attr->alt_ah_attr.grh.hop_limit; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_HOP_LIMIT_AL, 1); - mqpcb->traffic_class_al = - attr->alt_ah_attr.grh.traffic_class; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_TRAFFIC_CLASS_AL, 1); - } - } - - if (attr_mask & IB_QP_MIN_RNR_TIMER) { - mqpcb->min_rnr_nak_timer_field = attr->min_rnr_timer; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_MIN_RNR_NAK_TIMER_FIELD, 1); - } - - if (attr_mask & IB_QP_SQ_PSN) { - mqpcb->send_psn = attr->sq_psn; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_SEND_PSN, 1); - } - - if (attr_mask & IB_QP_DEST_QPN) { - mqpcb->dest_qp_nr = attr->dest_qp_num; - update_mask |= EHCA_BMASK_SET(MQPCB_MASK_DEST_QP_NR, 1); - } - - if (attr_mask & IB_QP_PATH_MIG_STATE) { - mqpcb->path_migration_state = attr->path_mig_state; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_PATH_MIGRATION_STATE, 1); - } - - if (attr_mask & IB_QP_CAP) { - mqpcb->max_nr_outst_send_wr = attr->cap.max_send_wr+1; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_SEND_WR, 1); - mqpcb->max_nr_outst_recv_wr = attr->cap.max_recv_wr+1; - update_mask |= - EHCA_BMASK_SET(MQPCB_MASK_MAX_NR_OUTST_RECV_WR, 1); - /* no support for max_send/recv_sge yet */ - } - - if (ehca_debug_level) - ehca_dmp(mqpcb, 4*70, "qp_num=%x", ibqp->qp_num); - - h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, - &my_qp->pf, - update_mask, - mqpcb, my_qp->galpas.kernel); - - if (h_ret != H_SUCCESS) { - ret = ehca2ib_return_code(h_ret); - ehca_err(ibqp->device, "hipz_h_modify_qp() failed rc=%lx " - "ehca_qp=%p qp_num=%x",h_ret, my_qp, ibqp->qp_num); - goto modify_qp_exit2; - } - - if ((my_qp->qp_type == IB_QPT_UD || - my_qp->qp_type == IB_QPT_GSI || - my_qp->qp_type == IB_QPT_SMI) && - statetrans == IB_QPST_SQE2RTS) { - /* doorbell to reprocessing wqes */ - iosync(); /* serialize GAL register access */ - hipz_update_sqa(my_qp, bad_wqe_cnt-1); - ehca_gen_dbg("doorbell for %x wqes", bad_wqe_cnt); - } - - if (statetrans == IB_QPST_RESET2INIT || - statetrans == IB_QPST_INIT2INIT) { - mqpcb->qp_enable = 1; - mqpcb->qp_state = EHCA_QPS_INIT; - update_mask = 0; - update_mask = EHCA_BMASK_SET(MQPCB_MASK_QP_ENABLE, 1); - - h_ret = hipz_h_modify_qp(shca->ipz_hca_handle, - my_qp->ipz_qp_handle, - &my_qp->pf, - update_mask, - mqpcb, - my_qp->galpas.kernel); - - if (h_ret != H_SUCCESS) { - ret = ehca2ib_return_code(h_ret); - ehca_err(ibqp->device, "ENABLE in context of " - "RESET_2_INIT failed! Maybe you didn't get " - "a LID h_ret=%lx ehca_qp=%p qp_num=%x", - h_ret, my_qp, ibqp->qp_num); - goto modify_qp_exit2; - } - } - - if (statetrans == IB_QPST_ANY2RESET) { - ipz_qeit_reset(&my_qp->ipz_rqueue); - ipz_qeit_reset(&my_qp->ipz_squeue); - } - - if (attr_mask & IB_QP_QKEY) - my_qp->qkey = attr->qkey; - -modify_qp_exit2: - if (squeue_locked) { /* this means: sqe -> rts */ - spin_unlock_irqrestore(&my_qp->spinlock_s, spl_flags); - my_qp->sqerr_purgeflag = 1; - } - -modify_qp_exit1: - kfree(mqpcb); - - return ret; -} - -int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, - struct ib_udata *udata) -{ - struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); - struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd, - ib_pd); - u32 cur_pid = current->tgid; - - if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && - my_pd->ownpid != cur_pid) { - ehca_err(ibqp->pd->device, "Invalid caller pid=%x ownpid=%x", - cur_pid, my_pd->ownpid); - return -EINVAL; - } - - return internal_modify_qp(ibqp, attr, attr_mask, 0); -} - -int ehca_query_qp(struct ib_qp *qp, - struct ib_qp_attr *qp_attr, - int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr) -{ - struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp); - struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd, - ib_pd); - struct ehca_shca *shca = container_of(qp->device, struct ehca_shca, - ib_device); - struct ipz_adapter_handle adapter_handle = shca->ipz_hca_handle; - struct hcp_modify_qp_control_block *qpcb; - u32 cur_pid = current->tgid; - int cnt, ret = 0; - u64 h_ret; - - if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && - my_pd->ownpid != cur_pid) { - ehca_err(qp->device, "Invalid caller pid=%x ownpid=%x", - cur_pid, my_pd->ownpid); - return -EINVAL; - } - - if (qp_attr_mask & QP_ATTR_QUERY_NOT_SUPPORTED) { - ehca_err(qp->device,"Invalid attribute mask " - "ehca_qp=%p qp_num=%x qp_attr_mask=%x ", - my_qp, qp->qp_num, qp_attr_mask); - return -EINVAL; - } - - qpcb = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL ); - if (!qpcb) { - ehca_err(qp->device,"Out of memory for qpcb " - "ehca_qp=%p qp_num=%x", my_qp, qp->qp_num); - return -ENOMEM; - } - - h_ret = hipz_h_query_qp(adapter_handle, - my_qp->ipz_qp_handle, - &my_qp->pf, - qpcb, my_qp->galpas.kernel); - - if (h_ret != H_SUCCESS) { - ret = ehca2ib_return_code(h_ret); - ehca_err(qp->device,"hipz_h_query_qp() failed " - "ehca_qp=%p qp_num=%x h_ret=%lx", - my_qp, qp->qp_num, h_ret); - goto query_qp_exit1; - } - - qp_attr->cur_qp_state = ehca2ib_qp_state(qpcb->qp_state); - qp_attr->qp_state = qp_attr->cur_qp_state; - - if (qp_attr->cur_qp_state == -EINVAL) { - ret = -EINVAL; - ehca_err(qp->device,"Got invalid ehca_qp_state=%x " - "ehca_qp=%p qp_num=%x", - qpcb->qp_state, my_qp, qp->qp_num); - goto query_qp_exit1; - } - - if (qp_attr->qp_state == IB_QPS_SQD) - qp_attr->sq_draining = 1; - - qp_attr->qkey = qpcb->qkey; - qp_attr->path_mtu = qpcb->path_mtu; - qp_attr->path_mig_state = qpcb->path_migration_state; - qp_attr->rq_psn = qpcb->receive_psn; - qp_attr->sq_psn = qpcb->send_psn; - qp_attr->min_rnr_timer = qpcb->min_rnr_nak_timer_field; - qp_attr->cap.max_send_wr = qpcb->max_nr_outst_send_wr-1; - qp_attr->cap.max_recv_wr = qpcb->max_nr_outst_recv_wr-1; - /* UD_AV CIRCUMVENTION */ - if (my_qp->qp_type == IB_QPT_UD) { - qp_attr->cap.max_send_sge = - qpcb->actual_nr_sges_in_sq_wqe - 2; - qp_attr->cap.max_recv_sge = - qpcb->actual_nr_sges_in_rq_wqe - 2; - } else { - qp_attr->cap.max_send_sge = - qpcb->actual_nr_sges_in_sq_wqe; - qp_attr->cap.max_recv_sge = - qpcb->actual_nr_sges_in_rq_wqe; - } - - qp_attr->cap.max_inline_data = my_qp->sq_max_inline_data_size; - qp_attr->dest_qp_num = qpcb->dest_qp_nr; - - qp_attr->pkey_index = - EHCA_BMASK_GET(MQPCB_PRIM_P_KEY_IDX, qpcb->prim_p_key_idx); - - qp_attr->port_num = - EHCA_BMASK_GET(MQPCB_PRIM_PHYS_PORT, qpcb->prim_phys_port); - - qp_attr->timeout = qpcb->timeout; - qp_attr->retry_cnt = qpcb->retry_count; - qp_attr->rnr_retry = qpcb->rnr_retry_count; - - qp_attr->alt_pkey_index = - EHCA_BMASK_GET(MQPCB_PRIM_P_KEY_IDX, qpcb->alt_p_key_idx); - - qp_attr->alt_port_num = qpcb->alt_phys_port; - qp_attr->alt_timeout = qpcb->timeout_al; - - /* primary av */ - qp_attr->ah_attr.sl = qpcb->service_level; - - if (qpcb->send_grh_flag) { - qp_attr->ah_attr.ah_flags = IB_AH_GRH; - } - - qp_attr->ah_attr.static_rate = qpcb->max_static_rate; - qp_attr->ah_attr.dlid = qpcb->dlid; - qp_attr->ah_attr.src_path_bits = qpcb->source_path_bits; - qp_attr->ah_attr.port_num = qp_attr->port_num; - - /* primary GRH */ - qp_attr->ah_attr.grh.traffic_class = qpcb->traffic_class; - qp_attr->ah_attr.grh.hop_limit = qpcb->hop_limit; - qp_attr->ah_attr.grh.sgid_index = qpcb->source_gid_idx; - qp_attr->ah_attr.grh.flow_label = qpcb->flow_label; - - for (cnt = 0; cnt < 16; cnt++) - qp_attr->ah_attr.grh.dgid.raw[cnt] = - qpcb->dest_gid.byte[cnt]; - - /* alternate AV */ - qp_attr->alt_ah_attr.sl = qpcb->service_level_al; - if (qpcb->send_grh_flag_al) { - qp_attr->alt_ah_attr.ah_flags = IB_AH_GRH; - } - - qp_attr->alt_ah_attr.static_rate = qpcb->max_static_rate_al; - qp_attr->alt_ah_attr.dlid = qpcb->dlid_al; - qp_attr->alt_ah_attr.src_path_bits = qpcb->source_path_bits_al; - - /* alternate GRH */ - qp_attr->alt_ah_attr.grh.traffic_class = qpcb->traffic_class_al; - qp_attr->alt_ah_attr.grh.hop_limit = qpcb->hop_limit_al; - qp_attr->alt_ah_attr.grh.sgid_index = qpcb->source_gid_idx_al; - qp_attr->alt_ah_attr.grh.flow_label = qpcb->flow_label_al; - - for (cnt = 0; cnt < 16; cnt++) - qp_attr->alt_ah_attr.grh.dgid.raw[cnt] = - qpcb->dest_gid_al.byte[cnt]; - - /* return init attributes given in ehca_create_qp */ - if (qp_init_attr) - *qp_init_attr = my_qp->init_attr; - - if (ehca_debug_level) - ehca_dmp(qpcb, 4*70, "qp_num=%x", qp->qp_num); - -query_qp_exit1: - kfree(qpcb); - - return ret; -} - -int ehca_destroy_qp(struct ib_qp *ibqp) -{ - struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp); - struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca, - ib_device); - struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd, - ib_pd); - u32 cur_pid = current->tgid; - u32 qp_num = ibqp->qp_num; - int ret; - u64 h_ret; - u8 port_num; - enum ib_qp_type qp_type; - unsigned long flags; - - if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && - my_pd->ownpid != cur_pid) { - ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x", - cur_pid, my_pd->ownpid); - return -EINVAL; - } - - if (my_qp->send_cq) { - ret = ehca_cq_unassign_qp(my_qp->send_cq, - my_qp->real_qp_num); - if (ret) { - ehca_err(ibqp->device, "Couldn't unassign qp from " - "send_cq ret=%x qp_num=%x cq_num=%x", ret, - my_qp->ib_qp.qp_num, my_qp->send_cq->cq_number); - return ret; - } - } - - spin_lock_irqsave(&ehca_qp_idr_lock, flags); - idr_remove(&ehca_qp_idr, my_qp->token); - spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); - - /* un-mmap if vma alloc */ - if (my_qp->uspace_rqueue) { - ret = ehca_munmap(my_qp->uspace_rqueue, - my_qp->ipz_rqueue.queue_length); - if (ret) - ehca_err(ibqp->device, "Could not munmap rqueue " - "qp_num=%x", qp_num); - ret = ehca_munmap(my_qp->uspace_squeue, - my_qp->ipz_squeue.queue_length); - if (ret) - ehca_err(ibqp->device, "Could not munmap squeue " - "qp_num=%x", qp_num); - ret = ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE); - if (ret) - ehca_err(ibqp->device, "Could not munmap fwh qp_num=%x", - qp_num); - } - - h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp); - if (h_ret != H_SUCCESS) { - ehca_err(ibqp->device, "hipz_h_destroy_qp() failed rc=%lx " - "ehca_qp=%p qp_num=%x", h_ret, my_qp, qp_num); - return ehca2ib_return_code(h_ret); - } - - port_num = my_qp->init_attr.port_num; - qp_type = my_qp->init_attr.qp_type; - - /* no support for IB_QPT_SMI yet */ - if (qp_type == IB_QPT_GSI) { - struct ib_event event; - ehca_info(ibqp->device, "device %s: port %x is inactive.", - shca->ib_device.name, port_num); - event.device = &shca->ib_device; - event.event = IB_EVENT_PORT_ERR; - event.element.port_num = port_num; - shca->sport[port_num - 1].port_state = IB_PORT_DOWN; - ib_dispatch_event(&event); - } - - ipz_queue_dtor(&my_qp->ipz_rqueue); - ipz_queue_dtor(&my_qp->ipz_squeue); - kmem_cache_free(qp_cache, my_qp); - return 0; -} - -int ehca_init_qp_cache(void) -{ - qp_cache = kmem_cache_create("ehca_cache_qp", - sizeof(struct ehca_qp), 0, - SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (!qp_cache) - return -ENOMEM; - return 0; -} - -void ehca_cleanup_qp_cache(void) -{ - if (qp_cache) - kmem_cache_destroy(qp_cache); -} diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_reqs.c b/trunk/drivers/infiniband/hw/ehca/ehca_reqs.c deleted file mode 100644 index b46bda1bf85d..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_reqs.c +++ /dev/null @@ -1,653 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * post_send/recv, poll_cq, req_notify - * - * Authors: Waleri Fomin - * Hoang-Nam Nguyen - * Reinhard Ernst - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#include -#include "ehca_classes.h" -#include "ehca_tools.h" -#include "ehca_qes.h" -#include "ehca_iverbs.h" -#include "hcp_if.h" -#include "hipz_fns.h" - -static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue, - struct ehca_wqe *wqe_p, - struct ib_recv_wr *recv_wr) -{ - u8 cnt_ds; - if (unlikely((recv_wr->num_sge < 0) || - (recv_wr->num_sge > ipz_rqueue->act_nr_of_sg))) { - ehca_gen_err("Invalid number of WQE SGE. " - "num_sqe=%x max_nr_of_sg=%x", - recv_wr->num_sge, ipz_rqueue->act_nr_of_sg); - return -EINVAL; /* invalid SG list length */ - } - - /* clear wqe header until sglist */ - memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list)); - - wqe_p->work_request_id = recv_wr->wr_id; - wqe_p->nr_of_data_seg = recv_wr->num_sge; - - for (cnt_ds = 0; cnt_ds < recv_wr->num_sge; cnt_ds++) { - wqe_p->u.all_rcv.sg_list[cnt_ds].vaddr = - recv_wr->sg_list[cnt_ds].addr; - wqe_p->u.all_rcv.sg_list[cnt_ds].lkey = - recv_wr->sg_list[cnt_ds].lkey; - wqe_p->u.all_rcv.sg_list[cnt_ds].length = - recv_wr->sg_list[cnt_ds].length; - } - - if (ehca_debug_level) { - ehca_gen_dbg("RECEIVE WQE written into ipz_rqueue=%p", ipz_rqueue); - ehca_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe"); - } - - return 0; -} - -#if defined(DEBUG_GSI_SEND_WR) - -/* need ib_mad struct */ -#include - -static void trace_send_wr_ud(const struct ib_send_wr *send_wr) -{ - int idx; - int j; - while (send_wr) { - struct ib_mad_hdr *mad_hdr = send_wr->wr.ud.mad_hdr; - struct ib_sge *sge = send_wr->sg_list; - ehca_gen_dbg("send_wr#%x wr_id=%lx num_sge=%x " - "send_flags=%x opcode=%x",idx, send_wr->wr_id, - send_wr->num_sge, send_wr->send_flags, - send_wr->opcode); - if (mad_hdr) { - ehca_gen_dbg("send_wr#%x mad_hdr base_version=%x " - "mgmt_class=%x class_version=%x method=%x " - "status=%x class_specific=%x tid=%lx " - "attr_id=%x resv=%x attr_mod=%x", - idx, mad_hdr->base_version, - mad_hdr->mgmt_class, - mad_hdr->class_version, mad_hdr->method, - mad_hdr->status, mad_hdr->class_specific, - mad_hdr->tid, mad_hdr->attr_id, - mad_hdr->resv, - mad_hdr->attr_mod); - } - for (j = 0; j < send_wr->num_sge; j++) { - u8 *data = (u8 *) abs_to_virt(sge->addr); - ehca_gen_dbg("send_wr#%x sge#%x addr=%p length=%x " - "lkey=%x", - idx, j, data, sge->length, sge->lkey); - /* assume length is n*16 */ - ehca_dmp(data, sge->length, "send_wr#%x sge#%x", - idx, j); - sge++; - } /* eof for j */ - idx++; - send_wr = send_wr->next; - } /* eof while send_wr */ -} - -#endif /* DEBUG_GSI_SEND_WR */ - -static inline int ehca_write_swqe(struct ehca_qp *qp, - struct ehca_wqe *wqe_p, - const struct ib_send_wr *send_wr) -{ - u32 idx; - u64 dma_length; - struct ehca_av *my_av; - u32 remote_qkey = send_wr->wr.ud.remote_qkey; - - if (unlikely((send_wr->num_sge < 0) || - (send_wr->num_sge > qp->ipz_squeue.act_nr_of_sg))) { - ehca_gen_err("Invalid number of WQE SGE. " - "num_sqe=%x max_nr_of_sg=%x", - send_wr->num_sge, qp->ipz_squeue.act_nr_of_sg); - return -EINVAL; /* invalid SG list length */ - } - - /* clear wqe header until sglist */ - memset(wqe_p, 0, offsetof(struct ehca_wqe, u.ud_av.sg_list)); - - wqe_p->work_request_id = send_wr->wr_id; - - switch (send_wr->opcode) { - case IB_WR_SEND: - case IB_WR_SEND_WITH_IMM: - wqe_p->optype = WQE_OPTYPE_SEND; - break; - case IB_WR_RDMA_WRITE: - case IB_WR_RDMA_WRITE_WITH_IMM: - wqe_p->optype = WQE_OPTYPE_RDMAWRITE; - break; - case IB_WR_RDMA_READ: - wqe_p->optype = WQE_OPTYPE_RDMAREAD; - break; - default: - ehca_gen_err("Invalid opcode=%x", send_wr->opcode); - return -EINVAL; /* invalid opcode */ - } - - wqe_p->wqef = (send_wr->opcode) & WQEF_HIGH_NIBBLE; - - wqe_p->wr_flag = 0; - - if (send_wr->send_flags & IB_SEND_SIGNALED) - wqe_p->wr_flag |= WQE_WRFLAG_REQ_SIGNAL_COM; - - if (send_wr->opcode == IB_WR_SEND_WITH_IMM || - send_wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM) { - /* this might not work as long as HW does not support it */ - wqe_p->immediate_data = be32_to_cpu(send_wr->imm_data); - wqe_p->wr_flag |= WQE_WRFLAG_IMM_DATA_PRESENT; - } - - wqe_p->nr_of_data_seg = send_wr->num_sge; - - switch (qp->qp_type) { - case IB_QPT_SMI: - case IB_QPT_GSI: - /* no break is intential here */ - case IB_QPT_UD: - /* IB 1.2 spec C10-15 compliance */ - if (send_wr->wr.ud.remote_qkey & 0x80000000) - remote_qkey = qp->qkey; - - wqe_p->destination_qp_number = send_wr->wr.ud.remote_qpn << 8; - wqe_p->local_ee_context_qkey = remote_qkey; - if (!send_wr->wr.ud.ah) { - ehca_gen_err("wr.ud.ah is NULL. qp=%p", qp); - return -EINVAL; - } - my_av = container_of(send_wr->wr.ud.ah, struct ehca_av, ib_ah); - wqe_p->u.ud_av.ud_av = my_av->av; - - /* - * omitted check of IB_SEND_INLINE - * since HW does not support it - */ - for (idx = 0; idx < send_wr->num_sge; idx++) { - wqe_p->u.ud_av.sg_list[idx].vaddr = - send_wr->sg_list[idx].addr; - wqe_p->u.ud_av.sg_list[idx].lkey = - send_wr->sg_list[idx].lkey; - wqe_p->u.ud_av.sg_list[idx].length = - send_wr->sg_list[idx].length; - } /* eof for idx */ - if (qp->qp_type == IB_QPT_SMI || - qp->qp_type == IB_QPT_GSI) - wqe_p->u.ud_av.ud_av.pmtu = 1; - if (qp->qp_type == IB_QPT_GSI) { - wqe_p->pkeyi = send_wr->wr.ud.pkey_index; -#ifdef DEBUG_GSI_SEND_WR - trace_send_wr_ud(send_wr); -#endif /* DEBUG_GSI_SEND_WR */ - } - break; - - case IB_QPT_UC: - if (send_wr->send_flags & IB_SEND_FENCE) - wqe_p->wr_flag |= WQE_WRFLAG_FENCE; - /* no break is intentional here */ - case IB_QPT_RC: - /* TODO: atomic not implemented */ - wqe_p->u.nud.remote_virtual_adress = - send_wr->wr.rdma.remote_addr; - wqe_p->u.nud.rkey = send_wr->wr.rdma.rkey; - - /* - * omitted checking of IB_SEND_INLINE - * since HW does not support it - */ - dma_length = 0; - for (idx = 0; idx < send_wr->num_sge; idx++) { - wqe_p->u.nud.sg_list[idx].vaddr = - send_wr->sg_list[idx].addr; - wqe_p->u.nud.sg_list[idx].lkey = - send_wr->sg_list[idx].lkey; - wqe_p->u.nud.sg_list[idx].length = - send_wr->sg_list[idx].length; - dma_length += send_wr->sg_list[idx].length; - } /* eof idx */ - wqe_p->u.nud.atomic_1st_op_dma_len = dma_length; - - break; - - default: - ehca_gen_err("Invalid qptype=%x", qp->qp_type); - return -EINVAL; - } - - if (ehca_debug_level) { - ehca_gen_dbg("SEND WQE written into queue qp=%p ", qp); - ehca_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "send wqe"); - } - return 0; -} - -/* map_ib_wc_status converts raw cqe_status to ib_wc_status */ -static inline void map_ib_wc_status(u32 cqe_status, - enum ib_wc_status *wc_status) -{ - if (unlikely(cqe_status & WC_STATUS_ERROR_BIT)) { - switch (cqe_status & 0x3F) { - case 0x01: - case 0x21: - *wc_status = IB_WC_LOC_LEN_ERR; - break; - case 0x02: - case 0x22: - *wc_status = IB_WC_LOC_QP_OP_ERR; - break; - case 0x03: - case 0x23: - *wc_status = IB_WC_LOC_EEC_OP_ERR; - break; - case 0x04: - case 0x24: - *wc_status = IB_WC_LOC_PROT_ERR; - break; - case 0x05: - case 0x25: - *wc_status = IB_WC_WR_FLUSH_ERR; - break; - case 0x06: - *wc_status = IB_WC_MW_BIND_ERR; - break; - case 0x07: /* remote error - look into bits 20:24 */ - switch ((cqe_status - & WC_STATUS_REMOTE_ERROR_FLAGS) >> 11) { - case 0x0: - /* - * PSN Sequence Error! - * couldn't find a matching status! - */ - *wc_status = IB_WC_GENERAL_ERR; - break; - case 0x1: - *wc_status = IB_WC_REM_INV_REQ_ERR; - break; - case 0x2: - *wc_status = IB_WC_REM_ACCESS_ERR; - break; - case 0x3: - *wc_status = IB_WC_REM_OP_ERR; - break; - case 0x4: - *wc_status = IB_WC_REM_INV_RD_REQ_ERR; - break; - } - break; - case 0x08: - *wc_status = IB_WC_RETRY_EXC_ERR; - break; - case 0x09: - *wc_status = IB_WC_RNR_RETRY_EXC_ERR; - break; - case 0x0A: - case 0x2D: - *wc_status = IB_WC_REM_ABORT_ERR; - break; - case 0x0B: - case 0x2E: - *wc_status = IB_WC_INV_EECN_ERR; - break; - case 0x0C: - case 0x2F: - *wc_status = IB_WC_INV_EEC_STATE_ERR; - break; - case 0x0D: - *wc_status = IB_WC_BAD_RESP_ERR; - break; - case 0x10: - /* WQE purged */ - *wc_status = IB_WC_WR_FLUSH_ERR; - break; - default: - *wc_status = IB_WC_FATAL_ERR; - - } - } else - *wc_status = IB_WC_SUCCESS; -} - -int ehca_post_send(struct ib_qp *qp, - struct ib_send_wr *send_wr, - struct ib_send_wr **bad_send_wr) -{ - struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp); - struct ib_send_wr *cur_send_wr; - struct ehca_wqe *wqe_p; - int wqe_cnt = 0; - int ret = 0; - unsigned long spl_flags; - - /* LOCK the QUEUE */ - spin_lock_irqsave(&my_qp->spinlock_s, spl_flags); - - /* loop processes list of send reqs */ - for (cur_send_wr = send_wr; cur_send_wr != NULL; - cur_send_wr = cur_send_wr->next) { - u64 start_offset = my_qp->ipz_squeue.current_q_offset; - /* get pointer next to free WQE */ - wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue); - if (unlikely(!wqe_p)) { - /* too many posted work requests: queue overflow */ - if (bad_send_wr) - *bad_send_wr = cur_send_wr; - if (wqe_cnt == 0) { - ret = -ENOMEM; - ehca_err(qp->device, "Too many posted WQEs " - "qp_num=%x", qp->qp_num); - } - goto post_send_exit0; - } - /* write a SEND WQE into the QUEUE */ - ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr); - /* - * if something failed, - * reset the free entry pointer to the start value - */ - if (unlikely(ret)) { - my_qp->ipz_squeue.current_q_offset = start_offset; - *bad_send_wr = cur_send_wr; - if (wqe_cnt == 0) { - ret = -EINVAL; - ehca_err(qp->device, "Could not write WQE " - "qp_num=%x", qp->qp_num); - } - goto post_send_exit0; - } - wqe_cnt++; - ehca_dbg(qp->device, "ehca_qp=%p qp_num=%x wqe_cnt=%d", - my_qp, qp->qp_num, wqe_cnt); - } /* eof for cur_send_wr */ - -post_send_exit0: - /* UNLOCK the QUEUE */ - spin_unlock_irqrestore(&my_qp->spinlock_s, spl_flags); - iosync(); /* serialize GAL register access */ - hipz_update_sqa(my_qp, wqe_cnt); - return ret; -} - -int ehca_post_recv(struct ib_qp *qp, - struct ib_recv_wr *recv_wr, - struct ib_recv_wr **bad_recv_wr) -{ - struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp); - struct ib_recv_wr *cur_recv_wr; - struct ehca_wqe *wqe_p; - int wqe_cnt = 0; - int ret = 0; - unsigned long spl_flags; - - /* LOCK the QUEUE */ - spin_lock_irqsave(&my_qp->spinlock_r, spl_flags); - - /* loop processes list of send reqs */ - for (cur_recv_wr = recv_wr; cur_recv_wr != NULL; - cur_recv_wr = cur_recv_wr->next) { - u64 start_offset = my_qp->ipz_rqueue.current_q_offset; - /* get pointer next to free WQE */ - wqe_p = ipz_qeit_get_inc(&my_qp->ipz_rqueue); - if (unlikely(!wqe_p)) { - /* too many posted work requests: queue overflow */ - if (bad_recv_wr) - *bad_recv_wr = cur_recv_wr; - if (wqe_cnt == 0) { - ret = -ENOMEM; - ehca_err(qp->device, "Too many posted WQEs " - "qp_num=%x", qp->qp_num); - } - goto post_recv_exit0; - } - /* write a RECV WQE into the QUEUE */ - ret = ehca_write_rwqe(&my_qp->ipz_rqueue, wqe_p, cur_recv_wr); - /* - * if something failed, - * reset the free entry pointer to the start value - */ - if (unlikely(ret)) { - my_qp->ipz_rqueue.current_q_offset = start_offset; - *bad_recv_wr = cur_recv_wr; - if (wqe_cnt == 0) { - ret = -EINVAL; - ehca_err(qp->device, "Could not write WQE " - "qp_num=%x", qp->qp_num); - } - goto post_recv_exit0; - } - wqe_cnt++; - ehca_gen_dbg("ehca_qp=%p qp_num=%x wqe_cnt=%d", - my_qp, qp->qp_num, wqe_cnt); - } /* eof for cur_recv_wr */ - -post_recv_exit0: - spin_unlock_irqrestore(&my_qp->spinlock_r, spl_flags); - iosync(); /* serialize GAL register access */ - hipz_update_rqa(my_qp, wqe_cnt); - return ret; -} - -/* - * ib_wc_opcode table converts ehca wc opcode to ib - * Since we use zero to indicate invalid opcode, the actual ib opcode must - * be decremented!!! - */ -static const u8 ib_wc_opcode[255] = { - [0x01] = IB_WC_RECV+1, - [0x02] = IB_WC_RECV_RDMA_WITH_IMM+1, - [0x04] = IB_WC_BIND_MW+1, - [0x08] = IB_WC_FETCH_ADD+1, - [0x10] = IB_WC_COMP_SWAP+1, - [0x20] = IB_WC_RDMA_WRITE+1, - [0x40] = IB_WC_RDMA_READ+1, - [0x80] = IB_WC_SEND+1 -}; - -/* internal function to poll one entry of cq */ -static inline int ehca_poll_cq_one(struct ib_cq *cq, struct ib_wc *wc) -{ - int ret = 0; - struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); - struct ehca_cqe *cqe; - int cqe_count = 0; - -poll_cq_one_read_cqe: - cqe = (struct ehca_cqe *) - ipz_qeit_get_inc_valid(&my_cq->ipz_queue); - if (!cqe) { - ret = -EAGAIN; - ehca_dbg(cq->device, "Completion queue is empty ehca_cq=%p " - "cq_num=%x ret=%x", my_cq, my_cq->cq_number, ret); - goto poll_cq_one_exit0; - } - - /* prevents loads being reordered across this point */ - rmb(); - - cqe_count++; - if (unlikely(cqe->status & WC_STATUS_PURGE_BIT)) { - struct ehca_qp *qp=ehca_cq_get_qp(my_cq, cqe->local_qp_number); - int purgeflag; - unsigned long spl_flags; - if (!qp) { - ehca_err(cq->device, "cq_num=%x qp_num=%x " - "could not find qp -> ignore cqe", - my_cq->cq_number, cqe->local_qp_number); - ehca_dmp(cqe, 64, "cq_num=%x qp_num=%x", - my_cq->cq_number, cqe->local_qp_number); - /* ignore this purged cqe */ - goto poll_cq_one_read_cqe; - } - spin_lock_irqsave(&qp->spinlock_s, spl_flags); - purgeflag = qp->sqerr_purgeflag; - spin_unlock_irqrestore(&qp->spinlock_s, spl_flags); - - if (purgeflag) { - ehca_dbg(cq->device, "Got CQE with purged bit qp_num=%x " - "src_qp=%x", - cqe->local_qp_number, cqe->remote_qp_number); - if (ehca_debug_level) - ehca_dmp(cqe, 64, "qp_num=%x src_qp=%x", - cqe->local_qp_number, - cqe->remote_qp_number); - /* - * ignore this to avoid double cqes of bad wqe - * that caused sqe and turn off purge flag - */ - qp->sqerr_purgeflag = 0; - goto poll_cq_one_read_cqe; - } - } - - /* tracing cqe */ - if (ehca_debug_level) { - ehca_dbg(cq->device, - "Received COMPLETION ehca_cq=%p cq_num=%x -----", - my_cq, my_cq->cq_number); - ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x", - my_cq, my_cq->cq_number); - ehca_dbg(cq->device, - "ehca_cq=%p cq_num=%x -------------------------", - my_cq, my_cq->cq_number); - } - - /* we got a completion! */ - wc->wr_id = cqe->work_request_id; - - /* eval ib_wc_opcode */ - wc->opcode = ib_wc_opcode[cqe->optype]-1; - if (unlikely(wc->opcode == -1)) { - ehca_err(cq->device, "Invalid cqe->OPType=%x cqe->status=%x " - "ehca_cq=%p cq_num=%x", - cqe->optype, cqe->status, my_cq, my_cq->cq_number); - /* dump cqe for other infos */ - ehca_dmp(cqe, 64, "ehca_cq=%p cq_num=%x", - my_cq, my_cq->cq_number); - /* update also queue adder to throw away this entry!!! */ - goto poll_cq_one_exit0; - } - /* eval ib_wc_status */ - if (unlikely(cqe->status & WC_STATUS_ERROR_BIT)) { - /* complete with errors */ - map_ib_wc_status(cqe->status, &wc->status); - wc->vendor_err = wc->status; - } else - wc->status = IB_WC_SUCCESS; - - wc->qp_num = cqe->local_qp_number; - wc->byte_len = cqe->nr_bytes_transferred; - wc->pkey_index = cqe->pkey_index; - wc->slid = cqe->rlid; - wc->dlid_path_bits = cqe->dlid; - wc->src_qp = cqe->remote_qp_number; - wc->wc_flags = cqe->w_completion_flags; - wc->imm_data = cpu_to_be32(cqe->immediate_data); - wc->sl = cqe->service_level; - - if (wc->status != IB_WC_SUCCESS) - ehca_dbg(cq->device, - "ehca_cq=%p cq_num=%x WARNING unsuccessful cqe " - "OPType=%x status=%x qp_num=%x src_qp=%x wr_id=%lx " - "cqe=%p", my_cq, my_cq->cq_number, cqe->optype, - cqe->status, cqe->local_qp_number, - cqe->remote_qp_number, cqe->work_request_id, cqe); - -poll_cq_one_exit0: - if (cqe_count > 0) - hipz_update_feca(my_cq, cqe_count); - - return ret; -} - -int ehca_poll_cq(struct ib_cq *cq, int num_entries, struct ib_wc *wc) -{ - struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); - int nr; - struct ib_wc *current_wc = wc; - int ret = 0; - unsigned long spl_flags; - - if (num_entries < 1) { - ehca_err(cq->device, "Invalid num_entries=%d ehca_cq=%p " - "cq_num=%x", num_entries, my_cq, my_cq->cq_number); - ret = -EINVAL; - goto poll_cq_exit0; - } - - spin_lock_irqsave(&my_cq->spinlock, spl_flags); - for (nr = 0; nr < num_entries; nr++) { - ret = ehca_poll_cq_one(cq, current_wc); - if (ret) - break; - current_wc++; - } /* eof for nr */ - spin_unlock_irqrestore(&my_cq->spinlock, spl_flags); - if (ret == -EAGAIN || !ret) - ret = nr; - -poll_cq_exit0: - return ret; -} - -int ehca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify cq_notify) -{ - struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); - - switch (cq_notify) { - case IB_CQ_SOLICITED: - hipz_set_cqx_n0(my_cq, 1); - break; - case IB_CQ_NEXT_COMP: - hipz_set_cqx_n1(my_cq, 1); - break; - default: - return -EINVAL; - } - - return 0; -} diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_sqp.c b/trunk/drivers/infiniband/hw/ehca/ehca_sqp.c deleted file mode 100644 index 9f16e9c79394..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_sqp.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * SQP functions - * - * Authors: Khadija Souissi - * Heiko J Schick - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#include -#include -#include "ehca_classes.h" -#include "ehca_tools.h" -#include "ehca_qes.h" -#include "ehca_iverbs.h" -#include "hcp_if.h" - - -/** - * ehca_define_sqp - Defines special queue pair 1 (GSI QP). When special queue - * pair is created successfully, the corresponding port gets active. - * - * Define Special Queue pair 0 (SMI QP) is still not supported. - * - * @qp_init_attr: Queue pair init attributes with port and queue pair type - */ - -u64 ehca_define_sqp(struct ehca_shca *shca, - struct ehca_qp *ehca_qp, - struct ib_qp_init_attr *qp_init_attr) -{ - u32 pma_qp_nr, bma_qp_nr; - u64 ret; - u8 port = qp_init_attr->port_num; - int counter; - - shca->sport[port - 1].port_state = IB_PORT_DOWN; - - switch (qp_init_attr->qp_type) { - case IB_QPT_SMI: - /* function not supported yet */ - break; - case IB_QPT_GSI: - ret = hipz_h_define_aqp1(shca->ipz_hca_handle, - ehca_qp->ipz_qp_handle, - ehca_qp->galpas.kernel, - (u32) qp_init_attr->port_num, - &pma_qp_nr, &bma_qp_nr); - - if (ret != H_SUCCESS) { - ehca_err(&shca->ib_device, - "Can't define AQP1 for port %x. rc=%lx", - port, ret); - return ret; - } - break; - default: - ehca_err(&shca->ib_device, "invalid qp_type=%x", - qp_init_attr->qp_type); - return H_PARAMETER; - } - - for (counter = 0; - shca->sport[port - 1].port_state != IB_PORT_ACTIVE && - counter < ehca_port_act_time; - counter++) { - ehca_dbg(&shca->ib_device, "... wait until port %x is active", - port); - msleep_interruptible(1000); - } - - if (counter == ehca_port_act_time) { - ehca_err(&shca->ib_device, "Port %x is not active.", port); - return H_HARDWARE; - } - - return H_SUCCESS; -} diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_tools.h b/trunk/drivers/infiniband/hw/ehca/ehca_tools.h deleted file mode 100644 index 9f56bb846d93..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_tools.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * auxiliary functions - * - * Authors: Christoph Raisch - * Hoang-Nam Nguyen - * Khadija Souissi - * Waleri Fomin - * Heiko J Schick - * - * Copyright (c) 2005 IBM Corporation - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef EHCA_TOOLS_H -#define EHCA_TOOLS_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -extern int ehca_debug_level; - -#define ehca_dbg(ib_dev, format, arg...) \ - do { \ - if (unlikely(ehca_debug_level)) \ - dev_printk(KERN_DEBUG, (ib_dev)->dma_device, \ - "PU%04x EHCA_DBG:%s " format "\n", \ - get_paca()->paca_index, __FUNCTION__, \ - ## arg); \ - } while (0) - -#define ehca_info(ib_dev, format, arg...) \ - dev_info((ib_dev)->dma_device, "PU%04x EHCA_INFO:%s " format "\n", \ - get_paca()->paca_index, __FUNCTION__, ## arg) - -#define ehca_warn(ib_dev, format, arg...) \ - dev_warn((ib_dev)->dma_device, "PU%04x EHCA_WARN:%s " format "\n", \ - get_paca()->paca_index, __FUNCTION__, ## arg) - -#define ehca_err(ib_dev, format, arg...) \ - dev_err((ib_dev)->dma_device, "PU%04x EHCA_ERR:%s " format "\n", \ - get_paca()->paca_index, __FUNCTION__, ## arg) - -/* use this one only if no ib_dev available */ -#define ehca_gen_dbg(format, arg...) \ - do { \ - if (unlikely(ehca_debug_level)) \ - printk(KERN_DEBUG "PU%04x EHCA_DBG:%s " format "\n",\ - get_paca()->paca_index, __FUNCTION__, ## arg); \ - } while (0) - -#define ehca_gen_warn(format, arg...) \ - do { \ - if (unlikely(ehca_debug_level)) \ - printk(KERN_INFO "PU%04x EHCA_WARN:%s " format "\n",\ - get_paca()->paca_index, __FUNCTION__, ## arg); \ - } while (0) - -#define ehca_gen_err(format, arg...) \ - printk(KERN_ERR "PU%04x EHCA_ERR:%s " format "\n", \ - get_paca()->paca_index, __FUNCTION__, ## arg) - -/** - * ehca_dmp - printk a memory block, whose length is n*8 bytes. - * Each line has the following layout: - * adr=X ofs=Y <8 bytes hex> <8 bytes hex> - */ -#define ehca_dmp(adr, len, format, args...) \ - do { \ - unsigned int x; \ - unsigned int l = (unsigned int)(len); \ - unsigned char *deb = (unsigned char*)(adr); \ - for (x = 0; x < l; x += 16) { \ - printk("EHCA_DMP:%s" format \ - " adr=%p ofs=%04x %016lx %016lx\n", \ - __FUNCTION__, ##args, deb, x, \ - *((u64 *)&deb[0]), *((u64 *)&deb[8])); \ - deb += 16; \ - } \ - } while (0) - -/* define a bitmask, little endian version */ -#define EHCA_BMASK(pos,length) (((pos)<<16)+(length)) - -/* define a bitmask, the ibm way... */ -#define EHCA_BMASK_IBM(from,to) (((63-to)<<16)+((to)-(from)+1)) - -/* internal function, don't use */ -#define EHCA_BMASK_SHIFTPOS(mask) (((mask)>>16)&0xffff) - -/* internal function, don't use */ -#define EHCA_BMASK_MASK(mask) (0xffffffffffffffffULL >> ((64-(mask))&0xffff)) - -/** - * EHCA_BMASK_SET - return value shifted and masked by mask - * variable|=EHCA_BMASK_SET(MY_MASK,0x4711) ORs the bits in variable - * variable&=~EHCA_BMASK_SET(MY_MASK,-1) clears the bits from the mask - * in variable - */ -#define EHCA_BMASK_SET(mask,value) \ - ((EHCA_BMASK_MASK(mask) & ((u64)(value)))<>EHCA_BMASK_SHIFTPOS(mask))) - - -/* Converts ehca to ib return code */ -static inline int ehca2ib_return_code(u64 ehca_rc) -{ - switch (ehca_rc) { - case H_SUCCESS: - return 0; - case H_BUSY: - return -EBUSY; - case H_NO_MEM: - return -ENOMEM; - default: - return -EINVAL; - } -} - - -#endif /* EHCA_TOOLS_H */ diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_uverbs.c b/trunk/drivers/infiniband/hw/ehca/ehca_uverbs.c deleted file mode 100644 index e08764e4aef2..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ehca_uverbs.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * userspace support verbs - * - * Authors: Christoph Raisch - * Hoang-Nam Nguyen - * Heiko J Schick - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include "ehca_classes.h" -#include "ehca_iverbs.h" -#include "ehca_mrmw.h" -#include "ehca_tools.h" -#include "hcp_if.h" - -struct ib_ucontext *ehca_alloc_ucontext(struct ib_device *device, - struct ib_udata *udata) -{ - struct ehca_ucontext *my_context; - - my_context = kzalloc(sizeof *my_context, GFP_KERNEL); - if (!my_context) { - ehca_err(device, "Out of memory device=%p", device); - return ERR_PTR(-ENOMEM); - } - - return &my_context->ib_ucontext; -} - -int ehca_dealloc_ucontext(struct ib_ucontext *context) -{ - kfree(container_of(context, struct ehca_ucontext, ib_ucontext)); - return 0; -} - -struct page *ehca_nopage(struct vm_area_struct *vma, - unsigned long address, int *type) -{ - struct page *mypage = NULL; - u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT; - u32 idr_handle = fileoffset >> 32; - u32 q_type = (fileoffset >> 28) & 0xF; /* CQ, QP,... */ - u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */ - u32 cur_pid = current->tgid; - unsigned long flags; - struct ehca_cq *cq; - struct ehca_qp *qp; - struct ehca_pd *pd; - u64 offset; - void *vaddr; - - switch (q_type) { - case 1: /* CQ */ - spin_lock_irqsave(&ehca_cq_idr_lock, flags); - cq = idr_find(&ehca_cq_idr, idr_handle); - spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); - - /* make sure this mmap really belongs to the authorized user */ - if (!cq) { - ehca_gen_err("cq is NULL ret=NOPAGE_SIGBUS"); - return NOPAGE_SIGBUS; - } - - if (cq->ownpid != cur_pid) { - ehca_err(cq->ib_cq.device, - "Invalid caller pid=%x ownpid=%x", - cur_pid, cq->ownpid); - return NOPAGE_SIGBUS; - } - - if (rsrc_type == 2) { - ehca_dbg(cq->ib_cq.device, "cq=%p cq queuearea", cq); - offset = address - vma->vm_start; - vaddr = ipz_qeit_calc(&cq->ipz_queue, offset); - ehca_dbg(cq->ib_cq.device, "offset=%lx vaddr=%p", - offset, vaddr); - mypage = virt_to_page(vaddr); - } - break; - - case 2: /* QP */ - spin_lock_irqsave(&ehca_qp_idr_lock, flags); - qp = idr_find(&ehca_qp_idr, idr_handle); - spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); - - /* make sure this mmap really belongs to the authorized user */ - if (!qp) { - ehca_gen_err("qp is NULL ret=NOPAGE_SIGBUS"); - return NOPAGE_SIGBUS; - } - - pd = container_of(qp->ib_qp.pd, struct ehca_pd, ib_pd); - if (pd->ownpid != cur_pid) { - ehca_err(qp->ib_qp.device, - "Invalid caller pid=%x ownpid=%x", - cur_pid, pd->ownpid); - return NOPAGE_SIGBUS; - } - - if (rsrc_type == 2) { /* rqueue */ - ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueuearea", qp); - offset = address - vma->vm_start; - vaddr = ipz_qeit_calc(&qp->ipz_rqueue, offset); - ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p", - offset, vaddr); - mypage = virt_to_page(vaddr); - } else if (rsrc_type == 3) { /* squeue */ - ehca_dbg(qp->ib_qp.device, "qp=%p qp squeuearea", qp); - offset = address - vma->vm_start; - vaddr = ipz_qeit_calc(&qp->ipz_squeue, offset); - ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p", - offset, vaddr); - mypage = virt_to_page(vaddr); - } - break; - - default: - ehca_gen_err("bad queue type %x", q_type); - return NOPAGE_SIGBUS; - } - - if (!mypage) { - ehca_gen_err("Invalid page adr==NULL ret=NOPAGE_SIGBUS"); - return NOPAGE_SIGBUS; - } - get_page(mypage); - - return mypage; -} - -static struct vm_operations_struct ehcau_vm_ops = { - .nopage = ehca_nopage, -}; - -int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) -{ - u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT; - u32 idr_handle = fileoffset >> 32; - u32 q_type = (fileoffset >> 28) & 0xF; /* CQ, QP,... */ - u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */ - u32 cur_pid = current->tgid; - u32 ret; - u64 vsize, physical; - unsigned long flags; - struct ehca_cq *cq; - struct ehca_qp *qp; - struct ehca_pd *pd; - - switch (q_type) { - case 1: /* CQ */ - spin_lock_irqsave(&ehca_cq_idr_lock, flags); - cq = idr_find(&ehca_cq_idr, idr_handle); - spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); - - /* make sure this mmap really belongs to the authorized user */ - if (!cq) - return -EINVAL; - - if (cq->ownpid != cur_pid) { - ehca_err(cq->ib_cq.device, - "Invalid caller pid=%x ownpid=%x", - cur_pid, cq->ownpid); - return -ENOMEM; - } - - if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context) - return -EINVAL; - - switch (rsrc_type) { - case 1: /* galpa fw handle */ - ehca_dbg(cq->ib_cq.device, "cq=%p cq triggerarea", cq); - vma->vm_flags |= VM_RESERVED; - vsize = vma->vm_end - vma->vm_start; - if (vsize != EHCA_PAGESIZE) { - ehca_err(cq->ib_cq.device, "invalid vsize=%lx", - vma->vm_end - vma->vm_start); - return -EINVAL; - } - - physical = cq->galpas.user.fw_handle; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - vma->vm_flags |= VM_IO | VM_RESERVED; - - ehca_dbg(cq->ib_cq.device, - "vsize=%lx physical=%lx", vsize, physical); - ret = remap_pfn_range(vma, vma->vm_start, - physical >> PAGE_SHIFT, vsize, - vma->vm_page_prot); - if (ret) { - ehca_err(cq->ib_cq.device, - "remap_pfn_range() failed ret=%x", - ret); - return -ENOMEM; - } - break; - - case 2: /* cq queue_addr */ - ehca_dbg(cq->ib_cq.device, "cq=%p cq q_addr", cq); - vma->vm_flags |= VM_RESERVED; - vma->vm_ops = &ehcau_vm_ops; - break; - - default: - ehca_err(cq->ib_cq.device, "bad resource type %x", - rsrc_type); - return -EINVAL; - } - break; - - case 2: /* QP */ - spin_lock_irqsave(&ehca_qp_idr_lock, flags); - qp = idr_find(&ehca_qp_idr, idr_handle); - spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); - - /* make sure this mmap really belongs to the authorized user */ - if (!qp) - return -EINVAL; - - pd = container_of(qp->ib_qp.pd, struct ehca_pd, ib_pd); - if (pd->ownpid != cur_pid) { - ehca_err(qp->ib_qp.device, - "Invalid caller pid=%x ownpid=%x", - cur_pid, pd->ownpid); - return -ENOMEM; - } - - if (!qp->ib_qp.uobject || qp->ib_qp.uobject->context != context) - return -EINVAL; - - switch (rsrc_type) { - case 1: /* galpa fw handle */ - ehca_dbg(qp->ib_qp.device, "qp=%p qp triggerarea", qp); - vma->vm_flags |= VM_RESERVED; - vsize = vma->vm_end - vma->vm_start; - if (vsize != EHCA_PAGESIZE) { - ehca_err(qp->ib_qp.device, "invalid vsize=%lx", - vma->vm_end - vma->vm_start); - return -EINVAL; - } - - physical = qp->galpas.user.fw_handle; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - vma->vm_flags |= VM_IO | VM_RESERVED; - - ehca_dbg(qp->ib_qp.device, "vsize=%lx physical=%lx", - vsize, physical); - ret = remap_pfn_range(vma, vma->vm_start, - physical >> PAGE_SHIFT, vsize, - vma->vm_page_prot); - if (ret) { - ehca_err(qp->ib_qp.device, - "remap_pfn_range() failed ret=%x", - ret); - return -ENOMEM; - } - break; - - case 2: /* qp rqueue_addr */ - ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueue_addr", qp); - vma->vm_flags |= VM_RESERVED; - vma->vm_ops = &ehcau_vm_ops; - break; - - case 3: /* qp squeue_addr */ - ehca_dbg(qp->ib_qp.device, "qp=%p qp squeue_addr", qp); - vma->vm_flags |= VM_RESERVED; - vma->vm_ops = &ehcau_vm_ops; - break; - - default: - ehca_err(qp->ib_qp.device, "bad resource type %x", - rsrc_type); - return -EINVAL; - } - break; - - default: - ehca_gen_err("bad queue type %x", q_type); - return -EINVAL; - } - - return 0; -} - -int ehca_mmap_nopage(u64 foffset, u64 length, void **mapped, - struct vm_area_struct **vma) -{ - down_write(¤t->mm->mmap_sem); - *mapped = (void*)do_mmap(NULL,0, length, PROT_WRITE, - MAP_SHARED | MAP_ANONYMOUS, - foffset); - up_write(¤t->mm->mmap_sem); - if (!(*mapped)) { - ehca_gen_err("couldn't mmap foffset=%lx length=%lx", - foffset, length); - return -EINVAL; - } - - *vma = find_vma(current->mm, (u64)*mapped); - if (!(*vma)) { - down_write(¤t->mm->mmap_sem); - do_munmap(current->mm, 0, length); - up_write(¤t->mm->mmap_sem); - ehca_gen_err("couldn't find vma queue=%p", *mapped); - return -EINVAL; - } - (*vma)->vm_flags |= VM_RESERVED; - (*vma)->vm_ops = &ehcau_vm_ops; - - return 0; -} - -int ehca_mmap_register(u64 physical, void **mapped, - struct vm_area_struct **vma) -{ - int ret; - unsigned long vsize; - /* ehca hw supports only 4k page */ - ret = ehca_mmap_nopage(0, EHCA_PAGESIZE, mapped, vma); - if (ret) { - ehca_gen_err("could'nt mmap physical=%lx", physical); - return ret; - } - - (*vma)->vm_flags |= VM_RESERVED; - vsize = (*vma)->vm_end - (*vma)->vm_start; - if (vsize != EHCA_PAGESIZE) { - ehca_gen_err("invalid vsize=%lx", - (*vma)->vm_end - (*vma)->vm_start); - return -EINVAL; - } - - (*vma)->vm_page_prot = pgprot_noncached((*vma)->vm_page_prot); - (*vma)->vm_flags |= VM_IO | VM_RESERVED; - - ret = remap_pfn_range((*vma), (*vma)->vm_start, - physical >> PAGE_SHIFT, vsize, - (*vma)->vm_page_prot); - if (ret) { - ehca_gen_err("remap_pfn_range() failed ret=%x", ret); - return -ENOMEM; - } - - return 0; - -} - -int ehca_munmap(unsigned long addr, size_t len) { - int ret = 0; - struct mm_struct *mm = current->mm; - if (mm) { - down_write(&mm->mmap_sem); - ret = do_munmap(mm, addr, len); - up_write(&mm->mmap_sem); - } - return ret; -} diff --git a/trunk/drivers/infiniband/hw/ehca/hcp_if.c b/trunk/drivers/infiniband/hw/ehca/hcp_if.c deleted file mode 100644 index 3fb46e67df87..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/hcp_if.c +++ /dev/null @@ -1,874 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Firmware Infiniband Interface code for POWER - * - * Authors: Christoph Raisch - * Hoang-Nam Nguyen - * Gerd Bayer - * Waleri Fomin - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "ehca_tools.h" -#include "hcp_if.h" -#include "hcp_phyp.h" -#include "hipz_fns.h" -#include "ipz_pt_fn.h" - -#define H_ALL_RES_QP_ENHANCED_OPS EHCA_BMASK_IBM(9, 11) -#define H_ALL_RES_QP_PTE_PIN EHCA_BMASK_IBM(12, 12) -#define H_ALL_RES_QP_SERVICE_TYPE EHCA_BMASK_IBM(13, 15) -#define H_ALL_RES_QP_LL_RQ_CQE_POSTING EHCA_BMASK_IBM(18, 18) -#define H_ALL_RES_QP_LL_SQ_CQE_POSTING EHCA_BMASK_IBM(19, 21) -#define H_ALL_RES_QP_SIGNALING_TYPE EHCA_BMASK_IBM(22, 23) -#define H_ALL_RES_QP_UD_AV_LKEY_CTRL EHCA_BMASK_IBM(31, 31) -#define H_ALL_RES_QP_RESOURCE_TYPE EHCA_BMASK_IBM(56, 63) - -#define H_ALL_RES_QP_MAX_OUTST_SEND_WR EHCA_BMASK_IBM(0, 15) -#define H_ALL_RES_QP_MAX_OUTST_RECV_WR EHCA_BMASK_IBM(16, 31) -#define H_ALL_RES_QP_MAX_SEND_SGE EHCA_BMASK_IBM(32, 39) -#define H_ALL_RES_QP_MAX_RECV_SGE EHCA_BMASK_IBM(40, 47) - -#define H_ALL_RES_QP_ACT_OUTST_SEND_WR EHCA_BMASK_IBM(16, 31) -#define H_ALL_RES_QP_ACT_OUTST_RECV_WR EHCA_BMASK_IBM(48, 63) -#define H_ALL_RES_QP_ACT_SEND_SGE EHCA_BMASK_IBM(8, 15) -#define H_ALL_RES_QP_ACT_RECV_SGE EHCA_BMASK_IBM(24, 31) - -#define H_ALL_RES_QP_SQUEUE_SIZE_PAGES EHCA_BMASK_IBM(0, 31) -#define H_ALL_RES_QP_RQUEUE_SIZE_PAGES EHCA_BMASK_IBM(32, 63) - -/* direct access qp controls */ -#define DAQP_CTRL_ENABLE 0x01 -#define DAQP_CTRL_SEND_COMP 0x20 -#define DAQP_CTRL_RECV_COMP 0x40 - -static u32 get_longbusy_msecs(int longbusy_rc) -{ - switch (longbusy_rc) { - case H_LONG_BUSY_ORDER_1_MSEC: - return 1; - case H_LONG_BUSY_ORDER_10_MSEC: - return 10; - case H_LONG_BUSY_ORDER_100_MSEC: - return 100; - case H_LONG_BUSY_ORDER_1_SEC: - return 1000; - case H_LONG_BUSY_ORDER_10_SEC: - return 10000; - case H_LONG_BUSY_ORDER_100_SEC: - return 100000; - default: - return 1; - } -} - -static long ehca_plpar_hcall_norets(unsigned long opcode, - unsigned long arg1, - unsigned long arg2, - unsigned long arg3, - unsigned long arg4, - unsigned long arg5, - unsigned long arg6, - unsigned long arg7) -{ - long ret; - int i, sleep_msecs; - - ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx " - "arg5=%lx arg6=%lx arg7=%lx", - opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7); - - for (i = 0; i < 5; i++) { - ret = plpar_hcall_norets(opcode, arg1, arg2, arg3, arg4, - arg5, arg6, arg7); - - if (H_IS_LONG_BUSY(ret)) { - sleep_msecs = get_longbusy_msecs(ret); - msleep_interruptible(sleep_msecs); - continue; - } - - if (ret < H_SUCCESS) - ehca_gen_err("opcode=%lx ret=%lx" - " arg1=%lx arg2=%lx arg3=%lx arg4=%lx" - " arg5=%lx arg6=%lx arg7=%lx ", - opcode, ret, - arg1, arg2, arg3, arg4, arg5, - arg6, arg7); - - ehca_gen_dbg("opcode=%lx ret=%lx", opcode, ret); - return ret; - - } - - return H_BUSY; -} - -static long ehca_plpar_hcall9(unsigned long opcode, - unsigned long *outs, /* array of 9 outputs */ - unsigned long arg1, - unsigned long arg2, - unsigned long arg3, - unsigned long arg4, - unsigned long arg5, - unsigned long arg6, - unsigned long arg7, - unsigned long arg8, - unsigned long arg9) -{ - long ret; - int i, sleep_msecs; - - ehca_gen_dbg("opcode=%lx arg1=%lx arg2=%lx arg3=%lx arg4=%lx " - "arg5=%lx arg6=%lx arg7=%lx arg8=%lx arg9=%lx", - opcode, arg1, arg2, arg3, arg4, arg5, arg6, arg7, - arg8, arg9); - - for (i = 0; i < 5; i++) { - ret = plpar_hcall9(opcode, outs, - arg1, arg2, arg3, arg4, arg5, - arg6, arg7, arg8, arg9); - - if (H_IS_LONG_BUSY(ret)) { - sleep_msecs = get_longbusy_msecs(ret); - msleep_interruptible(sleep_msecs); - continue; - } - - if (ret < H_SUCCESS) - ehca_gen_err("opcode=%lx ret=%lx" - " arg1=%lx arg2=%lx arg3=%lx arg4=%lx" - " arg5=%lx arg6=%lx arg7=%lx arg8=%lx" - " arg9=%lx" - " out1=%lx out2=%lx out3=%lx out4=%lx" - " out5=%lx out6=%lx out7=%lx out8=%lx" - " out9=%lx", - opcode, ret, - arg1, arg2, arg3, arg4, arg5, - arg6, arg7, arg8, arg9, - outs[0], outs[1], outs[2], outs[3], - outs[4], outs[5], outs[6], outs[7], - outs[8]); - - ehca_gen_dbg("opcode=%lx ret=%lx out1=%lx out2=%lx out3=%lx " - "out4=%lx out5=%lx out6=%lx out7=%lx out8=%lx " - "out9=%lx", - opcode, ret, outs[0], outs[1], outs[2], outs[3], - outs[4], outs[5], outs[6], outs[7], outs[8]); - return ret; - - } - - return H_BUSY; -} -u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle, - struct ehca_pfeq *pfeq, - const u32 neq_control, - const u32 number_of_entries, - struct ipz_eq_handle *eq_handle, - u32 *act_nr_of_entries, - u32 *act_pages, - u32 *eq_ist) -{ - u64 ret; - u64 outs[PLPAR_HCALL9_BUFSIZE]; - u64 allocate_controls; - - /* resource type */ - allocate_controls = 3ULL; - - /* ISN is associated */ - if (neq_control != 1) - allocate_controls = (1ULL << (63 - 7)) | allocate_controls; - else /* notification event queue */ - allocate_controls = (1ULL << 63) | allocate_controls; - - ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, - adapter_handle.handle, /* r4 */ - allocate_controls, /* r5 */ - number_of_entries, /* r6 */ - 0, 0, 0, 0, 0, 0); - eq_handle->handle = outs[0]; - *act_nr_of_entries = (u32)outs[3]; - *act_pages = (u32)outs[4]; - *eq_ist = (u32)outs[5]; - - if (ret == H_NOT_ENOUGH_RESOURCES) - ehca_gen_err("Not enough resource - ret=%lx ", ret); - - return ret; -} - -u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle, - struct ipz_eq_handle eq_handle, - const u64 event_mask) -{ - return ehca_plpar_hcall_norets(H_RESET_EVENTS, - adapter_handle.handle, /* r4 */ - eq_handle.handle, /* r5 */ - event_mask, /* r6 */ - 0, 0, 0, 0); -} - -u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle, - struct ehca_cq *cq, - struct ehca_alloc_cq_parms *param) -{ - u64 ret; - u64 outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, - adapter_handle.handle, /* r4 */ - 2, /* r5 */ - param->eq_handle.handle, /* r6 */ - cq->token, /* r7 */ - param->nr_cqe, /* r8 */ - 0, 0, 0, 0); - cq->ipz_cq_handle.handle = outs[0]; - param->act_nr_of_entries = (u32)outs[3]; - param->act_pages = (u32)outs[4]; - - if (ret == H_SUCCESS) - hcp_galpas_ctor(&cq->galpas, outs[5], outs[6]); - - if (ret == H_NOT_ENOUGH_RESOURCES) - ehca_gen_err("Not enough resources. ret=%lx", ret); - - return ret; -} - -u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle, - struct ehca_qp *qp, - struct ehca_alloc_qp_parms *parms) -{ - u64 ret; - u64 allocate_controls; - u64 max_r10_reg; - u64 outs[PLPAR_HCALL9_BUFSIZE]; - u16 max_nr_receive_wqes = qp->init_attr.cap.max_recv_wr + 1; - u16 max_nr_send_wqes = qp->init_attr.cap.max_send_wr + 1; - int daqp_ctrl = parms->daqp_ctrl; - - allocate_controls = - EHCA_BMASK_SET(H_ALL_RES_QP_ENHANCED_OPS, - (daqp_ctrl & DAQP_CTRL_ENABLE) ? 1 : 0) - | EHCA_BMASK_SET(H_ALL_RES_QP_PTE_PIN, 0) - | EHCA_BMASK_SET(H_ALL_RES_QP_SERVICE_TYPE, parms->servicetype) - | EHCA_BMASK_SET(H_ALL_RES_QP_SIGNALING_TYPE, parms->sigtype) - | EHCA_BMASK_SET(H_ALL_RES_QP_LL_RQ_CQE_POSTING, - (daqp_ctrl & DAQP_CTRL_RECV_COMP) ? 1 : 0) - | EHCA_BMASK_SET(H_ALL_RES_QP_LL_SQ_CQE_POSTING, - (daqp_ctrl & DAQP_CTRL_SEND_COMP) ? 1 : 0) - | EHCA_BMASK_SET(H_ALL_RES_QP_UD_AV_LKEY_CTRL, - parms->ud_av_l_key_ctl) - | EHCA_BMASK_SET(H_ALL_RES_QP_RESOURCE_TYPE, 1); - - max_r10_reg = - EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_SEND_WR, - max_nr_send_wqes) - | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_OUTST_RECV_WR, - max_nr_receive_wqes) - | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_SEND_SGE, - parms->max_send_sge) - | EHCA_BMASK_SET(H_ALL_RES_QP_MAX_RECV_SGE, - parms->max_recv_sge); - - ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, - adapter_handle.handle, /* r4 */ - allocate_controls, /* r5 */ - qp->send_cq->ipz_cq_handle.handle, - qp->recv_cq->ipz_cq_handle.handle, - parms->ipz_eq_handle.handle, - ((u64)qp->token << 32) | parms->pd.value, - max_r10_reg, /* r10 */ - parms->ud_av_l_key_ctl, /* r11 */ - 0); - qp->ipz_qp_handle.handle = outs[0]; - qp->real_qp_num = (u32)outs[1]; - parms->act_nr_send_sges = - (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_SEND_WR, outs[2]); - parms->act_nr_recv_wqes = - (u16)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_OUTST_RECV_WR, outs[2]); - parms->act_nr_send_sges = - (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_SEND_SGE, outs[3]); - parms->act_nr_recv_sges = - (u8)EHCA_BMASK_GET(H_ALL_RES_QP_ACT_RECV_SGE, outs[3]); - parms->nr_sq_pages = - (u32)EHCA_BMASK_GET(H_ALL_RES_QP_SQUEUE_SIZE_PAGES, outs[4]); - parms->nr_rq_pages = - (u32)EHCA_BMASK_GET(H_ALL_RES_QP_RQUEUE_SIZE_PAGES, outs[4]); - - if (ret == H_SUCCESS) - hcp_galpas_ctor(&qp->galpas, outs[6], outs[6]); - - if (ret == H_NOT_ENOUGH_RESOURCES) - ehca_gen_err("Not enough resources. ret=%lx", ret); - - return ret; -} - -u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle, - const u8 port_id, - struct hipz_query_port *query_port_response_block) -{ - u64 ret; - u64 r_cb = virt_to_abs(query_port_response_block); - - if (r_cb & (EHCA_PAGESIZE-1)) { - ehca_gen_err("response block not page aligned"); - return H_PARAMETER; - } - - ret = ehca_plpar_hcall_norets(H_QUERY_PORT, - adapter_handle.handle, /* r4 */ - port_id, /* r5 */ - r_cb, /* r6 */ - 0, 0, 0, 0); - - if (ehca_debug_level) - ehca_dmp(query_port_response_block, 64, "response_block"); - - return ret; -} - -u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle, - struct hipz_query_hca *query_hca_rblock) -{ - u64 r_cb = virt_to_abs(query_hca_rblock); - - if (r_cb & (EHCA_PAGESIZE-1)) { - ehca_gen_err("response_block=%p not page aligned", - query_hca_rblock); - return H_PARAMETER; - } - - return ehca_plpar_hcall_norets(H_QUERY_HCA, - adapter_handle.handle, /* r4 */ - r_cb, /* r5 */ - 0, 0, 0, 0, 0); -} - -u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle, - const u8 pagesize, - const u8 queue_type, - const u64 resource_handle, - const u64 logical_address_of_page, - u64 count) -{ - return ehca_plpar_hcall_norets(H_REGISTER_RPAGES, - adapter_handle.handle, /* r4 */ - queue_type | pagesize << 8, /* r5 */ - resource_handle, /* r6 */ - logical_address_of_page, /* r7 */ - count, /* r8 */ - 0, 0); -} - -u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle, - const struct ipz_eq_handle eq_handle, - struct ehca_pfeq *pfeq, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count) -{ - if (count != 1) { - ehca_gen_err("Ppage counter=%lx", count); - return H_PARAMETER; - } - return hipz_h_register_rpage(adapter_handle, - pagesize, - queue_type, - eq_handle.handle, - logical_address_of_page, count); -} - -u64 hipz_h_query_int_state(const struct ipz_adapter_handle adapter_handle, - u32 ist) -{ - u64 ret; - ret = ehca_plpar_hcall_norets(H_QUERY_INT_STATE, - adapter_handle.handle, /* r4 */ - ist, /* r5 */ - 0, 0, 0, 0, 0); - - if (ret != H_SUCCESS && ret != H_BUSY) - ehca_gen_err("Could not query interrupt state."); - - return ret; -} - -u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle, - const struct ipz_cq_handle cq_handle, - struct ehca_pfcq *pfcq, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count, - const struct h_galpa gal) -{ - if (count != 1) { - ehca_gen_err("Page counter=%lx", count); - return H_PARAMETER; - } - - return hipz_h_register_rpage(adapter_handle, pagesize, queue_type, - cq_handle.handle, logical_address_of_page, - count); -} - -u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count, - const struct h_galpa galpa) -{ - if (count != 1) { - ehca_gen_err("Page counter=%lx", count); - return H_PARAMETER; - } - - return hipz_h_register_rpage(adapter_handle,pagesize,queue_type, - qp_handle.handle,logical_address_of_page, - count); -} - -u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - void **log_addr_next_sq_wqe2processed, - void **log_addr_next_rq_wqe2processed, - int dis_and_get_function_code) -{ - u64 ret; - u64 outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs, - adapter_handle.handle, /* r4 */ - dis_and_get_function_code, /* r5 */ - qp_handle.handle, /* r6 */ - 0, 0, 0, 0, 0, 0); - if (log_addr_next_sq_wqe2processed) - *log_addr_next_sq_wqe2processed = (void*)outs[0]; - if (log_addr_next_rq_wqe2processed) - *log_addr_next_rq_wqe2processed = (void*)outs[1]; - - return ret; -} - -u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - const u64 update_mask, - struct hcp_modify_qp_control_block *mqpcb, - struct h_galpa gal) -{ - u64 ret; - u64 outs[PLPAR_HCALL9_BUFSIZE]; - ret = ehca_plpar_hcall9(H_MODIFY_QP, outs, - adapter_handle.handle, /* r4 */ - qp_handle.handle, /* r5 */ - update_mask, /* r6 */ - virt_to_abs(mqpcb), /* r7 */ - 0, 0, 0, 0, 0); - - if (ret == H_NOT_ENOUGH_RESOURCES) - ehca_gen_err("Insufficient resources ret=%lx", ret); - - return ret; -} - -u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - struct hcp_modify_qp_control_block *qqpcb, - struct h_galpa gal) -{ - return ehca_plpar_hcall_norets(H_QUERY_QP, - adapter_handle.handle, /* r4 */ - qp_handle.handle, /* r5 */ - virt_to_abs(qqpcb), /* r6 */ - 0, 0, 0, 0); -} - -u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle, - struct ehca_qp *qp) -{ - u64 ret; - u64 outs[PLPAR_HCALL9_BUFSIZE]; - - ret = hcp_galpas_dtor(&qp->galpas); - if (ret) { - ehca_gen_err("Could not destruct qp->galpas"); - return H_RESOURCE; - } - ret = ehca_plpar_hcall9(H_DISABLE_AND_GETC, outs, - adapter_handle.handle, /* r4 */ - /* function code */ - 1, /* r5 */ - qp->ipz_qp_handle.handle, /* r6 */ - 0, 0, 0, 0, 0, 0); - if (ret == H_HARDWARE) - ehca_gen_err("HCA not operational. ret=%lx", ret); - - ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE, - adapter_handle.handle, /* r4 */ - qp->ipz_qp_handle.handle, /* r5 */ - 0, 0, 0, 0, 0); - - if (ret == H_RESOURCE) - ehca_gen_err("Resource still in use. ret=%lx", ret); - - return ret; -} - -u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u32 port) -{ - return ehca_plpar_hcall_norets(H_DEFINE_AQP0, - adapter_handle.handle, /* r4 */ - qp_handle.handle, /* r5 */ - port, /* r6 */ - 0, 0, 0, 0); -} - -u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u32 port, u32 * pma_qp_nr, - u32 * bma_qp_nr) -{ - u64 ret; - u64 outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_DEFINE_AQP1, outs, - adapter_handle.handle, /* r4 */ - qp_handle.handle, /* r5 */ - port, /* r6 */ - 0, 0, 0, 0, 0, 0); - *pma_qp_nr = (u32)outs[0]; - *bma_qp_nr = (u32)outs[1]; - - if (ret == H_ALIAS_EXIST) - ehca_gen_err("AQP1 already exists. ret=%lx", ret); - - return ret; -} - -u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u16 mcg_dlid, - u64 subnet_prefix, u64 interface_id) -{ - u64 ret; - - ret = ehca_plpar_hcall_norets(H_ATTACH_MCQP, - adapter_handle.handle, /* r4 */ - qp_handle.handle, /* r5 */ - mcg_dlid, /* r6 */ - interface_id, /* r7 */ - subnet_prefix, /* r8 */ - 0, 0); - - if (ret == H_NOT_ENOUGH_RESOURCES) - ehca_gen_err("Not enough resources. ret=%lx", ret); - - return ret; -} - -u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u16 mcg_dlid, - u64 subnet_prefix, u64 interface_id) -{ - return ehca_plpar_hcall_norets(H_DETACH_MCQP, - adapter_handle.handle, /* r4 */ - qp_handle.handle, /* r5 */ - mcg_dlid, /* r6 */ - interface_id, /* r7 */ - subnet_prefix, /* r8 */ - 0, 0); -} - -u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle, - struct ehca_cq *cq, - u8 force_flag) -{ - u64 ret; - - ret = hcp_galpas_dtor(&cq->galpas); - if (ret) { - ehca_gen_err("Could not destruct cp->galpas"); - return H_RESOURCE; - } - - ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE, - adapter_handle.handle, /* r4 */ - cq->ipz_cq_handle.handle, /* r5 */ - force_flag != 0 ? 1L : 0L, /* r6 */ - 0, 0, 0, 0); - - if (ret == H_RESOURCE) - ehca_gen_err("H_FREE_RESOURCE failed ret=%lx ", ret); - - return ret; -} - -u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle, - struct ehca_eq *eq) -{ - u64 ret; - - ret = hcp_galpas_dtor(&eq->galpas); - if (ret) { - ehca_gen_err("Could not destruct eq->galpas"); - return H_RESOURCE; - } - - ret = ehca_plpar_hcall_norets(H_FREE_RESOURCE, - adapter_handle.handle, /* r4 */ - eq->ipz_eq_handle.handle, /* r5 */ - 0, 0, 0, 0, 0); - - if (ret == H_RESOURCE) - ehca_gen_err("Resource in use. ret=%lx ", ret); - - return ret; -} - -u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const u64 vaddr, - const u64 length, - const u32 access_ctrl, - const struct ipz_pd pd, - struct ehca_mr_hipzout_parms *outparms) -{ - u64 ret; - u64 outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, - adapter_handle.handle, /* r4 */ - 5, /* r5 */ - vaddr, /* r6 */ - length, /* r7 */ - (((u64)access_ctrl) << 32ULL), /* r8 */ - pd.value, /* r9 */ - 0, 0, 0); - outparms->handle.handle = outs[0]; - outparms->lkey = (u32)outs[2]; - outparms->rkey = (u32)outs[3]; - - return ret; -} - -u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count) -{ - u64 ret; - - if ((count > 1) && (logical_address_of_page & (EHCA_PAGESIZE-1))) { - ehca_gen_err("logical_address_of_page not on a 4k boundary " - "adapter_handle=%lx mr=%p mr_handle=%lx " - "pagesize=%x queue_type=%x " - "logical_address_of_page=%lx count=%lx", - adapter_handle.handle, mr, - mr->ipz_mr_handle.handle, pagesize, queue_type, - logical_address_of_page, count); - ret = H_PARAMETER; - } else - ret = hipz_h_register_rpage(adapter_handle, pagesize, - queue_type, - mr->ipz_mr_handle.handle, - logical_address_of_page, count); - return ret; -} - -u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - struct ehca_mr_hipzout_parms *outparms) -{ - u64 ret; - u64 outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_QUERY_MR, outs, - adapter_handle.handle, /* r4 */ - mr->ipz_mr_handle.handle, /* r5 */ - 0, 0, 0, 0, 0, 0, 0); - outparms->len = outs[0]; - outparms->vaddr = outs[1]; - outparms->acl = outs[4] >> 32; - outparms->lkey = (u32)(outs[5] >> 32); - outparms->rkey = (u32)(outs[5] & (0xffffffff)); - - return ret; -} - -u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr) -{ - return ehca_plpar_hcall_norets(H_FREE_RESOURCE, - adapter_handle.handle, /* r4 */ - mr->ipz_mr_handle.handle, /* r5 */ - 0, 0, 0, 0, 0); -} - -u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const u64 vaddr_in, - const u64 length, - const u32 access_ctrl, - const struct ipz_pd pd, - const u64 mr_addr_cb, - struct ehca_mr_hipzout_parms *outparms) -{ - u64 ret; - u64 outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_REREGISTER_PMR, outs, - adapter_handle.handle, /* r4 */ - mr->ipz_mr_handle.handle, /* r5 */ - vaddr_in, /* r6 */ - length, /* r7 */ - /* r8 */ - ((((u64)access_ctrl) << 32ULL) | pd.value), - mr_addr_cb, /* r9 */ - 0, 0, 0); - outparms->vaddr = outs[1]; - outparms->lkey = (u32)outs[2]; - outparms->rkey = (u32)outs[3]; - - return ret; -} - -u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const struct ehca_mr *orig_mr, - const u64 vaddr_in, - const u32 access_ctrl, - const struct ipz_pd pd, - struct ehca_mr_hipzout_parms *outparms) -{ - u64 ret; - u64 outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_REGISTER_SMR, outs, - adapter_handle.handle, /* r4 */ - orig_mr->ipz_mr_handle.handle, /* r5 */ - vaddr_in, /* r6 */ - (((u64)access_ctrl) << 32ULL), /* r7 */ - pd.value, /* r8 */ - 0, 0, 0, 0); - outparms->handle.handle = outs[0]; - outparms->lkey = (u32)outs[2]; - outparms->rkey = (u32)outs[3]; - - return ret; -} - -u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mw *mw, - const struct ipz_pd pd, - struct ehca_mw_hipzout_parms *outparms) -{ - u64 ret; - u64 outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_ALLOC_RESOURCE, outs, - adapter_handle.handle, /* r4 */ - 6, /* r5 */ - pd.value, /* r6 */ - 0, 0, 0, 0, 0, 0); - outparms->handle.handle = outs[0]; - outparms->rkey = (u32)outs[3]; - - return ret; -} - -u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mw *mw, - struct ehca_mw_hipzout_parms *outparms) -{ - u64 ret; - u64 outs[PLPAR_HCALL9_BUFSIZE]; - - ret = ehca_plpar_hcall9(H_QUERY_MW, outs, - adapter_handle.handle, /* r4 */ - mw->ipz_mw_handle.handle, /* r5 */ - 0, 0, 0, 0, 0, 0, 0); - outparms->rkey = (u32)outs[3]; - - return ret; -} - -u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mw *mw) -{ - return ehca_plpar_hcall_norets(H_FREE_RESOURCE, - adapter_handle.handle, /* r4 */ - mw->ipz_mw_handle.handle, /* r5 */ - 0, 0, 0, 0, 0); -} - -u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle, - const u64 ressource_handle, - void *rblock, - unsigned long *byte_count) -{ - u64 r_cb = virt_to_abs(rblock); - - if (r_cb & (EHCA_PAGESIZE-1)) { - ehca_gen_err("rblock not page aligned."); - return H_PARAMETER; - } - - return ehca_plpar_hcall_norets(H_ERROR_DATA, - adapter_handle.handle, - ressource_handle, - r_cb, - 0, 0, 0, 0); -} diff --git a/trunk/drivers/infiniband/hw/ehca/hcp_if.h b/trunk/drivers/infiniband/hw/ehca/hcp_if.h deleted file mode 100644 index 587ebd470959..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/hcp_if.h +++ /dev/null @@ -1,261 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Firmware Infiniband Interface code for POWER - * - * Authors: Christoph Raisch - * Hoang-Nam Nguyen - * Gerd Bayer - * Waleri Fomin - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HCP_IF_H__ -#define __HCP_IF_H__ - -#include "ehca_classes.h" -#include "ehca_tools.h" -#include "hipz_hw.h" - -/* - * hipz_h_alloc_resource_eq allocates EQ resources in HW and FW, initalize - * resources, create the empty EQPT (ring). - */ -u64 hipz_h_alloc_resource_eq(const struct ipz_adapter_handle adapter_handle, - struct ehca_pfeq *pfeq, - const u32 neq_control, - const u32 number_of_entries, - struct ipz_eq_handle *eq_handle, - u32 * act_nr_of_entries, - u32 * act_pages, - u32 * eq_ist); - -u64 hipz_h_reset_event(const struct ipz_adapter_handle adapter_handle, - struct ipz_eq_handle eq_handle, - const u64 event_mask); -/* - * hipz_h_allocate_resource_cq allocates CQ resources in HW and FW, initialize - * resources, create the empty CQPT (ring). - */ -u64 hipz_h_alloc_resource_cq(const struct ipz_adapter_handle adapter_handle, - struct ehca_cq *cq, - struct ehca_alloc_cq_parms *param); - - -/* - * hipz_h_alloc_resource_qp allocates QP resources in HW and FW, - * initialize resources, create empty QPPTs (2 rings). - */ -u64 hipz_h_alloc_resource_qp(const struct ipz_adapter_handle adapter_handle, - struct ehca_qp *qp, - struct ehca_alloc_qp_parms *parms); - -u64 hipz_h_query_port(const struct ipz_adapter_handle adapter_handle, - const u8 port_id, - struct hipz_query_port *query_port_response_block); - -u64 hipz_h_query_hca(const struct ipz_adapter_handle adapter_handle, - struct hipz_query_hca *query_hca_rblock); - -/* - * hipz_h_register_rpage internal function in hcp_if.h for all - * hcp_H_REGISTER_RPAGE calls. - */ -u64 hipz_h_register_rpage(const struct ipz_adapter_handle adapter_handle, - const u8 pagesize, - const u8 queue_type, - const u64 resource_handle, - const u64 logical_address_of_page, - u64 count); - -u64 hipz_h_register_rpage_eq(const struct ipz_adapter_handle adapter_handle, - const struct ipz_eq_handle eq_handle, - struct ehca_pfeq *pfeq, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count); - -u64 hipz_h_query_int_state(const struct ipz_adapter_handle - hcp_adapter_handle, - u32 ist); - -u64 hipz_h_register_rpage_cq(const struct ipz_adapter_handle adapter_handle, - const struct ipz_cq_handle cq_handle, - struct ehca_pfcq *pfcq, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count, - const struct h_galpa gal); - -u64 hipz_h_register_rpage_qp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count, - const struct h_galpa galpa); - -u64 hipz_h_disable_and_get_wqe(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - void **log_addr_next_sq_wqe_tb_processed, - void **log_addr_next_rq_wqe_tb_processed, - int dis_and_get_function_code); -enum hcall_sigt { - HCALL_SIGT_NO_CQE = 0, - HCALL_SIGT_BY_WQE = 1, - HCALL_SIGT_EVERY = 2 -}; - -u64 hipz_h_modify_qp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - const u64 update_mask, - struct hcp_modify_qp_control_block *mqpcb, - struct h_galpa gal); - -u64 hipz_h_query_qp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct ehca_pfqp *pfqp, - struct hcp_modify_qp_control_block *qqpcb, - struct h_galpa gal); - -u64 hipz_h_destroy_qp(const struct ipz_adapter_handle adapter_handle, - struct ehca_qp *qp); - -u64 hipz_h_define_aqp0(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u32 port); - -u64 hipz_h_define_aqp1(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u32 port, u32 * pma_qp_nr, - u32 * bma_qp_nr); - -u64 hipz_h_attach_mcqp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u16 mcg_dlid, - u64 subnet_prefix, u64 interface_id); - -u64 hipz_h_detach_mcqp(const struct ipz_adapter_handle adapter_handle, - const struct ipz_qp_handle qp_handle, - struct h_galpa gal, - u16 mcg_dlid, - u64 subnet_prefix, u64 interface_id); - -u64 hipz_h_destroy_cq(const struct ipz_adapter_handle adapter_handle, - struct ehca_cq *cq, - u8 force_flag); - -u64 hipz_h_destroy_eq(const struct ipz_adapter_handle adapter_handle, - struct ehca_eq *eq); - -/* - * hipz_h_alloc_resource_mr allocates MR resources in HW and FW, initialize - * resources. - */ -u64 hipz_h_alloc_resource_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const u64 vaddr, - const u64 length, - const u32 access_ctrl, - const struct ipz_pd pd, - struct ehca_mr_hipzout_parms *outparms); - -/* hipz_h_register_rpage_mr registers MR resource pages in HW and FW */ -u64 hipz_h_register_rpage_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const u8 pagesize, - const u8 queue_type, - const u64 logical_address_of_page, - const u64 count); - -/* hipz_h_query_mr queries MR in HW and FW */ -u64 hipz_h_query_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - struct ehca_mr_hipzout_parms *outparms); - -/* hipz_h_free_resource_mr frees MR resources in HW and FW */ -u64 hipz_h_free_resource_mr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr); - -/* hipz_h_reregister_pmr reregisters MR in HW and FW */ -u64 hipz_h_reregister_pmr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const u64 vaddr_in, - const u64 length, - const u32 access_ctrl, - const struct ipz_pd pd, - const u64 mr_addr_cb, - struct ehca_mr_hipzout_parms *outparms); - -/* hipz_h_register_smr register shared MR in HW and FW */ -u64 hipz_h_register_smr(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mr *mr, - const struct ehca_mr *orig_mr, - const u64 vaddr_in, - const u32 access_ctrl, - const struct ipz_pd pd, - struct ehca_mr_hipzout_parms *outparms); - -/* - * hipz_h_alloc_resource_mw allocates MW resources in HW and FW, initialize - * resources. - */ -u64 hipz_h_alloc_resource_mw(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mw *mw, - const struct ipz_pd pd, - struct ehca_mw_hipzout_parms *outparms); - -/* hipz_h_query_mw queries MW in HW and FW */ -u64 hipz_h_query_mw(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mw *mw, - struct ehca_mw_hipzout_parms *outparms); - -/* hipz_h_free_resource_mw frees MW resources in HW and FW */ -u64 hipz_h_free_resource_mw(const struct ipz_adapter_handle adapter_handle, - const struct ehca_mw *mw); - -u64 hipz_h_error_data(const struct ipz_adapter_handle adapter_handle, - const u64 ressource_handle, - void *rblock, - unsigned long *byte_count); - -#endif /* __HCP_IF_H__ */ diff --git a/trunk/drivers/infiniband/hw/ehca/hcp_phyp.c b/trunk/drivers/infiniband/hw/ehca/hcp_phyp.c deleted file mode 100644 index 0b1a4772c78a..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/hcp_phyp.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * load store abstraction for ehca register access with tracing - * - * Authors: Christoph Raisch - * Hoang-Nam Nguyen - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ehca_classes.h" -#include "hipz_hw.h" - -int hcall_map_page(u64 physaddr, u64 *mapaddr) -{ - *mapaddr = (u64)(ioremap(physaddr, EHCA_PAGESIZE)); - return 0; -} - -int hcall_unmap_page(u64 mapaddr) -{ - iounmap((volatile void __iomem*)mapaddr); - return 0; -} - -int hcp_galpas_ctor(struct h_galpas *galpas, - u64 paddr_kernel, u64 paddr_user) -{ - int ret = hcall_map_page(paddr_kernel, &galpas->kernel.fw_handle); - if (ret) - return ret; - - galpas->user.fw_handle = paddr_user; - - return 0; -} - -int hcp_galpas_dtor(struct h_galpas *galpas) -{ - if (galpas->kernel.fw_handle) { - int ret = hcall_unmap_page(galpas->kernel.fw_handle); - if (ret) - return ret; - } - - galpas->user.fw_handle = galpas->kernel.fw_handle = 0; - - return 0; -} diff --git a/trunk/drivers/infiniband/hw/ehca/hcp_phyp.h b/trunk/drivers/infiniband/hw/ehca/hcp_phyp.h deleted file mode 100644 index 5305c2a3ed94..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/hcp_phyp.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * Firmware calls - * - * Authors: Christoph Raisch - * Hoang-Nam Nguyen - * Waleri Fomin - * Gerd Bayer - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HCP_PHYP_H__ -#define __HCP_PHYP_H__ - - -/* - * eHCA page (mapped into memory) - * resource to access eHCA register pages in CPU address space -*/ -struct h_galpa { - u64 fw_handle; - /* for pSeries this is a 64bit memory address where - I/O memory is mapped into CPU address space (kv) */ -}; - -/* - * resource to access eHCA address space registers, all types - */ -struct h_galpas { - u32 pid; /*PID of userspace galpa checking */ - struct h_galpa user; /* user space accessible resource, - set to 0 if unused */ - struct h_galpa kernel; /* kernel space accessible resource, - set to 0 if unused */ -}; - -static inline u64 hipz_galpa_load(struct h_galpa galpa, u32 offset) -{ - u64 addr = galpa.fw_handle + offset; - return *(volatile u64 __force *)addr; -} - -static inline void hipz_galpa_store(struct h_galpa galpa, u32 offset, u64 value) -{ - u64 addr = galpa.fw_handle + offset; - *(volatile u64 __force *)addr = value; -} - -int hcp_galpas_ctor(struct h_galpas *galpas, - u64 paddr_kernel, u64 paddr_user); - -int hcp_galpas_dtor(struct h_galpas *galpas); - -int hcall_map_page(u64 physaddr, u64 * mapaddr); - -int hcall_unmap_page(u64 mapaddr); - -#endif diff --git a/trunk/drivers/infiniband/hw/ehca/hipz_fns.h b/trunk/drivers/infiniband/hw/ehca/hipz_fns.h deleted file mode 100644 index 9dac93d02140..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/hipz_fns.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * HW abstraction register functions - * - * Authors: Christoph Raisch - * Reinhard Ernst - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIPZ_FNS_H__ -#define __HIPZ_FNS_H__ - -#include "ehca_classes.h" -#include "hipz_hw.h" - -#include "hipz_fns_core.h" - -#define hipz_galpa_store_eq(gal, offset, value) \ - hipz_galpa_store(gal, EQTEMM_OFFSET(offset), value) - -#define hipz_galpa_load_eq(gal, offset) \ - hipz_galpa_load(gal, EQTEMM_OFFSET(offset)) - -#define hipz_galpa_store_qped(gal, offset, value) \ - hipz_galpa_store(gal, QPEDMM_OFFSET(offset), value) - -#define hipz_galpa_load_qped(gal, offset) \ - hipz_galpa_load(gal, QPEDMM_OFFSET(offset)) - -#define hipz_galpa_store_mrmw(gal, offset, value) \ - hipz_galpa_store(gal, MRMWMM_OFFSET(offset), value) - -#define hipz_galpa_load_mrmw(gal, offset) \ - hipz_galpa_load(gal, MRMWMM_OFFSET(offset)) - -#endif diff --git a/trunk/drivers/infiniband/hw/ehca/hipz_fns_core.h b/trunk/drivers/infiniband/hw/ehca/hipz_fns_core.h deleted file mode 100644 index 20898a153446..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/hipz_fns_core.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * HW abstraction register functions - * - * Authors: Christoph Raisch - * Heiko J Schick - * Hoang-Nam Nguyen - * Reinhard Ernst - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIPZ_FNS_CORE_H__ -#define __HIPZ_FNS_CORE_H__ - -#include "hcp_phyp.h" -#include "hipz_hw.h" - -#define hipz_galpa_store_cq(gal, offset, value) \ - hipz_galpa_store(gal, CQTEMM_OFFSET(offset), value) - -#define hipz_galpa_load_cq(gal, offset) \ - hipz_galpa_load(gal, CQTEMM_OFFSET(offset)) - -#define hipz_galpa_store_qp(gal,offset, value) \ - hipz_galpa_store(gal, QPTEMM_OFFSET(offset), value) -#define hipz_galpa_load_qp(gal, offset) \ - hipz_galpa_load(gal,QPTEMM_OFFSET(offset)) - -static inline void hipz_update_sqa(struct ehca_qp *qp, u16 nr_wqes) -{ - /* ringing doorbell :-) */ - hipz_galpa_store_qp(qp->galpas.kernel, qpx_sqa, - EHCA_BMASK_SET(QPX_SQADDER, nr_wqes)); -} - -static inline void hipz_update_rqa(struct ehca_qp *qp, u16 nr_wqes) -{ - /* ringing doorbell :-) */ - hipz_galpa_store_qp(qp->galpas.kernel, qpx_rqa, - EHCA_BMASK_SET(QPX_RQADDER, nr_wqes)); -} - -static inline void hipz_update_feca(struct ehca_cq *cq, u32 nr_cqes) -{ - hipz_galpa_store_cq(cq->galpas.kernel, cqx_feca, - EHCA_BMASK_SET(CQX_FECADDER, nr_cqes)); -} - -static inline void hipz_set_cqx_n0(struct ehca_cq *cq, u32 value) -{ - u64 cqx_n0_reg; - - hipz_galpa_store_cq(cq->galpas.kernel, cqx_n0, - EHCA_BMASK_SET(CQX_N0_GENERATE_SOLICITED_COMP_EVENT, - value)); - cqx_n0_reg = hipz_galpa_load_cq(cq->galpas.kernel, cqx_n0); -} - -static inline void hipz_set_cqx_n1(struct ehca_cq *cq, u32 value) -{ - u64 cqx_n1_reg; - - hipz_galpa_store_cq(cq->galpas.kernel, cqx_n1, - EHCA_BMASK_SET(CQX_N1_GENERATE_COMP_EVENT, value)); - cqx_n1_reg = hipz_galpa_load_cq(cq->galpas.kernel, cqx_n1); -} - -#endif /* __HIPZ_FNC_CORE_H__ */ diff --git a/trunk/drivers/infiniband/hw/ehca/hipz_hw.h b/trunk/drivers/infiniband/hw/ehca/hipz_hw.h deleted file mode 100644 index 3fc92b031c50..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/hipz_hw.h +++ /dev/null @@ -1,388 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * eHCA register definitions - * - * Authors: Waleri Fomin - * Christoph Raisch - * Reinhard Ernst - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __HIPZ_HW_H__ -#define __HIPZ_HW_H__ - -#include "ehca_tools.h" - -/* QP Table Entry Memory Map */ -struct hipz_qptemm { - u64 qpx_hcr; - u64 qpx_c; - u64 qpx_herr; - u64 qpx_aer; -/* 0x20*/ - u64 qpx_sqa; - u64 qpx_sqc; - u64 qpx_rqa; - u64 qpx_rqc; -/* 0x40*/ - u64 qpx_st; - u64 qpx_pmstate; - u64 qpx_pmfa; - u64 qpx_pkey; -/* 0x60*/ - u64 qpx_pkeya; - u64 qpx_pkeyb; - u64 qpx_pkeyc; - u64 qpx_pkeyd; -/* 0x80*/ - u64 qpx_qkey; - u64 qpx_dqp; - u64 qpx_dlidp; - u64 qpx_portp; -/* 0xa0*/ - u64 qpx_slidp; - u64 qpx_slidpp; - u64 qpx_dlida; - u64 qpx_porta; -/* 0xc0*/ - u64 qpx_slida; - u64 qpx_slidpa; - u64 qpx_slvl; - u64 qpx_ipd; -/* 0xe0*/ - u64 qpx_mtu; - u64 qpx_lato; - u64 qpx_rlimit; - u64 qpx_rnrlimit; -/* 0x100*/ - u64 qpx_t; - u64 qpx_sqhp; - u64 qpx_sqptp; - u64 qpx_nspsn; -/* 0x120*/ - u64 qpx_nspsnhwm; - u64 reserved1; - u64 qpx_sdsi; - u64 qpx_sdsbc; -/* 0x140*/ - u64 qpx_sqwsize; - u64 qpx_sqwts; - u64 qpx_lsn; - u64 qpx_nssn; -/* 0x160 */ - u64 qpx_mor; - u64 qpx_cor; - u64 qpx_sqsize; - u64 qpx_erc; -/* 0x180*/ - u64 qpx_rnrrc; - u64 qpx_ernrwt; - u64 qpx_rnrresp; - u64 qpx_lmsna; -/* 0x1a0 */ - u64 qpx_sqhpc; - u64 qpx_sqcptp; - u64 qpx_sigt; - u64 qpx_wqecnt; -/* 0x1c0*/ - u64 qpx_rqhp; - u64 qpx_rqptp; - u64 qpx_rqsize; - u64 qpx_nrr; -/* 0x1e0*/ - u64 qpx_rdmac; - u64 qpx_nrpsn; - u64 qpx_lapsn; - u64 qpx_lcr; -/* 0x200*/ - u64 qpx_rwc; - u64 qpx_rwva; - u64 qpx_rdsi; - u64 qpx_rdsbc; -/* 0x220*/ - u64 qpx_rqwsize; - u64 qpx_crmsn; - u64 qpx_rdd; - u64 qpx_larpsn; -/* 0x240*/ - u64 qpx_pd; - u64 qpx_scqn; - u64 qpx_rcqn; - u64 qpx_aeqn; -/* 0x260*/ - u64 qpx_aaelog; - u64 qpx_ram; - u64 qpx_rdmaqe0; - u64 qpx_rdmaqe1; -/* 0x280*/ - u64 qpx_rdmaqe2; - u64 qpx_rdmaqe3; - u64 qpx_nrpsnhwm; -/* 0x298*/ - u64 reserved[(0x400 - 0x298) / 8]; -/* 0x400 extended data */ - u64 reserved_ext[(0x500 - 0x400) / 8]; -/* 0x500 */ - u64 reserved2[(0x1000 - 0x500) / 8]; -/* 0x1000 */ -}; - -#define QPX_SQADDER EHCA_BMASK_IBM(48,63) -#define QPX_RQADDER EHCA_BMASK_IBM(48,63) - -#define QPTEMM_OFFSET(x) offsetof(struct hipz_qptemm,x) - -/* MRMWPT Entry Memory Map */ -struct hipz_mrmwmm { - /* 0x00 */ - u64 mrx_hcr; - - u64 mrx_c; - u64 mrx_herr; - u64 mrx_aer; - /* 0x20 */ - u64 mrx_pp; - u64 reserved1; - u64 reserved2; - u64 reserved3; - /* 0x40 */ - u64 reserved4[(0x200 - 0x40) / 8]; - /* 0x200 */ - u64 mrx_ctl[64]; - -}; - -#define MRMWMM_OFFSET(x) offsetof(struct hipz_mrmwmm,x) - -struct hipz_qpedmm { - /* 0x00 */ - u64 reserved0[(0x400) / 8]; - /* 0x400 */ - u64 qpedx_phh; - u64 qpedx_ppsgp; - /* 0x410 */ - u64 qpedx_ppsgu; - u64 qpedx_ppdgp; - /* 0x420 */ - u64 qpedx_ppdgu; - u64 qpedx_aph; - /* 0x430 */ - u64 qpedx_apsgp; - u64 qpedx_apsgu; - /* 0x440 */ - u64 qpedx_apdgp; - u64 qpedx_apdgu; - /* 0x450 */ - u64 qpedx_apav; - u64 qpedx_apsav; - /* 0x460 */ - u64 qpedx_hcr; - u64 reserved1[4]; - /* 0x488 */ - u64 qpedx_rrl0; - /* 0x490 */ - u64 qpedx_rrrkey0; - u64 qpedx_rrva0; - /* 0x4a0 */ - u64 reserved2; - u64 qpedx_rrl1; - /* 0x4b0 */ - u64 qpedx_rrrkey1; - u64 qpedx_rrva1; - /* 0x4c0 */ - u64 reserved3; - u64 qpedx_rrl2; - /* 0x4d0 */ - u64 qpedx_rrrkey2; - u64 qpedx_rrva2; - /* 0x4e0 */ - u64 reserved4; - u64 qpedx_rrl3; - /* 0x4f0 */ - u64 qpedx_rrrkey3; - u64 qpedx_rrva3; -}; - -#define QPEDMM_OFFSET(x) offsetof(struct hipz_qpedmm,x) - -/* CQ Table Entry Memory Map */ -struct hipz_cqtemm { - u64 cqx_hcr; - u64 cqx_c; - u64 cqx_herr; - u64 cqx_aer; -/* 0x20 */ - u64 cqx_ptp; - u64 cqx_tp; - u64 cqx_fec; - u64 cqx_feca; -/* 0x40 */ - u64 cqx_ep; - u64 cqx_eq; -/* 0x50 */ - u64 reserved1; - u64 cqx_n0; -/* 0x60 */ - u64 cqx_n1; - u64 reserved2[(0x1000 - 0x60) / 8]; -/* 0x1000 */ -}; - -#define CQX_FEC_CQE_CNT EHCA_BMASK_IBM(32,63) -#define CQX_FECADDER EHCA_BMASK_IBM(32,63) -#define CQX_N0_GENERATE_SOLICITED_COMP_EVENT EHCA_BMASK_IBM(0,0) -#define CQX_N1_GENERATE_COMP_EVENT EHCA_BMASK_IBM(0,0) - -#define CQTEMM_OFFSET(x) offsetof(struct hipz_cqtemm,x) - -/* EQ Table Entry Memory Map */ -struct hipz_eqtemm { - u64 eqx_hcr; - u64 eqx_c; - - u64 eqx_herr; - u64 eqx_aer; -/* 0x20 */ - u64 eqx_ptp; - u64 eqx_tp; - u64 eqx_ssba; - u64 eqx_psba; - -/* 0x40 */ - u64 eqx_cec; - u64 eqx_meql; - u64 eqx_xisbi; - u64 eqx_xisc; -/* 0x60 */ - u64 eqx_it; - -}; - -#define EQTEMM_OFFSET(x) offsetof(struct hipz_eqtemm,x) - -/* access control defines for MR/MW */ -#define HIPZ_ACCESSCTRL_L_WRITE 0x00800000 -#define HIPZ_ACCESSCTRL_R_WRITE 0x00400000 -#define HIPZ_ACCESSCTRL_R_READ 0x00200000 -#define HIPZ_ACCESSCTRL_R_ATOMIC 0x00100000 -#define HIPZ_ACCESSCTRL_MW_BIND 0x00080000 - -/* query hca response block */ -struct hipz_query_hca { - u32 cur_reliable_dg; - u32 cur_qp; - u32 cur_cq; - u32 cur_eq; - u32 cur_mr; - u32 cur_mw; - u32 cur_ee_context; - u32 cur_mcast_grp; - u32 cur_qp_attached_mcast_grp; - u32 reserved1; - u32 cur_ipv6_qp; - u32 cur_eth_qp; - u32 cur_hp_mr; - u32 reserved2[3]; - u32 max_rd_domain; - u32 max_qp; - u32 max_cq; - u32 max_eq; - u32 max_mr; - u32 max_hp_mr; - u32 max_mw; - u32 max_mrwpte; - u32 max_special_mrwpte; - u32 max_rd_ee_context; - u32 max_mcast_grp; - u32 max_total_mcast_qp_attach; - u32 max_mcast_qp_attach; - u32 max_raw_ipv6_qp; - u32 max_raw_ethy_qp; - u32 internal_clock_frequency; - u32 max_pd; - u32 max_ah; - u32 max_cqe; - u32 max_wqes_wq; - u32 max_partitions; - u32 max_rr_ee_context; - u32 max_rr_qp; - u32 max_rr_hca; - u32 max_act_wqs_ee_context; - u32 max_act_wqs_qp; - u32 max_sge; - u32 max_sge_rd; - u32 memory_page_size_supported; - u64 max_mr_size; - u32 local_ca_ack_delay; - u32 num_ports; - u32 vendor_id; - u32 vendor_part_id; - u32 hw_ver; - u64 node_guid; - u64 hca_cap_indicators; - u32 data_counter_register_size; - u32 max_shared_rq; - u32 max_isns_eq; - u32 max_neq; -} __attribute__ ((packed)); - -/* query port response block */ -struct hipz_query_port { - u32 state; - u32 bad_pkey_cntr; - u32 lmc; - u32 lid; - u32 subnet_timeout; - u32 qkey_viol_cntr; - u32 sm_sl; - u32 sm_lid; - u32 capability_mask; - u32 init_type_reply; - u32 pkey_tbl_len; - u32 gid_tbl_len; - u64 gid_prefix; - u32 port_nr; - u16 pkey_entries[16]; - u8 reserved1[32]; - u32 trent_size; - u32 trbuf_size; - u64 max_msg_sz; - u32 max_mtu; - u32 vl_cap; - u8 reserved2[1900]; - u64 guid_entries[255]; -} __attribute__ ((packed)); - -#endif diff --git a/trunk/drivers/infiniband/hw/ehca/ipz_pt_fn.c b/trunk/drivers/infiniband/hw/ehca/ipz_pt_fn.c deleted file mode 100644 index e028ff1588cc..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ipz_pt_fn.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * internal queue handling - * - * Authors: Waleri Fomin - * Reinhard Ernst - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include "ehca_tools.h" -#include "ipz_pt_fn.h" - -void *ipz_qpageit_get_inc(struct ipz_queue *queue) -{ - void *ret = ipz_qeit_get(queue); - queue->current_q_offset += queue->pagesize; - if (queue->current_q_offset > queue->queue_length) { - queue->current_q_offset -= queue->pagesize; - ret = NULL; - } - if (((u64)ret) % EHCA_PAGESIZE) { - ehca_gen_err("ERROR!! not at PAGE-Boundary"); - return NULL; - } - return ret; -} - -void *ipz_qeit_eq_get_inc(struct ipz_queue *queue) -{ - void *ret = ipz_qeit_get(queue); - u64 last_entry_in_q = queue->queue_length - queue->qe_size; - - queue->current_q_offset += queue->qe_size; - if (queue->current_q_offset > last_entry_in_q) { - queue->current_q_offset = 0; - queue->toggle_state = (~queue->toggle_state) & 1; - } - - return ret; -} - -int ipz_queue_ctor(struct ipz_queue *queue, - const u32 nr_of_pages, - const u32 pagesize, const u32 qe_size, const u32 nr_of_sg) -{ - int pages_per_kpage = PAGE_SIZE >> EHCA_PAGESHIFT; - int f; - - if (pagesize > PAGE_SIZE) { - ehca_gen_err("FATAL ERROR: pagesize=%x is greater " - "than kernel page size", pagesize); - return 0; - } - if (!pages_per_kpage) { - ehca_gen_err("FATAL ERROR: invalid kernel page size. " - "pages_per_kpage=%x", pages_per_kpage); - return 0; - } - queue->queue_length = nr_of_pages * pagesize; - queue->queue_pages = vmalloc(nr_of_pages * sizeof(void *)); - if (!queue->queue_pages) { - ehca_gen_err("ERROR!! didn't get the memory"); - return 0; - } - memset(queue->queue_pages, 0, nr_of_pages * sizeof(void *)); - /* - * allocate pages for queue: - * outer loop allocates whole kernel pages (page aligned) and - * inner loop divides a kernel page into smaller hca queue pages - */ - f = 0; - while (f < nr_of_pages) { - u8 *kpage = (u8*)get_zeroed_page(GFP_KERNEL); - int k; - if (!kpage) - goto ipz_queue_ctor_exit0; /*NOMEM*/ - for (k = 0; k < pages_per_kpage && f < nr_of_pages; k++) { - (queue->queue_pages)[f] = (struct ipz_page *)kpage; - kpage += EHCA_PAGESIZE; - f++; - } - } - - queue->current_q_offset = 0; - queue->qe_size = qe_size; - queue->act_nr_of_sg = nr_of_sg; - queue->pagesize = pagesize; - queue->toggle_state = 1; - return 1; - - ipz_queue_ctor_exit0: - ehca_gen_err("Couldn't get alloc pages queue=%p f=%x nr_of_pages=%x", - queue, f, nr_of_pages); - for (f = 0; f < nr_of_pages; f += pages_per_kpage) { - if (!(queue->queue_pages)[f]) - break; - free_page((unsigned long)(queue->queue_pages)[f]); - } - return 0; -} - -int ipz_queue_dtor(struct ipz_queue *queue) -{ - int pages_per_kpage = PAGE_SIZE >> EHCA_PAGESHIFT; - int g; - int nr_pages; - - if (!queue || !queue->queue_pages) { - ehca_gen_dbg("queue or queue_pages is NULL"); - return 0; - } - nr_pages = queue->queue_length / queue->pagesize; - for (g = 0; g < nr_pages; g += pages_per_kpage) - free_page((unsigned long)(queue->queue_pages)[g]); - vfree(queue->queue_pages); - - return 1; -} diff --git a/trunk/drivers/infiniband/hw/ehca/ipz_pt_fn.h b/trunk/drivers/infiniband/hw/ehca/ipz_pt_fn.h deleted file mode 100644 index 2f13509d5257..000000000000 --- a/trunk/drivers/infiniband/hw/ehca/ipz_pt_fn.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - * IBM eServer eHCA Infiniband device driver for Linux on POWER - * - * internal queue handling - * - * Authors: Waleri Fomin - * Reinhard Ernst - * Christoph Raisch - * - * Copyright (c) 2005 IBM Corporation - * - * All rights reserved. - * - * This source code is distributed under a dual license of GPL v2.0 and OpenIB - * BSD. - * - * OpenIB BSD License - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __IPZ_PT_FN_H__ -#define __IPZ_PT_FN_H__ - -#define EHCA_PAGESHIFT 12 -#define EHCA_PAGESIZE 4096UL -#define EHCA_PAGEMASK (~(EHCA_PAGESIZE-1)) -#define EHCA_PT_ENTRIES 512UL - -#include "ehca_tools.h" -#include "ehca_qes.h" - -/* struct generic ehca page */ -struct ipz_page { - u8 entries[EHCA_PAGESIZE]; -}; - -/* struct generic queue in linux kernel virtual memory (kv) */ -struct ipz_queue { - u64 current_q_offset; /* current queue entry */ - - struct ipz_page **queue_pages; /* array of pages belonging to queue */ - u32 qe_size; /* queue entry size */ - u32 act_nr_of_sg; - u32 queue_length; /* queue length allocated in bytes */ - u32 pagesize; - u32 toggle_state; /* toggle flag - per page */ - u32 dummy3; /* 64 bit alignment */ -}; - -/* - * return current Queue Entry for a certain q_offset - * returns address (kv) of Queue Entry - */ -static inline void *ipz_qeit_calc(struct ipz_queue *queue, u64 q_offset) -{ - struct ipz_page *current_page; - if (q_offset >= queue->queue_length) - return NULL; - current_page = (queue->queue_pages)[q_offset >> EHCA_PAGESHIFT]; - return ¤t_page->entries[q_offset & (EHCA_PAGESIZE - 1)]; -} - -/* - * return current Queue Entry - * returns address (kv) of Queue Entry - */ -static inline void *ipz_qeit_get(struct ipz_queue *queue) -{ - return ipz_qeit_calc(queue, queue->current_q_offset); -} - -/* - * return current Queue Page , increment Queue Page iterator from - * page to page in struct ipz_queue, last increment will return 0! and - * NOT wrap - * returns address (kv) of Queue Page - * warning don't use in parallel with ipz_QE_get_inc() - */ -void *ipz_qpageit_get_inc(struct ipz_queue *queue); - -/* - * return current Queue Entry, increment Queue Entry iterator by one - * step in struct ipz_queue, will wrap in ringbuffer - * returns address (kv) of Queue Entry BEFORE increment - * warning don't use in parallel with ipz_qpageit_get_inc() - * warning unpredictable results may occur if steps>act_nr_of_queue_entries - */ -static inline void *ipz_qeit_get_inc(struct ipz_queue *queue) -{ - void *ret = ipz_qeit_get(queue); - queue->current_q_offset += queue->qe_size; - if (queue->current_q_offset >= queue->queue_length) { - queue->current_q_offset = 0; - /* toggle the valid flag */ - queue->toggle_state = (~queue->toggle_state) & 1; - } - - return ret; -} - -/* - * return current Queue Entry, increment Queue Entry iterator by one - * step in struct ipz_queue, will wrap in ringbuffer - * returns address (kv) of Queue Entry BEFORE increment - * returns 0 and does not increment, if wrong valid state - * warning don't use in parallel with ipz_qpageit_get_inc() - * warning unpredictable results may occur if steps>act_nr_of_queue_entries - */ -static inline void *ipz_qeit_get_inc_valid(struct ipz_queue *queue) -{ - struct ehca_cqe *cqe = ipz_qeit_get(queue); - u32 cqe_flags = cqe->cqe_flags; - - if ((cqe_flags >> 7) != (queue->toggle_state & 1)) - return NULL; - - ipz_qeit_get_inc(queue); - return cqe; -} - -/* - * returns and resets Queue Entry iterator - * returns address (kv) of first Queue Entry - */ -static inline void *ipz_qeit_reset(struct ipz_queue *queue) -{ - queue->current_q_offset = 0; - return ipz_qeit_get(queue); -} - -/* struct generic page table */ -struct ipz_pt { - u64 entries[EHCA_PT_ENTRIES]; -}; - -/* struct page table for a queue, only to be used in pf */ -struct ipz_qpt { - /* queue page tables (kv), use u64 because we know the element length */ - u64 *qpts; - u32 n_qpts; - u32 n_ptes; /* number of page table entries */ - u64 *current_pte_addr; -}; - -/* - * constructor for a ipz_queue_t, placement new for ipz_queue_t, - * new for all dependent datastructors - * all QP Tables are the same - * flow: - * allocate+pin queue - * see ipz_qpt_ctor() - * returns true if ok, false if out of memory - */ -int ipz_queue_ctor(struct ipz_queue *queue, const u32 nr_of_pages, - const u32 pagesize, const u32 qe_size, - const u32 nr_of_sg); - -/* - * destructor for a ipz_queue_t - * -# free queue - * see ipz_queue_ctor() - * returns true if ok, false if queue was NULL-ptr of free failed - */ -int ipz_queue_dtor(struct ipz_queue *queue); - -/* - * constructor for a ipz_qpt_t, - * placement new for struct ipz_queue, new for all dependent datastructors - * all QP Tables are the same, - * flow: - * -# allocate+pin queue - * -# initialise ptcb - * -# allocate+pin PTs - * -# link PTs to a ring, according to HCA Arch, set bit62 id needed - * -# the ring must have room for exactly nr_of_PTEs - * see ipz_qpt_ctor() - */ -void ipz_qpt_ctor(struct ipz_qpt *qpt, - const u32 nr_of_qes, - const u32 pagesize, - const u32 qe_size, - const u8 lowbyte, const u8 toggle, - u32 * act_nr_of_QEs, u32 * act_nr_of_pages); - -/* - * return current Queue Entry, increment Queue Entry iterator by one - * step in struct ipz_queue, will wrap in ringbuffer - * returns address (kv) of Queue Entry BEFORE increment - * warning don't use in parallel with ipz_qpageit_get_inc() - * warning unpredictable results may occur if steps>act_nr_of_queue_entries - * fix EQ page problems - */ -void *ipz_qeit_eq_get_inc(struct ipz_queue *queue); - -/* - * return current Event Queue Entry, increment Queue Entry iterator - * by one step in struct ipz_queue if valid, will wrap in ringbuffer - * returns address (kv) of Queue Entry BEFORE increment - * returns 0 and does not increment, if wrong valid state - * warning don't use in parallel with ipz_queue_QPageit_get_inc() - * warning unpredictable results may occur if steps>act_nr_of_queue_entries - */ -static inline void *ipz_eqit_eq_get_inc_valid(struct ipz_queue *queue) -{ - void *ret = ipz_qeit_get(queue); - u32 qe = *(u8 *) ret; - if ((qe >> 7) != (queue->toggle_state & 1)) - return NULL; - ipz_qeit_eq_get_inc(queue); /* this is a good one */ - return ret; -} - -/* returns address (GX) of first queue entry */ -static inline u64 ipz_qpt_get_firstpage(struct ipz_qpt *qpt) -{ - return be64_to_cpu(qpt->qpts[0]); -} - -/* returns address (kv) of first page of queue page table */ -static inline void *ipz_qpt_get_qpt(struct ipz_qpt *qpt) -{ - return qpt->qpts; -} - -#endif /* __IPZ_PT_FN_H__ */ diff --git a/trunk/drivers/infiniband/hw/ipath/Kconfig b/trunk/drivers/infiniband/hw/ipath/Kconfig index 574a678e7fdd..1db9489f1e82 100644 --- a/trunk/drivers/infiniband/hw/ipath/Kconfig +++ b/trunk/drivers/infiniband/hw/ipath/Kconfig @@ -1,9 +1,16 @@ -config INFINIBAND_IPATH +config IPATH_CORE tristate "QLogic InfiniPath Driver" - depends on PCI_MSI && 64BIT && INFINIBAND + depends on 64BIT && PCI_MSI && NET + ---help--- + This is a low-level driver for QLogic InfiniPath host channel + adapters (HCAs) based on the HT-400 and PE-800 chips. + +config INFINIBAND_IPATH + tristate "QLogic InfiniPath Verbs Driver" + depends on IPATH_CORE && INFINIBAND ---help--- - This is a driver for QLogic InfiniPath host channel adapters, - including InfiniBand verbs support. This driver allows these - devices to be used with both kernel upper level protocols such - as IP-over-InfiniBand as well as with userspace applications - (in conjunction with InfiniBand userspace access). + This is a driver that provides InfiniBand verbs support for + QLogic InfiniPath host channel adapters (HCAs). This + allows these devices to be used with both kernel upper level + protocols such as IP-over-InfiniBand as well as with userspace + applications (in conjunction with InfiniBand userspace access). diff --git a/trunk/drivers/infiniband/hw/ipath/Makefile b/trunk/drivers/infiniband/hw/ipath/Makefile index 5e29cb0095e5..b0bf72864130 100644 --- a/trunk/drivers/infiniband/hw/ipath/Makefile +++ b/trunk/drivers/infiniband/hw/ipath/Makefile @@ -1,35 +1,36 @@ EXTRA_CFLAGS += -DIPATH_IDSTR='"QLogic kernel.org driver"' \ -DIPATH_KERN_TYPE=0 +obj-$(CONFIG_IPATH_CORE) += ipath_core.o obj-$(CONFIG_INFINIBAND_IPATH) += ib_ipath.o -ib_ipath-y := \ - ipath_cq.o \ +ipath_core-y := \ ipath_diag.o \ ipath_driver.o \ ipath_eeprom.o \ ipath_file_ops.o \ ipath_fs.o \ - ipath_iba6110.o \ - ipath_iba6120.o \ + ipath_ht400.o \ ipath_init_chip.o \ ipath_intr.o \ - ipath_keys.o \ ipath_layer.o \ + ipath_pe800.o \ + ipath_stats.o \ + ipath_sysfs.o \ + ipath_user_pages.o + +ipath_core-$(CONFIG_X86_64) += ipath_wc_x86_64.o + +ib_ipath-y := \ + ipath_cq.o \ + ipath_keys.o \ ipath_mad.o \ - ipath_mmap.o \ ipath_mr.o \ ipath_qp.o \ ipath_rc.o \ ipath_ruc.o \ ipath_srq.o \ - ipath_stats.o \ - ipath_sysfs.o \ ipath_uc.o \ ipath_ud.o \ - ipath_user_pages.o \ - ipath_verbs_mcast.o \ - ipath_verbs.o - -ib_ipath-$(CONFIG_X86_64) += ipath_wc_x86_64.o -ib_ipath-$(CONFIG_PPC64) += ipath_wc_ppc64.o + ipath_verbs.o \ + ipath_verbs_mcast.o diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_common.h b/trunk/drivers/infiniband/hw/ipath/ipath_common.h index f577905e3aca..062bd392e7e5 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_common.h +++ b/trunk/drivers/infiniband/hw/ipath/ipath_common.h @@ -106,9 +106,9 @@ struct infinipath_stats { __u64 sps_ether_spkts; /* number of "ethernet" packets received by driver */ __u64 sps_ether_rpkts; - /* number of SMA packets sent by driver. Obsolete. */ + /* number of SMA packets sent by driver */ __u64 sps_sma_spkts; - /* number of SMA packets received by driver. Obsolete. */ + /* number of SMA packets received by driver */ __u64 sps_sma_rpkts; /* number of times all ports rcvhdrq was full and packet dropped */ __u64 sps_hdrqfull; @@ -138,7 +138,7 @@ struct infinipath_stats { __u64 sps_pageunlocks; /* * Number of packets dropped in kernel other than errors (ether - * packets if ipath not configured, etc.) + * packets if ipath not configured, sma/mad, etc.) */ __u64 sps_krdrops; /* pad for future growth */ @@ -153,6 +153,8 @@ struct infinipath_stats { #define IPATH_STATUS_DISABLED 0x2 /* hardware disabled */ /* Device has been disabled via admin request */ #define IPATH_STATUS_ADMIN_DISABLED 0x4 +#define IPATH_STATUS_OIB_SMA 0x8 /* ipath_mad kernel SMA running */ +#define IPATH_STATUS_SMA 0x10 /* user SMA running */ /* Chip has been found and initted */ #define IPATH_STATUS_CHIP_PRESENT 0x20 /* IB link is at ACTIVE, usable for data traffic */ @@ -463,11 +465,12 @@ struct __ipath_sendpkt { struct ipath_iovec sps_iov[4]; }; -/* Passed into diag data special file's ->write method. */ -struct ipath_diag_pkt { - __u32 unit; - __u64 data; - __u32 len; +/* Passed into SMA special file's ->read and ->write methods. */ +struct ipath_sma_pkt +{ + __u32 unit; /* unit on which to send packet */ + __u64 data; /* address of payload in userspace */ + __u32 len; /* length of payload */ }; /* diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_cq.c b/trunk/drivers/infiniband/hw/ipath/ipath_cq.c index 049221bc590e..3efee341c9bc 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_cq.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_cq.c @@ -42,28 +42,20 @@ * @entry: work completion entry to add * @sig: true if @entry is a solicitated entry * - * This may be called with qp->s_lock held. + * This may be called with one of the qp->s_lock or qp->r_rq.lock held. */ void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int solicited) { - struct ipath_cq_wc *wc = cq->queue; unsigned long flags; - u32 head; u32 next; spin_lock_irqsave(&cq->lock, flags); - /* - * Note that the head pointer might be writable by user processes. - * Take care to verify it is a sane value. - */ - head = wc->head; - if (head >= (unsigned) cq->ibcq.cqe) { - head = cq->ibcq.cqe; + if (cq->head == cq->ibcq.cqe) next = 0; - } else - next = head + 1; - if (unlikely(next == wc->tail)) { + else + next = cq->head + 1; + if (unlikely(next == cq->tail)) { spin_unlock_irqrestore(&cq->lock, flags); if (cq->ibcq.event_handler) { struct ib_event ev; @@ -75,8 +67,8 @@ void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int solicited) } return; } - wc->queue[head] = *entry; - wc->head = next; + cq->queue[cq->head] = *entry; + cq->head = next; if (cq->notify == IB_CQ_NEXT_COMP || (cq->notify == IB_CQ_SOLICITED && solicited)) { @@ -109,20 +101,19 @@ void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int solicited) int ipath_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry) { struct ipath_cq *cq = to_icq(ibcq); - struct ipath_cq_wc *wc = cq->queue; unsigned long flags; int npolled; spin_lock_irqsave(&cq->lock, flags); for (npolled = 0; npolled < num_entries; ++npolled, ++entry) { - if (wc->tail == wc->head) + if (cq->tail == cq->head) break; - *entry = wc->queue[wc->tail]; - if (wc->tail >= cq->ibcq.cqe) - wc->tail = 0; + *entry = cq->queue[cq->tail]; + if (cq->tail == cq->ibcq.cqe) + cq->tail = 0; else - wc->tail++; + cq->tail++; } spin_unlock_irqrestore(&cq->lock, flags); @@ -169,74 +160,38 @@ struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries, { struct ipath_ibdev *dev = to_idev(ibdev); struct ipath_cq *cq; - struct ipath_cq_wc *wc; + struct ib_wc *wc; struct ib_cq *ret; - if (entries < 1 || entries > ib_ipath_max_cqes) { + if (entries > ib_ipath_max_cqes) { ret = ERR_PTR(-EINVAL); - goto done; + goto bail; } if (dev->n_cqs_allocated == ib_ipath_max_cqs) { ret = ERR_PTR(-ENOMEM); - goto done; + goto bail; } - /* Allocate the completion queue structure. */ + /* + * Need to use vmalloc() if we want to support large #s of + * entries. + */ cq = kmalloc(sizeof(*cq), GFP_KERNEL); if (!cq) { ret = ERR_PTR(-ENOMEM); - goto done; + goto bail; } /* - * Allocate the completion queue entries and head/tail pointers. - * This is allocated separately so that it can be resized and - * also mapped into user space. - * We need to use vmalloc() in order to support mmap and large - * numbers of entries. + * Need to use vmalloc() if we want to support large #s of entries. */ - wc = vmalloc_user(sizeof(*wc) + sizeof(struct ib_wc) * entries); + wc = vmalloc(sizeof(*wc) * (entries + 1)); if (!wc) { + kfree(cq); ret = ERR_PTR(-ENOMEM); - goto bail_cq; + goto bail; } - - /* - * Return the address of the WC as the offset to mmap. - * See ipath_mmap() for details. - */ - if (udata && udata->outlen >= sizeof(__u64)) { - struct ipath_mmap_info *ip; - __u64 offset = (__u64) wc; - int err; - - err = ib_copy_to_udata(udata, &offset, sizeof(offset)); - if (err) { - ret = ERR_PTR(err); - goto bail_wc; - } - - /* Allocate info for ipath_mmap(). */ - ip = kmalloc(sizeof(*ip), GFP_KERNEL); - if (!ip) { - ret = ERR_PTR(-ENOMEM); - goto bail_wc; - } - cq->ip = ip; - ip->context = context; - ip->obj = wc; - kref_init(&ip->ref); - ip->mmap_cnt = 0; - ip->size = PAGE_ALIGN(sizeof(*wc) + - sizeof(struct ib_wc) * entries); - spin_lock_irq(&dev->pending_lock); - ip->next = dev->pending_mmaps; - dev->pending_mmaps = ip; - spin_unlock_irq(&dev->pending_lock); - } else - cq->ip = NULL; - /* * ib_create_cq() will initialize cq->ibcq except for cq->ibcq.cqe. * The number of entries should be >= the number requested or return @@ -247,22 +202,15 @@ struct ib_cq *ipath_create_cq(struct ib_device *ibdev, int entries, cq->triggered = 0; spin_lock_init(&cq->lock); tasklet_init(&cq->comptask, send_complete, (unsigned long)cq); - wc->head = 0; - wc->tail = 0; + cq->head = 0; + cq->tail = 0; cq->queue = wc; ret = &cq->ibcq; dev->n_cqs_allocated++; - goto done; -bail_wc: - vfree(wc); - -bail_cq: - kfree(cq); - -done: +bail: return ret; } @@ -281,10 +229,7 @@ int ipath_destroy_cq(struct ib_cq *ibcq) tasklet_kill(&cq->comptask); dev->n_cqs_allocated--; - if (cq->ip) - kref_put(&cq->ip->ref, ipath_release_mmap_info); - else - vfree(cq->queue); + vfree(cq->queue); kfree(cq); return 0; @@ -308,7 +253,7 @@ int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify) spin_lock_irqsave(&cq->lock, flags); /* * Don't change IB_CQ_NEXT_COMP to IB_CQ_SOLICITED but allow - * any other transitions (see C11-31 and C11-32 in ch. 11.4.2.2). + * any other transitions. */ if (cq->notify != IB_CQ_NEXT_COMP) cq->notify = notify; @@ -319,86 +264,46 @@ int ipath_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify notify) int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata) { struct ipath_cq *cq = to_icq(ibcq); - struct ipath_cq_wc *old_wc = cq->queue; - struct ipath_cq_wc *wc; - u32 head, tail, n; + struct ib_wc *wc, *old_wc; + u32 n; int ret; - if (cqe < 1 || cqe > ib_ipath_max_cqes) { - ret = -EINVAL; - goto bail; - } - /* * Need to use vmalloc() if we want to support large #s of entries. */ - wc = vmalloc_user(sizeof(*wc) + sizeof(struct ib_wc) * cqe); + wc = vmalloc(sizeof(*wc) * (cqe + 1)); if (!wc) { ret = -ENOMEM; goto bail; } - /* - * Return the address of the WC as the offset to mmap. - * See ipath_mmap() for details. - */ - if (udata && udata->outlen >= sizeof(__u64)) { - __u64 offset = (__u64) wc; - - ret = ib_copy_to_udata(udata, &offset, sizeof(offset)); - if (ret) - goto bail; - } - spin_lock_irq(&cq->lock); - /* - * Make sure head and tail are sane since they - * might be user writable. - */ - head = old_wc->head; - if (head > (u32) cq->ibcq.cqe) - head = (u32) cq->ibcq.cqe; - tail = old_wc->tail; - if (tail > (u32) cq->ibcq.cqe) - tail = (u32) cq->ibcq.cqe; - if (head < tail) - n = cq->ibcq.cqe + 1 + head - tail; + if (cq->head < cq->tail) + n = cq->ibcq.cqe + 1 + cq->head - cq->tail; else - n = head - tail; + n = cq->head - cq->tail; if (unlikely((u32)cqe < n)) { spin_unlock_irq(&cq->lock); vfree(wc); ret = -EOVERFLOW; goto bail; } - for (n = 0; tail != head; n++) { - wc->queue[n] = old_wc->queue[tail]; - if (tail == (u32) cq->ibcq.cqe) - tail = 0; + for (n = 0; cq->tail != cq->head; n++) { + wc[n] = cq->queue[cq->tail]; + if (cq->tail == cq->ibcq.cqe) + cq->tail = 0; else - tail++; + cq->tail++; } cq->ibcq.cqe = cqe; - wc->head = n; - wc->tail = 0; + cq->head = n; + cq->tail = 0; + old_wc = cq->queue; cq->queue = wc; spin_unlock_irq(&cq->lock); vfree(old_wc); - if (cq->ip) { - struct ipath_ibdev *dev = to_idev(ibcq->device); - struct ipath_mmap_info *ip = cq->ip; - - ip->obj = wc; - ip->size = PAGE_ALIGN(sizeof(*wc) + - sizeof(struct ib_wc) * cqe); - spin_lock_irq(&dev->pending_lock); - ip->next = dev->pending_mmaps; - dev->pending_mmaps = ip; - spin_unlock_irq(&dev->pending_lock); - } - ret = 0; bail: diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_debug.h b/trunk/drivers/infiniband/hw/ipath/ipath_debug.h index df69f0d80b8b..f415beda0d32 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_debug.h +++ b/trunk/drivers/infiniband/hw/ipath/ipath_debug.h @@ -60,6 +60,7 @@ #define __IPATH_USER_SEND 0x1000 /* use user mode send */ #define __IPATH_KERNEL_SEND 0x2000 /* use kernel mode send */ #define __IPATH_EPKTDBG 0x4000 /* print ethernet packet data */ +#define __IPATH_SMADBG 0x8000 /* sma packet debug */ #define __IPATH_IPATHDBG 0x10000 /* Ethernet (IPATH) gen debug */ #define __IPATH_IPATHWARN 0x20000 /* Ethernet (IPATH) warnings */ #define __IPATH_IPATHERR 0x40000 /* Ethernet (IPATH) errors */ @@ -83,6 +84,7 @@ /* print mmap/nopage stuff, not using VDBG any more */ #define __IPATH_MMDBG 0x0 #define __IPATH_EPKTDBG 0x0 /* print ethernet packet data */ +#define __IPATH_SMADBG 0x0 /* process startup (init)/exit messages */ #define __IPATH_IPATHDBG 0x0 /* Ethernet (IPATH) table dump on */ #define __IPATH_IPATHWARN 0x0 /* Ethernet (IPATH) warnings on */ #define __IPATH_IPATHERR 0x0 /* Ethernet (IPATH) errors on */ diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_diag.c b/trunk/drivers/infiniband/hw/ipath/ipath_diag.c index 29958b6e0214..147dd89e21c9 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_diag.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_diag.c @@ -41,12 +41,11 @@ * through the /sys/bus/pci resource mmap interface. */ -#include #include -#include #include #include "ipath_kernel.h" +#include "ipath_layer.h" #include "ipath_common.h" int ipath_diag_inuse; @@ -275,158 +274,6 @@ static int ipath_diag_open(struct inode *in, struct file *fp) return ret; } -static ssize_t ipath_diagpkt_write(struct file *fp, - const char __user *data, - size_t count, loff_t *off); - -static struct file_operations diagpkt_file_ops = { - .owner = THIS_MODULE, - .write = ipath_diagpkt_write, -}; - -static struct cdev *diagpkt_cdev; -static struct class_device *diagpkt_class_dev; - -int __init ipath_diagpkt_add(void) -{ - return ipath_cdev_init(IPATH_DIAGPKT_MINOR, - "ipath_diagpkt", &diagpkt_file_ops, - &diagpkt_cdev, &diagpkt_class_dev); -} - -void __exit ipath_diagpkt_remove(void) -{ - ipath_cdev_cleanup(&diagpkt_cdev, &diagpkt_class_dev); -} - -/** - * ipath_diagpkt_write - write an IB packet - * @fp: the diag data device file pointer - * @data: ipath_diag_pkt structure saying where to get the packet - * @count: size of data to write - * @off: unused by this code - */ -static ssize_t ipath_diagpkt_write(struct file *fp, - const char __user *data, - size_t count, loff_t *off) -{ - u32 __iomem *piobuf; - u32 plen, clen, pbufn; - struct ipath_diag_pkt dp; - u32 *tmpbuf = NULL; - struct ipath_devdata *dd; - ssize_t ret = 0; - u64 val; - - if (count < sizeof(dp)) { - ret = -EINVAL; - goto bail; - } - - if (copy_from_user(&dp, data, sizeof(dp))) { - ret = -EFAULT; - goto bail; - } - - /* send count must be an exact number of dwords */ - if (dp.len & 3) { - ret = -EINVAL; - goto bail; - } - - clen = dp.len >> 2; - - dd = ipath_lookup(dp.unit); - if (!dd || !(dd->ipath_flags & IPATH_PRESENT) || - !dd->ipath_kregbase) { - ipath_cdbg(VERBOSE, "illegal unit %u for diag data send\n", - dp.unit); - ret = -ENODEV; - goto bail; - } - - if (ipath_diag_inuse && !diag_set_link && - !(dd->ipath_flags & IPATH_LINKACTIVE)) { - diag_set_link = 1; - ipath_cdbg(VERBOSE, "Trying to set to set link active for " - "diag pkt\n"); - ipath_set_linkstate(dd, IPATH_IB_LINKARM); - ipath_set_linkstate(dd, IPATH_IB_LINKACTIVE); - } - - if (!(dd->ipath_flags & IPATH_INITTED)) { - /* no hardware, freeze, etc. */ - ipath_cdbg(VERBOSE, "unit %u not usable\n", dd->ipath_unit); - ret = -ENODEV; - goto bail; - } - val = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK; - if (val != IPATH_IBSTATE_INIT && val != IPATH_IBSTATE_ARM && - val != IPATH_IBSTATE_ACTIVE) { - ipath_cdbg(VERBOSE, "unit %u not ready (state %llx)\n", - dd->ipath_unit, (unsigned long long) val); - ret = -EINVAL; - goto bail; - } - - /* need total length before first word written */ - /* +1 word is for the qword padding */ - plen = sizeof(u32) + dp.len; - - if ((plen + 4) > dd->ipath_ibmaxlen) { - ipath_dbg("Pkt len 0x%x > ibmaxlen %x\n", - plen - 4, dd->ipath_ibmaxlen); - ret = -EINVAL; - goto bail; /* before writing pbc */ - } - tmpbuf = vmalloc(plen); - if (!tmpbuf) { - dev_info(&dd->pcidev->dev, "Unable to allocate tmp buffer, " - "failing\n"); - ret = -ENOMEM; - goto bail; - } - - if (copy_from_user(tmpbuf, - (const void __user *) (unsigned long) dp.data, - dp.len)) { - ret = -EFAULT; - goto bail; - } - - piobuf = ipath_getpiobuf(dd, &pbufn); - if (!piobuf) { - ipath_cdbg(VERBOSE, "No PIO buffers avail unit for %u\n", - dd->ipath_unit); - ret = -EBUSY; - goto bail; - } - - plen >>= 2; /* in dwords */ - - if (ipath_debug & __IPATH_PKTDBG) - ipath_cdbg(VERBOSE, "unit %u 0x%x+1w pio%d\n", - dd->ipath_unit, plen - 1, pbufn); - - /* we have to flush after the PBC for correctness on some cpus - * or WC buffer can be written out of order */ - writeq(plen, piobuf); - ipath_flush_wc(); - /* copy all by the trigger word, then flush, so it's written - * to chip before trigger word, then write trigger word, then - * flush again, so packet is sent. */ - __iowrite32_copy(piobuf + 2, tmpbuf, clen - 1); - ipath_flush_wc(); - __raw_writel(tmpbuf[clen - 1], piobuf + clen + 1); - ipath_flush_wc(); - - ret = sizeof(dp); - -bail: - vfree(tmpbuf); - return ret; -} - static int ipath_diag_release(struct inode *in, struct file *fp) { mutex_lock(&ipath_mutex); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_driver.c b/trunk/drivers/infiniband/hw/ipath/ipath_driver.c index 2108466c7e33..f98518d912b5 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_driver.c @@ -39,7 +39,7 @@ #include #include "ipath_kernel.h" -#include "ipath_verbs.h" +#include "ipath_layer.h" #include "ipath_common.h" static void ipath_update_pio_bufs(struct ipath_devdata *); @@ -51,6 +51,8 @@ const char *ipath_get_unit_name(int unit) return iname; } +EXPORT_SYMBOL_GPL(ipath_get_unit_name); + #define DRIVER_LOAD_MSG "QLogic " IPATH_DRV_NAME " loaded: " #define PFX IPATH_DRV_NAME ": " @@ -58,13 +60,13 @@ const char *ipath_get_unit_name(int unit) * The size has to be longer than this string, so we can append * board/chip information to it in the init code. */ -const char ib_ipath_version[] = IPATH_IDSTR "\n"; +const char ipath_core_version[] = IPATH_IDSTR "\n"; static struct idr unit_table; DEFINE_SPINLOCK(ipath_devs_lock); LIST_HEAD(ipath_dev_list); -wait_queue_head_t ipath_state_wait; +wait_queue_head_t ipath_sma_state_wait; unsigned ipath_debug = __IPATH_INFO; @@ -401,10 +403,10 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, /* setup the chip-specific functions, as early as possible. */ switch (ent->device) { case PCI_DEVICE_ID_INFINIPATH_HT: - ipath_init_iba6110_funcs(dd); + ipath_init_ht400_funcs(dd); break; case PCI_DEVICE_ID_INFINIPATH_PE800: - ipath_init_iba6120_funcs(dd); + ipath_init_pe800_funcs(dd); break; default: ipath_dev_err(dd, "Found unknown QLogic deviceid 0x%x, " @@ -438,13 +440,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, } dd->ipath_pcirev = rev; -#if defined(__powerpc__) - /* There isn't a generic way to specify writethrough mappings */ - dd->ipath_kregbase = __ioremap(addr, len, - (_PAGE_NO_CACHE|_PAGE_WRITETHRU)); -#else dd->ipath_kregbase = ioremap_nocache(addr, len); -#endif if (!dd->ipath_kregbase) { ipath_dbg("Unable to map io addr %llx to kvirt, failing\n", @@ -507,7 +503,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, ipathfs_add_device(dd); ipath_user_add(dd); ipath_diag_add(dd); - ipath_register_ib_device(dd); + ipath_layer_add(dd); goto bail; @@ -536,7 +532,7 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev) return; dd = pci_get_drvdata(pdev); - ipath_unregister_ib_device(dd->verbs_dev); + ipath_layer_remove(dd); ipath_diag_remove(dd); ipath_user_remove(dd); ipathfs_remove_device(dd); @@ -611,23 +607,21 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first, * * wait up to msecs milliseconds for IB link state change to occur for * now, take the easy polling route. Currently used only by - * ipath_set_linkstate. Returns 0 if state reached, otherwise + * ipath_layer_set_linkstate. Returns 0 if state reached, otherwise * -ETIMEDOUT state can have multiple states set, for any of several * transitions. */ -static int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, - int msecs) +int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, int msecs) { - dd->ipath_state_wanted = state; - wait_event_interruptible_timeout(ipath_state_wait, + dd->ipath_sma_state_wanted = state; + wait_event_interruptible_timeout(ipath_sma_state_wait, (dd->ipath_flags & state), msecs_to_jiffies(msecs)); - dd->ipath_state_wanted = 0; + dd->ipath_sma_state_wanted = 0; if (!(dd->ipath_flags & state)) { u64 val; - ipath_cdbg(VERBOSE, "Didn't reach linkstate %s within %u" - " ms\n", + ipath_cdbg(SMA, "Didn't reach linkstate %s within %u ms\n", /* test INIT ahead of DOWN, both can be set */ (state & IPATH_LINKINIT) ? "INIT" : ((state & IPATH_LINKDOWN) ? "DOWN" : @@ -813,6 +807,58 @@ struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd, return skb; } +/** + * ipath_rcv_layer - receive a packet for the layered (ethernet) driver + * @dd: the infinipath device + * @etail: the sk_buff number + * @tlen: the total packet length + * @hdr: the ethernet header + * + * Separate routine for better overall optimization + */ +static void ipath_rcv_layer(struct ipath_devdata *dd, u32 etail, + u32 tlen, struct ether_header *hdr) +{ + u32 elen; + u8 pad, *bthbytes; + struct sk_buff *skb, *nskb; + + if (dd->ipath_port0_skbs && + hdr->sub_opcode == IPATH_ITH4X_OPCODE_ENCAP) { + /* + * Allocate a new sk_buff to replace the one we give + * to the network stack. + */ + nskb = ipath_alloc_skb(dd, GFP_ATOMIC); + if (!nskb) { + /* count OK packets that we drop */ + ipath_stats.sps_krdrops++; + return; + } + + bthbytes = (u8 *) hdr->bth; + pad = (bthbytes[1] >> 4) & 3; + /* +CRC32 */ + elen = tlen - (sizeof(*hdr) + pad + sizeof(u32)); + + skb = dd->ipath_port0_skbs[etail]; + dd->ipath_port0_skbs[etail] = nskb; + skb_put(skb, elen); + + dd->ipath_f_put_tid(dd, etail + (u64 __iomem *) + ((char __iomem *) dd->ipath_kregbase + + dd->ipath_rcvegrbase), 0, + virt_to_phys(nskb->data)); + + __ipath_layer_rcv(dd, hdr, skb); + + /* another ether packet received */ + ipath_stats.sps_ether_rpkts++; + } + else if (hdr->sub_opcode == IPATH_ITH4X_OPCODE_LID_ARP) + __ipath_layer_rcv_lid(dd, hdr); +} + static void ipath_rcv_hdrerr(struct ipath_devdata *dd, u32 eflags, u32 l, @@ -926,17 +972,26 @@ void ipath_kreceive(struct ipath_devdata *dd) if (unlikely(eflags)) ipath_rcv_hdrerr(dd, eflags, l, etail, rc); else if (etype == RCVHQ_RCV_TYPE_NON_KD) { - ipath_ib_rcv(dd->verbs_dev, rc + 1, ebuf, tlen); - if (dd->ipath_lli_counter) - dd->ipath_lli_counter--; - ipath_cdbg(PKT, "typ %x, opcode %x (eager, " - "qp=%x), len %x; ignored\n", - etype, bthbytes[0], qp, tlen); + int ret = __ipath_verbs_rcv(dd, rc + 1, + ebuf, tlen); + if (ret == -ENODEV) + ipath_cdbg(VERBOSE, + "received IB packet, " + "not SMA (QP=%x)\n", qp); + if (dd->ipath_lli_counter) + dd->ipath_lli_counter--; + + } else if (etype == RCVHQ_RCV_TYPE_EAGER) { + if (qp == IPATH_KD_QP && + bthbytes[0] == ipath_layer_rcv_opcode && + ebuf) + ipath_rcv_layer(dd, etail, tlen, + (struct ether_header *)hdr); + else + ipath_cdbg(PKT, "typ %x, opcode %x (eager, " + "qp=%x), len %x; ignored\n", + etype, bthbytes[0], qp, tlen); } - else if (etype == RCVHQ_RCV_TYPE_EAGER) - ipath_cdbg(PKT, "typ %x, opcode %x (eager, " - "qp=%x), len %x; ignored\n", - etype, bthbytes[0], qp, tlen); else if (etype == RCVHQ_RCV_TYPE_EXPECTED) ipath_dbg("Bug: Expected TID, opcode %x; ignored\n", be32_to_cpu(hdr->bth[0]) & 0xff); @@ -969,8 +1024,7 @@ void ipath_kreceive(struct ipath_devdata *dd) */ if (l == hdrqtail || (i && !(i&0xf))) { u64 lval; - if (l == hdrqtail) - /* request IBA6120 interrupt only on last */ + if (l == hdrqtail) /* PE-800 interrupt only on last */ lval = dd->ipath_rhdrhead_intr_off | l; else lval = l; @@ -984,7 +1038,7 @@ void ipath_kreceive(struct ipath_devdata *dd) } if (!dd->ipath_rhdrhead_intr_off && !reloop) { - /* IBA6110 workaround; we can have a race clearing chip + /* HT-400 workaround; we can have a race clearing chip * interrupt with another interrupt about to be delivered, * and can clear it before it is delivered on the GPIO * workaround. By doing the extra check here for the @@ -1157,7 +1211,7 @@ int ipath_setrcvhdrsize(struct ipath_devdata *dd, unsigned rhdrsize) * * do appropriate marking as busy, etc. * returns buffer number if one found (>=0), negative number is error. - * Used by ipath_layer_send + * Used by ipath_sma_send_pkt and ipath_layer_send */ u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 * pbufnum) { @@ -1263,6 +1317,13 @@ u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 * pbufnum) goto bail; } + if (updated) + /* + * ran out of bufs, now some (at least this one we just + * got) are now available, so tell the layered driver. + */ + __ipath_layer_intr(dd, IPATH_LAYER_INT_SEND_CONTINUE); + /* * set next starting place. Since it's just an optimization, * it doesn't matter who wins on this, so no locking @@ -1439,7 +1500,7 @@ int ipath_waitfor_mdio_cmdready(struct ipath_devdata *dd) return ret; } -static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) +void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) { static const char *what[4] = { [0] = "DOWN", @@ -1450,7 +1511,7 @@ static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) int linkcmd = (which >> INFINIPATH_IBCC_LINKCMD_SHIFT) & INFINIPATH_IBCC_LINKCMD_MASK; - ipath_cdbg(VERBOSE, "Trying to move unit %u to %s, current ltstate " + ipath_cdbg(SMA, "Trying to move unit %u to %s, current ltstate " "is %s\n", dd->ipath_unit, what[linkcmd], ipath_ibcstatus_str[ @@ -1459,7 +1520,7 @@ static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) & INFINIPATH_IBCS_LINKTRAININGSTATE_MASK]); /* flush all queued sends when going to DOWN or INIT, to be sure that - * they don't block MAD packets */ + * they don't block SMA and other MAD packets */ if (!linkcmd || linkcmd == INFINIPATH_IBCC_LINKCMD_INIT) { ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, INFINIPATH_S_ABORT); @@ -1473,180 +1534,6 @@ static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which) dd->ipath_ibcctrl | which); } -int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate) -{ - u32 lstate; - int ret; - - switch (newstate) { - case IPATH_IB_LINKDOWN: - ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_POLL << - INFINIPATH_IBCC_LINKINITCMD_SHIFT); - /* don't wait */ - ret = 0; - goto bail; - - case IPATH_IB_LINKDOWN_SLEEP: - ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_SLEEP << - INFINIPATH_IBCC_LINKINITCMD_SHIFT); - /* don't wait */ - ret = 0; - goto bail; - - case IPATH_IB_LINKDOWN_DISABLE: - ipath_set_ib_lstate(dd, - INFINIPATH_IBCC_LINKINITCMD_DISABLE << - INFINIPATH_IBCC_LINKINITCMD_SHIFT); - /* don't wait */ - ret = 0; - goto bail; - - case IPATH_IB_LINKINIT: - if (dd->ipath_flags & IPATH_LINKINIT) { - ret = 0; - goto bail; - } - ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_INIT << - INFINIPATH_IBCC_LINKCMD_SHIFT); - lstate = IPATH_LINKINIT; - break; - - case IPATH_IB_LINKARM: - if (dd->ipath_flags & IPATH_LINKARMED) { - ret = 0; - goto bail; - } - if (!(dd->ipath_flags & - (IPATH_LINKINIT | IPATH_LINKACTIVE))) { - ret = -EINVAL; - goto bail; - } - ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ARMED << - INFINIPATH_IBCC_LINKCMD_SHIFT); - /* - * Since the port can transition to ACTIVE by receiving - * a non VL 15 packet, wait for either state. - */ - lstate = IPATH_LINKARMED | IPATH_LINKACTIVE; - break; - - case IPATH_IB_LINKACTIVE: - if (dd->ipath_flags & IPATH_LINKACTIVE) { - ret = 0; - goto bail; - } - if (!(dd->ipath_flags & IPATH_LINKARMED)) { - ret = -EINVAL; - goto bail; - } - ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ACTIVE << - INFINIPATH_IBCC_LINKCMD_SHIFT); - lstate = IPATH_LINKACTIVE; - break; - - default: - ipath_dbg("Invalid linkstate 0x%x requested\n", newstate); - ret = -EINVAL; - goto bail; - } - ret = ipath_wait_linkstate(dd, lstate, 2000); - -bail: - return ret; -} - -/** - * ipath_set_mtu - set the MTU - * @dd: the infinipath device - * @arg: the new MTU - * - * we can handle "any" incoming size, the issue here is whether we - * need to restrict our outgoing size. For now, we don't do any - * sanity checking on this, and we don't deal with what happens to - * programs that are already running when the size changes. - * NOTE: changing the MTU will usually cause the IBC to go back to - * link initialize (IPATH_IBSTATE_INIT) state... - */ -int ipath_set_mtu(struct ipath_devdata *dd, u16 arg) -{ - u32 piosize; - int changed = 0; - int ret; - - /* - * mtu is IB data payload max. It's the largest power of 2 less - * than piosize (or even larger, since it only really controls the - * largest we can receive; we can send the max of the mtu and - * piosize). We check that it's one of the valid IB sizes. - */ - if (arg != 256 && arg != 512 && arg != 1024 && arg != 2048 && - arg != 4096) { - ipath_dbg("Trying to set invalid mtu %u, failing\n", arg); - ret = -EINVAL; - goto bail; - } - if (dd->ipath_ibmtu == arg) { - ret = 0; /* same as current */ - goto bail; - } - - piosize = dd->ipath_ibmaxlen; - dd->ipath_ibmtu = arg; - - if (arg >= (piosize - IPATH_PIO_MAXIBHDR)) { - /* Only if it's not the initial value (or reset to it) */ - if (piosize != dd->ipath_init_ibmaxlen) { - dd->ipath_ibmaxlen = piosize; - changed = 1; - } - } else if ((arg + IPATH_PIO_MAXIBHDR) != dd->ipath_ibmaxlen) { - piosize = arg + IPATH_PIO_MAXIBHDR; - ipath_cdbg(VERBOSE, "ibmaxlen was 0x%x, setting to 0x%x " - "(mtu 0x%x)\n", dd->ipath_ibmaxlen, piosize, - arg); - dd->ipath_ibmaxlen = piosize; - changed = 1; - } - - if (changed) { - /* - * set the IBC maxpktlength to the size of our pio - * buffers in words - */ - u64 ibc = dd->ipath_ibcctrl; - ibc &= ~(INFINIPATH_IBCC_MAXPKTLEN_MASK << - INFINIPATH_IBCC_MAXPKTLEN_SHIFT); - - piosize = piosize - 2 * sizeof(u32); /* ignore pbc */ - dd->ipath_ibmaxlen = piosize; - piosize /= sizeof(u32); /* in words */ - /* - * for ICRC, which we only send in diag test pkt mode, and - * we don't need to worry about that for mtu - */ - piosize += 1; - - ibc |= piosize << INFINIPATH_IBCC_MAXPKTLEN_SHIFT; - dd->ipath_ibcctrl = ibc; - ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, - dd->ipath_ibcctrl); - dd->ipath_f_tidtemplate(dd); - } - - ret = 0; - -bail: - return ret; -} - -int ipath_set_lid(struct ipath_devdata *dd, u32 arg, u8 lmc) -{ - dd->ipath_lid = arg; - dd->ipath_lmc = lmc; - - return 0; -} - /** * ipath_read_kreg64_port - read a device's per-port 64-bit kernel register * @dd: the infinipath device @@ -1750,6 +1637,13 @@ void ipath_shutdown_device(struct ipath_devdata *dd) ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_DISABLE << INFINIPATH_IBCC_LINKINITCMD_SHIFT); + /* + * we are shutting down, so tell the layered driver. We don't do + * this on just a link state change, much like ethernet, a cable + * unplug, etc. doesn't change driver state + */ + ipath_layer_intr(dd, IPATH_LAYER_INT_IF_DOWN); + /* disable IBC */ dd->ipath_control &= ~INFINIPATH_C_LINKENABLE; ipath_write_kreg(dd, dd->ipath_kregs->kr_control, @@ -1849,7 +1743,7 @@ static int __init infinipath_init(void) { int ret; - ipath_dbg(KERN_INFO DRIVER_LOAD_MSG "%s", ib_ipath_version); + ipath_dbg(KERN_INFO DRIVER_LOAD_MSG "%s", ipath_core_version); /* * These must be called before the driver is registered with @@ -1882,18 +1776,8 @@ static int __init infinipath_init(void) goto bail_group; } - ret = ipath_diagpkt_add(); - if (ret < 0) { - printk(KERN_ERR IPATH_DRV_NAME ": Unable to create " - "diag data device: error %d\n", -ret); - goto bail_ipathfs; - } - goto bail; -bail_ipathfs: - ipath_exit_ipathfs(); - bail_group: ipath_driver_remove_group(&ipath_driver.driver); @@ -2004,8 +1888,6 @@ static void __exit infinipath_cleanup(void) struct ipath_devdata *dd, *tmp; unsigned long flags; - ipath_diagpkt_remove(); - ipath_exit_ipathfs(); ipath_driver_remove_group(&ipath_driver.driver); @@ -2116,22 +1998,5 @@ int ipath_reset_device(int unit) return ret; } -int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv) -{ - u64 val; - if ( new_pol_inv > INFINIPATH_XGXS_RX_POL_MASK ) { - return -1; - } - if ( dd->ipath_rx_pol_inv != new_pol_inv ) { - dd->ipath_rx_pol_inv = new_pol_inv; - val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig); - val &= ~(INFINIPATH_XGXS_RX_POL_MASK << - INFINIPATH_XGXS_RX_POL_SHIFT); - val |= ((u64)dd->ipath_rx_pol_inv) << - INFINIPATH_XGXS_RX_POL_SHIFT; - ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val); - } - return 0; -} module_init(infinipath_init); module_exit(infinipath_cleanup); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c b/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c index 29930e22318e..bbaa70e57db1 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_file_ops.c @@ -39,6 +39,7 @@ #include #include "ipath_kernel.h" +#include "ipath_layer.h" #include "ipath_common.h" static int ipath_open(struct inode *, struct file *); @@ -984,17 +985,15 @@ static int mmap_piobufs(struct vm_area_struct *vma, * write combining behavior we want on the PIO buffers! */ -#if defined(__powerpc__) - /* There isn't a generic way to specify writethrough mappings */ - pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; - pgprot_val(vma->vm_page_prot) |= _PAGE_WRITETHRU; - pgprot_val(vma->vm_page_prot) &= ~_PAGE_GUARDED; -#endif + if (vma->vm_flags & VM_READ) { + dev_info(&dd->pcidev->dev, + "Can't map piobufs as readable (flags=%lx)\n", + vma->vm_flags); + ret = -EPERM; + goto bail; + } - /* - * don't allow them to later change to readable with mprotect (for when - * not initially mapped readable, as is normally the case) - */ + /* don't allow them to later change to readable with mprotect */ vma->vm_flags &= ~VM_MAYREAD; vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND; @@ -1110,7 +1109,7 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma) ret = mmap_rcvegrbufs(vma, pd); else if (pgaddr == (u64) pd->port_rcvhdrq_phys) { /* - * The rcvhdrq itself; readonly except on HT (so have + * The rcvhdrq itself; readonly except on HT-400 (so have * to allow writable mapping), multiple pages, contiguous * from an i/o perspective. */ @@ -1150,7 +1149,6 @@ static unsigned int ipath_poll(struct file *fp, struct ipath_portdata *pd; u32 head, tail; int bit; - unsigned pollflag = 0; struct ipath_devdata *dd; pd = port_fp(fp); @@ -1187,12 +1185,9 @@ static unsigned int ipath_poll(struct file *fp, clear_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag); pd->port_rcvwait_to++; } - else - pollflag = POLLIN | POLLRDNORM; } else { /* it's already happened; don't do wait_event overhead */ - pollflag = POLLIN | POLLRDNORM; pd->port_rcvnowait++; } @@ -1200,7 +1195,7 @@ static unsigned int ipath_poll(struct file *fp, ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, dd->ipath_rcvctrl); - return pollflag; + return 0; } static int try_alloc_port(struct ipath_devdata *dd, int port, @@ -1302,14 +1297,14 @@ static int find_best_unit(struct file *fp) * This code is present to allow a knowledgeable person to * specify the layout of processes to processors before opening * this driver, and then we'll assign the process to the "closest" - * InfiniPath chip to that processor (we assume reasonable connectivity, + * HT-400 to that processor (we assume reasonable connectivity, * for now). This code assumes that if affinity has been set * before this point, that at most one cpu is set; for now this * is reasonable. I check for both cpus_empty() and cpus_full(), * in case some kernel variant sets none of the bits when no * affinity is set. 2.6.11 and 12 kernels have all present * cpus set. Some day we'll have to fix it up further to handle - * a cpu subset. This algorithm fails for two HT chips connected + * a cpu subset. This algorithm fails for two HT-400's connected * in tunnel fashion. Eventually this needs real topology * information. There may be some issues with dual core numbering * as well. This needs more work prior to release. @@ -1820,7 +1815,7 @@ int ipath_user_add(struct ipath_devdata *dd) if (ret < 0) { ipath_dev_err(dd, "Could not create wildcard " "minor: error %d\n", -ret); - goto bail_user; + goto bail_sma; } atomic_set(&user_setup, 1); @@ -1836,7 +1831,7 @@ int ipath_user_add(struct ipath_devdata *dd) goto bail; -bail_user: +bail_sma: user_cleanup(); bail: return ret; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_fs.c b/trunk/drivers/infiniband/hw/ipath/ipath_fs.c index a5eb30a06a5c..0936d8e8d704 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_fs.c @@ -191,8 +191,8 @@ static ssize_t atomic_port_info_read(struct file *file, char __user *buf, portinfo[4] = (dd->ipath_lid << 16); /* - * Notimpl yet SMLID. - * CapabilityMask is 0, we don't support any of these + * Notimpl yet SMLID (should we store this in the driver, in case + * SMA dies?) CapabilityMask is 0, we don't support any of these * DiagCode is 0; we don't store any diag info for now Notimpl yet * M_KeyLeasePeriod (we don't support M_Key) */ diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_iba6110.c b/trunk/drivers/infiniband/hw/ipath/ipath_ht400.c similarity index 97% rename from trunk/drivers/infiniband/hw/ipath/ipath_iba6110.c rename to trunk/drivers/infiniband/hw/ipath/ipath_ht400.c index bf2455a6d562..3db015da6e77 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_iba6110.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_ht400.c @@ -33,7 +33,7 @@ /* * This file contains all of the code that is specific to the InfiniPath - * HT chip. + * HT-400 chip. */ #include @@ -43,7 +43,7 @@ #include "ipath_registers.h" /* - * This lists the InfiniPath registers, in the actual chip layout. + * This lists the InfiniPath HT400 registers, in the actual chip layout. * This structure should never be directly accessed. * * The names are in InterCap form because they're taken straight from @@ -461,9 +461,8 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg, * times. */ if (dd->ipath_flags & IPATH_INITTED) { - ipath_dev_err(dd, "Fatal Hardware Error (freeze " - "mode), no longer usable, SN %.16s\n", - dd->ipath_serial); + ipath_dev_err(dd, "Fatal Error (freeze " + "mode), no longer usable\n"); isfatal = 1; } *dd->ipath_statusp &= ~IPATH_STATUS_IB_READY; @@ -538,7 +537,7 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg, if (hwerrs & INFINIPATH_HWE_HTCMISCERR7) strlcat(msg, "[HT core Misc7]", msgl); if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) { - strlcat(msg, "[Memory BIST test failed, InfiniPath hardware unusable]", + strlcat(msg, "[Memory BIST test failed, HT-400 unusable]", msgl); /* ignore from now on, so disable until driver reloaded */ dd->ipath_hwerrmask &= ~INFINIPATH_HWE_MEMBISTFAILED; @@ -554,7 +553,7 @@ static void ipath_ht_handle_hwerrors(struct ipath_devdata *dd, char *msg, if (hwerrs & _IPATH_PLL_FAIL) { snprintf(bitsmsg, sizeof bitsmsg, - "[PLL failed (%llx), InfiniPath hardware unusable]", + "[PLL failed (%llx), HT-400 unusable]", (unsigned long long) (hwerrs & _IPATH_PLL_FAIL)); strlcat(msg, bitsmsg, msgl); /* ignore from now on, so disable until driver reloaded */ @@ -611,18 +610,18 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name, break; case 5: /* - * original production board; two production levels, with + * HT-460 original production board; two production levels, with * different serial number ranges. See ipath_ht_early_init() for * case where we enable IPATH_GPIO_INTR for later serial # range. */ - n = "InfiniPath_QHT7040"; + n = "InfiniPath_HT-460"; break; case 6: n = "OEM_Board_3"; break; case 7: - /* small form factor production board */ - n = "InfiniPath_QHT7140"; + /* HT-460 small form factor production board */ + n = "InfiniPath_HT-465"; break; case 8: n = "LS/X-1"; @@ -634,7 +633,7 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name, n = "OEM_Board_2"; break; case 11: - n = "InfiniPath_HT-470"; /* obsoleted */ + n = "InfiniPath_HT-470"; break; case 12: n = "OEM_Board_4"; @@ -642,7 +641,7 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name, default: /* don't know, just print the number */ ipath_dev_err(dd, "Don't yet know about board " "with ID %u\n", boardrev); - snprintf(name, namelen, "Unknown_InfiniPath_QHT7xxx_%u", + snprintf(name, namelen, "Unknown_InfiniPath_HT-4xx_%u", boardrev); break; } @@ -651,10 +650,11 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name, if (dd->ipath_majrev != 3 || (dd->ipath_minrev < 2 || dd->ipath_minrev > 3)) { /* - * This version of the driver only supports Rev 3.2 and 3.3 + * This version of the driver only supports the HT-400 + * Rev 3.2 */ ipath_dev_err(dd, - "Unsupported InfiniPath hardware revision %u.%u!\n", + "Unsupported HT-400 revision %u.%u!\n", dd->ipath_majrev, dd->ipath_minrev); ret = 1; goto bail; @@ -738,7 +738,7 @@ static void ipath_check_htlink(struct ipath_devdata *dd) static int ipath_setup_ht_reset(struct ipath_devdata *dd) { - ipath_dbg("No reset possible for this InfiniPath hardware\n"); + ipath_dbg("No reset possible for HT-400\n"); return 0; } @@ -925,7 +925,7 @@ static int set_int_handler(struct ipath_devdata *dd, struct pci_dev *pdev, /* * kernels with CONFIG_PCI_MSI set the vector in the irq field of - * struct pci_device, so we use that to program the internal + * struct pci_device, so we use that to program the HT-400 internal * interrupt register (not config space) with that value. The BIOS * must still have done the basic MSI setup. */ @@ -1013,7 +1013,7 @@ static int ipath_setup_ht_config(struct ipath_devdata *dd, * @dd: the infinipath device * * Called during driver unload. - * This is currently a nop for the HT chip, not for all chips + * This is currently a nop for the HT-400, not for all chips */ static void ipath_setup_ht_cleanup(struct ipath_devdata *dd) { @@ -1290,15 +1290,6 @@ static int ipath_ht_bringup_serdes(struct ipath_devdata *dd) val &= ~INFINIPATH_XGXS_RESET; change = 1; } - if (((val >> INFINIPATH_XGXS_RX_POL_SHIFT) & - INFINIPATH_XGXS_RX_POL_MASK) != dd->ipath_rx_pol_inv ) { - /* need to compensate for Tx inversion in partner */ - val &= ~(INFINIPATH_XGXS_RX_POL_MASK << - INFINIPATH_XGXS_RX_POL_SHIFT); - val |= dd->ipath_rx_pol_inv << - INFINIPATH_XGXS_RX_POL_SHIFT; - change = 1; - } if (change) ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val); @@ -1479,7 +1470,7 @@ static int ipath_ht_early_init(struct ipath_devdata *dd) dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE; /* - * For HT, we allocate a somewhat overly large eager buffer, + * For HT-400, we allocate a somewhat overly large eager buffer, * such that we can guarantee that we can receive the largest * packet that we can send out. To truly support a 4KB MTU, * we need to bump this to a large value. To date, other than @@ -1540,7 +1531,7 @@ static int ipath_ht_early_init(struct ipath_devdata *dd) if(dd->ipath_boardrev == 5 && dd->ipath_serial[0] == '1' && dd->ipath_serial[1] == '2' && dd->ipath_serial[2] == '8') { /* - * Later production QHT7040 has same changes as QHT7140, so + * Later production HT-460 has same changes as HT-465, so * can use GPIO interrupts. They have serial #'s starting * with 128, rather than 112. */ @@ -1569,13 +1560,13 @@ static int ipath_ht_get_base_info(struct ipath_portdata *pd, void *kbase) } /** - * ipath_init_iba6110_funcs - set up the chip-specific function pointers + * ipath_init_ht400_funcs - set up the chip-specific function pointers * @dd: the infinipath device * * This is global, and is called directly at init to set up the * chip-specific function pointers for later use. */ -void ipath_init_iba6110_funcs(struct ipath_devdata *dd) +void ipath_init_ht400_funcs(struct ipath_devdata *dd) { dd->ipath_f_intrsetup = ipath_ht_intconfig; dd->ipath_f_bus = ipath_setup_ht_config; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_init_chip.c b/trunk/drivers/infiniband/hw/ipath/ipath_init_chip.c index 44669dc2e22d..414cdd1d80a6 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_init_chip.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_init_chip.c @@ -53,8 +53,8 @@ module_param_named(cfgports, ipath_cfgports, ushort, S_IRUGO); MODULE_PARM_DESC(cfgports, "Set max number of ports to use"); /* - * Number of buffers reserved for driver (verbs and layered drivers.) - * Reserved at end of buffer list. Initialized based on + * Number of buffers reserved for driver (layered drivers and SMA + * send). Reserved at end of buffer list. Initialized based on * number of PIO buffers if not set via module interface. * The problem with this is that it's global, but we'll use different * numbers for different chip types. So the default value is not @@ -80,7 +80,7 @@ MODULE_PARM_DESC(kpiobufs, "Set number of PIO buffers for driver"); * * Allocate the eager TID buffers and program them into infinipath. * We use the network layer alloc_skb() allocator to allocate the - * memory, and either use the buffers as is for things like verbs + * memory, and either use the buffers as is for things like SMA * packets, or pass the buffers up to the ipath layered driver and * thence the network layer, replacing them as we do so (see * ipath_rcv_layer()). @@ -240,11 +240,7 @@ static int init_chip_first(struct ipath_devdata *dd, "only supports %u\n", ipath_cfgports, dd->ipath_portcnt); } - /* - * Allocate full portcnt array, rather than just cfgports, because - * cleanup iterates across all possible ports. - */ - dd->ipath_pd = kzalloc(sizeof(*dd->ipath_pd) * dd->ipath_portcnt, + dd->ipath_pd = kzalloc(sizeof(*dd->ipath_pd) * dd->ipath_cfgports, GFP_KERNEL); if (!dd->ipath_pd) { @@ -450,9 +446,9 @@ static void enable_chip(struct ipath_devdata *dd, u32 val; int i; - if (!reinit) - init_waitqueue_head(&ipath_state_wait); - + if (!reinit) { + init_waitqueue_head(&ipath_sma_state_wait); + } ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, dd->ipath_rcvctrl); @@ -691,7 +687,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) dd->ipath_pioavregs = ALIGN(val, sizeof(u64) * BITS_PER_BYTE / 2) / (sizeof(u64) * BITS_PER_BYTE / 2); if (ipath_kpiobufs == 0) { - /* not set by user (this is default) */ + /* not set by user, or set explictly to default */ if ((dd->ipath_piobcnt2k + dd->ipath_piobcnt4k) > 128) kpiobufs = 32; else @@ -950,7 +946,6 @@ static int ipath_set_kpiobufs(const char *str, struct kernel_param *kp) dd->ipath_piobcnt2k + dd->ipath_piobcnt4k - val; } - ipath_kpiobufs = val; ret = 0; bail: spin_unlock_irqrestore(&ipath_devs_lock, flags); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_intr.c b/trunk/drivers/infiniband/hw/ipath/ipath_intr.c index 49bf7bb15b04..280e732660a1 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_intr.c @@ -34,7 +34,7 @@ #include #include "ipath_kernel.h" -#include "ipath_verbs.h" +#include "ipath_layer.h" #include "ipath_common.h" /* These are all rcv-related errors which we want to count for stats */ @@ -201,7 +201,7 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd, ib_linkstate(lstate)); } else - ipath_cdbg(VERBOSE, "Unit %u link state %s, last " + ipath_cdbg(SMA, "Unit %u link state %s, last " "was %s\n", dd->ipath_unit, ib_linkstate(lstate), ib_linkstate((unsigned) @@ -213,7 +213,7 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd, if (lstate == IPATH_IBSTATE_INIT || lstate == IPATH_IBSTATE_ARM || lstate == IPATH_IBSTATE_ACTIVE) - ipath_cdbg(VERBOSE, "Unit %u link state down" + ipath_cdbg(SMA, "Unit %u link state down" " (state 0x%x), from %s\n", dd->ipath_unit, (u32)val & IPATH_IBSTATE_MASK, @@ -269,7 +269,7 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd, INFINIPATH_IBCS_LINKSTATE_MASK) == INFINIPATH_IBCS_L_STATE_ACTIVE) /* if from up to down be more vocal */ - ipath_cdbg(VERBOSE, + ipath_cdbg(SMA, "Unit %u link now down (%s)\n", dd->ipath_unit, ipath_ibcstatus_str[ltstate]); @@ -289,6 +289,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd, *dd->ipath_statusp |= IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF; dd->ipath_f_setextled(dd, lstate, ltstate); + + __ipath_layer_intr(dd, IPATH_LAYER_INT_IF_UP); } else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_INIT) { /* * set INIT and DOWN. Down is checked by most of the other @@ -596,11 +598,11 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs) if (!noprint && *msg) ipath_dev_err(dd, "%s error\n", msg); - if (dd->ipath_state_wanted & dd->ipath_flags) { - ipath_cdbg(VERBOSE, "driver wanted state %x, iflags now %x, " - "waking\n", dd->ipath_state_wanted, + if (dd->ipath_sma_state_wanted & dd->ipath_flags) { + ipath_cdbg(VERBOSE, "sma wanted state %x, iflags now %x, " + "waking\n", dd->ipath_sma_state_wanted, dd->ipath_flags); - wake_up_interruptible(&ipath_state_wait); + wake_up_interruptible(&ipath_sma_state_wait); } return chkerrpkts; @@ -706,7 +708,11 @@ static void handle_layer_pioavail(struct ipath_devdata *dd) { int ret; - ret = ipath_ib_piobufavail(dd->verbs_dev); + ret = __ipath_layer_intr(dd, IPATH_LAYER_INT_SEND_CONTINUE); + if (ret > 0) + goto set; + + ret = __ipath_verbs_piobufavail(dd); if (ret > 0) goto set; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_kernel.h b/trunk/drivers/infiniband/hw/ipath/ipath_kernel.h index a8a56276ff1d..e9f374fb641e 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/trunk/drivers/infiniband/hw/ipath/ipath_kernel.h @@ -132,6 +132,12 @@ struct _ipath_layer { void *l_arg; }; +/* Verbs layer interface */ +struct _verbs_layer { + void *l_arg; + struct timer_list l_timer; +}; + struct ipath_devdata { struct list_head ipath_list; @@ -192,8 +198,7 @@ struct ipath_devdata { void (*ipath_f_setextled)(struct ipath_devdata *, u64, u64); /* fill out chip-specific fields */ int (*ipath_f_get_base_info)(struct ipath_portdata *, void *); - struct ipath_ibdev *verbs_dev; - struct timer_list verbs_timer; + struct _verbs_layer verbs_layer; /* total dwords sent (summed from counter) */ u64 ipath_sword; /* total dwords rcvd (summed from counter) */ @@ -236,7 +241,7 @@ struct ipath_devdata { u64 ipath_tidtemplate; /* value to write to free TIDs */ u64 ipath_tidinvalid; - /* IBA6120 rcv interrupt setup */ + /* PE-800 rcv interrupt setup */ u64 ipath_rhdrhead_intr_off; /* size of memory at ipath_kregbase */ @@ -245,8 +250,8 @@ struct ipath_devdata { u32 ipath_pioavregs; /* IPATH_POLL, etc. */ u32 ipath_flags; - /* ipath_flags driver is waiting for */ - u32 ipath_state_wanted; + /* ipath_flags sma is waiting for */ + u32 ipath_sma_state_wanted; /* last buffer for user use, first buf for kernel use is this * index. */ u32 ipath_lastport_piobuf; @@ -306,6 +311,10 @@ struct ipath_devdata { u32 ipath_pcibar0; /* so we can rewrite it after a chip reset */ u32 ipath_pcibar1; + /* sequential tries for SMA send and no bufs */ + u32 ipath_nosma_bufs; + /* duration (seconds) ipath_nosma_bufs set */ + u32 ipath_nosma_secs; /* HT/PCI Vendor ID (here for NodeInfo) */ u16 ipath_vendorid; @@ -503,8 +512,6 @@ struct ipath_devdata { u8 ipath_pci_cacheline; /* LID mask control */ u8 ipath_lmc; - /* Rx Polarity inversion (compensate for ~tx on partner) */ - u8 ipath_rx_pol_inv; /* local link integrity counter */ u32 ipath_lli_counter; @@ -516,6 +523,18 @@ extern struct list_head ipath_dev_list; extern spinlock_t ipath_devs_lock; extern struct ipath_devdata *ipath_lookup(int unit); +extern u16 ipath_layer_rcv_opcode; +extern int __ipath_layer_intr(struct ipath_devdata *, u32); +extern int ipath_layer_intr(struct ipath_devdata *, u32); +extern int __ipath_layer_rcv(struct ipath_devdata *, void *, + struct sk_buff *); +extern int __ipath_layer_rcv_lid(struct ipath_devdata *, void *); +extern int __ipath_verbs_piobufavail(struct ipath_devdata *); +extern int __ipath_verbs_rcv(struct ipath_devdata *, void *, void *, u32); + +void ipath_layer_add(struct ipath_devdata *); +void ipath_layer_remove(struct ipath_devdata *); + int ipath_init_chip(struct ipath_devdata *, int); int ipath_enable_wc(struct ipath_devdata *dd); void ipath_disable_wc(struct ipath_devdata *dd); @@ -530,8 +549,9 @@ void ipath_cdev_cleanup(struct cdev **cdevp, int ipath_diag_add(struct ipath_devdata *); void ipath_diag_remove(struct ipath_devdata *); +void ipath_diag_bringup_link(struct ipath_devdata *); -extern wait_queue_head_t ipath_state_wait; +extern wait_queue_head_t ipath_sma_state_wait; int ipath_user_add(struct ipath_devdata *dd); void ipath_user_remove(struct ipath_devdata *dd); @@ -562,14 +582,12 @@ void ipath_free_pddata(struct ipath_devdata *, struct ipath_portdata *); int ipath_parse_ushort(const char *str, unsigned short *valp); +int ipath_wait_linkstate(struct ipath_devdata *, u32, int); +void ipath_set_ib_lstate(struct ipath_devdata *, int); void ipath_kreceive(struct ipath_devdata *); int ipath_setrcvhdrsize(struct ipath_devdata *, unsigned); int ipath_reset_device(int); void ipath_get_faststats(unsigned long); -int ipath_set_linkstate(struct ipath_devdata *, u8); -int ipath_set_mtu(struct ipath_devdata *, u16); -int ipath_set_lid(struct ipath_devdata *, u32, u8); -int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv); /* for use in system calls, where we want to know device type, etc. */ #define port_fp(fp) ((struct ipath_portdata *) (fp)->private_data) @@ -624,8 +642,10 @@ void ipath_free_data(struct ipath_portdata *dd); int ipath_waitfor_mdio_cmdready(struct ipath_devdata *); int ipath_waitfor_complete(struct ipath_devdata *, ipath_kreg, u64, u64 *); u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *); -void ipath_init_iba6120_funcs(struct ipath_devdata *); -void ipath_init_iba6110_funcs(struct ipath_devdata *); +/* init PE-800-specific func */ +void ipath_init_pe800_funcs(struct ipath_devdata *); +/* init HT-400-specific func */ +void ipath_init_ht400_funcs(struct ipath_devdata *); void ipath_get_eeprom_info(struct ipath_devdata *); u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg); @@ -781,7 +801,7 @@ static inline u32 ipath_read_creg32(const struct ipath_devdata *dd, struct device_driver; -extern const char ib_ipath_version[]; +extern const char ipath_core_version[]; int ipath_driver_create_group(struct device_driver *); void ipath_driver_remove_group(struct device_driver *); @@ -790,9 +810,6 @@ int ipath_device_create_group(struct device *, struct ipath_devdata *); void ipath_device_remove_group(struct device *, struct ipath_devdata *); int ipath_expose_reset(struct device *); -int ipath_diagpkt_add(void); -void ipath_diagpkt_remove(void); - int ipath_init_ipathfs(void); void ipath_exit_ipathfs(void); int ipathfs_add_device(struct ipath_devdata *); @@ -814,10 +831,10 @@ const char *ipath_get_unit_name(int unit); extern struct mutex ipath_mutex; -#define IPATH_DRV_NAME "ib_ipath" +#define IPATH_DRV_NAME "ipath_core" #define IPATH_MAJOR 233 #define IPATH_USER_MINOR_BASE 0 -#define IPATH_DIAGPKT_MINOR 127 +#define IPATH_SMA_MINOR 128 #define IPATH_DIAG_MINOR_BASE 129 #define IPATH_NMINORS 255 diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_keys.c b/trunk/drivers/infiniband/hw/ipath/ipath_keys.c index ba1b93226caa..a5ca279370aa 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_keys.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_keys.c @@ -34,7 +34,6 @@ #include #include "ipath_verbs.h" -#include "ipath_kernel.h" /** * ipath_alloc_lkey - allocate an lkey @@ -61,7 +60,7 @@ int ipath_alloc_lkey(struct ipath_lkey_table *rkt, struct ipath_mregion *mr) r = (r + 1) & (rkt->max - 1); if (r == n) { spin_unlock_irqrestore(&rkt->lock, flags); - ipath_dbg(KERN_INFO "LKEY table full\n"); + _VERBS_INFO("LKEY table full\n"); ret = 0; goto bail; } diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_layer.c b/trunk/drivers/infiniband/hw/ipath/ipath_layer.c index e46aa4ed2a7e..b28c6f81c731 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_layer.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_layer.c @@ -42,20 +42,26 @@ #include "ipath_kernel.h" #include "ipath_layer.h" -#include "ipath_verbs.h" #include "ipath_common.h" /* Acquire before ipath_devs_lock. */ static DEFINE_MUTEX(ipath_layer_mutex); +static int ipath_verbs_registered; + u16 ipath_layer_rcv_opcode; static int (*layer_intr)(void *, u32); static int (*layer_rcv)(void *, void *, struct sk_buff *); static int (*layer_rcv_lid)(void *, void *); +static int (*verbs_piobufavail)(void *); +static void (*verbs_rcv)(void *, void *, void *, u32); static void *(*layer_add_one)(int, struct ipath_devdata *); static void (*layer_remove_one)(void *); +static void *(*verbs_add_one)(int, struct ipath_devdata *); +static void (*verbs_remove_one)(void *); +static void (*verbs_timer_cb)(void *); int __ipath_layer_intr(struct ipath_devdata *dd, u32 arg) { @@ -101,16 +107,302 @@ int __ipath_layer_rcv_lid(struct ipath_devdata *dd, void *hdr) return ret; } -void ipath_layer_lid_changed(struct ipath_devdata *dd) +int __ipath_verbs_piobufavail(struct ipath_devdata *dd) +{ + int ret = -ENODEV; + + if (dd->verbs_layer.l_arg && verbs_piobufavail) + ret = verbs_piobufavail(dd->verbs_layer.l_arg); + + return ret; +} + +int __ipath_verbs_rcv(struct ipath_devdata *dd, void *rc, void *ebuf, + u32 tlen) +{ + int ret = -ENODEV; + + if (dd->verbs_layer.l_arg && verbs_rcv) { + verbs_rcv(dd->verbs_layer.l_arg, rc, ebuf, tlen); + ret = 0; + } + + return ret; +} + +int ipath_layer_set_linkstate(struct ipath_devdata *dd, u8 newstate) { + u32 lstate; + int ret; + + switch (newstate) { + case IPATH_IB_LINKDOWN: + ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_POLL << + INFINIPATH_IBCC_LINKINITCMD_SHIFT); + /* don't wait */ + ret = 0; + goto bail; + + case IPATH_IB_LINKDOWN_SLEEP: + ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_SLEEP << + INFINIPATH_IBCC_LINKINITCMD_SHIFT); + /* don't wait */ + ret = 0; + goto bail; + + case IPATH_IB_LINKDOWN_DISABLE: + ipath_set_ib_lstate(dd, + INFINIPATH_IBCC_LINKINITCMD_DISABLE << + INFINIPATH_IBCC_LINKINITCMD_SHIFT); + /* don't wait */ + ret = 0; + goto bail; + + case IPATH_IB_LINKINIT: + if (dd->ipath_flags & IPATH_LINKINIT) { + ret = 0; + goto bail; + } + ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_INIT << + INFINIPATH_IBCC_LINKCMD_SHIFT); + lstate = IPATH_LINKINIT; + break; + + case IPATH_IB_LINKARM: + if (dd->ipath_flags & IPATH_LINKARMED) { + ret = 0; + goto bail; + } + if (!(dd->ipath_flags & + (IPATH_LINKINIT | IPATH_LINKACTIVE))) { + ret = -EINVAL; + goto bail; + } + ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ARMED << + INFINIPATH_IBCC_LINKCMD_SHIFT); + /* + * Since the port can transition to ACTIVE by receiving + * a non VL 15 packet, wait for either state. + */ + lstate = IPATH_LINKARMED | IPATH_LINKACTIVE; + break; + + case IPATH_IB_LINKACTIVE: + if (dd->ipath_flags & IPATH_LINKACTIVE) { + ret = 0; + goto bail; + } + if (!(dd->ipath_flags & IPATH_LINKARMED)) { + ret = -EINVAL; + goto bail; + } + ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ACTIVE << + INFINIPATH_IBCC_LINKCMD_SHIFT); + lstate = IPATH_LINKACTIVE; + break; + + default: + ipath_dbg("Invalid linkstate 0x%x requested\n", newstate); + ret = -EINVAL; + goto bail; + } + ret = ipath_wait_linkstate(dd, lstate, 2000); + +bail: + return ret; +} + +EXPORT_SYMBOL_GPL(ipath_layer_set_linkstate); + +/** + * ipath_layer_set_mtu - set the MTU + * @dd: the infinipath device + * @arg: the new MTU + * + * we can handle "any" incoming size, the issue here is whether we + * need to restrict our outgoing size. For now, we don't do any + * sanity checking on this, and we don't deal with what happens to + * programs that are already running when the size changes. + * NOTE: changing the MTU will usually cause the IBC to go back to + * link initialize (IPATH_IBSTATE_INIT) state... + */ +int ipath_layer_set_mtu(struct ipath_devdata *dd, u16 arg) +{ + u32 piosize; + int changed = 0; + int ret; + + /* + * mtu is IB data payload max. It's the largest power of 2 less + * than piosize (or even larger, since it only really controls the + * largest we can receive; we can send the max of the mtu and + * piosize). We check that it's one of the valid IB sizes. + */ + if (arg != 256 && arg != 512 && arg != 1024 && arg != 2048 && + arg != 4096) { + ipath_dbg("Trying to set invalid mtu %u, failing\n", arg); + ret = -EINVAL; + goto bail; + } + if (dd->ipath_ibmtu == arg) { + ret = 0; /* same as current */ + goto bail; + } + + piosize = dd->ipath_ibmaxlen; + dd->ipath_ibmtu = arg; + + if (arg >= (piosize - IPATH_PIO_MAXIBHDR)) { + /* Only if it's not the initial value (or reset to it) */ + if (piosize != dd->ipath_init_ibmaxlen) { + dd->ipath_ibmaxlen = piosize; + changed = 1; + } + } else if ((arg + IPATH_PIO_MAXIBHDR) != dd->ipath_ibmaxlen) { + piosize = arg + IPATH_PIO_MAXIBHDR; + ipath_cdbg(VERBOSE, "ibmaxlen was 0x%x, setting to 0x%x " + "(mtu 0x%x)\n", dd->ipath_ibmaxlen, piosize, + arg); + dd->ipath_ibmaxlen = piosize; + changed = 1; + } + + if (changed) { + /* + * set the IBC maxpktlength to the size of our pio + * buffers in words + */ + u64 ibc = dd->ipath_ibcctrl; + ibc &= ~(INFINIPATH_IBCC_MAXPKTLEN_MASK << + INFINIPATH_IBCC_MAXPKTLEN_SHIFT); + + piosize = piosize - 2 * sizeof(u32); /* ignore pbc */ + dd->ipath_ibmaxlen = piosize; + piosize /= sizeof(u32); /* in words */ + /* + * for ICRC, which we only send in diag test pkt mode, and + * we don't need to worry about that for mtu + */ + piosize += 1; + + ibc |= piosize << INFINIPATH_IBCC_MAXPKTLEN_SHIFT; + dd->ipath_ibcctrl = ibc; + ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, + dd->ipath_ibcctrl); + dd->ipath_f_tidtemplate(dd); + } + + ret = 0; + +bail: + return ret; +} + +EXPORT_SYMBOL_GPL(ipath_layer_set_mtu); + +int ipath_set_lid(struct ipath_devdata *dd, u32 arg, u8 lmc) +{ + dd->ipath_lid = arg; + dd->ipath_lmc = lmc; + mutex_lock(&ipath_layer_mutex); if (dd->ipath_layer.l_arg && layer_intr) layer_intr(dd->ipath_layer.l_arg, IPATH_LAYER_INT_LID); mutex_unlock(&ipath_layer_mutex); + + return 0; +} + +EXPORT_SYMBOL_GPL(ipath_set_lid); + +int ipath_layer_set_guid(struct ipath_devdata *dd, __be64 guid) +{ + /* XXX - need to inform anyone who cares this just happened. */ + dd->ipath_guid = guid; + return 0; +} + +EXPORT_SYMBOL_GPL(ipath_layer_set_guid); + +__be64 ipath_layer_get_guid(struct ipath_devdata *dd) +{ + return dd->ipath_guid; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_guid); + +u32 ipath_layer_get_nguid(struct ipath_devdata *dd) +{ + return dd->ipath_nguid; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_nguid); + +u32 ipath_layer_get_majrev(struct ipath_devdata *dd) +{ + return dd->ipath_majrev; } +EXPORT_SYMBOL_GPL(ipath_layer_get_majrev); + +u32 ipath_layer_get_minrev(struct ipath_devdata *dd) +{ + return dd->ipath_minrev; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_minrev); + +u32 ipath_layer_get_pcirev(struct ipath_devdata *dd) +{ + return dd->ipath_pcirev; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_pcirev); + +u32 ipath_layer_get_flags(struct ipath_devdata *dd) +{ + return dd->ipath_flags; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_flags); + +struct device *ipath_layer_get_device(struct ipath_devdata *dd) +{ + return &dd->pcidev->dev; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_device); + +u16 ipath_layer_get_deviceid(struct ipath_devdata *dd) +{ + return dd->ipath_deviceid; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_deviceid); + +u32 ipath_layer_get_vendorid(struct ipath_devdata *dd) +{ + return dd->ipath_vendorid; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_vendorid); + +u64 ipath_layer_get_lastibcstat(struct ipath_devdata *dd) +{ + return dd->ipath_lastibcstat; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_lastibcstat); + +u32 ipath_layer_get_ibmtu(struct ipath_devdata *dd) +{ + return dd->ipath_ibmtu; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_ibmtu); + void ipath_layer_add(struct ipath_devdata *dd) { mutex_lock(&ipath_layer_mutex); @@ -119,6 +411,10 @@ void ipath_layer_add(struct ipath_devdata *dd) dd->ipath_layer.l_arg = layer_add_one(dd->ipath_unit, dd); + if (verbs_add_one) + dd->verbs_layer.l_arg = + verbs_add_one(dd->ipath_unit, dd); + mutex_unlock(&ipath_layer_mutex); } @@ -131,6 +427,11 @@ void ipath_layer_remove(struct ipath_devdata *dd) dd->ipath_layer.l_arg = NULL; } + if (dd->verbs_layer.l_arg && verbs_remove_one) { + verbs_remove_one(dd->verbs_layer.l_arg); + dd->verbs_layer.l_arg = NULL; + } + mutex_unlock(&ipath_layer_mutex); } @@ -162,6 +463,9 @@ int ipath_layer_register(void *(*l_add)(int, struct ipath_devdata *), if (dd->ipath_layer.l_arg) continue; + if (!(*dd->ipath_statusp & IPATH_STATUS_SMA)) + *dd->ipath_statusp |= IPATH_STATUS_OIB_SMA; + spin_unlock_irqrestore(&ipath_devs_lock, flags); dd->ipath_layer.l_arg = l_add(dd->ipath_unit, dd); spin_lock_irqsave(&ipath_devs_lock, flags); @@ -205,6 +509,107 @@ void ipath_layer_unregister(void) EXPORT_SYMBOL_GPL(ipath_layer_unregister); +static void __ipath_verbs_timer(unsigned long arg) +{ + struct ipath_devdata *dd = (struct ipath_devdata *) arg; + + /* + * If port 0 receive packet interrupts are not available, or + * can be missed, poll the receive queue + */ + if (dd->ipath_flags & IPATH_POLL_RX_INTR) + ipath_kreceive(dd); + + /* Handle verbs layer timeouts. */ + if (dd->verbs_layer.l_arg && verbs_timer_cb) + verbs_timer_cb(dd->verbs_layer.l_arg); + + mod_timer(&dd->verbs_layer.l_timer, jiffies + 1); +} + +/** + * ipath_verbs_register - verbs layer registration + * @l_piobufavail: callback for when PIO buffers become available + * @l_rcv: callback for receiving a packet + * @l_timer_cb: timer callback + * @ipath_devdata: device data structure is put here + */ +int ipath_verbs_register(void *(*l_add)(int, struct ipath_devdata *), + void (*l_remove)(void *arg), + int (*l_piobufavail) (void *arg), + void (*l_rcv) (void *arg, void *rhdr, + void *data, u32 tlen), + void (*l_timer_cb) (void *arg)) +{ + struct ipath_devdata *dd, *tmp; + unsigned long flags; + + mutex_lock(&ipath_layer_mutex); + + verbs_add_one = l_add; + verbs_remove_one = l_remove; + verbs_piobufavail = l_piobufavail; + verbs_rcv = l_rcv; + verbs_timer_cb = l_timer_cb; + + spin_lock_irqsave(&ipath_devs_lock, flags); + + list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) { + if (!(dd->ipath_flags & IPATH_INITTED)) + continue; + + if (dd->verbs_layer.l_arg) + continue; + + spin_unlock_irqrestore(&ipath_devs_lock, flags); + dd->verbs_layer.l_arg = l_add(dd->ipath_unit, dd); + spin_lock_irqsave(&ipath_devs_lock, flags); + } + + spin_unlock_irqrestore(&ipath_devs_lock, flags); + mutex_unlock(&ipath_layer_mutex); + + ipath_verbs_registered = 1; + + return 0; +} + +EXPORT_SYMBOL_GPL(ipath_verbs_register); + +void ipath_verbs_unregister(void) +{ + struct ipath_devdata *dd, *tmp; + unsigned long flags; + + mutex_lock(&ipath_layer_mutex); + spin_lock_irqsave(&ipath_devs_lock, flags); + + list_for_each_entry_safe(dd, tmp, &ipath_dev_list, ipath_list) { + *dd->ipath_statusp &= ~IPATH_STATUS_OIB_SMA; + + if (dd->verbs_layer.l_arg && verbs_remove_one) { + spin_unlock_irqrestore(&ipath_devs_lock, flags); + verbs_remove_one(dd->verbs_layer.l_arg); + spin_lock_irqsave(&ipath_devs_lock, flags); + dd->verbs_layer.l_arg = NULL; + } + } + + spin_unlock_irqrestore(&ipath_devs_lock, flags); + + verbs_add_one = NULL; + verbs_remove_one = NULL; + verbs_piobufavail = NULL; + verbs_rcv = NULL; + verbs_timer_cb = NULL; + + ipath_verbs_registered = 0; + + mutex_unlock(&ipath_layer_mutex); +} + +EXPORT_SYMBOL_GPL(ipath_verbs_unregister); + int ipath_layer_open(struct ipath_devdata *dd, u32 * pktmax) { int ret; @@ -293,6 +698,390 @@ u16 ipath_layer_get_bcast(struct ipath_devdata *dd) EXPORT_SYMBOL_GPL(ipath_layer_get_bcast); +u32 ipath_layer_get_cr_errpkey(struct ipath_devdata *dd) +{ + return ipath_read_creg32(dd, dd->ipath_cregs->cr_errpkey); +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_cr_errpkey); + +static void update_sge(struct ipath_sge_state *ss, u32 length) +{ + struct ipath_sge *sge = &ss->sge; + + sge->vaddr += length; + sge->length -= length; + sge->sge_length -= length; + if (sge->sge_length == 0) { + if (--ss->num_sge) + *sge = *ss->sg_list++; + } else if (sge->length == 0 && sge->mr != NULL) { + if (++sge->n >= IPATH_SEGSZ) { + if (++sge->m >= sge->mr->mapsz) + return; + sge->n = 0; + } + sge->vaddr = sge->mr->map[sge->m]->segs[sge->n].vaddr; + sge->length = sge->mr->map[sge->m]->segs[sge->n].length; + } +} + +#ifdef __LITTLE_ENDIAN +static inline u32 get_upper_bits(u32 data, u32 shift) +{ + return data >> shift; +} + +static inline u32 set_upper_bits(u32 data, u32 shift) +{ + return data << shift; +} + +static inline u32 clear_upper_bytes(u32 data, u32 n, u32 off) +{ + data <<= ((sizeof(u32) - n) * BITS_PER_BYTE); + data >>= ((sizeof(u32) - n - off) * BITS_PER_BYTE); + return data; +} +#else +static inline u32 get_upper_bits(u32 data, u32 shift) +{ + return data << shift; +} + +static inline u32 set_upper_bits(u32 data, u32 shift) +{ + return data >> shift; +} + +static inline u32 clear_upper_bytes(u32 data, u32 n, u32 off) +{ + data >>= ((sizeof(u32) - n) * BITS_PER_BYTE); + data <<= ((sizeof(u32) - n - off) * BITS_PER_BYTE); + return data; +} +#endif + +static void copy_io(u32 __iomem *piobuf, struct ipath_sge_state *ss, + u32 length) +{ + u32 extra = 0; + u32 data = 0; + u32 last; + + while (1) { + u32 len = ss->sge.length; + u32 off; + + BUG_ON(len == 0); + if (len > length) + len = length; + if (len > ss->sge.sge_length) + len = ss->sge.sge_length; + /* If the source address is not aligned, try to align it. */ + off = (unsigned long)ss->sge.vaddr & (sizeof(u32) - 1); + if (off) { + u32 *addr = (u32 *)((unsigned long)ss->sge.vaddr & + ~(sizeof(u32) - 1)); + u32 v = get_upper_bits(*addr, off * BITS_PER_BYTE); + u32 y; + + y = sizeof(u32) - off; + if (len > y) + len = y; + if (len + extra >= sizeof(u32)) { + data |= set_upper_bits(v, extra * + BITS_PER_BYTE); + len = sizeof(u32) - extra; + if (len == length) { + last = data; + break; + } + __raw_writel(data, piobuf); + piobuf++; + extra = 0; + data = 0; + } else { + /* Clear unused upper bytes */ + data |= clear_upper_bytes(v, len, extra); + if (len == length) { + last = data; + break; + } + extra += len; + } + } else if (extra) { + /* Source address is aligned. */ + u32 *addr = (u32 *) ss->sge.vaddr; + int shift = extra * BITS_PER_BYTE; + int ushift = 32 - shift; + u32 l = len; + + while (l >= sizeof(u32)) { + u32 v = *addr; + + data |= set_upper_bits(v, shift); + __raw_writel(data, piobuf); + data = get_upper_bits(v, ushift); + piobuf++; + addr++; + l -= sizeof(u32); + } + /* + * We still have 'extra' number of bytes leftover. + */ + if (l) { + u32 v = *addr; + + if (l + extra >= sizeof(u32)) { + data |= set_upper_bits(v, shift); + len -= l + extra - sizeof(u32); + if (len == length) { + last = data; + break; + } + __raw_writel(data, piobuf); + piobuf++; + extra = 0; + data = 0; + } else { + /* Clear unused upper bytes */ + data |= clear_upper_bytes(v, l, + extra); + if (len == length) { + last = data; + break; + } + extra += l; + } + } else if (len == length) { + last = data; + break; + } + } else if (len == length) { + u32 w; + + /* + * Need to round up for the last dword in the + * packet. + */ + w = (len + 3) >> 2; + __iowrite32_copy(piobuf, ss->sge.vaddr, w - 1); + piobuf += w - 1; + last = ((u32 *) ss->sge.vaddr)[w - 1]; + break; + } else { + u32 w = len >> 2; + + __iowrite32_copy(piobuf, ss->sge.vaddr, w); + piobuf += w; + + extra = len & (sizeof(u32) - 1); + if (extra) { + u32 v = ((u32 *) ss->sge.vaddr)[w]; + + /* Clear unused upper bytes */ + data = clear_upper_bytes(v, extra, 0); + } + } + update_sge(ss, len); + length -= len; + } + /* Update address before sending packet. */ + update_sge(ss, length); + /* must flush early everything before trigger word */ + ipath_flush_wc(); + __raw_writel(last, piobuf); + /* be sure trigger word is written */ + ipath_flush_wc(); +} + +/** + * ipath_verbs_send - send a packet from the verbs layer + * @dd: the infinipath device + * @hdrwords: the number of words in the header + * @hdr: the packet header + * @len: the length of the packet in bytes + * @ss: the SGE to send + * + * This is like ipath_sma_send_pkt() in that we need to be able to send + * packets after the chip is initialized (MADs) but also like + * ipath_layer_send_hdr() since its used by the verbs layer. + */ +int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords, + u32 *hdr, u32 len, struct ipath_sge_state *ss) +{ + u32 __iomem *piobuf; + u32 plen; + int ret; + + /* +1 is for the qword padding of pbc */ + plen = hdrwords + ((len + 3) >> 2) + 1; + if (unlikely((plen << 2) > dd->ipath_ibmaxlen)) { + ipath_dbg("packet len 0x%x too long, failing\n", plen); + ret = -EINVAL; + goto bail; + } + + /* Get a PIO buffer to use. */ + piobuf = ipath_getpiobuf(dd, NULL); + if (unlikely(piobuf == NULL)) { + ret = -EBUSY; + goto bail; + } + + /* + * Write len to control qword, no flags. + * We have to flush after the PBC for correctness on some cpus + * or WC buffer can be written out of order. + */ + writeq(plen, piobuf); + ipath_flush_wc(); + piobuf += 2; + if (len == 0) { + /* + * If there is just the header portion, must flush before + * writing last word of header for correctness, and after + * the last header word (trigger word). + */ + __iowrite32_copy(piobuf, hdr, hdrwords - 1); + ipath_flush_wc(); + __raw_writel(hdr[hdrwords - 1], piobuf + hdrwords - 1); + ipath_flush_wc(); + ret = 0; + goto bail; + } + + __iowrite32_copy(piobuf, hdr, hdrwords); + piobuf += hdrwords; + + /* The common case is aligned and contained in one segment. */ + if (likely(ss->num_sge == 1 && len <= ss->sge.length && + !((unsigned long)ss->sge.vaddr & (sizeof(u32) - 1)))) { + u32 w; + u32 *addr = (u32 *) ss->sge.vaddr; + + /* Update address before sending packet. */ + update_sge(ss, len); + /* Need to round up for the last dword in the packet. */ + w = (len + 3) >> 2; + __iowrite32_copy(piobuf, addr, w - 1); + /* must flush early everything before trigger word */ + ipath_flush_wc(); + __raw_writel(addr[w - 1], piobuf + w - 1); + /* be sure trigger word is written */ + ipath_flush_wc(); + ret = 0; + goto bail; + } + copy_io(piobuf, ss, len); + ret = 0; + +bail: + return ret; +} + +EXPORT_SYMBOL_GPL(ipath_verbs_send); + +int ipath_layer_snapshot_counters(struct ipath_devdata *dd, u64 *swords, + u64 *rwords, u64 *spkts, u64 *rpkts, + u64 *xmit_wait) +{ + int ret; + + if (!(dd->ipath_flags & IPATH_INITTED)) { + /* no hardware, freeze, etc. */ + ipath_dbg("unit %u not usable\n", dd->ipath_unit); + ret = -EINVAL; + goto bail; + } + *swords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt); + *rwords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt); + *spkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt); + *rpkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt); + *xmit_wait = ipath_snap_cntr(dd, dd->ipath_cregs->cr_sendstallcnt); + + ret = 0; + +bail: + return ret; +} + +EXPORT_SYMBOL_GPL(ipath_layer_snapshot_counters); + +/** + * ipath_layer_get_counters - get various chip counters + * @dd: the infinipath device + * @cntrs: counters are placed here + * + * Return the counters needed by recv_pma_get_portcounters(). + */ +int ipath_layer_get_counters(struct ipath_devdata *dd, + struct ipath_layer_counters *cntrs) +{ + int ret; + + if (!(dd->ipath_flags & IPATH_INITTED)) { + /* no hardware, freeze, etc. */ + ipath_dbg("unit %u not usable\n", dd->ipath_unit); + ret = -EINVAL; + goto bail; + } + cntrs->symbol_error_counter = + ipath_snap_cntr(dd, dd->ipath_cregs->cr_ibsymbolerrcnt); + cntrs->link_error_recovery_counter = + ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkerrrecovcnt); + /* + * The link downed counter counts when the other side downs the + * connection. We add in the number of times we downed the link + * due to local link integrity errors to compensate. + */ + cntrs->link_downed_counter = + ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkdowncnt); + cntrs->port_rcv_errors = + ipath_snap_cntr(dd, dd->ipath_cregs->cr_rxdroppktcnt) + + ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvovflcnt) + + ipath_snap_cntr(dd, dd->ipath_cregs->cr_portovflcnt) + + ipath_snap_cntr(dd, dd->ipath_cregs->cr_err_rlencnt) + + ipath_snap_cntr(dd, dd->ipath_cregs->cr_invalidrlencnt) + + ipath_snap_cntr(dd, dd->ipath_cregs->cr_erricrccnt) + + ipath_snap_cntr(dd, dd->ipath_cregs->cr_errvcrccnt) + + ipath_snap_cntr(dd, dd->ipath_cregs->cr_errlpcrccnt) + + ipath_snap_cntr(dd, dd->ipath_cregs->cr_badformatcnt); + cntrs->port_rcv_remphys_errors = + ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvebpcnt); + cntrs->port_xmit_discards = + ipath_snap_cntr(dd, dd->ipath_cregs->cr_unsupvlcnt); + cntrs->port_xmit_data = + ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt); + cntrs->port_rcv_data = + ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt); + cntrs->port_xmit_packets = + ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt); + cntrs->port_rcv_packets = + ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt); + cntrs->local_link_integrity_errors = dd->ipath_lli_errors; + cntrs->excessive_buffer_overrun_errors = 0; /* XXX */ + + ret = 0; + +bail: + return ret; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_counters); + +int ipath_layer_want_buffer(struct ipath_devdata *dd) +{ + set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl); + ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, + dd->ipath_sendctrl); + + return 0; +} + +EXPORT_SYMBOL_GPL(ipath_layer_want_buffer); + int ipath_layer_send_hdr(struct ipath_devdata *dd, struct ether_header *hdr) { int ret = 0; @@ -364,3 +1153,389 @@ int ipath_layer_set_piointbufavail_int(struct ipath_devdata *dd) } EXPORT_SYMBOL_GPL(ipath_layer_set_piointbufavail_int); + +int ipath_layer_enable_timer(struct ipath_devdata *dd) +{ + /* + * HT-400 has a design flaw where the chip and kernel idea + * of the tail register don't always agree, and therefore we won't + * get an interrupt on the next packet received. + * If the board supports per packet receive interrupts, use it. + * Otherwise, the timer function periodically checks for packets + * to cover this case. + * Either way, the timer is needed for verbs layer related + * processing. + */ + if (dd->ipath_flags & IPATH_GPIO_INTR) { + ipath_write_kreg(dd, dd->ipath_kregs->kr_debugportselect, + 0x2074076542310ULL); + /* Enable GPIO bit 2 interrupt */ + ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, + (u64) (1 << 2)); + } + + init_timer(&dd->verbs_layer.l_timer); + dd->verbs_layer.l_timer.function = __ipath_verbs_timer; + dd->verbs_layer.l_timer.data = (unsigned long)dd; + dd->verbs_layer.l_timer.expires = jiffies + 1; + add_timer(&dd->verbs_layer.l_timer); + + return 0; +} + +EXPORT_SYMBOL_GPL(ipath_layer_enable_timer); + +int ipath_layer_disable_timer(struct ipath_devdata *dd) +{ + /* Disable GPIO bit 2 interrupt */ + if (dd->ipath_flags & IPATH_GPIO_INTR) + ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, 0); + + del_timer_sync(&dd->verbs_layer.l_timer); + + return 0; +} + +EXPORT_SYMBOL_GPL(ipath_layer_disable_timer); + +/** + * ipath_layer_set_verbs_flags - set the verbs layer flags + * @dd: the infinipath device + * @flags: the flags to set + */ +int ipath_layer_set_verbs_flags(struct ipath_devdata *dd, unsigned flags) +{ + struct ipath_devdata *ss; + unsigned long lflags; + + spin_lock_irqsave(&ipath_devs_lock, lflags); + + list_for_each_entry(ss, &ipath_dev_list, ipath_list) { + if (!(ss->ipath_flags & IPATH_INITTED)) + continue; + if ((flags & IPATH_VERBS_KERNEL_SMA) && + !(*ss->ipath_statusp & IPATH_STATUS_SMA)) + *ss->ipath_statusp |= IPATH_STATUS_OIB_SMA; + else + *ss->ipath_statusp &= ~IPATH_STATUS_OIB_SMA; + } + + spin_unlock_irqrestore(&ipath_devs_lock, lflags); + + return 0; +} + +EXPORT_SYMBOL_GPL(ipath_layer_set_verbs_flags); + +/** + * ipath_layer_get_npkeys - return the size of the PKEY table for port 0 + * @dd: the infinipath device + */ +unsigned ipath_layer_get_npkeys(struct ipath_devdata *dd) +{ + return ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys); +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_npkeys); + +/** + * ipath_layer_get_pkey - return the indexed PKEY from the port 0 PKEY table + * @dd: the infinipath device + * @index: the PKEY index + */ +unsigned ipath_layer_get_pkey(struct ipath_devdata *dd, unsigned index) +{ + unsigned ret; + + if (index >= ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys)) + ret = 0; + else + ret = dd->ipath_pd[0]->port_pkeys[index]; + + return ret; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_pkey); + +/** + * ipath_layer_get_pkeys - return the PKEY table for port 0 + * @dd: the infinipath device + * @pkeys: the pkey table is placed here + */ +int ipath_layer_get_pkeys(struct ipath_devdata *dd, u16 * pkeys) +{ + struct ipath_portdata *pd = dd->ipath_pd[0]; + + memcpy(pkeys, pd->port_pkeys, sizeof(pd->port_pkeys)); + + return 0; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_pkeys); + +/** + * rm_pkey - decrecment the reference count for the given PKEY + * @dd: the infinipath device + * @key: the PKEY index + * + * Return true if this was the last reference and the hardware table entry + * needs to be changed. + */ +static int rm_pkey(struct ipath_devdata *dd, u16 key) +{ + int i; + int ret; + + for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) { + if (dd->ipath_pkeys[i] != key) + continue; + if (atomic_dec_and_test(&dd->ipath_pkeyrefs[i])) { + dd->ipath_pkeys[i] = 0; + ret = 1; + goto bail; + } + break; + } + + ret = 0; + +bail: + return ret; +} + +/** + * add_pkey - add the given PKEY to the hardware table + * @dd: the infinipath device + * @key: the PKEY + * + * Return an error code if unable to add the entry, zero if no change, + * or 1 if the hardware PKEY register needs to be updated. + */ +static int add_pkey(struct ipath_devdata *dd, u16 key) +{ + int i; + u16 lkey = key & 0x7FFF; + int any = 0; + int ret; + + if (lkey == 0x7FFF) { + ret = 0; + goto bail; + } + + /* Look for an empty slot or a matching PKEY. */ + for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) { + if (!dd->ipath_pkeys[i]) { + any++; + continue; + } + /* If it matches exactly, try to increment the ref count */ + if (dd->ipath_pkeys[i] == key) { + if (atomic_inc_return(&dd->ipath_pkeyrefs[i]) > 1) { + ret = 0; + goto bail; + } + /* Lost the race. Look for an empty slot below. */ + atomic_dec(&dd->ipath_pkeyrefs[i]); + any++; + } + /* + * It makes no sense to have both the limited and unlimited + * PKEY set at the same time since the unlimited one will + * disable the limited one. + */ + if ((dd->ipath_pkeys[i] & 0x7FFF) == lkey) { + ret = -EEXIST; + goto bail; + } + } + if (!any) { + ret = -EBUSY; + goto bail; + } + for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) { + if (!dd->ipath_pkeys[i] && + atomic_inc_return(&dd->ipath_pkeyrefs[i]) == 1) { + /* for ipathstats, etc. */ + ipath_stats.sps_pkeys[i] = lkey; + dd->ipath_pkeys[i] = key; + ret = 1; + goto bail; + } + } + ret = -EBUSY; + +bail: + return ret; +} + +/** + * ipath_layer_set_pkeys - set the PKEY table for port 0 + * @dd: the infinipath device + * @pkeys: the PKEY table + */ +int ipath_layer_set_pkeys(struct ipath_devdata *dd, u16 * pkeys) +{ + struct ipath_portdata *pd; + int i; + int changed = 0; + + pd = dd->ipath_pd[0]; + + for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) { + u16 key = pkeys[i]; + u16 okey = pd->port_pkeys[i]; + + if (key == okey) + continue; + /* + * The value of this PKEY table entry is changing. + * Remove the old entry in the hardware's array of PKEYs. + */ + if (okey & 0x7FFF) + changed |= rm_pkey(dd, okey); + if (key & 0x7FFF) { + int ret = add_pkey(dd, key); + + if (ret < 0) + key = 0; + else + changed |= ret; + } + pd->port_pkeys[i] = key; + } + if (changed) { + u64 pkey; + + pkey = (u64) dd->ipath_pkeys[0] | + ((u64) dd->ipath_pkeys[1] << 16) | + ((u64) dd->ipath_pkeys[2] << 32) | + ((u64) dd->ipath_pkeys[3] << 48); + ipath_cdbg(VERBOSE, "p0 new pkey reg %llx\n", + (unsigned long long) pkey); + ipath_write_kreg(dd, dd->ipath_kregs->kr_partitionkey, + pkey); + } + return 0; +} + +EXPORT_SYMBOL_GPL(ipath_layer_set_pkeys); + +/** + * ipath_layer_get_linkdowndefaultstate - get the default linkdown state + * @dd: the infinipath device + * + * Returns zero if the default is POLL, 1 if the default is SLEEP. + */ +int ipath_layer_get_linkdowndefaultstate(struct ipath_devdata *dd) +{ + return !!(dd->ipath_ibcctrl & INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE); +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_linkdowndefaultstate); + +/** + * ipath_layer_set_linkdowndefaultstate - set the default linkdown state + * @dd: the infinipath device + * @sleep: the new state + * + * Note that this will only take effect when the link state changes. + */ +int ipath_layer_set_linkdowndefaultstate(struct ipath_devdata *dd, + int sleep) +{ + if (sleep) + dd->ipath_ibcctrl |= INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE; + else + dd->ipath_ibcctrl &= ~INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE; + ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, + dd->ipath_ibcctrl); + return 0; +} + +EXPORT_SYMBOL_GPL(ipath_layer_set_linkdowndefaultstate); + +int ipath_layer_get_phyerrthreshold(struct ipath_devdata *dd) +{ + return (dd->ipath_ibcctrl >> + INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) & + INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_phyerrthreshold); + +/** + * ipath_layer_set_phyerrthreshold - set the physical error threshold + * @dd: the infinipath device + * @n: the new threshold + * + * Note that this will only take effect when the link state changes. + */ +int ipath_layer_set_phyerrthreshold(struct ipath_devdata *dd, unsigned n) +{ + unsigned v; + + v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) & + INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK; + if (v != n) { + dd->ipath_ibcctrl &= + ~(INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK << + INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT); + dd->ipath_ibcctrl |= + (u64) n << INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT; + ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, + dd->ipath_ibcctrl); + } + return 0; +} + +EXPORT_SYMBOL_GPL(ipath_layer_set_phyerrthreshold); + +int ipath_layer_get_overrunthreshold(struct ipath_devdata *dd) +{ + return (dd->ipath_ibcctrl >> + INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) & + INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK; +} + +EXPORT_SYMBOL_GPL(ipath_layer_get_overrunthreshold); + +/** + * ipath_layer_set_overrunthreshold - set the overrun threshold + * @dd: the infinipath device + * @n: the new threshold + * + * Note that this will only take effect when the link state changes. + */ +int ipath_layer_set_overrunthreshold(struct ipath_devdata *dd, unsigned n) +{ + unsigned v; + + v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) & + INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK; + if (v != n) { + dd->ipath_ibcctrl &= + ~(INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK << + INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT); + dd->ipath_ibcctrl |= + (u64) n << INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT; + ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, + dd->ipath_ibcctrl); + } + return 0; +} + +EXPORT_SYMBOL_GPL(ipath_layer_set_overrunthreshold); + +int ipath_layer_get_boardname(struct ipath_devdata *dd, char *name, + size_t namelen) +{ + return dd->ipath_f_get_boardname(dd, name, namelen); +} +EXPORT_SYMBOL_GPL(ipath_layer_get_boardname); + +u32 ipath_layer_get_rcvhdrentsize(struct ipath_devdata *dd) +{ + return dd->ipath_rcvhdrentsize; +} +EXPORT_SYMBOL_GPL(ipath_layer_get_rcvhdrentsize); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_layer.h b/trunk/drivers/infiniband/hw/ipath/ipath_layer.h index 3854a4eae684..71485096fcac 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_layer.h +++ b/trunk/drivers/infiniband/hw/ipath/ipath_layer.h @@ -40,9 +40,73 @@ */ struct sk_buff; +struct ipath_sge_state; struct ipath_devdata; struct ether_header; +struct ipath_layer_counters { + u64 symbol_error_counter; + u64 link_error_recovery_counter; + u64 link_downed_counter; + u64 port_rcv_errors; + u64 port_rcv_remphys_errors; + u64 port_xmit_discards; + u64 port_xmit_data; + u64 port_rcv_data; + u64 port_xmit_packets; + u64 port_rcv_packets; + u32 local_link_integrity_errors; + u32 excessive_buffer_overrun_errors; +}; + +/* + * A segment is a linear region of low physical memory. + * XXX Maybe we should use phys addr here and kmap()/kunmap(). + * Used by the verbs layer. + */ +struct ipath_seg { + void *vaddr; + size_t length; +}; + +/* The number of ipath_segs that fit in a page. */ +#define IPATH_SEGSZ (PAGE_SIZE / sizeof (struct ipath_seg)) + +struct ipath_segarray { + struct ipath_seg segs[IPATH_SEGSZ]; +}; + +struct ipath_mregion { + u64 user_base; /* User's address for this region */ + u64 iova; /* IB start address of this region */ + size_t length; + u32 lkey; + u32 offset; /* offset (bytes) to start of region */ + int access_flags; + u32 max_segs; /* number of ipath_segs in all the arrays */ + u32 mapsz; /* size of the map array */ + struct ipath_segarray *map[0]; /* the segments */ +}; + +/* + * These keep track of the copy progress within a memory region. + * Used by the verbs layer. + */ +struct ipath_sge { + struct ipath_mregion *mr; + void *vaddr; /* current pointer into the segment */ + u32 sge_length; /* length of the SGE */ + u32 length; /* remaining length of the segment */ + u16 m; /* current index: mr->map[m] */ + u16 n; /* current index: mr->map[m]->segs[n] */ +}; + +struct ipath_sge_state { + struct ipath_sge *sg_list; /* next SGE to be used if any */ + struct ipath_sge sge; /* progress state for the current SGE */ + u8 num_sge; +}; + int ipath_layer_register(void *(*l_add)(int, struct ipath_devdata *), void (*l_remove)(void *), int (*l_intr)(void *, u32), @@ -50,14 +114,62 @@ int ipath_layer_register(void *(*l_add)(int, struct ipath_devdata *), struct sk_buff *), u16 rcv_opcode, int (*l_rcv_lid)(void *, void *)); +int ipath_verbs_register(void *(*l_add)(int, struct ipath_devdata *), + void (*l_remove)(void *arg), + int (*l_piobufavail)(void *arg), + void (*l_rcv)(void *arg, void *rhdr, + void *data, u32 tlen), + void (*l_timer_cb)(void *arg)); void ipath_layer_unregister(void); +void ipath_verbs_unregister(void); int ipath_layer_open(struct ipath_devdata *, u32 * pktmax); u16 ipath_layer_get_lid(struct ipath_devdata *dd); int ipath_layer_get_mac(struct ipath_devdata *dd, u8 *); u16 ipath_layer_get_bcast(struct ipath_devdata *dd); +u32 ipath_layer_get_cr_errpkey(struct ipath_devdata *dd); +int ipath_layer_set_linkstate(struct ipath_devdata *dd, u8 state); +int ipath_layer_set_mtu(struct ipath_devdata *, u16); +int ipath_set_lid(struct ipath_devdata *, u32, u8); int ipath_layer_send_hdr(struct ipath_devdata *dd, struct ether_header *hdr); +int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords, + u32 * hdr, u32 len, struct ipath_sge_state *ss); int ipath_layer_set_piointbufavail_int(struct ipath_devdata *dd); +int ipath_layer_get_boardname(struct ipath_devdata *dd, char *name, + size_t namelen); +int ipath_layer_snapshot_counters(struct ipath_devdata *dd, u64 *swords, + u64 *rwords, u64 *spkts, u64 *rpkts, + u64 *xmit_wait); +int ipath_layer_get_counters(struct ipath_devdata *dd, + struct ipath_layer_counters *cntrs); +int ipath_layer_want_buffer(struct ipath_devdata *dd); +int ipath_layer_set_guid(struct ipath_devdata *, __be64 guid); +__be64 ipath_layer_get_guid(struct ipath_devdata *); +u32 ipath_layer_get_nguid(struct ipath_devdata *); +u32 ipath_layer_get_majrev(struct ipath_devdata *); +u32 ipath_layer_get_minrev(struct ipath_devdata *); +u32 ipath_layer_get_pcirev(struct ipath_devdata *); +u32 ipath_layer_get_flags(struct ipath_devdata *dd); +struct device *ipath_layer_get_device(struct ipath_devdata *dd); +u16 ipath_layer_get_deviceid(struct ipath_devdata *dd); +u32 ipath_layer_get_vendorid(struct ipath_devdata *); +u64 ipath_layer_get_lastibcstat(struct ipath_devdata *dd); +u32 ipath_layer_get_ibmtu(struct ipath_devdata *dd); +int ipath_layer_enable_timer(struct ipath_devdata *dd); +int ipath_layer_disable_timer(struct ipath_devdata *dd); +int ipath_layer_set_verbs_flags(struct ipath_devdata *dd, unsigned flags); +unsigned ipath_layer_get_npkeys(struct ipath_devdata *dd); +unsigned ipath_layer_get_pkey(struct ipath_devdata *dd, unsigned index); +int ipath_layer_get_pkeys(struct ipath_devdata *dd, u16 *pkeys); +int ipath_layer_set_pkeys(struct ipath_devdata *dd, u16 *pkeys); +int ipath_layer_get_linkdowndefaultstate(struct ipath_devdata *dd); +int ipath_layer_set_linkdowndefaultstate(struct ipath_devdata *dd, + int sleep); +int ipath_layer_get_phyerrthreshold(struct ipath_devdata *dd); +int ipath_layer_set_phyerrthreshold(struct ipath_devdata *dd, unsigned n); +int ipath_layer_get_overrunthreshold(struct ipath_devdata *dd); +int ipath_layer_set_overrunthreshold(struct ipath_devdata *dd, unsigned n); +u32 ipath_layer_get_rcvhdrentsize(struct ipath_devdata *dd); /* ipath_ether interrupt values */ #define IPATH_LAYER_INT_IF_UP 0x2 @@ -66,6 +178,9 @@ int ipath_layer_set_piointbufavail_int(struct ipath_devdata *dd); #define IPATH_LAYER_INT_SEND_CONTINUE 0x10 #define IPATH_LAYER_INT_BCAST 0x40 +/* _verbs_layer.l_flags */ +#define IPATH_VERBS_KERNEL_SMA 0x1 + extern unsigned ipath_debug; /* debugging bit mask */ #endif /* _IPATH_LAYER_H */ diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_mad.c b/trunk/drivers/infiniband/hw/ipath/ipath_mad.c index 72d1db89db8f..d3402341b7d0 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_mad.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_mad.c @@ -101,15 +101,15 @@ static int recv_subn_get_nodeinfo(struct ib_smp *smp, nip->num_ports = ibdev->phys_port_cnt; /* This is already in network order */ nip->sys_guid = to_idev(ibdev)->sys_image_guid; - nip->node_guid = dd->ipath_guid; + nip->node_guid = ipath_layer_get_guid(dd); nip->port_guid = nip->sys_guid; - nip->partition_cap = cpu_to_be16(ipath_get_npkeys(dd)); - nip->device_id = cpu_to_be16(dd->ipath_deviceid); - majrev = dd->ipath_majrev; - minrev = dd->ipath_minrev; + nip->partition_cap = cpu_to_be16(ipath_layer_get_npkeys(dd)); + nip->device_id = cpu_to_be16(ipath_layer_get_deviceid(dd)); + majrev = ipath_layer_get_majrev(dd); + minrev = ipath_layer_get_minrev(dd); nip->revision = cpu_to_be32((majrev << 16) | minrev); nip->local_port_num = port; - vendor = dd->ipath_vendorid; + vendor = ipath_layer_get_vendorid(dd); nip->vendor_id[0] = 0; nip->vendor_id[1] = vendor >> 8; nip->vendor_id[2] = vendor; @@ -133,89 +133,13 @@ static int recv_subn_get_guidinfo(struct ib_smp *smp, */ if (startgx == 0) /* The first is a copy of the read-only HW GUID. */ - *p = to_idev(ibdev)->dd->ipath_guid; + *p = ipath_layer_get_guid(to_idev(ibdev)->dd); else smp->status |= IB_SMP_INVALID_FIELD; return reply(smp); } - -static int get_overrunthreshold(struct ipath_devdata *dd) -{ - return (dd->ipath_ibcctrl >> - INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) & - INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK; -} - -/** - * set_overrunthreshold - set the overrun threshold - * @dd: the infinipath device - * @n: the new threshold - * - * Note that this will only take effect when the link state changes. - */ -static int set_overrunthreshold(struct ipath_devdata *dd, unsigned n) -{ - unsigned v; - - v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) & - INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK; - if (v != n) { - dd->ipath_ibcctrl &= - ~(INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK << - INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT); - dd->ipath_ibcctrl |= - (u64) n << INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT; - ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, - dd->ipath_ibcctrl); - } - return 0; -} - -static int get_phyerrthreshold(struct ipath_devdata *dd) -{ - return (dd->ipath_ibcctrl >> - INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) & - INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK; -} - -/** - * set_phyerrthreshold - set the physical error threshold - * @dd: the infinipath device - * @n: the new threshold - * - * Note that this will only take effect when the link state changes. - */ -static int set_phyerrthreshold(struct ipath_devdata *dd, unsigned n) -{ - unsigned v; - - v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) & - INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK; - if (v != n) { - dd->ipath_ibcctrl &= - ~(INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK << - INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT); - dd->ipath_ibcctrl |= - (u64) n << INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT; - ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, - dd->ipath_ibcctrl); - } - return 0; -} - -/** - * get_linkdowndefaultstate - get the default linkdown state - * @dd: the infinipath device - * - * Returns zero if the default is POLL, 1 if the default is SLEEP. - */ -static int get_linkdowndefaultstate(struct ipath_devdata *dd) -{ - return !!(dd->ipath_ibcctrl & INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE); -} - static int recv_subn_get_portinfo(struct ib_smp *smp, struct ib_device *ibdev, u8 port) { @@ -242,7 +166,7 @@ static int recv_subn_get_portinfo(struct ib_smp *smp, (dev->mkeyprot_resv_lmc >> 6) == 0) pip->mkey = dev->mkey; pip->gid_prefix = dev->gid_prefix; - lid = dev->dd->ipath_lid; + lid = ipath_layer_get_lid(dev->dd); pip->lid = lid ? cpu_to_be16(lid) : IB_LID_PERMISSIVE; pip->sm_lid = cpu_to_be16(dev->sm_lid); pip->cap_mask = cpu_to_be32(dev->port_cap_flags); @@ -253,14 +177,14 @@ static int recv_subn_get_portinfo(struct ib_smp *smp, pip->link_width_supported = 3; /* 1x or 4x */ pip->link_width_active = 2; /* 4x */ pip->linkspeed_portstate = 0x10; /* 2.5Gbps */ - ibcstat = dev->dd->ipath_lastibcstat; + ibcstat = ipath_layer_get_lastibcstat(dev->dd); pip->linkspeed_portstate |= ((ibcstat >> 4) & 0x3) + 1; pip->portphysstate_linkdown = (ipath_cvt_physportstate[ibcstat & 0xf] << 4) | - (get_linkdowndefaultstate(dev->dd) ? 1 : 2); + (ipath_layer_get_linkdowndefaultstate(dev->dd) ? 1 : 2); pip->mkeyprot_resv_lmc = dev->mkeyprot_resv_lmc; pip->linkspeedactive_enabled = 0x11; /* 2.5Gbps, 2.5Gbps */ - switch (dev->dd->ipath_ibmtu) { + switch (ipath_layer_get_ibmtu(dev->dd)) { case 4096: mtu = IB_MTU_4096; break; @@ -293,7 +217,7 @@ static int recv_subn_get_portinfo(struct ib_smp *smp, pip->mkey_violations = cpu_to_be16(dev->mkey_violations); /* P_KeyViolations are counted by hardware. */ pip->pkey_violations = - cpu_to_be16((ipath_get_cr_errpkey(dev->dd) - + cpu_to_be16((ipath_layer_get_cr_errpkey(dev->dd) - dev->z_pkey_violations) & 0xFFFF); pip->qkey_violations = cpu_to_be16(dev->qkey_violations); /* Only the hardware GUID is supported for now */ @@ -302,8 +226,8 @@ static int recv_subn_get_portinfo(struct ib_smp *smp, /* 32.768 usec. response time (guessing) */ pip->resv_resptimevalue = 3; pip->localphyerrors_overrunerrors = - (get_phyerrthreshold(dev->dd) << 4) | - get_overrunthreshold(dev->dd); + (ipath_layer_get_phyerrthreshold(dev->dd) << 4) | + ipath_layer_get_overrunthreshold(dev->dd); /* pip->max_credit_hint; */ /* pip->link_roundtrip_latency[3]; */ @@ -313,20 +237,6 @@ static int recv_subn_get_portinfo(struct ib_smp *smp, return ret; } -/** - * get_pkeys - return the PKEY table for port 0 - * @dd: the infinipath device - * @pkeys: the pkey table is placed here - */ -static int get_pkeys(struct ipath_devdata *dd, u16 * pkeys) -{ - struct ipath_portdata *pd = dd->ipath_pd[0]; - - memcpy(pkeys, pd->port_pkeys, sizeof(pd->port_pkeys)); - - return 0; -} - static int recv_subn_get_pkeytable(struct ib_smp *smp, struct ib_device *ibdev) { @@ -339,9 +249,9 @@ static int recv_subn_get_pkeytable(struct ib_smp *smp, memset(smp->data, 0, sizeof(smp->data)); if (startpx == 0) { struct ipath_ibdev *dev = to_idev(ibdev); - unsigned i, n = ipath_get_npkeys(dev->dd); + unsigned i, n = ipath_layer_get_npkeys(dev->dd); - get_pkeys(dev->dd, p); + ipath_layer_get_pkeys(dev->dd, p); for (i = 0; i < n; i++) q[i] = cpu_to_be16(p[i]); @@ -358,24 +268,6 @@ static int recv_subn_set_guidinfo(struct ib_smp *smp, return recv_subn_get_guidinfo(smp, ibdev); } -/** - * set_linkdowndefaultstate - set the default linkdown state - * @dd: the infinipath device - * @sleep: the new state - * - * Note that this will only take effect when the link state changes. - */ -static int set_linkdowndefaultstate(struct ipath_devdata *dd, int sleep) -{ - if (sleep) - dd->ipath_ibcctrl |= INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE; - else - dd->ipath_ibcctrl &= ~INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE; - ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl, - dd->ipath_ibcctrl); - return 0; -} - /** * recv_subn_set_portinfo - set port information * @smp: the incoming SM packet @@ -398,7 +290,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, u8 state; u16 lstate; u32 mtu; - int ret, ore; + int ret; if (be32_to_cpu(smp->attr_mod) > ibdev->phys_port_cnt) goto err; @@ -412,7 +304,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, dev->mkey_lease_period = be16_to_cpu(pip->mkey_lease_period); lid = be16_to_cpu(pip->lid); - if (lid != dev->dd->ipath_lid) { + if (lid != ipath_layer_get_lid(dev->dd)) { /* Must be a valid unicast LID address. */ if (lid == 0 || lid >= IPATH_MULTICAST_LID_BASE) goto err; @@ -450,11 +342,11 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, case 0: /* NOP */ break; case 1: /* SLEEP */ - if (set_linkdowndefaultstate(dev->dd, 1)) + if (ipath_layer_set_linkdowndefaultstate(dev->dd, 1)) goto err; break; case 2: /* POLL */ - if (set_linkdowndefaultstate(dev->dd, 0)) + if (ipath_layer_set_linkdowndefaultstate(dev->dd, 0)) goto err; break; default: @@ -484,7 +376,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, /* XXX We have already partially updated our state! */ goto err; } - ipath_set_mtu(dev->dd, mtu); + ipath_layer_set_mtu(dev->dd, mtu); dev->sm_sl = pip->neighbormtu_mastersmsl & 0xF; @@ -500,16 +392,20 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, * later. */ if (pip->pkey_violations == 0) - dev->z_pkey_violations = ipath_get_cr_errpkey(dev->dd); + dev->z_pkey_violations = + ipath_layer_get_cr_errpkey(dev->dd); if (pip->qkey_violations == 0) dev->qkey_violations = 0; - ore = pip->localphyerrors_overrunerrors; - if (set_phyerrthreshold(dev->dd, (ore >> 4) & 0xF)) + if (ipath_layer_set_phyerrthreshold( + dev->dd, + (pip->localphyerrors_overrunerrors >> 4) & 0xF)) goto err; - if (set_overrunthreshold(dev->dd, (ore & 0xF))) + if (ipath_layer_set_overrunthreshold( + dev->dd, + (pip->localphyerrors_overrunerrors & 0xF))) goto err; dev->subnet_timeout = pip->clientrereg_resv_subnetto & 0x1F; @@ -527,7 +423,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, * is down or is being set to down. */ state = pip->linkspeed_portstate & 0xF; - flags = dev->dd->ipath_flags; + flags = ipath_layer_get_flags(dev->dd); lstate = (pip->portphysstate_linkdown >> 4) & 0xF; if (lstate && !(state == IB_PORT_DOWN || state == IB_PORT_NOP)) goto err; @@ -543,7 +439,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, /* FALLTHROUGH */ case IB_PORT_DOWN: if (lstate == 0) - if (get_linkdowndefaultstate(dev->dd)) + if (ipath_layer_get_linkdowndefaultstate(dev->dd)) lstate = IPATH_IB_LINKDOWN_SLEEP; else lstate = IPATH_IB_LINKDOWN; @@ -555,7 +451,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, lstate = IPATH_IB_LINKDOWN_DISABLE; else goto err; - ipath_set_linkstate(dev->dd, lstate); + ipath_layer_set_linkstate(dev->dd, lstate); if (flags & IPATH_LINKACTIVE) { event.event = IB_EVENT_PORT_ERR; ib_dispatch_event(&event); @@ -564,7 +460,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, case IB_PORT_ARMED: if (!(flags & (IPATH_LINKINIT | IPATH_LINKACTIVE))) break; - ipath_set_linkstate(dev->dd, IPATH_IB_LINKARM); + ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKARM); if (flags & IPATH_LINKACTIVE) { event.event = IB_EVENT_PORT_ERR; ib_dispatch_event(&event); @@ -573,7 +469,7 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, case IB_PORT_ACTIVE: if (!(flags & IPATH_LINKARMED)) break; - ipath_set_linkstate(dev->dd, IPATH_IB_LINKACTIVE); + ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKACTIVE); event.event = IB_EVENT_PORT_ACTIVE; ib_dispatch_event(&event); break; @@ -597,152 +493,6 @@ static int recv_subn_set_portinfo(struct ib_smp *smp, return ret; } -/** - * rm_pkey - decrecment the reference count for the given PKEY - * @dd: the infinipath device - * @key: the PKEY index - * - * Return true if this was the last reference and the hardware table entry - * needs to be changed. - */ -static int rm_pkey(struct ipath_devdata *dd, u16 key) -{ - int i; - int ret; - - for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) { - if (dd->ipath_pkeys[i] != key) - continue; - if (atomic_dec_and_test(&dd->ipath_pkeyrefs[i])) { - dd->ipath_pkeys[i] = 0; - ret = 1; - goto bail; - } - break; - } - - ret = 0; - -bail: - return ret; -} - -/** - * add_pkey - add the given PKEY to the hardware table - * @dd: the infinipath device - * @key: the PKEY - * - * Return an error code if unable to add the entry, zero if no change, - * or 1 if the hardware PKEY register needs to be updated. - */ -static int add_pkey(struct ipath_devdata *dd, u16 key) -{ - int i; - u16 lkey = key & 0x7FFF; - int any = 0; - int ret; - - if (lkey == 0x7FFF) { - ret = 0; - goto bail; - } - - /* Look for an empty slot or a matching PKEY. */ - for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) { - if (!dd->ipath_pkeys[i]) { - any++; - continue; - } - /* If it matches exactly, try to increment the ref count */ - if (dd->ipath_pkeys[i] == key) { - if (atomic_inc_return(&dd->ipath_pkeyrefs[i]) > 1) { - ret = 0; - goto bail; - } - /* Lost the race. Look for an empty slot below. */ - atomic_dec(&dd->ipath_pkeyrefs[i]); - any++; - } - /* - * It makes no sense to have both the limited and unlimited - * PKEY set at the same time since the unlimited one will - * disable the limited one. - */ - if ((dd->ipath_pkeys[i] & 0x7FFF) == lkey) { - ret = -EEXIST; - goto bail; - } - } - if (!any) { - ret = -EBUSY; - goto bail; - } - for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) { - if (!dd->ipath_pkeys[i] && - atomic_inc_return(&dd->ipath_pkeyrefs[i]) == 1) { - /* for ipathstats, etc. */ - ipath_stats.sps_pkeys[i] = lkey; - dd->ipath_pkeys[i] = key; - ret = 1; - goto bail; - } - } - ret = -EBUSY; - -bail: - return ret; -} - -/** - * set_pkeys - set the PKEY table for port 0 - * @dd: the infinipath device - * @pkeys: the PKEY table - */ -static int set_pkeys(struct ipath_devdata *dd, u16 *pkeys) -{ - struct ipath_portdata *pd; - int i; - int changed = 0; - - pd = dd->ipath_pd[0]; - - for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) { - u16 key = pkeys[i]; - u16 okey = pd->port_pkeys[i]; - - if (key == okey) - continue; - /* - * The value of this PKEY table entry is changing. - * Remove the old entry in the hardware's array of PKEYs. - */ - if (okey & 0x7FFF) - changed |= rm_pkey(dd, okey); - if (key & 0x7FFF) { - int ret = add_pkey(dd, key); - - if (ret < 0) - key = 0; - else - changed |= ret; - } - pd->port_pkeys[i] = key; - } - if (changed) { - u64 pkey; - - pkey = (u64) dd->ipath_pkeys[0] | - ((u64) dd->ipath_pkeys[1] << 16) | - ((u64) dd->ipath_pkeys[2] << 32) | - ((u64) dd->ipath_pkeys[3] << 48); - ipath_cdbg(VERBOSE, "p0 new pkey reg %llx\n", - (unsigned long long) pkey); - ipath_write_kreg(dd, dd->ipath_kregs->kr_partitionkey, - pkey); - } - return 0; -} - static int recv_subn_set_pkeytable(struct ib_smp *smp, struct ib_device *ibdev) { @@ -750,12 +500,13 @@ static int recv_subn_set_pkeytable(struct ib_smp *smp, __be16 *p = (__be16 *) smp->data; u16 *q = (u16 *) smp->data; struct ipath_ibdev *dev = to_idev(ibdev); - unsigned i, n = ipath_get_npkeys(dev->dd); + unsigned i, n = ipath_layer_get_npkeys(dev->dd); for (i = 0; i < n; i++) q[i] = be16_to_cpu(p[i]); - if (startpx != 0 || set_pkeys(dev->dd, q) != 0) + if (startpx != 0 || + ipath_layer_set_pkeys(dev->dd, q) != 0) smp->status |= IB_SMP_INVALID_FIELD; return recv_subn_get_pkeytable(smp, ibdev); @@ -1093,10 +844,10 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp, struct ib_pma_portcounters *p = (struct ib_pma_portcounters *) pmp->data; struct ipath_ibdev *dev = to_idev(ibdev); - struct ipath_verbs_counters cntrs; + struct ipath_layer_counters cntrs; u8 port_select = p->port_select; - ipath_get_counters(dev->dd, &cntrs); + ipath_layer_get_counters(dev->dd, &cntrs); /* Adjust counters for any resets done. */ cntrs.symbol_error_counter -= dev->z_symbol_error_counter; @@ -1193,8 +944,8 @@ static int recv_pma_get_portcounters_ext(struct ib_perf *pmp, u64 swords, rwords, spkts, rpkts, xwait; u8 port_select = p->port_select; - ipath_snapshot_counters(dev->dd, &swords, &rwords, &spkts, - &rpkts, &xwait); + ipath_layer_snapshot_counters(dev->dd, &swords, &rwords, &spkts, + &rpkts, &xwait); /* Adjust counters for any resets done. */ swords -= dev->z_port_xmit_data; @@ -1227,13 +978,13 @@ static int recv_pma_set_portcounters(struct ib_perf *pmp, struct ib_pma_portcounters *p = (struct ib_pma_portcounters *) pmp->data; struct ipath_ibdev *dev = to_idev(ibdev); - struct ipath_verbs_counters cntrs; + struct ipath_layer_counters cntrs; /* * Since the HW doesn't support clearing counters, we save the * current count and subtract it from future responses. */ - ipath_get_counters(dev->dd, &cntrs); + ipath_layer_get_counters(dev->dd, &cntrs); if (p->counter_select & IB_PMA_SEL_SYMBOL_ERROR) dev->z_symbol_error_counter = cntrs.symbol_error_counter; @@ -1290,8 +1041,8 @@ static int recv_pma_set_portcounters_ext(struct ib_perf *pmp, struct ipath_ibdev *dev = to_idev(ibdev); u64 swords, rwords, spkts, rpkts, xwait; - ipath_snapshot_counters(dev->dd, &swords, &rwords, &spkts, - &rpkts, &xwait); + ipath_layer_snapshot_counters(dev->dd, &swords, &rwords, &spkts, + &rpkts, &xwait); if (p->counter_select & IB_PMA_SELX_PORT_XMIT_DATA) dev->z_port_xmit_data = swords; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_mmap.c b/trunk/drivers/infiniband/hw/ipath/ipath_mmap.c deleted file mode 100644 index 11b7378ff214..000000000000 --- a/trunk/drivers/infiniband/hw/ipath/ipath_mmap.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2006 QLogic, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include "ipath_verbs.h" - -/** - * ipath_release_mmap_info - free mmap info structure - * @ref: a pointer to the kref within struct ipath_mmap_info - */ -void ipath_release_mmap_info(struct kref *ref) -{ - struct ipath_mmap_info *ip = - container_of(ref, struct ipath_mmap_info, ref); - - vfree(ip->obj); - kfree(ip); -} - -/* - * open and close keep track of how many times the CQ is mapped, - * to avoid releasing it. - */ -static void ipath_vma_open(struct vm_area_struct *vma) -{ - struct ipath_mmap_info *ip = vma->vm_private_data; - - kref_get(&ip->ref); - ip->mmap_cnt++; -} - -static void ipath_vma_close(struct vm_area_struct *vma) -{ - struct ipath_mmap_info *ip = vma->vm_private_data; - - ip->mmap_cnt--; - kref_put(&ip->ref, ipath_release_mmap_info); -} - -static struct vm_operations_struct ipath_vm_ops = { - .open = ipath_vma_open, - .close = ipath_vma_close, -}; - -/** - * ipath_mmap - create a new mmap region - * @context: the IB user context of the process making the mmap() call - * @vma: the VMA to be initialized - * Return zero if the mmap is OK. Otherwise, return an errno. - */ -int ipath_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) -{ - struct ipath_ibdev *dev = to_idev(context->device); - unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; - unsigned long size = vma->vm_end - vma->vm_start; - struct ipath_mmap_info *ip, **pp; - int ret = -EINVAL; - - /* - * Search the device's list of objects waiting for a mmap call. - * Normally, this list is very short since a call to create a - * CQ, QP, or SRQ is soon followed by a call to mmap(). - */ - spin_lock_irq(&dev->pending_lock); - for (pp = &dev->pending_mmaps; (ip = *pp); pp = &ip->next) { - /* Only the creator is allowed to mmap the object */ - if (context != ip->context || (void *) offset != ip->obj) - continue; - /* Don't allow a mmap larger than the object. */ - if (size > ip->size) - break; - - *pp = ip->next; - spin_unlock_irq(&dev->pending_lock); - - ret = remap_vmalloc_range(vma, ip->obj, 0); - if (ret) - goto done; - vma->vm_ops = &ipath_vm_ops; - vma->vm_private_data = ip; - ipath_vma_open(vma); - goto done; - } - spin_unlock_irq(&dev->pending_lock); -done: - return ret; -} diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_mr.c b/trunk/drivers/infiniband/hw/ipath/ipath_mr.c index b36f6fb3e37a..4ac31a5da330 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_mr.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_mr.c @@ -36,18 +36,6 @@ #include "ipath_verbs.h" -/* Fast memory region */ -struct ipath_fmr { - struct ib_fmr ibfmr; - u8 page_shift; - struct ipath_mregion mr; /* must be last */ -}; - -static inline struct ipath_fmr *to_ifmr(struct ib_fmr *ibfmr) -{ - return container_of(ibfmr, struct ipath_fmr, ibfmr); -} - /** * ipath_get_dma_mr - get a DMA memory region * @pd: protection domain for this memory region diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c b/trunk/drivers/infiniband/hw/ipath/ipath_pe800.c similarity index 95% rename from trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c rename to trunk/drivers/infiniband/hw/ipath/ipath_pe800.c index d86516d23df6..b83f66d8262c 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_iba6120.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_pe800.c @@ -32,7 +32,7 @@ */ /* * This file contains all of the code that is specific to the - * InfiniPath PCIe chip. + * InfiniPath PE-800 chip. */ #include @@ -45,9 +45,9 @@ /* * This file contains all the chip-specific register information and - * access functions for the QLogic InfiniPath PCI-Express chip. + * access functions for the QLogic InfiniPath PE800, the PCI-Express chip. * - * This lists the InfiniPath registers, in the actual chip layout. + * This lists the InfiniPath PE800 registers, in the actual chip layout. * This structure should never be directly accessed. */ struct _infinipath_do_not_use_kernel_regs { @@ -213,6 +213,7 @@ static const struct ipath_kregs ipath_pe_kregs = { .kr_rcvhdraddr = IPATH_KREG_OFFSET(RcvHdrAddr0), .kr_rcvhdrtailaddr = IPATH_KREG_OFFSET(RcvHdrTailAddr0), + /* This group is pe-800-specific; and used only in this file */ /* The rcvpktled register controls one of the debug port signals, so * a packet activity LED can be connected to it. */ .kr_rcvpktledcnt = IPATH_KREG_OFFSET(RcvPktLEDCnt), @@ -363,9 +364,8 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg, * and we get here multiple times */ if (dd->ipath_flags & IPATH_INITTED) { - ipath_dev_err(dd, "Fatal Hardware Error (freeze " - "mode), no longer usable, SN %.16s\n", - dd->ipath_serial); + ipath_dev_err(dd, "Fatal Error (freeze " + "mode), no longer usable\n"); isfatal = 1; } /* @@ -388,7 +388,7 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg, *msg = '\0'; if (hwerrs & INFINIPATH_HWE_MEMBISTFAILED) { - strlcat(msg, "[Memory BIST test failed, InfiniPath hardware unusable]", + strlcat(msg, "[Memory BIST test failed, PE-800 unusable]", msgl); /* ignore from now on, so disable until driver reloaded */ *dd->ipath_statusp |= IPATH_STATUS_HWERROR; @@ -433,7 +433,7 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg, if (hwerrs & _IPATH_PLL_FAIL) { snprintf(bitsmsg, sizeof bitsmsg, - "[PLL failed (%llx), InfiniPath hardware unusable]", + "[PLL failed (%llx), PE-800 unusable]", (unsigned long long) hwerrs & _IPATH_PLL_FAIL); strlcat(msg, bitsmsg, msgl); /* ignore from now on, so disable until driver reloaded */ @@ -511,25 +511,22 @@ static int ipath_pe_boardname(struct ipath_devdata *dd, char *name, n = "InfiniPath_Emulation"; break; case 1: - n = "InfiniPath_QLE7140-Bringup"; + n = "InfiniPath_PE-800-Bringup"; break; case 2: - n = "InfiniPath_QLE7140"; + n = "InfiniPath_PE-880"; break; case 3: - n = "InfiniPath_QMI7140"; + n = "InfiniPath_PE-850"; break; case 4: - n = "InfiniPath_QEM7140"; - break; - case 5: - n = "InfiniPath_QMH7140"; + n = "InfiniPath_PE-860"; break; default: ipath_dev_err(dd, "Don't yet know about board with ID %u\n", boardrev); - snprintf(name, namelen, "Unknown_InfiniPath_PCIe_%u", + snprintf(name, namelen, "Unknown_InfiniPath_PE-8xx_%u", boardrev); break; } @@ -537,7 +534,7 @@ static int ipath_pe_boardname(struct ipath_devdata *dd, char *name, snprintf(name, namelen, "%s", n); if (dd->ipath_majrev != 4 || !dd->ipath_minrev || dd->ipath_minrev>2) { - ipath_dev_err(dd, "Unsupported InfiniPath hardware revision %u.%u!\n", + ipath_dev_err(dd, "Unsupported PE-800 revision %u.%u!\n", dd->ipath_majrev, dd->ipath_minrev); ret = 1; } else @@ -654,15 +651,6 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd) val &= ~INFINIPATH_XGXS_RESET; change = 1; } - if (((val >> INFINIPATH_XGXS_RX_POL_SHIFT) & - INFINIPATH_XGXS_RX_POL_MASK) != dd->ipath_rx_pol_inv ) { - /* need to compensate for Tx inversion in partner */ - val &= ~(INFINIPATH_XGXS_RX_POL_MASK << - INFINIPATH_XGXS_RX_POL_SHIFT); - val |= dd->ipath_rx_pol_inv << - INFINIPATH_XGXS_RX_POL_SHIFT; - change = 1; - } if (change) ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val); @@ -717,7 +705,7 @@ static void ipath_pe_quiet_serdes(struct ipath_devdata *dd) ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val); } -/* this is not yet needed on this chip, so just return 0. */ +/* this is not yet needed on the PE800, so just return 0. */ static int ipath_pe_intconfig(struct ipath_devdata *dd) { return 0; @@ -771,8 +759,8 @@ static void ipath_setup_pe_setextled(struct ipath_devdata *dd, u64 lst, * * This is called during driver unload. * We do the pci_disable_msi here, not in generic code, because it - * isn't used for the HT chips. If we do end up needing pci_enable_msi - * at some point in the future for HT, we'll move the call back + * isn't used for the HT-400. If we do end up needing pci_enable_msi + * at some point in the future for HT-400, we'll move the call back * into the main init_one code. */ static void ipath_setup_pe_cleanup(struct ipath_devdata *dd) @@ -792,10 +780,10 @@ static void ipath_setup_pe_cleanup(struct ipath_devdata *dd) * late in 2.6.16). * All that can be done is to edit the kernel source to remove the quirk * check until that is fixed. - * We do not need to call enable_msi() for our HyperTransport chip, - * even though it uses MSI, and we want to avoid the quirk warning, so - * So we call enable_msi only for PCIe. If we do end up needing - * pci_enable_msi at some point in the future for HT, we'll move the + * We do not need to call enable_msi() for our HyperTransport chip (HT-400), + * even those it uses MSI, and we want to avoid the quirk warning, so + * So we call enable_msi only for the PE-800. If we do end up needing + * pci_enable_msi at some point in the future for HT-400, we'll move the * call back into the main init_one code. * We save the msi lo and hi values, so we can restore them after * chip reset (the kernel PCI infrastructure doesn't yet handle that @@ -983,7 +971,8 @@ static int ipath_setup_pe_reset(struct ipath_devdata *dd) int ret; /* Use ERROR so it shows up in logs, etc. */ - ipath_dev_err(dd, "Resetting InfiniPath unit %u\n", dd->ipath_unit); + ipath_dev_err(dd, "Resetting PE-800 unit %u\n", + dd->ipath_unit); /* keep chip from being accessed in a few places */ dd->ipath_flags &= ~(IPATH_INITTED|IPATH_PRESENT); val = dd->ipath_control | INFINIPATH_C_RESET; @@ -1089,7 +1078,7 @@ static void ipath_pe_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr, * @port: the port * * clear all TID entries for a port, expected and eager. - * Used from ipath_close(). On this chip, TIDs are only 32 bits, + * Used from ipath_close(). On PE800, TIDs are only 32 bits, * not 64, but they are still on 64 bit boundaries, so tidbase * is declared as u64 * for the pointer math, even though we write 32 bits */ @@ -1159,9 +1148,9 @@ static int ipath_pe_early_init(struct ipath_devdata *dd) dd->ipath_flags |= IPATH_4BYTE_TID; /* - * For openfabrics, we need to be able to handle an IB header of - * 24 dwords. HT chip has arbitrary sized receive buffers, so we - * made them the same size as the PIO buffers. This chip does not + * For openib, we need to be able to handle an IB header of 96 bytes + * or 24 dwords. HT-400 has arbitrary sized receive buffers, so we + * made them the same size as the PIO buffers. The PE-800 does not * handle arbitrary size buffers, so we need the header large enough * to handle largest IB header, but still have room for a 2KB MTU * standard IB packet. @@ -1169,10 +1158,11 @@ static int ipath_pe_early_init(struct ipath_devdata *dd) dd->ipath_rcvhdrentsize = 24; dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE; - /* - * To truly support a 4KB MTU (for usermode), we need to - * bump this to a larger value. For now, we use them for - * the kernel only. + /* For HT-400, we allocate a somewhat overly large eager buffer, + * such that we can guarantee that we can receive the largest packet + * that we can send out. To truly support a 4KB MTU, we need to + * bump this to a larger value. We'll do this when I get around to + * testing 4KB sends on the PE-800, which I have not yet done. */ dd->ipath_rcvegrbufsize = 2048; /* @@ -1185,9 +1175,9 @@ static int ipath_pe_early_init(struct ipath_devdata *dd) dd->ipath_init_ibmaxlen = dd->ipath_ibmaxlen; /* - * We can request a receive interrupt for 1 or + * For PE-800, we can request a receive interrupt for 1 or * more packets from current offset. For now, we set this - * up for a single packet. + * up for a single packet, to match the HT-400 behavior. */ dd->ipath_rhdrhead_intr_off = 1ULL<<32; @@ -1226,13 +1216,13 @@ static int ipath_pe_get_base_info(struct ipath_portdata *pd, void *kbase) } /** - * ipath_init_iba6120_funcs - set up the chip-specific function pointers + * ipath_init_pe800_funcs - set up the chip-specific function pointers * @dd: the infinipath device * * This is global, and is called directly at init to set up the * chip-specific function pointers for later use. */ -void ipath_init_iba6120_funcs(struct ipath_devdata *dd) +void ipath_init_pe800_funcs(struct ipath_devdata *dd) { dd->ipath_f_intrsetup = ipath_pe_intconfig; dd->ipath_f_bus = ipath_setup_pe_config; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_qp.c b/trunk/drivers/infiniband/hw/ipath/ipath_qp.c index 224b0f40767f..83e557be591e 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_qp.c @@ -35,7 +35,7 @@ #include #include "ipath_verbs.h" -#include "ipath_kernel.h" +#include "ipath_common.h" #define BITS_PER_PAGE (PAGE_SIZE*BITS_PER_BYTE) #define BITS_PER_PAGE_MASK (BITS_PER_PAGE-1) @@ -44,6 +44,19 @@ #define find_next_offset(map, off) find_next_zero_bit((map)->page, \ BITS_PER_PAGE, off) +#define TRANS_INVALID 0 +#define TRANS_ANY2RST 1 +#define TRANS_RST2INIT 2 +#define TRANS_INIT2INIT 3 +#define TRANS_INIT2RTR 4 +#define TRANS_RTR2RTS 5 +#define TRANS_RTS2RTS 6 +#define TRANS_SQERR2RTS 7 +#define TRANS_ANY2ERR 8 +#define TRANS_RTS2SQD 9 /* XXX Wait for expected ACKs & signal event */ +#define TRANS_SQD2SQD 10 /* error if not drained & parameter change */ +#define TRANS_SQD2RTS 11 /* error if not drained */ + /* * Convert the AETH credit code into the number of credits. */ @@ -274,7 +287,7 @@ void ipath_free_all_qps(struct ipath_qp_table *qpt) free_qpn(qpt, qp->ibqp.qp_num); if (!atomic_dec_and_test(&qp->refcount) || !ipath_destroy_qp(&qp->ibqp)) - ipath_dbg(KERN_INFO "QP memory leak!\n"); + _VERBS_INFO("QP memory leak!\n"); qp = nqp; } } @@ -342,10 +355,8 @@ static void ipath_reset_qp(struct ipath_qp *qp) qp->s_last = 0; qp->s_ssn = 1; qp->s_lsn = 0; - if (qp->r_rq.wq) { - qp->r_rq.wq->head = 0; - qp->r_rq.wq->tail = 0; - } + qp->r_rq.head = 0; + qp->r_rq.tail = 0; qp->r_reuse_sge = 0; } @@ -362,8 +373,8 @@ void ipath_error_qp(struct ipath_qp *qp) struct ipath_ibdev *dev = to_idev(qp->ibqp.device); struct ib_wc wc; - ipath_dbg(KERN_INFO "QP%d/%d in error state\n", - qp->ibqp.qp_num, qp->remote_qpn); + _VERBS_INFO("QP%d/%d in error state\n", + qp->ibqp.qp_num, qp->remote_qpn); spin_lock(&dev->pending_lock); /* XXX What if its already removed by the timeout code? */ @@ -399,32 +410,15 @@ void ipath_error_qp(struct ipath_qp *qp) qp->s_hdrwords = 0; qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE; - if (qp->r_rq.wq) { - struct ipath_rwq *wq; - u32 head; - u32 tail; - - spin_lock(&qp->r_rq.lock); - - /* sanity check pointers before trusting them */ - wq = qp->r_rq.wq; - head = wq->head; - if (head >= qp->r_rq.size) - head = 0; - tail = wq->tail; - if (tail >= qp->r_rq.size) - tail = 0; - wc.opcode = IB_WC_RECV; - while (tail != head) { - wc.wr_id = get_rwqe_ptr(&qp->r_rq, tail)->wr_id; - if (++tail >= qp->r_rq.size) - tail = 0; - ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); - } - wq->tail = tail; - - spin_unlock(&qp->r_rq.lock); + wc.opcode = IB_WC_RECV; + spin_lock(&qp->r_rq.lock); + while (qp->r_rq.tail != qp->r_rq.head) { + wc.wr_id = get_rwqe_ptr(&qp->r_rq, qp->r_rq.tail)->wr_id; + if (++qp->r_rq.tail >= qp->r_rq.size) + qp->r_rq.tail = 0; + ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); } + spin_unlock(&qp->r_rq.lock); } /** @@ -432,12 +426,11 @@ void ipath_error_qp(struct ipath_qp *qp) * @ibqp: the queue pair who's attributes we're modifying * @attr: the new attributes * @attr_mask: the mask of attributes to modify - * @udata: user data for ipathverbs.so * * Returns 0 on success, otherwise returns an errno. */ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, - int attr_mask, struct ib_udata *udata) + int attr_mask) { struct ipath_ibdev *dev = to_idev(ibqp->device); struct ipath_qp *qp = to_iqp(ibqp); @@ -455,46 +448,19 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, attr_mask)) goto inval; - if (attr_mask & IB_QP_AV) { + if (attr_mask & IB_QP_AV) if (attr->ah_attr.dlid == 0 || attr->ah_attr.dlid >= IPATH_MULTICAST_LID_BASE) goto inval; - if ((attr->ah_attr.ah_flags & IB_AH_GRH) && - (attr->ah_attr.grh.sgid_index > 1)) - goto inval; - } - if (attr_mask & IB_QP_PKEY_INDEX) - if (attr->pkey_index >= ipath_get_npkeys(dev->dd)) + if (attr->pkey_index >= ipath_layer_get_npkeys(dev->dd)) goto inval; if (attr_mask & IB_QP_MIN_RNR_TIMER) if (attr->min_rnr_timer > 31) goto inval; - if (attr_mask & IB_QP_PORT) - if (attr->port_num == 0 || - attr->port_num > ibqp->device->phys_port_cnt) - goto inval; - - if (attr_mask & IB_QP_PATH_MTU) - if (attr->path_mtu > IB_MTU_4096) - goto inval; - - if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) - if (attr->max_dest_rd_atomic > 1) - goto inval; - - if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) - if (attr->max_rd_atomic > 1) - goto inval; - - if (attr_mask & IB_QP_PATH_MIG_STATE) - if (attr->path_mig_state != IB_MIG_MIGRATED && - attr->path_mig_state != IB_MIG_REARM) - goto inval; - switch (new_state) { case IB_QPS_RESET: ipath_reset_qp(qp); @@ -545,9 +511,6 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, if (attr_mask & IB_QP_MIN_RNR_TIMER) qp->r_min_rnr_timer = attr->min_rnr_timer; - if (attr_mask & IB_QP_TIMEOUT) - qp->timeout = attr->timeout; - if (attr_mask & IB_QP_QKEY) qp->qkey = attr->qkey; @@ -580,7 +543,7 @@ int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, attr->dest_qp_num = qp->remote_qpn; attr->qp_access_flags = qp->qp_access_flags; attr->cap.max_send_wr = qp->s_size - 1; - attr->cap.max_recv_wr = qp->ibqp.srq ? 0 : qp->r_rq.size - 1; + attr->cap.max_recv_wr = qp->r_rq.size - 1; attr->cap.max_send_sge = qp->s_max_sge; attr->cap.max_recv_sge = qp->r_rq.max_sge; attr->cap.max_inline_data = 0; @@ -594,7 +557,7 @@ int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, attr->max_dest_rd_atomic = 1; attr->min_rnr_timer = qp->r_min_rnr_timer; attr->port_num = 1; - attr->timeout = qp->timeout; + attr->timeout = 0; attr->retry_cnt = qp->s_retry_cnt; attr->rnr_retry = qp->s_rnr_retry; attr->alt_port_num = 0; @@ -606,10 +569,9 @@ int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, init_attr->recv_cq = qp->ibqp.recv_cq; init_attr->srq = qp->ibqp.srq; init_attr->cap = attr->cap; - if (qp->s_flags & (1 << IPATH_S_SIGNAL_REQ_WR)) - init_attr->sq_sig_type = IB_SIGNAL_REQ_WR; - else - init_attr->sq_sig_type = IB_SIGNAL_ALL_WR; + init_attr->sq_sig_type = + (qp->s_flags & (1 << IPATH_S_SIGNAL_REQ_WR)) + ? IB_SIGNAL_REQ_WR : 0; init_attr->qp_type = qp->ibqp.qp_type; init_attr->port_num = 1; return 0; @@ -634,23 +596,13 @@ __be32 ipath_compute_aeth(struct ipath_qp *qp) } else { u32 min, max, x; u32 credits; - struct ipath_rwq *wq = qp->r_rq.wq; - u32 head; - u32 tail; - - /* sanity check pointers before trusting them */ - head = wq->head; - if (head >= qp->r_rq.size) - head = 0; - tail = wq->tail; - if (tail >= qp->r_rq.size) - tail = 0; + /* * Compute the number of credits available (RWQEs). * XXX Not holding the r_rq.lock here so there is a small * chance that the pair of reads are not atomic. */ - credits = head - tail; + credits = qp->r_rq.head - qp->r_rq.tail; if ((int)credits < 0) credits += qp->r_rq.size; /* @@ -727,37 +679,27 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, case IB_QPT_UD: case IB_QPT_SMI: case IB_QPT_GSI: - sz = sizeof(*qp); - if (init_attr->srq) { - struct ipath_srq *srq = to_isrq(init_attr->srq); - - sz += sizeof(*qp->r_sg_list) * - srq->rq.max_sge; - } else - sz += sizeof(*qp->r_sg_list) * - init_attr->cap.max_recv_sge; - qp = kmalloc(sz, GFP_KERNEL); + qp = kmalloc(sizeof(*qp), GFP_KERNEL); if (!qp) { + vfree(swq); ret = ERR_PTR(-ENOMEM); - goto bail_swq; + goto bail; } if (init_attr->srq) { - sz = 0; qp->r_rq.size = 0; qp->r_rq.max_sge = 0; qp->r_rq.wq = NULL; - init_attr->cap.max_recv_wr = 0; - init_attr->cap.max_recv_sge = 0; } else { qp->r_rq.size = init_attr->cap.max_recv_wr + 1; qp->r_rq.max_sge = init_attr->cap.max_recv_sge; - sz = (sizeof(struct ib_sge) * qp->r_rq.max_sge) + + sz = (sizeof(struct ipath_sge) * qp->r_rq.max_sge) + sizeof(struct ipath_rwqe); - qp->r_rq.wq = vmalloc_user(sizeof(struct ipath_rwq) + - qp->r_rq.size * sz); + qp->r_rq.wq = vmalloc(qp->r_rq.size * sz); if (!qp->r_rq.wq) { + kfree(qp); + vfree(swq); ret = ERR_PTR(-ENOMEM); - goto bail_qp; + goto bail; } } @@ -777,19 +719,24 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, qp->s_wq = swq; qp->s_size = init_attr->cap.max_send_wr + 1; qp->s_max_sge = init_attr->cap.max_send_sge; - if (init_attr->sq_sig_type == IB_SIGNAL_REQ_WR) - qp->s_flags = 1 << IPATH_S_SIGNAL_REQ_WR; - else - qp->s_flags = 0; + qp->s_flags = init_attr->sq_sig_type == IB_SIGNAL_REQ_WR ? + 1 << IPATH_S_SIGNAL_REQ_WR : 0; dev = to_idev(ibpd->device); err = ipath_alloc_qpn(&dev->qp_table, qp, init_attr->qp_type); if (err) { + vfree(swq); + vfree(qp->r_rq.wq); + kfree(qp); ret = ERR_PTR(err); - goto bail_rwq; + goto bail; } - qp->ip = NULL; ipath_reset_qp(qp); + + /* Tell the core driver that the kernel SMA is present. */ + if (init_attr->qp_type == IB_QPT_SMI) + ipath_layer_set_verbs_flags(dev->dd, + IPATH_VERBS_KERNEL_SMA); break; default: @@ -800,63 +747,8 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, init_attr->cap.max_inline_data = 0; - /* - * Return the address of the RWQ as the offset to mmap. - * See ipath_mmap() for details. - */ - if (udata && udata->outlen >= sizeof(__u64)) { - struct ipath_mmap_info *ip; - __u64 offset = (__u64) qp->r_rq.wq; - int err; - - err = ib_copy_to_udata(udata, &offset, sizeof(offset)); - if (err) { - ret = ERR_PTR(err); - goto bail_rwq; - } - - if (qp->r_rq.wq) { - /* Allocate info for ipath_mmap(). */ - ip = kmalloc(sizeof(*ip), GFP_KERNEL); - if (!ip) { - ret = ERR_PTR(-ENOMEM); - goto bail_rwq; - } - qp->ip = ip; - ip->context = ibpd->uobject->context; - ip->obj = qp->r_rq.wq; - kref_init(&ip->ref); - ip->mmap_cnt = 0; - ip->size = PAGE_ALIGN(sizeof(struct ipath_rwq) + - qp->r_rq.size * sz); - spin_lock_irq(&dev->pending_lock); - ip->next = dev->pending_mmaps; - dev->pending_mmaps = ip; - spin_unlock_irq(&dev->pending_lock); - } - } - - spin_lock(&dev->n_qps_lock); - if (dev->n_qps_allocated == ib_ipath_max_qps) { - spin_unlock(&dev->n_qps_lock); - ret = ERR_PTR(-ENOMEM); - goto bail_ip; - } - - dev->n_qps_allocated++; - spin_unlock(&dev->n_qps_lock); - ret = &qp->ibqp; - goto bail; -bail_ip: - kfree(qp->ip); -bail_rwq: - vfree(qp->r_rq.wq); -bail_qp: - kfree(qp); -bail_swq: - vfree(swq); bail: return ret; } @@ -876,12 +768,15 @@ int ipath_destroy_qp(struct ib_qp *ibqp) struct ipath_ibdev *dev = to_idev(ibqp->device); unsigned long flags; - spin_lock_irqsave(&qp->s_lock, flags); + /* Tell the core driver that the kernel SMA is gone. */ + if (qp->ibqp.qp_type == IB_QPT_SMI) + ipath_layer_set_verbs_flags(dev->dd, 0); + + spin_lock_irqsave(&qp->r_rq.lock, flags); + spin_lock(&qp->s_lock); qp->state = IB_QPS_ERR; - spin_unlock_irqrestore(&qp->s_lock, flags); - spin_lock(&dev->n_qps_lock); - dev->n_qps_allocated--; - spin_unlock(&dev->n_qps_lock); + spin_unlock(&qp->s_lock); + spin_unlock_irqrestore(&qp->r_rq.lock, flags); /* Stop the sending tasklet. */ tasklet_kill(&qp->s_task); @@ -902,11 +797,8 @@ int ipath_destroy_qp(struct ib_qp *ibqp) if (atomic_read(&qp->refcount) != 0) ipath_free_qp(&dev->qp_table, qp); - if (qp->ip) - kref_put(&qp->ip->ref, ipath_release_mmap_info); - else - vfree(qp->r_rq.wq); vfree(qp->s_wq); + vfree(qp->r_rq.wq); kfree(qp); return 0; } @@ -958,8 +850,8 @@ void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc) struct ipath_ibdev *dev = to_idev(qp->ibqp.device); struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last); - ipath_dbg(KERN_INFO "Send queue error on QP%d/%d: err: %d\n", - qp->ibqp.qp_num, qp->remote_qpn, wc->status); + _VERBS_INFO("Send queue error on QP%d/%d: err: %d\n", + qp->ibqp.qp_num, qp->remote_qpn, wc->status); spin_lock(&dev->pending_lock); /* XXX What if its already removed by the timeout code? */ diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_rc.c b/trunk/drivers/infiniband/hw/ipath/ipath_rc.c index a08654042c03..774d1615ce2f 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_rc.c @@ -32,7 +32,7 @@ */ #include "ipath_verbs.h" -#include "ipath_kernel.h" +#include "ipath_common.h" /* cut down ridiculously long IB macro names */ #define OP(x) IB_OPCODE_RC_##x @@ -540,7 +540,7 @@ static void send_rc_ack(struct ipath_qp *qp) lrh0 = IPATH_LRH_GRH; } /* read pkey_index w/o lock (its atomic) */ - bth0 = ipath_get_pkey(dev->dd, qp->s_pkey_index); + bth0 = ipath_layer_get_pkey(dev->dd, qp->s_pkey_index); if (qp->r_nak_state) ohdr->u.aeth = cpu_to_be32((qp->r_msn & IPATH_MSN_MASK) | (qp->r_nak_state << @@ -557,7 +557,7 @@ static void send_rc_ack(struct ipath_qp *qp) hdr.lrh[0] = cpu_to_be16(lrh0); hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); hdr.lrh[2] = cpu_to_be16(hwords + SIZE_OF_CRC); - hdr.lrh[3] = cpu_to_be16(dev->dd->ipath_lid); + hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd)); ohdr->bth[0] = cpu_to_be32(bth0); ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); ohdr->bth[2] = cpu_to_be32(qp->r_ack_psn & IPATH_PSN_MASK); @@ -1323,7 +1323,8 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, * the eager header buffer size to 56 bytes so the last 4 * bytes of the BTH header (PSN) is in the data buffer. */ - header_in_data = dev->dd->ipath_rcvhdrentsize == 16; + header_in_data = + ipath_layer_get_rcvhdrentsize(dev->dd) == 16; if (header_in_data) { psn = be32_to_cpu(((__be32 *) data)[0]); data += sizeof(__be32); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_registers.h b/trunk/drivers/infiniband/hw/ipath/ipath_registers.h index 6e23b3d632b8..89df8f5ea998 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_registers.h +++ b/trunk/drivers/infiniband/hw/ipath/ipath_registers.h @@ -36,7 +36,8 @@ /* * This file should only be included by kernel source, and by the diags. It - * defines the registers, and their contents, for InfiniPath chips. + * defines the registers, and their contents, for the InfiniPath HT-400 + * chip. */ /* @@ -282,12 +283,10 @@ #define INFINIPATH_XGXS_RESET 0x7ULL #define INFINIPATH_XGXS_MDIOADDR_MASK 0xfULL #define INFINIPATH_XGXS_MDIOADDR_SHIFT 4 -#define INFINIPATH_XGXS_RX_POL_SHIFT 19 -#define INFINIPATH_XGXS_RX_POL_MASK 0xfULL #define INFINIPATH_RT_ADDR_MASK 0xFFFFFFFFFFULL /* 40 bits valid */ -/* TID entries (memory), HT-only */ +/* TID entries (memory), HT400-only */ #define INFINIPATH_RT_VALID 0x8000000000000000ULL #define INFINIPATH_RT_ADDR_SHIFT 0 #define INFINIPATH_RT_BUFSIZE_MASK 0x3FFF diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_ruc.c b/trunk/drivers/infiniband/hw/ipath/ipath_ruc.c index 5c1da2d25e03..772bc59fb85c 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_ruc.c @@ -32,7 +32,7 @@ */ #include "ipath_verbs.h" -#include "ipath_kernel.h" +#include "ipath_common.h" /* * Convert the AETH RNR timeout code into the number of milliseconds. @@ -106,54 +106,6 @@ void ipath_insert_rnr_queue(struct ipath_qp *qp) spin_unlock_irqrestore(&dev->pending_lock, flags); } -static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe) -{ - struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - int user = to_ipd(qp->ibqp.pd)->user; - int i, j, ret; - struct ib_wc wc; - - qp->r_len = 0; - for (i = j = 0; i < wqe->num_sge; i++) { - if (wqe->sg_list[i].length == 0) - continue; - /* Check LKEY */ - if ((user && wqe->sg_list[i].lkey == 0) || - !ipath_lkey_ok(&dev->lk_table, - &qp->r_sg_list[j], &wqe->sg_list[i], - IB_ACCESS_LOCAL_WRITE)) - goto bad_lkey; - qp->r_len += wqe->sg_list[i].length; - j++; - } - qp->r_sge.sge = qp->r_sg_list[0]; - qp->r_sge.sg_list = qp->r_sg_list + 1; - qp->r_sge.num_sge = j; - ret = 1; - goto bail; - -bad_lkey: - wc.wr_id = wqe->wr_id; - wc.status = IB_WC_LOC_PROT_ERR; - wc.opcode = IB_WC_RECV; - wc.vendor_err = 0; - wc.byte_len = 0; - wc.imm_data = 0; - wc.qp_num = qp->ibqp.qp_num; - wc.src_qp = 0; - wc.wc_flags = 0; - wc.pkey_index = 0; - wc.slid = 0; - wc.sl = 0; - wc.dlid_path_bits = 0; - wc.port_num = 0; - /* Signal solicited completion event. */ - ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); - ret = 0; -bail: - return ret; -} - /** * ipath_get_rwqe - copy the next RWQE into the QP's RWQE * @qp: the QP @@ -167,71 +119,71 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) { unsigned long flags; struct ipath_rq *rq; - struct ipath_rwq *wq; struct ipath_srq *srq; struct ipath_rwqe *wqe; - void (*handler)(struct ib_event *, void *); - u32 tail; - int ret; + int ret = 1; - if (qp->ibqp.srq) { - srq = to_isrq(qp->ibqp.srq); - handler = srq->ibsrq.event_handler; - rq = &srq->rq; - } else { - srq = NULL; - handler = NULL; + if (!qp->ibqp.srq) { rq = &qp->r_rq; - } + spin_lock_irqsave(&rq->lock, flags); - spin_lock_irqsave(&rq->lock, flags); - wq = rq->wq; - tail = wq->tail; - /* Validate tail before using it since it is user writable. */ - if (tail >= rq->size) - tail = 0; - do { - if (unlikely(tail == wq->head)) { - spin_unlock_irqrestore(&rq->lock, flags); + if (unlikely(rq->tail == rq->head)) { ret = 0; - goto bail; + goto done; } - wqe = get_rwqe_ptr(rq, tail); - if (++tail >= rq->size) - tail = 0; - } while (!wr_id_only && !init_sge(qp, wqe)); - qp->r_wr_id = wqe->wr_id; - wq->tail = tail; + wqe = get_rwqe_ptr(rq, rq->tail); + qp->r_wr_id = wqe->wr_id; + if (!wr_id_only) { + qp->r_sge.sge = wqe->sg_list[0]; + qp->r_sge.sg_list = wqe->sg_list + 1; + qp->r_sge.num_sge = wqe->num_sge; + qp->r_len = wqe->length; + } + if (++rq->tail >= rq->size) + rq->tail = 0; + goto done; + } + + srq = to_isrq(qp->ibqp.srq); + rq = &srq->rq; + spin_lock_irqsave(&rq->lock, flags); - ret = 1; - if (handler) { + if (unlikely(rq->tail == rq->head)) { + ret = 0; + goto done; + } + wqe = get_rwqe_ptr(rq, rq->tail); + qp->r_wr_id = wqe->wr_id; + if (!wr_id_only) { + qp->r_sge.sge = wqe->sg_list[0]; + qp->r_sge.sg_list = wqe->sg_list + 1; + qp->r_sge.num_sge = wqe->num_sge; + qp->r_len = wqe->length; + } + if (++rq->tail >= rq->size) + rq->tail = 0; + if (srq->ibsrq.event_handler) { + struct ib_event ev; u32 n; - /* - * validate head pointer value and compute - * the number of remaining WQEs. - */ - n = wq->head; - if (n >= rq->size) - n = 0; - if (n < tail) - n += rq->size - tail; + if (rq->head < rq->tail) + n = rq->size + rq->head - rq->tail; else - n -= tail; + n = rq->head - rq->tail; if (n < srq->limit) { - struct ib_event ev; - srq->limit = 0; spin_unlock_irqrestore(&rq->lock, flags); ev.device = qp->ibqp.device; ev.element.srq = qp->ibqp.srq; ev.event = IB_EVENT_SRQ_LIMIT_REACHED; - handler(&ev, srq->ibsrq.srq_context); + srq->ibsrq.event_handler(&ev, + srq->ibsrq.srq_context); goto bail; } } - spin_unlock_irqrestore(&rq->lock, flags); +done: + spin_unlock_irqrestore(&rq->lock, flags); bail: return ret; } @@ -470,15 +422,6 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp) wake_up(&qp->wait); } -static int want_buffer(struct ipath_devdata *dd) -{ - set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl); - ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, - dd->ipath_sendctrl); - - return 0; -} - /** * ipath_no_bufs_available - tell the layer driver we need buffers * @qp: the QP that caused the problem @@ -495,7 +438,7 @@ void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev) list_add_tail(&qp->piowait, &dev->piowait); spin_unlock_irqrestore(&dev->pending_lock, flags); /* - * Note that as soon as want_buffer() is called and + * Note that as soon as ipath_layer_want_buffer() is called and * possibly before it returns, ipath_ib_piobufavail() * could be called. If we are still in the tasklet function, * tasklet_hi_schedule() will not call us until the next time @@ -505,7 +448,7 @@ void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev) */ clear_bit(IPATH_S_BUSY, &qp->s_flags); tasklet_unlock(&qp->s_task); - want_buffer(dev->dd); + ipath_layer_want_buffer(dev->dd); dev->n_piowait++; } @@ -620,7 +563,7 @@ u32 ipath_make_grh(struct ipath_ibdev *dev, struct ib_grh *hdr, hdr->hop_limit = grh->hop_limit; /* The SGID is 32-bit aligned. */ hdr->sgid.global.subnet_prefix = dev->gid_prefix; - hdr->sgid.global.interface_id = dev->dd->ipath_guid; + hdr->sgid.global.interface_id = ipath_layer_get_guid(dev->dd); hdr->dgid = grh->dgid; /* GRH header size in 32-bit words. */ @@ -652,7 +595,8 @@ void ipath_do_ruc_send(unsigned long data) if (test_and_set_bit(IPATH_S_BUSY, &qp->s_flags)) goto bail; - if (unlikely(qp->remote_ah_attr.dlid == dev->dd->ipath_lid)) { + if (unlikely(qp->remote_ah_attr.dlid == + ipath_layer_get_lid(dev->dd))) { ipath_ruc_loopback(qp); goto clear; } @@ -719,8 +663,8 @@ void ipath_do_ruc_send(unsigned long data) qp->s_hdr.lrh[1] = cpu_to_be16(qp->remote_ah_attr.dlid); qp->s_hdr.lrh[2] = cpu_to_be16(qp->s_hdrwords + nwords + SIZE_OF_CRC); - qp->s_hdr.lrh[3] = cpu_to_be16(dev->dd->ipath_lid); - bth0 |= ipath_get_pkey(dev->dd, qp->s_pkey_index); + qp->s_hdr.lrh[3] = cpu_to_be16(ipath_layer_get_lid(dev->dd)); + bth0 |= ipath_layer_get_pkey(dev->dd, qp->s_pkey_index); bth0 |= extra_bytes << 20; ohdr->bth[0] = cpu_to_be32(bth0); ohdr->bth[1] = cpu_to_be32(qp->remote_qpn); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_srq.c b/trunk/drivers/infiniband/hw/ipath/ipath_srq.c index 941e866d9517..f760434660bd 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_srq.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_srq.c @@ -48,39 +48,66 @@ int ipath_post_srq_receive(struct ib_srq *ibsrq, struct ib_recv_wr *wr, struct ib_recv_wr **bad_wr) { struct ipath_srq *srq = to_isrq(ibsrq); - struct ipath_rwq *wq; + struct ipath_ibdev *dev = to_idev(ibsrq->device); unsigned long flags; int ret; for (; wr; wr = wr->next) { struct ipath_rwqe *wqe; u32 next; - int i; + int i, j; - if ((unsigned) wr->num_sge > srq->rq.max_sge) { + if (wr->num_sge > srq->rq.max_sge) { *bad_wr = wr; ret = -ENOMEM; goto bail; } spin_lock_irqsave(&srq->rq.lock, flags); - wq = srq->rq.wq; - next = wq->head + 1; + next = srq->rq.head + 1; if (next >= srq->rq.size) next = 0; - if (next == wq->tail) { + if (next == srq->rq.tail) { spin_unlock_irqrestore(&srq->rq.lock, flags); *bad_wr = wr; ret = -ENOMEM; goto bail; } - wqe = get_rwqe_ptr(&srq->rq, wq->head); + wqe = get_rwqe_ptr(&srq->rq, srq->rq.head); wqe->wr_id = wr->wr_id; - wqe->num_sge = wr->num_sge; - for (i = 0; i < wr->num_sge; i++) - wqe->sg_list[i] = wr->sg_list[i]; - wq->head = next; + wqe->sg_list[0].mr = NULL; + wqe->sg_list[0].vaddr = NULL; + wqe->sg_list[0].length = 0; + wqe->sg_list[0].sge_length = 0; + wqe->length = 0; + for (i = 0, j = 0; i < wr->num_sge; i++) { + /* Check LKEY */ + if (to_ipd(srq->ibsrq.pd)->user && + wr->sg_list[i].lkey == 0) { + spin_unlock_irqrestore(&srq->rq.lock, + flags); + *bad_wr = wr; + ret = -EINVAL; + goto bail; + } + if (wr->sg_list[i].length == 0) + continue; + if (!ipath_lkey_ok(&dev->lk_table, + &wqe->sg_list[j], + &wr->sg_list[i], + IB_ACCESS_LOCAL_WRITE)) { + spin_unlock_irqrestore(&srq->rq.lock, + flags); + *bad_wr = wr; + ret = -EINVAL; + goto bail; + } + wqe->length += wr->sg_list[i].length; + j++; + } + wqe->num_sge = j; + srq->rq.head = next; spin_unlock_irqrestore(&srq->rq.lock, flags); } ret = 0; @@ -106,95 +133,53 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd, if (dev->n_srqs_allocated == ib_ipath_max_srqs) { ret = ERR_PTR(-ENOMEM); - goto done; + goto bail; } if (srq_init_attr->attr.max_wr == 0) { ret = ERR_PTR(-EINVAL); - goto done; + goto bail; } if ((srq_init_attr->attr.max_sge > ib_ipath_max_srq_sges) || (srq_init_attr->attr.max_wr > ib_ipath_max_srq_wrs)) { ret = ERR_PTR(-EINVAL); - goto done; + goto bail; } srq = kmalloc(sizeof(*srq), GFP_KERNEL); if (!srq) { ret = ERR_PTR(-ENOMEM); - goto done; + goto bail; } /* * Need to use vmalloc() if we want to support large #s of entries. */ srq->rq.size = srq_init_attr->attr.max_wr + 1; - srq->rq.max_sge = srq_init_attr->attr.max_sge; - sz = sizeof(struct ib_sge) * srq->rq.max_sge + + sz = sizeof(struct ipath_sge) * srq_init_attr->attr.max_sge + sizeof(struct ipath_rwqe); - srq->rq.wq = vmalloc_user(sizeof(struct ipath_rwq) + srq->rq.size * sz); + srq->rq.wq = vmalloc(srq->rq.size * sz); if (!srq->rq.wq) { + kfree(srq); ret = ERR_PTR(-ENOMEM); - goto bail_srq; + goto bail; } - /* - * Return the address of the RWQ as the offset to mmap. - * See ipath_mmap() for details. - */ - if (udata && udata->outlen >= sizeof(__u64)) { - struct ipath_mmap_info *ip; - __u64 offset = (__u64) srq->rq.wq; - int err; - - err = ib_copy_to_udata(udata, &offset, sizeof(offset)); - if (err) { - ret = ERR_PTR(err); - goto bail_wq; - } - - /* Allocate info for ipath_mmap(). */ - ip = kmalloc(sizeof(*ip), GFP_KERNEL); - if (!ip) { - ret = ERR_PTR(-ENOMEM); - goto bail_wq; - } - srq->ip = ip; - ip->context = ibpd->uobject->context; - ip->obj = srq->rq.wq; - kref_init(&ip->ref); - ip->mmap_cnt = 0; - ip->size = PAGE_ALIGN(sizeof(struct ipath_rwq) + - srq->rq.size * sz); - spin_lock_irq(&dev->pending_lock); - ip->next = dev->pending_mmaps; - dev->pending_mmaps = ip; - spin_unlock_irq(&dev->pending_lock); - } else - srq->ip = NULL; - /* * ib_create_srq() will initialize srq->ibsrq. */ spin_lock_init(&srq->rq.lock); - srq->rq.wq->head = 0; - srq->rq.wq->tail = 0; + srq->rq.head = 0; + srq->rq.tail = 0; srq->rq.max_sge = srq_init_attr->attr.max_sge; srq->limit = srq_init_attr->attr.srq_limit; - dev->n_srqs_allocated++; - ret = &srq->ibsrq; - goto done; -bail_wq: - vfree(srq->rq.wq); - -bail_srq: - kfree(srq); + dev->n_srqs_allocated++; -done: +bail: return ret; } @@ -203,131 +188,84 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd, * @ibsrq: the SRQ to modify * @attr: the new attributes of the SRQ * @attr_mask: indicates which attributes to modify - * @udata: user data for ipathverbs.so */ int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, - enum ib_srq_attr_mask attr_mask, - struct ib_udata *udata) + enum ib_srq_attr_mask attr_mask) { struct ipath_srq *srq = to_isrq(ibsrq); - int ret = 0; - - if (attr_mask & IB_SRQ_MAX_WR) { - struct ipath_rwq *owq; - struct ipath_rwq *wq; - struct ipath_rwqe *p; - u32 sz, size, n, head, tail; + unsigned long flags; + int ret; - /* Check that the requested sizes are below the limits. */ + if (attr_mask & IB_SRQ_MAX_WR) if ((attr->max_wr > ib_ipath_max_srq_wrs) || - ((attr_mask & IB_SRQ_LIMIT) ? - attr->srq_limit : srq->limit) > attr->max_wr) { + (attr->max_sge > srq->rq.max_sge)) { ret = -EINVAL; goto bail; } + if (attr_mask & IB_SRQ_LIMIT) + if (attr->srq_limit >= srq->rq.size) { + ret = -EINVAL; + goto bail; + } + + if (attr_mask & IB_SRQ_MAX_WR) { + struct ipath_rwqe *wq, *p; + u32 sz, size, n; + sz = sizeof(struct ipath_rwqe) + - srq->rq.max_sge * sizeof(struct ib_sge); + attr->max_sge * sizeof(struct ipath_sge); size = attr->max_wr + 1; - wq = vmalloc_user(sizeof(struct ipath_rwq) + size * sz); + wq = vmalloc(size * sz); if (!wq) { ret = -ENOMEM; goto bail; } - /* - * Return the address of the RWQ as the offset to mmap. - * See ipath_mmap() for details. - */ - if (udata && udata->inlen >= sizeof(__u64)) { - __u64 offset_addr; - __u64 offset = (__u64) wq; - - ret = ib_copy_from_udata(&offset_addr, udata, - sizeof(offset_addr)); - if (ret) { - vfree(wq); - goto bail; - } - udata->outbuf = (void __user *) offset_addr; - ret = ib_copy_to_udata(udata, &offset, - sizeof(offset)); - if (ret) { - vfree(wq); - goto bail; - } - } - - spin_lock_irq(&srq->rq.lock); - /* - * validate head pointer value and compute - * the number of remaining WQEs. - */ - owq = srq->rq.wq; - head = owq->head; - if (head >= srq->rq.size) - head = 0; - tail = owq->tail; - if (tail >= srq->rq.size) - tail = 0; - n = head; - if (n < tail) - n += srq->rq.size - tail; + spin_lock_irqsave(&srq->rq.lock, flags); + if (srq->rq.head < srq->rq.tail) + n = srq->rq.size + srq->rq.head - srq->rq.tail; else - n -= tail; - if (size <= n) { - spin_unlock_irq(&srq->rq.lock); + n = srq->rq.head - srq->rq.tail; + if (size <= n || size <= srq->limit) { + spin_unlock_irqrestore(&srq->rq.lock, flags); vfree(wq); ret = -EINVAL; goto bail; } n = 0; - p = wq->wq; - while (tail != head) { + p = wq; + while (srq->rq.tail != srq->rq.head) { struct ipath_rwqe *wqe; int i; - wqe = get_rwqe_ptr(&srq->rq, tail); + wqe = get_rwqe_ptr(&srq->rq, srq->rq.tail); p->wr_id = wqe->wr_id; + p->length = wqe->length; p->num_sge = wqe->num_sge; for (i = 0; i < wqe->num_sge; i++) p->sg_list[i] = wqe->sg_list[i]; n++; p = (struct ipath_rwqe *)((char *) p + sz); - if (++tail >= srq->rq.size) - tail = 0; + if (++srq->rq.tail >= srq->rq.size) + srq->rq.tail = 0; } + vfree(srq->rq.wq); srq->rq.wq = wq; srq->rq.size = size; - wq->head = n; - wq->tail = 0; - if (attr_mask & IB_SRQ_LIMIT) - srq->limit = attr->srq_limit; - spin_unlock_irq(&srq->rq.lock); - - vfree(owq); - - if (srq->ip) { - struct ipath_mmap_info *ip = srq->ip; - struct ipath_ibdev *dev = to_idev(srq->ibsrq.device); - - ip->obj = wq; - ip->size = PAGE_ALIGN(sizeof(struct ipath_rwq) + - size * sz); - spin_lock_irq(&dev->pending_lock); - ip->next = dev->pending_mmaps; - dev->pending_mmaps = ip; - spin_unlock_irq(&dev->pending_lock); - } - } else if (attr_mask & IB_SRQ_LIMIT) { - spin_lock_irq(&srq->rq.lock); - if (attr->srq_limit >= srq->rq.size) - ret = -EINVAL; - else - srq->limit = attr->srq_limit; - spin_unlock_irq(&srq->rq.lock); + srq->rq.head = n; + srq->rq.tail = 0; + srq->rq.max_sge = attr->max_sge; + spin_unlock_irqrestore(&srq->rq.lock, flags); } + if (attr_mask & IB_SRQ_LIMIT) { + spin_lock_irqsave(&srq->rq.lock, flags); + srq->limit = attr->srq_limit; + spin_unlock_irqrestore(&srq->rq.lock, flags); + } + ret = 0; + bail: return ret; } diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_stats.c b/trunk/drivers/infiniband/hw/ipath/ipath_stats.c index 30a825928fcf..70351b7e35c0 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_stats.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_stats.c @@ -271,6 +271,33 @@ void ipath_get_faststats(unsigned long opaque) } } + if (dd->ipath_nosma_bufs) { + dd->ipath_nosma_secs += 5; + if (dd->ipath_nosma_secs >= 30) { + ipath_cdbg(SMA, "No SMA bufs avail %u seconds; " + "cancelling pending sends\n", + dd->ipath_nosma_secs); + /* + * issue an abort as well, in case we have a packet + * stuck in launch fifo. This could corrupt an + * outgoing user packet in the worst case, + * but this is a pretty catastrophic, anyway. + */ + ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, + INFINIPATH_S_ABORT); + ipath_disarm_piobufs(dd, dd->ipath_lastport_piobuf, + dd->ipath_piobcnt2k + + dd->ipath_piobcnt4k - + dd->ipath_lastport_piobuf); + /* start again, if necessary */ + dd->ipath_nosma_secs = 0; + } else + ipath_cdbg(SMA, "No SMA bufs avail %u tries, " + "after %u seconds\n", + dd->ipath_nosma_bufs, + dd->ipath_nosma_secs); + } + done: mod_timer(&dd->ipath_stats_timer, jiffies + HZ * 5); } diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_sysfs.c b/trunk/drivers/infiniband/hw/ipath/ipath_sysfs.c index e299148c4b68..b98821d7801d 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_sysfs.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_sysfs.c @@ -35,6 +35,7 @@ #include #include "ipath_kernel.h" +#include "ipath_layer.h" #include "ipath_common.h" /** @@ -75,7 +76,7 @@ int ipath_parse_ushort(const char *str, unsigned short *valp) static ssize_t show_version(struct device_driver *dev, char *buf) { /* The string printed here is already newline-terminated. */ - return scnprintf(buf, PAGE_SIZE, "%s", ib_ipath_version); + return scnprintf(buf, PAGE_SIZE, "%s", ipath_core_version); } static ssize_t show_num_units(struct device_driver *dev, char *buf) @@ -107,8 +108,8 @@ static const char *ipath_status_str[] = { "Initted", "Disabled", "Admin_Disabled", - "", /* This used to be the old "OIB_SMA" status. */ - "", /* This used to be the old "SMA" status. */ + "OIB_SMA", + "SMA", "Present", "IB_link_up", "IB_configured", @@ -226,6 +227,7 @@ static ssize_t store_mlid(struct device *dev, unit = dd->ipath_unit; dd->ipath_mlid = mlid; + ipath_layer_intr(dd, IPATH_LAYER_INT_BCAST); goto bail; invalid: @@ -465,7 +467,7 @@ static ssize_t store_link_state(struct device *dev, if (ret < 0) goto invalid; - r = ipath_set_linkstate(dd, state); + r = ipath_layer_set_linkstate(dd, state); if (r < 0) { ret = r; goto bail; @@ -500,7 +502,7 @@ static ssize_t store_mtu(struct device *dev, if (ret < 0) goto invalid; - r = ipath_set_mtu(dd, mtu); + r = ipath_layer_set_mtu(dd, mtu); if (r < 0) ret = r; @@ -561,33 +563,6 @@ static ssize_t store_enabled(struct device *dev, return ret; } -static ssize_t store_rx_pol_inv(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct ipath_devdata *dd = dev_get_drvdata(dev); - int ret, r; - u16 val; - - ret = ipath_parse_ushort(buf, &val); - if (ret < 0) - goto invalid; - - r = ipath_set_rx_pol_inv(dd, val); - if (r < 0) { - ret = r; - goto bail; - } - - goto bail; -invalid: - ipath_dev_err(dd, "attempt to set invalid Rx Polarity invert\n"); -bail: - return ret; -} - - static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL); static DRIVER_ATTR(version, S_IRUGO, show_version, NULL); @@ -614,7 +589,6 @@ static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); static DEVICE_ATTR(status_str, S_IRUGO, show_status_str, NULL); static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL); static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL); -static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv); static struct attribute *dev_attributes[] = { &dev_attr_guid.attr, @@ -629,7 +603,6 @@ static struct attribute *dev_attributes[] = { &dev_attr_boardversion.attr, &dev_attr_unit.attr, &dev_attr_enabled.attr, - &dev_attr_rx_pol_inv.attr, NULL }; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_uc.c b/trunk/drivers/infiniband/hw/ipath/ipath_uc.c index 0fd3cded16ba..c33abea2d5a7 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_uc.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_uc.c @@ -32,7 +32,7 @@ */ #include "ipath_verbs.h" -#include "ipath_kernel.h" +#include "ipath_common.h" /* cut down ridiculously long IB macro names */ #define OP(x) IB_OPCODE_UC_##x @@ -261,7 +261,8 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, * size to 56 bytes so the last 4 bytes of * the BTH header (PSN) is in the data buffer. */ - header_in_data = dev->dd->ipath_rcvhdrentsize == 16; + header_in_data = + ipath_layer_get_rcvhdrentsize(dev->dd) == 16; if (header_in_data) { psn = be32_to_cpu(((__be32 *) data)[0]); data += sizeof(__be32); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_ud.c b/trunk/drivers/infiniband/hw/ipath/ipath_ud.c index 6991d1d74e3c..3466129af804 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_ud.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_ud.c @@ -34,54 +34,7 @@ #include #include "ipath_verbs.h" -#include "ipath_kernel.h" - -static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe, - u32 *lengthp, struct ipath_sge_state *ss) -{ - struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - int user = to_ipd(qp->ibqp.pd)->user; - int i, j, ret; - struct ib_wc wc; - - *lengthp = 0; - for (i = j = 0; i < wqe->num_sge; i++) { - if (wqe->sg_list[i].length == 0) - continue; - /* Check LKEY */ - if ((user && wqe->sg_list[i].lkey == 0) || - !ipath_lkey_ok(&dev->lk_table, - j ? &ss->sg_list[j - 1] : &ss->sge, - &wqe->sg_list[i], IB_ACCESS_LOCAL_WRITE)) - goto bad_lkey; - *lengthp += wqe->sg_list[i].length; - j++; - } - ss->num_sge = j; - ret = 1; - goto bail; - -bad_lkey: - wc.wr_id = wqe->wr_id; - wc.status = IB_WC_LOC_PROT_ERR; - wc.opcode = IB_WC_RECV; - wc.vendor_err = 0; - wc.byte_len = 0; - wc.imm_data = 0; - wc.qp_num = qp->ibqp.qp_num; - wc.src_qp = 0; - wc.wc_flags = 0; - wc.pkey_index = 0; - wc.slid = 0; - wc.sl = 0; - wc.dlid_path_bits = 0; - wc.port_num = 0; - /* Signal solicited completion event. */ - ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); - ret = 0; -bail: - return ret; -} +#include "ipath_common.h" /** * ipath_ud_loopback - handle send on loopback QPs @@ -93,8 +46,6 @@ static int init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe, * * This is called from ipath_post_ud_send() to forward a WQE addressed * to the same HCA. - * Note that the receive interrupt handler may be calling ipath_ud_rcv() - * while this is being called. */ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_sge_state *ss, @@ -109,11 +60,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_srq *srq; struct ipath_sge_state rsge; struct ipath_sge *sge; - struct ipath_rwq *wq; struct ipath_rwqe *wqe; - void (*handler)(struct ib_event *, void *); - u32 tail; - u32 rlen; qp = ipath_lookup_qpn(&dev->qp_table, wr->wr.ud.remote_qpn); if (!qp) @@ -147,13 +94,6 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, wc->imm_data = 0; } - if (wr->num_sge > 1) { - rsge.sg_list = kmalloc((wr->num_sge - 1) * - sizeof(struct ipath_sge), - GFP_ATOMIC); - } else - rsge.sg_list = NULL; - /* * Get the next work request entry to find where to put the data. * Note that it is safe to drop the lock after changing rq->tail @@ -161,52 +101,37 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, */ if (qp->ibqp.srq) { srq = to_isrq(qp->ibqp.srq); - handler = srq->ibsrq.event_handler; rq = &srq->rq; } else { srq = NULL; - handler = NULL; rq = &qp->r_rq; } - spin_lock_irqsave(&rq->lock, flags); - wq = rq->wq; - tail = wq->tail; - while (1) { - if (unlikely(tail == wq->head)) { - spin_unlock_irqrestore(&rq->lock, flags); - dev->n_pkt_drops++; - goto bail_sge; - } - wqe = get_rwqe_ptr(rq, tail); - if (++tail >= rq->size) - tail = 0; - if (init_sge(qp, wqe, &rlen, &rsge)) - break; - wq->tail = tail; + if (rq->tail == rq->head) { + spin_unlock_irqrestore(&rq->lock, flags); + dev->n_pkt_drops++; + goto done; } /* Silently drop packets which are too big. */ - if (wc->byte_len > rlen) { + wqe = get_rwqe_ptr(rq, rq->tail); + if (wc->byte_len > wqe->length) { spin_unlock_irqrestore(&rq->lock, flags); dev->n_pkt_drops++; - goto bail_sge; + goto done; } - wq->tail = tail; wc->wr_id = wqe->wr_id; - if (handler) { + rsge.sge = wqe->sg_list[0]; + rsge.sg_list = wqe->sg_list + 1; + rsge.num_sge = wqe->num_sge; + if (++rq->tail >= rq->size) + rq->tail = 0; + if (srq && srq->ibsrq.event_handler) { u32 n; - /* - * validate head pointer value and compute - * the number of remaining WQEs. - */ - n = wq->head; - if (n >= rq->size) - n = 0; - if (n < tail) - n += rq->size - tail; + if (rq->head < rq->tail) + n = rq->size + rq->head - rq->tail; else - n -= tail; + n = rq->head - rq->tail; if (n < srq->limit) { struct ib_event ev; @@ -215,12 +140,12 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, ev.device = qp->ibqp.device; ev.element.srq = qp->ibqp.srq; ev.event = IB_EVENT_SRQ_LIMIT_REACHED; - handler(&ev, srq->ibsrq.srq_context); + srq->ibsrq.event_handler(&ev, + srq->ibsrq.srq_context); } else spin_unlock_irqrestore(&rq->lock, flags); } else spin_unlock_irqrestore(&rq->lock, flags); - ah_attr = &to_iah(wr->wr.ud.ah)->attr; if (ah_attr->ah_flags & IB_AH_GRH) { ipath_copy_sge(&rsge, &ah_attr->grh, sizeof(struct ib_grh)); @@ -261,7 +186,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, wc->src_qp = sqp->ibqp.qp_num; /* XXX do we know which pkey matched? Only needed for GSI. */ wc->pkey_index = 0; - wc->slid = dev->dd->ipath_lid | + wc->slid = ipath_layer_get_lid(dev->dd) | (ah_attr->src_path_bits & ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1)); wc->sl = ah_attr->sl; @@ -271,8 +196,6 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, ipath_cq_enter(to_icq(qp->ibqp.recv_cq), wc, wr->send_flags & IB_SEND_SOLICITED); -bail_sge: - kfree(rsge.sg_list); done: if (atomic_dec_and_test(&qp->refcount)) wake_up(&qp->wait); @@ -353,7 +276,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) ss.num_sge++; } /* Check for invalid packet size. */ - if (len > dev->dd->ipath_ibmtu) { + if (len > ipath_layer_get_ibmtu(dev->dd)) { ret = -EINVAL; goto bail; } @@ -375,7 +298,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) dev->n_unicast_xmit++; lid = ah_attr->dlid & ~((1 << (dev->mkeyprot_resv_lmc & 7)) - 1); - if (unlikely(lid == dev->dd->ipath_lid)) { + if (unlikely(lid == ipath_layer_get_lid(dev->dd))) { /* * Pass in an uninitialized ib_wc to save stack * space. @@ -404,7 +327,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) qp->s_hdr.u.l.grh.sgid.global.subnet_prefix = dev->gid_prefix; qp->s_hdr.u.l.grh.sgid.global.interface_id = - dev->dd->ipath_guid; + ipath_layer_get_guid(dev->dd); qp->s_hdr.u.l.grh.dgid = ah_attr->grh.dgid; /* * Don't worry about sending to locally attached multicast @@ -434,7 +357,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) qp->s_hdr.lrh[0] = cpu_to_be16(lrh0); qp->s_hdr.lrh[1] = cpu_to_be16(ah_attr->dlid); /* DEST LID */ qp->s_hdr.lrh[2] = cpu_to_be16(hwords + nwords + SIZE_OF_CRC); - lid = dev->dd->ipath_lid; + lid = ipath_layer_get_lid(dev->dd); if (lid) { lid |= ah_attr->src_path_bits & ((1 << (dev->mkeyprot_resv_lmc & 7)) - 1); @@ -445,7 +368,7 @@ int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr) bth0 |= 1 << 23; bth0 |= extra_bytes << 20; bth0 |= qp->ibqp.qp_type == IB_QPT_SMI ? IPATH_DEFAULT_P_KEY : - ipath_get_pkey(dev->dd, qp->s_pkey_index); + ipath_layer_get_pkey(dev->dd, qp->s_pkey_index); ohdr->bth[0] = cpu_to_be32(bth0); /* * Use the multicast QP if the destination LID is a multicast LID. @@ -510,9 +433,13 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, int opcode; u32 hdrsize; u32 pad; + unsigned long flags; struct ib_wc wc; u32 qkey; u32 src_qp; + struct ipath_rq *rq; + struct ipath_srq *srq; + struct ipath_rwqe *wqe; u16 dlid; int header_in_data; @@ -531,7 +458,8 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, * the eager header buffer size to 56 bytes so the last 12 * bytes of the IB header is in the data buffer. */ - header_in_data = dev->dd->ipath_rcvhdrentsize == 16; + header_in_data = + ipath_layer_get_rcvhdrentsize(dev->dd) == 16; if (header_in_data) { qkey = be32_to_cpu(((__be32 *) data)[1]); src_qp = be32_to_cpu(((__be32 *) data)[2]); @@ -619,10 +547,19 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, /* * Get the next work request entry to find where to put the data. + * Note that it is safe to drop the lock after changing rq->tail + * since ipath_post_receive() won't fill the empty slot. */ - if (qp->r_reuse_sge) - qp->r_reuse_sge = 0; - else if (!ipath_get_rwqe(qp, 0)) { + if (qp->ibqp.srq) { + srq = to_isrq(qp->ibqp.srq); + rq = &srq->rq; + } else { + srq = NULL; + rq = &qp->r_rq; + } + spin_lock_irqsave(&rq->lock, flags); + if (rq->tail == rq->head) { + spin_unlock_irqrestore(&rq->lock, flags); /* * Count VL15 packets dropped due to no receive buffer. * Otherwise, count them as buffer overruns since usually, @@ -636,11 +573,39 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, goto bail; } /* Silently drop packets which are too big. */ - if (wc.byte_len > qp->r_len) { - qp->r_reuse_sge = 1; + wqe = get_rwqe_ptr(rq, rq->tail); + if (wc.byte_len > wqe->length) { + spin_unlock_irqrestore(&rq->lock, flags); dev->n_pkt_drops++; goto bail; } + wc.wr_id = wqe->wr_id; + qp->r_sge.sge = wqe->sg_list[0]; + qp->r_sge.sg_list = wqe->sg_list + 1; + qp->r_sge.num_sge = wqe->num_sge; + if (++rq->tail >= rq->size) + rq->tail = 0; + if (srq && srq->ibsrq.event_handler) { + u32 n; + + if (rq->head < rq->tail) + n = rq->size + rq->head - rq->tail; + else + n = rq->head - rq->tail; + if (n < srq->limit) { + struct ib_event ev; + + srq->limit = 0; + spin_unlock_irqrestore(&rq->lock, flags); + ev.device = qp->ibqp.device; + ev.element.srq = qp->ibqp.srq; + ev.event = IB_EVENT_SRQ_LIMIT_REACHED; + srq->ibsrq.event_handler(&ev, + srq->ibsrq.srq_context); + } else + spin_unlock_irqrestore(&rq->lock, flags); + } else + spin_unlock_irqrestore(&rq->lock, flags); if (has_grh) { ipath_copy_sge(&qp->r_sge, &hdr->u.l.grh, sizeof(struct ib_grh)); @@ -649,7 +614,6 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, ipath_skip_sge(&qp->r_sge, sizeof(struct ib_grh)); ipath_copy_sge(&qp->r_sge, data, wc.byte_len - sizeof(struct ib_grh)); - wc.wr_id = qp->r_wr_id; wc.status = IB_WC_SUCCESS; wc.opcode = IB_WC_RECV; wc.vendor_err = 0; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c index b8381c5e72bd..d70a9b6b5239 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.c @@ -33,13 +33,15 @@ #include #include -#include #include #include "ipath_kernel.h" #include "ipath_verbs.h" #include "ipath_common.h" +/* Not static, because we don't want the compiler removing it */ +const char ipath_verbs_version[] = "ipath_verbs " IPATH_IDSTR; + static unsigned int ib_ipath_qp_table_size = 251; module_param_named(qp_table_size, ib_ipath_qp_table_size, uint, S_IRUGO); MODULE_PARM_DESC(qp_table_size, "QP table size"); @@ -50,6 +52,10 @@ module_param_named(lkey_table_size, ib_ipath_lkey_table_size, uint, MODULE_PARM_DESC(lkey_table_size, "LKEY table size in bits (2^n, 1 <= n <= 23)"); +unsigned int ib_ipath_debug; /* debug mask */ +module_param_named(debug, ib_ipath_debug, uint, S_IWUSR | S_IRUGO); +MODULE_PARM_DESC(debug, "Verbs debug mask"); + static unsigned int ib_ipath_max_pds = 0xFFFF; module_param_named(max_pds, ib_ipath_max_pds, uint, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(max_pds, @@ -73,10 +79,6 @@ module_param_named(max_qp_wrs, ib_ipath_max_qp_wrs, uint, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(max_qp_wrs, "Maximum number of QP WRs to support"); -unsigned int ib_ipath_max_qps = 16384; -module_param_named(max_qps, ib_ipath_max_qps, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(max_qps, "Maximum number of QPs to support"); - unsigned int ib_ipath_max_sges = 0x60; module_param_named(max_sges, ib_ipath_max_sges, uint, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(max_sges, "Maximum number of SGEs to support"); @@ -107,9 +109,9 @@ module_param_named(max_srq_wrs, ib_ipath_max_srq_wrs, uint, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(max_srq_wrs, "Maximum number of SRQ WRs support"); -static unsigned int ib_ipath_disable_sma; -module_param_named(disable_sma, ib_ipath_disable_sma, uint, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(ib_ipath_disable_sma, "Disable the SMA"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("QLogic "); +MODULE_DESCRIPTION("QLogic InfiniPath driver"); const int ib_ipath_state_ops[IB_QPS_ERR + 1] = { [IB_QPS_RESET] = 0, @@ -123,16 +125,6 @@ const int ib_ipath_state_ops[IB_QPS_ERR + 1] = { [IB_QPS_ERR] = 0, }; -struct ipath_ucontext { - struct ib_ucontext ibucontext; -}; - -static inline struct ipath_ucontext *to_iucontext(struct ib_ucontext - *ibucontext) -{ - return container_of(ibucontext, struct ipath_ucontext, ibucontext); -} - /* * Translate ib_wr_opcode into ib_wc_opcode. */ @@ -285,12 +277,11 @@ static int ipath_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, struct ib_recv_wr **bad_wr) { struct ipath_qp *qp = to_iqp(ibqp); - struct ipath_rwq *wq = qp->r_rq.wq; unsigned long flags; int ret; /* Check that state is OK to post receive. */ - if (!(ib_ipath_state_ops[qp->state] & IPATH_POST_RECV_OK) || !wq) { + if (!(ib_ipath_state_ops[qp->state] & IPATH_POST_RECV_OK)) { *bad_wr = wr; ret = -EINVAL; goto bail; @@ -299,31 +290,59 @@ static int ipath_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, for (; wr; wr = wr->next) { struct ipath_rwqe *wqe; u32 next; - int i; + int i, j; - if ((unsigned) wr->num_sge > qp->r_rq.max_sge) { + if (wr->num_sge > qp->r_rq.max_sge) { *bad_wr = wr; ret = -ENOMEM; goto bail; } spin_lock_irqsave(&qp->r_rq.lock, flags); - next = wq->head + 1; + next = qp->r_rq.head + 1; if (next >= qp->r_rq.size) next = 0; - if (next == wq->tail) { + if (next == qp->r_rq.tail) { spin_unlock_irqrestore(&qp->r_rq.lock, flags); *bad_wr = wr; ret = -ENOMEM; goto bail; } - wqe = get_rwqe_ptr(&qp->r_rq, wq->head); + wqe = get_rwqe_ptr(&qp->r_rq, qp->r_rq.head); wqe->wr_id = wr->wr_id; - wqe->num_sge = wr->num_sge; - for (i = 0; i < wr->num_sge; i++) - wqe->sg_list[i] = wr->sg_list[i]; - wq->head = next; + wqe->sg_list[0].mr = NULL; + wqe->sg_list[0].vaddr = NULL; + wqe->sg_list[0].length = 0; + wqe->sg_list[0].sge_length = 0; + wqe->length = 0; + for (i = 0, j = 0; i < wr->num_sge; i++) { + /* Check LKEY */ + if (to_ipd(qp->ibqp.pd)->user && + wr->sg_list[i].lkey == 0) { + spin_unlock_irqrestore(&qp->r_rq.lock, + flags); + *bad_wr = wr; + ret = -EINVAL; + goto bail; + } + if (wr->sg_list[i].length == 0) + continue; + if (!ipath_lkey_ok( + &to_idev(qp->ibqp.device)->lk_table, + &wqe->sg_list[j], &wr->sg_list[i], + IB_ACCESS_LOCAL_WRITE)) { + spin_unlock_irqrestore(&qp->r_rq.lock, + flags); + *bad_wr = wr; + ret = -EINVAL; + goto bail; + } + wqe->length += wr->sg_list[i].length; + j++; + } + wqe->num_sge = j; + qp->r_rq.head = next; spin_unlock_irqrestore(&qp->r_rq.lock, flags); } ret = 0; @@ -358,9 +377,6 @@ static void ipath_qp_rcv(struct ipath_ibdev *dev, switch (qp->ibqp.qp_type) { case IB_QPT_SMI: case IB_QPT_GSI: - if (ib_ipath_disable_sma) - break; - /* FALLTHROUGH */ case IB_QPT_UD: ipath_ud_rcv(dev, hdr, has_grh, data, tlen, qp); break; @@ -379,7 +395,7 @@ static void ipath_qp_rcv(struct ipath_ibdev *dev, } /** - * ipath_ib_rcv - process an incoming packet + * ipath_ib_rcv - process and incoming packet * @arg: the device pointer * @rhdr: the header of the packet * @data: the packet data @@ -388,9 +404,9 @@ static void ipath_qp_rcv(struct ipath_ibdev *dev, * This is called from ipath_kreceive() to process an incoming packet at * interrupt level. Tlen is the length of the header + data + CRC in bytes. */ -void ipath_ib_rcv(struct ipath_ibdev *dev, void *rhdr, void *data, - u32 tlen) +static void ipath_ib_rcv(void *arg, void *rhdr, void *data, u32 tlen) { + struct ipath_ibdev *dev = (struct ipath_ibdev *) arg; struct ipath_ib_header *hdr = rhdr; struct ipath_other_headers *ohdr; struct ipath_qp *qp; @@ -411,7 +427,7 @@ void ipath_ib_rcv(struct ipath_ibdev *dev, void *rhdr, void *data, lid = be16_to_cpu(hdr->lrh[1]); if (lid < IPATH_MULTICAST_LID_BASE) { lid &= ~((1 << (dev->mkeyprot_resv_lmc & 7)) - 1); - if (unlikely(lid != dev->dd->ipath_lid)) { + if (unlikely(lid != ipath_layer_get_lid(dev->dd))) { dev->rcv_errors++; goto bail; } @@ -479,8 +495,9 @@ bail:; * This is called from ipath_do_rcv_timer() at interrupt level to check for * QPs which need retransmits and to collect performance numbers. */ -void ipath_ib_timer(struct ipath_ibdev *dev) +static void ipath_ib_timer(void *arg) { + struct ipath_ibdev *dev = (struct ipath_ibdev *) arg; struct ipath_qp *resend = NULL; struct list_head *last; struct ipath_qp *qp; @@ -522,19 +539,19 @@ void ipath_ib_timer(struct ipath_ibdev *dev) if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_STARTED && --dev->pma_sample_start == 0) { dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_RUNNING; - ipath_snapshot_counters(dev->dd, &dev->ipath_sword, - &dev->ipath_rword, - &dev->ipath_spkts, - &dev->ipath_rpkts, - &dev->ipath_xmit_wait); + ipath_layer_snapshot_counters(dev->dd, &dev->ipath_sword, + &dev->ipath_rword, + &dev->ipath_spkts, + &dev->ipath_rpkts, + &dev->ipath_xmit_wait); } if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_RUNNING) { if (dev->pma_sample_interval == 0) { u64 ta, tb, tc, td, te; dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_DONE; - ipath_snapshot_counters(dev->dd, &ta, &tb, - &tc, &td, &te); + ipath_layer_snapshot_counters(dev->dd, &ta, &tb, + &tc, &td, &te); dev->ipath_sword = ta - dev->ipath_sword; dev->ipath_rword = tb - dev->ipath_rword; @@ -564,362 +581,6 @@ void ipath_ib_timer(struct ipath_ibdev *dev) } } -static void update_sge(struct ipath_sge_state *ss, u32 length) -{ - struct ipath_sge *sge = &ss->sge; - - sge->vaddr += length; - sge->length -= length; - sge->sge_length -= length; - if (sge->sge_length == 0) { - if (--ss->num_sge) - *sge = *ss->sg_list++; - } else if (sge->length == 0 && sge->mr != NULL) { - if (++sge->n >= IPATH_SEGSZ) { - if (++sge->m >= sge->mr->mapsz) - return; - sge->n = 0; - } - sge->vaddr = sge->mr->map[sge->m]->segs[sge->n].vaddr; - sge->length = sge->mr->map[sge->m]->segs[sge->n].length; - } -} - -#ifdef __LITTLE_ENDIAN -static inline u32 get_upper_bits(u32 data, u32 shift) -{ - return data >> shift; -} - -static inline u32 set_upper_bits(u32 data, u32 shift) -{ - return data << shift; -} - -static inline u32 clear_upper_bytes(u32 data, u32 n, u32 off) -{ - data <<= ((sizeof(u32) - n) * BITS_PER_BYTE); - data >>= ((sizeof(u32) - n - off) * BITS_PER_BYTE); - return data; -} -#else -static inline u32 get_upper_bits(u32 data, u32 shift) -{ - return data << shift; -} - -static inline u32 set_upper_bits(u32 data, u32 shift) -{ - return data >> shift; -} - -static inline u32 clear_upper_bytes(u32 data, u32 n, u32 off) -{ - data >>= ((sizeof(u32) - n) * BITS_PER_BYTE); - data <<= ((sizeof(u32) - n - off) * BITS_PER_BYTE); - return data; -} -#endif - -static void copy_io(u32 __iomem *piobuf, struct ipath_sge_state *ss, - u32 length) -{ - u32 extra = 0; - u32 data = 0; - u32 last; - - while (1) { - u32 len = ss->sge.length; - u32 off; - - BUG_ON(len == 0); - if (len > length) - len = length; - if (len > ss->sge.sge_length) - len = ss->sge.sge_length; - /* If the source address is not aligned, try to align it. */ - off = (unsigned long)ss->sge.vaddr & (sizeof(u32) - 1); - if (off) { - u32 *addr = (u32 *)((unsigned long)ss->sge.vaddr & - ~(sizeof(u32) - 1)); - u32 v = get_upper_bits(*addr, off * BITS_PER_BYTE); - u32 y; - - y = sizeof(u32) - off; - if (len > y) - len = y; - if (len + extra >= sizeof(u32)) { - data |= set_upper_bits(v, extra * - BITS_PER_BYTE); - len = sizeof(u32) - extra; - if (len == length) { - last = data; - break; - } - __raw_writel(data, piobuf); - piobuf++; - extra = 0; - data = 0; - } else { - /* Clear unused upper bytes */ - data |= clear_upper_bytes(v, len, extra); - if (len == length) { - last = data; - break; - } - extra += len; - } - } else if (extra) { - /* Source address is aligned. */ - u32 *addr = (u32 *) ss->sge.vaddr; - int shift = extra * BITS_PER_BYTE; - int ushift = 32 - shift; - u32 l = len; - - while (l >= sizeof(u32)) { - u32 v = *addr; - - data |= set_upper_bits(v, shift); - __raw_writel(data, piobuf); - data = get_upper_bits(v, ushift); - piobuf++; - addr++; - l -= sizeof(u32); - } - /* - * We still have 'extra' number of bytes leftover. - */ - if (l) { - u32 v = *addr; - - if (l + extra >= sizeof(u32)) { - data |= set_upper_bits(v, shift); - len -= l + extra - sizeof(u32); - if (len == length) { - last = data; - break; - } - __raw_writel(data, piobuf); - piobuf++; - extra = 0; - data = 0; - } else { - /* Clear unused upper bytes */ - data |= clear_upper_bytes(v, l, - extra); - if (len == length) { - last = data; - break; - } - extra += l; - } - } else if (len == length) { - last = data; - break; - } - } else if (len == length) { - u32 w; - - /* - * Need to round up for the last dword in the - * packet. - */ - w = (len + 3) >> 2; - __iowrite32_copy(piobuf, ss->sge.vaddr, w - 1); - piobuf += w - 1; - last = ((u32 *) ss->sge.vaddr)[w - 1]; - break; - } else { - u32 w = len >> 2; - - __iowrite32_copy(piobuf, ss->sge.vaddr, w); - piobuf += w; - - extra = len & (sizeof(u32) - 1); - if (extra) { - u32 v = ((u32 *) ss->sge.vaddr)[w]; - - /* Clear unused upper bytes */ - data = clear_upper_bytes(v, extra, 0); - } - } - update_sge(ss, len); - length -= len; - } - /* Update address before sending packet. */ - update_sge(ss, length); - /* must flush early everything before trigger word */ - ipath_flush_wc(); - __raw_writel(last, piobuf); - /* be sure trigger word is written */ - ipath_flush_wc(); -} - -/** - * ipath_verbs_send - send a packet - * @dd: the infinipath device - * @hdrwords: the number of words in the header - * @hdr: the packet header - * @len: the length of the packet in bytes - * @ss: the SGE to send - */ -int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords, - u32 *hdr, u32 len, struct ipath_sge_state *ss) -{ - u32 __iomem *piobuf; - u32 plen; - int ret; - - /* +1 is for the qword padding of pbc */ - plen = hdrwords + ((len + 3) >> 2) + 1; - if (unlikely((plen << 2) > dd->ipath_ibmaxlen)) { - ipath_dbg("packet len 0x%x too long, failing\n", plen); - ret = -EINVAL; - goto bail; - } - - /* Get a PIO buffer to use. */ - piobuf = ipath_getpiobuf(dd, NULL); - if (unlikely(piobuf == NULL)) { - ret = -EBUSY; - goto bail; - } - - /* - * Write len to control qword, no flags. - * We have to flush after the PBC for correctness on some cpus - * or WC buffer can be written out of order. - */ - writeq(plen, piobuf); - ipath_flush_wc(); - piobuf += 2; - if (len == 0) { - /* - * If there is just the header portion, must flush before - * writing last word of header for correctness, and after - * the last header word (trigger word). - */ - __iowrite32_copy(piobuf, hdr, hdrwords - 1); - ipath_flush_wc(); - __raw_writel(hdr[hdrwords - 1], piobuf + hdrwords - 1); - ipath_flush_wc(); - ret = 0; - goto bail; - } - - __iowrite32_copy(piobuf, hdr, hdrwords); - piobuf += hdrwords; - - /* The common case is aligned and contained in one segment. */ - if (likely(ss->num_sge == 1 && len <= ss->sge.length && - !((unsigned long)ss->sge.vaddr & (sizeof(u32) - 1)))) { - u32 w; - u32 *addr = (u32 *) ss->sge.vaddr; - - /* Update address before sending packet. */ - update_sge(ss, len); - /* Need to round up for the last dword in the packet. */ - w = (len + 3) >> 2; - __iowrite32_copy(piobuf, addr, w - 1); - /* must flush early everything before trigger word */ - ipath_flush_wc(); - __raw_writel(addr[w - 1], piobuf + w - 1); - /* be sure trigger word is written */ - ipath_flush_wc(); - ret = 0; - goto bail; - } - copy_io(piobuf, ss, len); - ret = 0; - -bail: - return ret; -} - -int ipath_snapshot_counters(struct ipath_devdata *dd, u64 *swords, - u64 *rwords, u64 *spkts, u64 *rpkts, - u64 *xmit_wait) -{ - int ret; - - if (!(dd->ipath_flags & IPATH_INITTED)) { - /* no hardware, freeze, etc. */ - ipath_dbg("unit %u not usable\n", dd->ipath_unit); - ret = -EINVAL; - goto bail; - } - *swords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt); - *rwords = ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt); - *spkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt); - *rpkts = ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt); - *xmit_wait = ipath_snap_cntr(dd, dd->ipath_cregs->cr_sendstallcnt); - - ret = 0; - -bail: - return ret; -} - -/** - * ipath_get_counters - get various chip counters - * @dd: the infinipath device - * @cntrs: counters are placed here - * - * Return the counters needed by recv_pma_get_portcounters(). - */ -int ipath_get_counters(struct ipath_devdata *dd, - struct ipath_verbs_counters *cntrs) -{ - int ret; - - if (!(dd->ipath_flags & IPATH_INITTED)) { - /* no hardware, freeze, etc. */ - ipath_dbg("unit %u not usable\n", dd->ipath_unit); - ret = -EINVAL; - goto bail; - } - cntrs->symbol_error_counter = - ipath_snap_cntr(dd, dd->ipath_cregs->cr_ibsymbolerrcnt); - cntrs->link_error_recovery_counter = - ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkerrrecovcnt); - /* - * The link downed counter counts when the other side downs the - * connection. We add in the number of times we downed the link - * due to local link integrity errors to compensate. - */ - cntrs->link_downed_counter = - ipath_snap_cntr(dd, dd->ipath_cregs->cr_iblinkdowncnt); - cntrs->port_rcv_errors = - ipath_snap_cntr(dd, dd->ipath_cregs->cr_rxdroppktcnt) + - ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvovflcnt) + - ipath_snap_cntr(dd, dd->ipath_cregs->cr_portovflcnt) + - ipath_snap_cntr(dd, dd->ipath_cregs->cr_err_rlencnt) + - ipath_snap_cntr(dd, dd->ipath_cregs->cr_invalidrlencnt) + - ipath_snap_cntr(dd, dd->ipath_cregs->cr_erricrccnt) + - ipath_snap_cntr(dd, dd->ipath_cregs->cr_errvcrccnt) + - ipath_snap_cntr(dd, dd->ipath_cregs->cr_errlpcrccnt) + - ipath_snap_cntr(dd, dd->ipath_cregs->cr_badformatcnt); - cntrs->port_rcv_remphys_errors = - ipath_snap_cntr(dd, dd->ipath_cregs->cr_rcvebpcnt); - cntrs->port_xmit_discards = - ipath_snap_cntr(dd, dd->ipath_cregs->cr_unsupvlcnt); - cntrs->port_xmit_data = - ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordsendcnt); - cntrs->port_rcv_data = - ipath_snap_cntr(dd, dd->ipath_cregs->cr_wordrcvcnt); - cntrs->port_xmit_packets = - ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktsendcnt); - cntrs->port_rcv_packets = - ipath_snap_cntr(dd, dd->ipath_cregs->cr_pktrcvcnt); - cntrs->local_link_integrity_errors = dd->ipath_lli_errors; - cntrs->excessive_buffer_overrun_errors = 0; /* XXX */ - - ret = 0; - -bail: - return ret; -} - /** * ipath_ib_piobufavail - callback when a PIO buffer is available * @arg: the device pointer @@ -930,8 +591,9 @@ int ipath_get_counters(struct ipath_devdata *dd, * QPs waiting for buffers (for now, just do a tasklet_hi_schedule and * return zero). */ -int ipath_ib_piobufavail(struct ipath_ibdev *dev) +static int ipath_ib_piobufavail(void *arg) { + struct ipath_ibdev *dev = (struct ipath_ibdev *) arg; struct ipath_qp *qp; unsigned long flags; @@ -962,14 +624,14 @@ static int ipath_query_device(struct ib_device *ibdev, IB_DEVICE_BAD_QKEY_CNTR | IB_DEVICE_SHUTDOWN_PORT | IB_DEVICE_SYS_IMAGE_GUID; props->page_size_cap = PAGE_SIZE; - props->vendor_id = dev->dd->ipath_vendorid; - props->vendor_part_id = dev->dd->ipath_deviceid; - props->hw_ver = dev->dd->ipath_pcirev; + props->vendor_id = ipath_layer_get_vendorid(dev->dd); + props->vendor_part_id = ipath_layer_get_deviceid(dev->dd); + props->hw_ver = ipath_layer_get_pcirev(dev->dd); props->sys_image_guid = dev->sys_image_guid; props->max_mr_size = ~0ull; - props->max_qp = ib_ipath_max_qps; + props->max_qp = dev->qp_table.max; props->max_qp_wr = ib_ipath_max_qp_wrs; props->max_sge = ib_ipath_max_sges; props->max_cq = ib_ipath_max_cqs; @@ -985,7 +647,7 @@ static int ipath_query_device(struct ib_device *ibdev, props->max_srq_sge = ib_ipath_max_srq_sges; /* props->local_ca_ack_delay */ props->atomic_cap = IB_ATOMIC_HCA; - props->max_pkeys = ipath_get_npkeys(dev->dd); + props->max_pkeys = ipath_layer_get_npkeys(dev->dd); props->max_mcast_grp = ib_ipath_max_mcast_grps; props->max_mcast_qp_attach = ib_ipath_max_mcast_qp_attached; props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * @@ -1010,17 +672,12 @@ const u8 ipath_cvt_physportstate[16] = { [INFINIPATH_IBCS_LT_STATE_RECOVERIDLE] = 6, }; -u32 ipath_get_cr_errpkey(struct ipath_devdata *dd) -{ - return ipath_read_creg32(dd, dd->ipath_cregs->cr_errpkey); -} - static int ipath_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr *props) { struct ipath_ibdev *dev = to_idev(ibdev); enum ib_mtu mtu; - u16 lid = dev->dd->ipath_lid; + u16 lid = ipath_layer_get_lid(dev->dd); u64 ibcstat; memset(props, 0, sizeof(*props)); @@ -1028,16 +685,16 @@ static int ipath_query_port(struct ib_device *ibdev, props->lmc = dev->mkeyprot_resv_lmc & 7; props->sm_lid = dev->sm_lid; props->sm_sl = dev->sm_sl; - ibcstat = dev->dd->ipath_lastibcstat; + ibcstat = ipath_layer_get_lastibcstat(dev->dd); props->state = ((ibcstat >> 4) & 0x3) + 1; /* See phys_state_show() */ props->phys_state = ipath_cvt_physportstate[ - dev->dd->ipath_lastibcstat & 0xf]; + ipath_layer_get_lastibcstat(dev->dd) & 0xf]; props->port_cap_flags = dev->port_cap_flags; props->gid_tbl_len = 1; props->max_msg_sz = 0x80000000; - props->pkey_tbl_len = ipath_get_npkeys(dev->dd); - props->bad_pkey_cntr = ipath_get_cr_errpkey(dev->dd) - + props->pkey_tbl_len = ipath_layer_get_npkeys(dev->dd); + props->bad_pkey_cntr = ipath_layer_get_cr_errpkey(dev->dd) - dev->z_pkey_violations; props->qkey_viol_cntr = dev->qkey_violations; props->active_width = IB_WIDTH_4X; @@ -1047,7 +704,7 @@ static int ipath_query_port(struct ib_device *ibdev, props->init_type_reply = 0; props->max_mtu = IB_MTU_4096; - switch (dev->dd->ipath_ibmtu) { + switch (ipath_layer_get_ibmtu(dev->dd)) { case 4096: mtu = IB_MTU_4096; break; @@ -1106,7 +763,7 @@ static int ipath_modify_port(struct ib_device *ibdev, dev->port_cap_flags |= props->set_port_cap_mask; dev->port_cap_flags &= ~props->clr_port_cap_mask; if (port_modify_mask & IB_PORT_SHUTDOWN) - ipath_set_linkstate(dev->dd, IPATH_IB_LINKDOWN); + ipath_layer_set_linkstate(dev->dd, IPATH_IB_LINKDOWN); if (port_modify_mask & IB_PORT_RESET_QKEY_CNTR) dev->qkey_violations = 0; return 0; @@ -1123,7 +780,7 @@ static int ipath_query_gid(struct ib_device *ibdev, u8 port, goto bail; } gid->global.subnet_prefix = dev->gid_prefix; - gid->global.interface_id = dev->dd->ipath_guid; + gid->global.interface_id = ipath_layer_get_guid(dev->dd); ret = 0; @@ -1146,22 +803,18 @@ static struct ib_pd *ipath_alloc_pd(struct ib_device *ibdev, * we allow allocations of more than we report for this value. */ - pd = kmalloc(sizeof *pd, GFP_KERNEL); - if (!pd) { + if (dev->n_pds_allocated == ib_ipath_max_pds) { ret = ERR_PTR(-ENOMEM); goto bail; } - spin_lock(&dev->n_pds_lock); - if (dev->n_pds_allocated == ib_ipath_max_pds) { - spin_unlock(&dev->n_pds_lock); - kfree(pd); + pd = kmalloc(sizeof *pd, GFP_KERNEL); + if (!pd) { ret = ERR_PTR(-ENOMEM); goto bail; } dev->n_pds_allocated++; - spin_unlock(&dev->n_pds_lock); /* ib_alloc_pd() will initialize pd->ibpd. */ pd->user = udata != NULL; @@ -1177,9 +830,7 @@ static int ipath_dealloc_pd(struct ib_pd *ibpd) struct ipath_pd *pd = to_ipd(ibpd); struct ipath_ibdev *dev = to_idev(ibpd->device); - spin_lock(&dev->n_pds_lock); dev->n_pds_allocated--; - spin_unlock(&dev->n_pds_lock); kfree(pd); @@ -1200,6 +851,11 @@ static struct ib_ah *ipath_create_ah(struct ib_pd *pd, struct ib_ah *ret; struct ipath_ibdev *dev = to_idev(pd->device); + if (dev->n_ahs_allocated == ib_ipath_max_ahs) { + ret = ERR_PTR(-ENOMEM); + goto bail; + } + /* A multicast address requires a GRH (see ch. 8.4.1). */ if (ah_attr->dlid >= IPATH_MULTICAST_LID_BASE && ah_attr->dlid != IPATH_PERMISSIVE_LID && @@ -1225,16 +881,7 @@ static struct ib_ah *ipath_create_ah(struct ib_pd *pd, goto bail; } - spin_lock(&dev->n_ahs_lock); - if (dev->n_ahs_allocated == ib_ipath_max_ahs) { - spin_unlock(&dev->n_ahs_lock); - kfree(ah); - ret = ERR_PTR(-ENOMEM); - goto bail; - } - dev->n_ahs_allocated++; - spin_unlock(&dev->n_ahs_lock); /* ib_create_ah() will initialize ah->ibah. */ ah->attr = *ah_attr; @@ -1256,9 +903,7 @@ static int ipath_destroy_ah(struct ib_ah *ibah) struct ipath_ibdev *dev = to_idev(ibah->device); struct ipath_ah *ah = to_iah(ibah); - spin_lock(&dev->n_ahs_lock); dev->n_ahs_allocated--; - spin_unlock(&dev->n_ahs_lock); kfree(ah); @@ -1274,50 +919,25 @@ static int ipath_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr) return 0; } -/** - * ipath_get_npkeys - return the size of the PKEY table for port 0 - * @dd: the infinipath device - */ -unsigned ipath_get_npkeys(struct ipath_devdata *dd) -{ - return ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys); -} - -/** - * ipath_get_pkey - return the indexed PKEY from the port 0 PKEY table - * @dd: the infinipath device - * @index: the PKEY index - */ -unsigned ipath_get_pkey(struct ipath_devdata *dd, unsigned index) -{ - unsigned ret; - - if (index >= ARRAY_SIZE(dd->ipath_pd[0]->port_pkeys)) - ret = 0; - else - ret = dd->ipath_pd[0]->port_pkeys[index]; - - return ret; -} - static int ipath_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) { struct ipath_ibdev *dev = to_idev(ibdev); int ret; - if (index >= ipath_get_npkeys(dev->dd)) { + if (index >= ipath_layer_get_npkeys(dev->dd)) { ret = -EINVAL; goto bail; } - *pkey = ipath_get_pkey(dev->dd, index); + *pkey = ipath_layer_get_pkey(dev->dd, index); ret = 0; bail: return ret; } + /** * ipath_alloc_ucontext - allocate a ucontest * @ibdev: the infiniband device @@ -1350,91 +970,26 @@ static int ipath_dealloc_ucontext(struct ib_ucontext *context) static int ipath_verbs_register_sysfs(struct ib_device *dev); -static void __verbs_timer(unsigned long arg) -{ - struct ipath_devdata *dd = (struct ipath_devdata *) arg; - - /* - * If port 0 receive packet interrupts are not available, or - * can be missed, poll the receive queue - */ - if (dd->ipath_flags & IPATH_POLL_RX_INTR) - ipath_kreceive(dd); - - /* Handle verbs layer timeouts. */ - ipath_ib_timer(dd->verbs_dev); - - mod_timer(&dd->verbs_timer, jiffies + 1); -} - -static int enable_timer(struct ipath_devdata *dd) -{ - /* - * Early chips had a design flaw where the chip and kernel idea - * of the tail register don't always agree, and therefore we won't - * get an interrupt on the next packet received. - * If the board supports per packet receive interrupts, use it. - * Otherwise, the timer function periodically checks for packets - * to cover this case. - * Either way, the timer is needed for verbs layer related - * processing. - */ - if (dd->ipath_flags & IPATH_GPIO_INTR) { - ipath_write_kreg(dd, dd->ipath_kregs->kr_debugportselect, - 0x2074076542310ULL); - /* Enable GPIO bit 2 interrupt */ - ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, - (u64) (1 << 2)); - } - - init_timer(&dd->verbs_timer); - dd->verbs_timer.function = __verbs_timer; - dd->verbs_timer.data = (unsigned long)dd; - dd->verbs_timer.expires = jiffies + 1; - add_timer(&dd->verbs_timer); - - return 0; -} - -static int disable_timer(struct ipath_devdata *dd) -{ - /* Disable GPIO bit 2 interrupt */ - if (dd->ipath_flags & IPATH_GPIO_INTR) - ipath_write_kreg(dd, dd->ipath_kregs->kr_gpio_mask, 0); - - del_timer_sync(&dd->verbs_timer); - - return 0; -} - /** * ipath_register_ib_device - register our device with the infiniband core + * @unit: the device number to register * @dd: the device data structure * Return the allocated ipath_ibdev pointer or NULL on error. */ -int ipath_register_ib_device(struct ipath_devdata *dd) +static void *ipath_register_ib_device(int unit, struct ipath_devdata *dd) { - struct ipath_verbs_counters cntrs; + struct ipath_layer_counters cntrs; struct ipath_ibdev *idev; struct ib_device *dev; int ret; idev = (struct ipath_ibdev *)ib_alloc_device(sizeof *idev); - if (idev == NULL) { - ret = -ENOMEM; + if (idev == NULL) goto bail; - } dev = &idev->ibdev; /* Only need to initialize non-zero fields. */ - spin_lock_init(&idev->n_pds_lock); - spin_lock_init(&idev->n_ahs_lock); - spin_lock_init(&idev->n_cqs_lock); - spin_lock_init(&idev->n_qps_lock); - spin_lock_init(&idev->n_srqs_lock); - spin_lock_init(&idev->n_mcast_grps_lock); - spin_lock_init(&idev->qp_table.lock); spin_lock_init(&idev->lk_table.lock); idev->sm_lid = __constant_be16_to_cpu(IB_LID_PERMISSIVE); @@ -1475,7 +1030,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd) idev->link_width_enabled = 3; /* 1x or 4x */ /* Snapshot current HW counters to "clear" them. */ - ipath_get_counters(dd, &cntrs); + ipath_layer_get_counters(dd, &cntrs); idev->z_symbol_error_counter = cntrs.symbol_error_counter; idev->z_link_error_recovery_counter = cntrs.link_error_recovery_counter; @@ -1499,14 +1054,14 @@ int ipath_register_ib_device(struct ipath_devdata *dd) * device types in the system, we can't be sure this is unique. */ if (!sys_image_guid) - sys_image_guid = dd->ipath_guid; + sys_image_guid = ipath_layer_get_guid(dd); idev->sys_image_guid = sys_image_guid; - idev->ib_unit = dd->ipath_unit; + idev->ib_unit = unit; idev->dd = dd; strlcpy(dev->name, "ipath%d", IB_DEVICE_NAME_MAX); dev->owner = THIS_MODULE; - dev->node_guid = dd->ipath_guid; + dev->node_guid = ipath_layer_get_guid(dd); dev->uverbs_abi_ver = IPATH_UVERBS_ABI_VERSION; dev->uverbs_cmd_mask = (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | @@ -1538,9 +1093,9 @@ int ipath_register_ib_device(struct ipath_devdata *dd) (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) | (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ) | (1ull << IB_USER_VERBS_CMD_POST_SRQ_RECV); - dev->node_type = RDMA_NODE_IB_CA; + dev->node_type = IB_NODE_CA; dev->phys_port_cnt = 1; - dev->dma_device = &dd->pcidev->dev; + dev->dma_device = ipath_layer_get_device(dd); dev->class_dev.dev = dev->dma_device; dev->query_device = ipath_query_device; dev->modify_device = ipath_modify_device; @@ -1582,10 +1137,9 @@ int ipath_register_ib_device(struct ipath_devdata *dd) dev->attach_mcast = ipath_multicast_attach; dev->detach_mcast = ipath_multicast_detach; dev->process_mad = ipath_process_mad; - dev->mmap = ipath_mmap; snprintf(dev->node_desc, sizeof(dev->node_desc), - IPATH_IDSTR " %s", system_utsname.nodename); + IPATH_IDSTR " %s kernel_SMA", system_utsname.nodename); ret = ib_register_device(dev); if (ret) @@ -1594,7 +1148,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd) if (ipath_verbs_register_sysfs(dev)) goto err_class; - enable_timer(dd); + ipath_layer_enable_timer(dd); goto bail; @@ -1606,32 +1160,37 @@ int ipath_register_ib_device(struct ipath_devdata *dd) kfree(idev->qp_table.table); err_qp: ib_dealloc_device(dev); - ipath_dev_err(dd, "cannot register verbs: %d!\n", -ret); + _VERBS_ERROR("ib_ipath%d cannot register verbs (%d)!\n", + unit, -ret); idev = NULL; bail: - dd->verbs_dev = idev; - return ret; + return idev; } -void ipath_unregister_ib_device(struct ipath_ibdev *dev) +static void ipath_unregister_ib_device(void *arg) { + struct ipath_ibdev *dev = (struct ipath_ibdev *) arg; struct ib_device *ibdev = &dev->ibdev; - disable_timer(dev->dd); + ipath_layer_disable_timer(dev->dd); ib_unregister_device(ibdev); if (!list_empty(&dev->pending[0]) || !list_empty(&dev->pending[1]) || !list_empty(&dev->pending[2])) - ipath_dev_err(dev->dd, "pending list not empty!\n"); + _VERBS_ERROR("ipath%d pending list not empty!\n", + dev->ib_unit); if (!list_empty(&dev->piowait)) - ipath_dev_err(dev->dd, "piowait list not empty!\n"); + _VERBS_ERROR("ipath%d piowait list not empty!\n", + dev->ib_unit); if (!list_empty(&dev->rnrwait)) - ipath_dev_err(dev->dd, "rnrwait list not empty!\n"); + _VERBS_ERROR("ipath%d rnrwait list not empty!\n", + dev->ib_unit); if (!ipath_mcast_tree_empty()) - ipath_dev_err(dev->dd, "multicast table memory leak!\n"); + _VERBS_ERROR("ipath%d multicast table memory leak!\n", + dev->ib_unit); /* * Note that ipath_unregister_ib_device() can be called before all * the QPs are destroyed! @@ -1642,12 +1201,25 @@ void ipath_unregister_ib_device(struct ipath_ibdev *dev) ib_dealloc_device(ibdev); } +static int __init ipath_verbs_init(void) +{ + return ipath_verbs_register(ipath_register_ib_device, + ipath_unregister_ib_device, + ipath_ib_piobufavail, ipath_ib_rcv, + ipath_ib_timer); +} + +static void __exit ipath_verbs_cleanup(void) +{ + ipath_verbs_unregister(); +} + static ssize_t show_rev(struct class_device *cdev, char *buf) { struct ipath_ibdev *dev = container_of(cdev, struct ipath_ibdev, ibdev.class_dev); - return sprintf(buf, "%x\n", dev->dd->ipath_pcirev); + return sprintf(buf, "%x\n", ipath_layer_get_pcirev(dev->dd)); } static ssize_t show_hca(struct class_device *cdev, char *buf) @@ -1656,7 +1228,7 @@ static ssize_t show_hca(struct class_device *cdev, char *buf) container_of(cdev, struct ipath_ibdev, ibdev.class_dev); int ret; - ret = dev->dd->ipath_f_get_boardname(dev->dd, buf, 128); + ret = ipath_layer_get_boardname(dev->dd, buf, 128); if (ret < 0) goto bail; strcat(buf, "\n"); @@ -1733,3 +1305,6 @@ static int ipath_verbs_register_sysfs(struct ib_device *dev) bail: return ret; } + +module_init(ipath_verbs_init); +module_exit(ipath_verbs_cleanup); diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h index 09bbb3f9a217..2df684727dc1 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/trunk/drivers/infiniband/hw/ipath/ipath_verbs.h @@ -38,10 +38,10 @@ #include #include #include -#include #include #include "ipath_layer.h" +#include "verbs_debug.h" #define QPN_MAX (1 << 24) #define QPNMAP_ENTRIES (QPN_MAX / PAGE_SIZE / BITS_PER_BYTE) @@ -50,7 +50,7 @@ * Increment this value if any changes that break userspace ABI * compatibility are made. */ -#define IPATH_UVERBS_ABI_VERSION 2 +#define IPATH_UVERBS_ABI_VERSION 1 /* * Define an ib_cq_notify value that is not valid so we know when CQ @@ -152,6 +152,19 @@ struct ipath_mcast { int n_attached; }; +/* Memory region */ +struct ipath_mr { + struct ib_mr ibmr; + struct ipath_mregion mr; /* must be last */ +}; + +/* Fast memory region */ +struct ipath_fmr { + struct ib_fmr ibfmr; + u8 page_shift; + struct ipath_mregion mr; /* must be last */ +}; + /* Protection domain */ struct ipath_pd { struct ib_pd ibpd; @@ -165,89 +178,58 @@ struct ipath_ah { }; /* - * This structure is used by ipath_mmap() to validate an offset - * when an mmap() request is made. The vm_area_struct then uses - * this as its vm_private_data. - */ -struct ipath_mmap_info { - struct ipath_mmap_info *next; - struct ib_ucontext *context; - void *obj; - struct kref ref; - unsigned size; - unsigned mmap_cnt; -}; - -/* - * This structure is used to contain the head pointer, tail pointer, - * and completion queue entries as a single memory allocation so - * it can be mmap'ed into user space. + * Quick description of our CQ/QP locking scheme: + * + * We have one global lock that protects dev->cq/qp_table. Each + * struct ipath_cq/qp also has its own lock. An individual qp lock + * may be taken inside of an individual cq lock. Both cqs attached to + * a qp may be locked, with the send cq locked first. No other + * nesting should be done. + * + * Each struct ipath_cq/qp also has an atomic_t ref count. The + * pointer from the cq/qp_table to the struct counts as one reference. + * This reference also is good for access through the consumer API, so + * modifying the CQ/QP etc doesn't need to take another reference. + * Access because of a completion being polled does need a reference. + * + * Finally, each struct ipath_cq/qp has a wait_queue_head_t for the + * destroy function to sleep on. + * + * This means that access from the consumer API requires nothing but + * taking the struct's lock. + * + * Access because of a completion event should go as follows: + * - lock cq/qp_table and look up struct + * - increment ref count in struct + * - drop cq/qp_table lock + * - lock struct, do your thing, and unlock struct + * - decrement ref count; if zero, wake up waiters + * + * To destroy a CQ/QP, we can do the following: + * - lock cq/qp_table, remove pointer, unlock cq/qp_table lock + * - decrement ref count + * - wait_event until ref count is zero + * + * It is the consumer's responsibilty to make sure that no QP + * operations (WQE posting or state modification) are pending when the + * QP is destroyed. Also, the consumer must make sure that calls to + * qp_modify are serialized. + * + * Possible optimizations (wait for profile data to see if/where we + * have locks bouncing between CPUs): + * - split cq/qp table lock into n separate (cache-aligned) locks, + * indexed (say) by the page in the table */ -struct ipath_cq_wc { - u32 head; /* index of next entry to fill */ - u32 tail; /* index of next ib_poll_cq() entry */ - struct ib_wc queue[1]; /* this is actually size ibcq.cqe + 1 */ -}; -/* - * The completion queue structure. - */ struct ipath_cq { struct ib_cq ibcq; struct tasklet_struct comptask; spinlock_t lock; u8 notify; u8 triggered; - struct ipath_cq_wc *queue; - struct ipath_mmap_info *ip; -}; - -/* - * A segment is a linear region of low physical memory. - * XXX Maybe we should use phys addr here and kmap()/kunmap(). - * Used by the verbs layer. - */ -struct ipath_seg { - void *vaddr; - size_t length; -}; - -/* The number of ipath_segs that fit in a page. */ -#define IPATH_SEGSZ (PAGE_SIZE / sizeof (struct ipath_seg)) - -struct ipath_segarray { - struct ipath_seg segs[IPATH_SEGSZ]; -}; - -struct ipath_mregion { - u64 user_base; /* User's address for this region */ - u64 iova; /* IB start address of this region */ - size_t length; - u32 lkey; - u32 offset; /* offset (bytes) to start of region */ - int access_flags; - u32 max_segs; /* number of ipath_segs in all the arrays */ - u32 mapsz; /* size of the map array */ - struct ipath_segarray *map[0]; /* the segments */ -}; - -/* - * These keep track of the copy progress within a memory region. - * Used by the verbs layer. - */ -struct ipath_sge { - struct ipath_mregion *mr; - void *vaddr; /* current pointer into the segment */ - u32 sge_length; /* length of the SGE */ - u32 length; /* remaining length of the segment */ - u16 m; /* current index: mr->map[m] */ - u16 n; /* current index: mr->map[m]->segs[n] */ -}; - -/* Memory region */ -struct ipath_mr { - struct ib_mr ibmr; - struct ipath_mregion mr; /* must be last */ + u32 head; /* new records added to the head */ + u32 tail; /* poll_cq() reads from here. */ + struct ib_wc *queue; /* this is actually ibcq.cqe + 1 */ }; /* @@ -266,50 +248,32 @@ struct ipath_swqe { /* * Receive work request queue entry. - * The size of the sg_list is determined when the QP (or SRQ) is created - * and stored in qp->r_rq.max_sge (or srq->rq.max_sge). + * The size of the sg_list is determined when the QP is created and stored + * in qp->r_max_sge. */ struct ipath_rwqe { u64 wr_id; + u32 length; /* total length of data in sg_list */ u8 num_sge; - struct ib_sge sg_list[0]; -}; - -/* - * This structure is used to contain the head pointer, tail pointer, - * and receive work queue entries as a single memory allocation so - * it can be mmap'ed into user space. - * Note that the wq array elements are variable size so you can't - * just index into the array to get the N'th element; - * use get_rwqe_ptr() instead. - */ -struct ipath_rwq { - u32 head; /* new work requests posted to the head */ - u32 tail; /* receives pull requests from here. */ - struct ipath_rwqe wq[0]; + struct ipath_sge sg_list[0]; }; struct ipath_rq { - struct ipath_rwq *wq; spinlock_t lock; + u32 head; /* new work requests posted to the head */ + u32 tail; /* receives pull requests from here. */ u32 size; /* size of RWQE array */ u8 max_sge; + struct ipath_rwqe *wq; /* RWQE array */ }; struct ipath_srq { struct ib_srq ibsrq; struct ipath_rq rq; - struct ipath_mmap_info *ip; /* send signal when number of RWQEs < limit */ u32 limit; }; -struct ipath_sge_state { - struct ipath_sge *sg_list; /* next SGE to be used if any */ - struct ipath_sge sge; /* progress state for the current SGE */ - u8 num_sge; -}; - /* * Variables prefixed with s_ are for the requester (sender). * Variables prefixed with r_ are for the responder (receiver). @@ -329,7 +293,6 @@ struct ipath_qp { atomic_t refcount; wait_queue_head_t wait; struct tasklet_struct s_task; - struct ipath_mmap_info *ip; struct ipath_sge_state *s_cur_sge; struct ipath_sge_state s_sge; /* current send request data */ /* current RDMA read send data */ @@ -371,7 +334,6 @@ struct ipath_qp { u8 s_retry; /* requester retry counter */ u8 s_rnr_retry; /* requester RNR retry counter */ u8 s_pkey_index; /* PKEY index to use */ - u8 timeout; /* Timeout for this QP */ enum ib_mtu path_mtu; u32 remote_qpn; u32 qkey; /* QKEY for this QP (for UD or RD) */ @@ -383,8 +345,7 @@ struct ipath_qp { u32 s_ssn; /* SSN of tail entry */ u32 s_lsn; /* limit sequence number (credit) */ struct ipath_swqe *s_wq; /* send work queue */ - struct ipath_rq r_rq; /* receive work queue */ - struct ipath_sge r_sg_list[0]; /* verified SGEs */ + struct ipath_rq r_rq; /* receive work queue */ }; /* @@ -408,15 +369,15 @@ static inline struct ipath_swqe *get_swqe_ptr(struct ipath_qp *qp, /* * Since struct ipath_rwqe is not a fixed size, we can't simply index into - * struct ipath_rwq.wq. This function does the array index computation. + * struct ipath_rq.wq. This function does the array index computation. */ static inline struct ipath_rwqe *get_rwqe_ptr(struct ipath_rq *rq, unsigned n) { return (struct ipath_rwqe *) - ((char *) rq->wq->wq + + ((char *) rq->wq + (sizeof(struct ipath_rwqe) + - rq->max_sge * sizeof(struct ib_sge)) * n); + rq->max_sge * sizeof(struct ipath_sge)) * n); } /* @@ -456,7 +417,6 @@ struct ipath_ibdev { struct ib_device ibdev; struct list_head dev_list; struct ipath_devdata *dd; - struct ipath_mmap_info *pending_mmaps; int ib_unit; /* This is the device number */ u16 sm_lid; /* in host order */ u8 sm_sl; @@ -475,20 +435,11 @@ struct ipath_ibdev { __be64 sys_image_guid; /* in network order */ __be64 gid_prefix; /* in network order */ __be64 mkey; - u32 n_pds_allocated; /* number of PDs allocated for device */ - spinlock_t n_pds_lock; u32 n_ahs_allocated; /* number of AHs allocated for device */ - spinlock_t n_ahs_lock; u32 n_cqs_allocated; /* number of CQs allocated for device */ - spinlock_t n_cqs_lock; - u32 n_qps_allocated; /* number of QPs allocated for device */ - spinlock_t n_qps_lock; u32 n_srqs_allocated; /* number of SRQs allocated for device */ - spinlock_t n_srqs_lock; u32 n_mcast_grps_allocated; /* number of mcast groups allocated */ - spinlock_t n_mcast_grps_lock; - u64 ipath_sword; /* total dwords sent (sample result) */ u64 ipath_rword; /* total dwords received (sample result) */ u64 ipath_spkts; /* total packets sent (sample result) */ @@ -543,19 +494,8 @@ struct ipath_ibdev { struct ipath_opcode_stats opstats[128]; }; -struct ipath_verbs_counters { - u64 symbol_error_counter; - u64 link_error_recovery_counter; - u64 link_downed_counter; - u64 port_rcv_errors; - u64 port_rcv_remphys_errors; - u64 port_xmit_discards; - u64 port_xmit_data; - u64 port_rcv_data; - u64 port_xmit_packets; - u64 port_rcv_packets; - u32 local_link_integrity_errors; - u32 excessive_buffer_overrun_errors; +struct ipath_ucontext { + struct ib_ucontext ibucontext; }; static inline struct ipath_mr *to_imr(struct ib_mr *ibmr) @@ -563,6 +503,11 @@ static inline struct ipath_mr *to_imr(struct ib_mr *ibmr) return container_of(ibmr, struct ipath_mr, ibmr); } +static inline struct ipath_fmr *to_ifmr(struct ib_fmr *ibfmr) +{ + return container_of(ibfmr, struct ipath_fmr, ibfmr); +} + static inline struct ipath_pd *to_ipd(struct ib_pd *ibpd) { return container_of(ibpd, struct ipath_pd, ibpd); @@ -600,6 +545,12 @@ int ipath_process_mad(struct ib_device *ibdev, struct ib_grh *in_grh, struct ib_mad *in_mad, struct ib_mad *out_mad); +static inline struct ipath_ucontext *to_iucontext(struct ib_ucontext + *ibucontext) +{ + return container_of(ibucontext, struct ipath_ucontext, ibucontext); +} + /* * Compare the lower 24 bits of the two values. * Returns an integer <, ==, or > than zero. @@ -611,13 +562,6 @@ static inline int ipath_cmp24(u32 a, u32 b) struct ipath_mcast *ipath_mcast_find(union ib_gid *mgid); -int ipath_snapshot_counters(struct ipath_devdata *dd, u64 *swords, - u64 *rwords, u64 *spkts, u64 *rpkts, - u64 *xmit_wait); - -int ipath_get_counters(struct ipath_devdata *dd, - struct ipath_verbs_counters *cntrs); - int ipath_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); @@ -635,7 +579,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, int ipath_destroy_qp(struct ib_qp *ibqp); int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, - int attr_mask, struct ib_udata *udata); + int attr_mask); int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, struct ib_qp_init_attr *init_attr); @@ -648,9 +592,6 @@ void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc); void ipath_get_credit(struct ipath_qp *qp, u32 aeth); -int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords, - u32 *hdr, u32 len, struct ipath_sge_state *ss); - void ipath_cq_enter(struct ipath_cq *cq, struct ib_wc *entry, int sig); int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss, @@ -697,8 +638,7 @@ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd, struct ib_udata *udata); int ipath_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, - enum ib_srq_attr_mask attr_mask, - struct ib_udata *udata); + enum ib_srq_attr_mask attr_mask); int ipath_query_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr); @@ -740,10 +680,6 @@ int ipath_unmap_fmr(struct list_head *fmr_list); int ipath_dealloc_fmr(struct ib_fmr *ibfmr); -void ipath_release_mmap_info(struct kref *ref); - -int ipath_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); - void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev); void ipath_insert_rnr_queue(struct ipath_qp *qp); @@ -764,22 +700,6 @@ int ipath_make_rc_req(struct ipath_qp *qp, struct ipath_other_headers *ohdr, int ipath_make_uc_req(struct ipath_qp *qp, struct ipath_other_headers *ohdr, u32 pmtu, u32 *bth0p, u32 *bth2p); -int ipath_register_ib_device(struct ipath_devdata *); - -void ipath_unregister_ib_device(struct ipath_ibdev *); - -void ipath_ib_rcv(struct ipath_ibdev *, void *, void *, u32); - -int ipath_ib_piobufavail(struct ipath_ibdev *); - -void ipath_ib_timer(struct ipath_ibdev *); - -unsigned ipath_get_npkeys(struct ipath_devdata *); - -u32 ipath_get_cr_errpkey(struct ipath_devdata *); - -unsigned ipath_get_pkey(struct ipath_devdata *, unsigned); - extern const enum ib_wc_opcode ib_ipath_wc_opcode[]; extern const u8 ipath_cvt_physportstate[]; @@ -794,8 +714,6 @@ extern unsigned int ib_ipath_max_cqs; extern unsigned int ib_ipath_max_qp_wrs; -extern unsigned int ib_ipath_max_qps; - extern unsigned int ib_ipath_max_sges; extern unsigned int ib_ipath_max_mcast_grps; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c b/trunk/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c index 085e28b939ec..ee0e1d96d723 100644 --- a/trunk/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c +++ b/trunk/drivers/infiniband/hw/ipath/ipath_verbs_mcast.c @@ -207,17 +207,12 @@ static int ipath_mcast_add(struct ipath_ibdev *dev, goto bail; } - spin_lock(&dev->n_mcast_grps_lock); if (dev->n_mcast_grps_allocated == ib_ipath_max_mcast_grps) { - spin_unlock(&dev->n_mcast_grps_lock); ret = ENOMEM; goto bail; } dev->n_mcast_grps_allocated++; - spin_unlock(&dev->n_mcast_grps_lock); - - mcast->n_attached++; list_add_tail_rcu(&mqp->list, &mcast->qp_list); @@ -348,9 +343,7 @@ int ipath_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) atomic_dec(&mcast->refcount); wait_event(mcast->wait, !atomic_read(&mcast->refcount)); ipath_mcast_free(mcast); - spin_lock(&dev->n_mcast_grps_lock); dev->n_mcast_grps_allocated--; - spin_unlock(&dev->n_mcast_grps_lock); } ret = 0; diff --git a/trunk/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c b/trunk/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c deleted file mode 100644 index 036fde662aa9..000000000000 --- a/trunk/drivers/infiniband/hw/ipath/ipath_wc_ppc64.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2006 QLogic, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * This file is conditionally built on PowerPC only. Otherwise weak symbol - * versions of the functions exported from here are used. - */ - -#include "ipath_kernel.h" - -/** - * ipath_unordered_wc - indicate whether write combining is ordered - * - * PowerPC systems (at least those in the 970 processor family) - * write partially filled store buffers in address order, but will write - * completely filled store buffers in "random" order, and therefore must - * have serialization for correctness with current InfiniPath chips. - * - */ -int ipath_unordered_wc(void) -{ - return 1; -} diff --git a/trunk/drivers/infiniband/hw/ipath/verbs_debug.h b/trunk/drivers/infiniband/hw/ipath/verbs_debug.h new file mode 100644 index 000000000000..6186676f2a16 --- /dev/null +++ b/trunk/drivers/infiniband/hw/ipath/verbs_debug.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2006 QLogic, Inc. All rights reserved. + * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _VERBS_DEBUG_H +#define _VERBS_DEBUG_H + +/* + * This file contains tracing code for the ib_ipath kernel module. + */ +#ifndef _VERBS_DEBUGGING /* tracing enabled or not */ +#define _VERBS_DEBUGGING 1 +#endif + +extern unsigned ib_ipath_debug; + +#define _VERBS_ERROR(fmt,...) \ + do { \ + printk(KERN_ERR "%s: " fmt, "ib_ipath", ##__VA_ARGS__); \ + } while(0) + +#define _VERBS_UNIT_ERROR(unit,fmt,...) \ + do { \ + printk(KERN_ERR "%s: " fmt, "ib_ipath", ##__VA_ARGS__); \ + } while(0) + +#if _VERBS_DEBUGGING + +/* + * Mask values for debugging. The scheme allows us to compile out any + * of the debug tracing stuff, and if compiled in, to enable or + * disable dynamically. + * This can be set at modprobe time also: + * modprobe ib_path ib_ipath_debug=3 + */ + +#define __VERBS_INFO 0x1 /* generic low verbosity stuff */ +#define __VERBS_DBG 0x2 /* generic debug */ +#define __VERBS_VDBG 0x4 /* verbose debug */ +#define __VERBS_SMADBG 0x8000 /* sma packet debug */ + +#define _VERBS_INFO(fmt,...) \ + do { \ + if (unlikely(ib_ipath_debug&__VERBS_INFO)) \ + printk(KERN_INFO "%s: " fmt,"ib_ipath", \ + ##__VA_ARGS__); \ + } while(0) + +#define _VERBS_DBG(fmt,...) \ + do { \ + if (unlikely(ib_ipath_debug&__VERBS_DBG)) \ + printk(KERN_DEBUG "%s: " fmt, __func__, \ + ##__VA_ARGS__); \ + } while(0) + +#define _VERBS_VDBG(fmt,...) \ + do { \ + if (unlikely(ib_ipath_debug&__VERBS_VDBG)) \ + printk(KERN_DEBUG "%s: " fmt, __func__, \ + ##__VA_ARGS__); \ + } while(0) + +#define _VERBS_SMADBG(fmt,...) \ + do { \ + if (unlikely(ib_ipath_debug&__VERBS_SMADBG)) \ + printk(KERN_DEBUG "%s: " fmt, __func__, \ + ##__VA_ARGS__); \ + } while(0) + +#else /* ! _VERBS_DEBUGGING */ + +#define _VERBS_INFO(fmt,...) +#define _VERBS_DBG(fmt,...) +#define _VERBS_VDBG(fmt,...) +#define _VERBS_SMADBG(fmt,...) + +#endif /* _VERBS_DEBUGGING */ + +#endif /* _VERBS_DEBUG_H */ diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_allocator.c b/trunk/drivers/infiniband/hw/mthca/mthca_allocator.c index f930e55b58fc..9ba3211cef7c 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_allocator.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_allocator.c @@ -41,11 +41,9 @@ /* Trivial bitmap-based allocator */ u32 mthca_alloc(struct mthca_alloc *alloc) { - unsigned long flags; u32 obj; - spin_lock_irqsave(&alloc->lock, flags); - + spin_lock(&alloc->lock); obj = find_next_zero_bit(alloc->table, alloc->max, alloc->last); if (obj >= alloc->max) { alloc->top = (alloc->top + alloc->max) & alloc->mask; @@ -58,24 +56,19 @@ u32 mthca_alloc(struct mthca_alloc *alloc) } else obj = -1; - spin_unlock_irqrestore(&alloc->lock, flags); + spin_unlock(&alloc->lock); return obj; } void mthca_free(struct mthca_alloc *alloc, u32 obj) { - unsigned long flags; - obj &= alloc->max - 1; - - spin_lock_irqsave(&alloc->lock, flags); - + spin_lock(&alloc->lock); clear_bit(obj, alloc->table); alloc->last = min(alloc->last, obj); alloc->top = (alloc->top + alloc->max) & alloc->mask; - - spin_unlock_irqrestore(&alloc->lock, flags); + spin_unlock(&alloc->lock); } int mthca_alloc_init(struct mthca_alloc *alloc, u32 num, u32 mask, @@ -115,15 +108,14 @@ void mthca_alloc_cleanup(struct mthca_alloc *alloc) * serialize access to the array. */ -#define MTHCA_ARRAY_MASK (PAGE_SIZE / sizeof (void *) - 1) - void *mthca_array_get(struct mthca_array *array, int index) { int p = (index * sizeof (void *)) >> PAGE_SHIFT; - if (array->page_list[p].page) - return array->page_list[p].page[index & MTHCA_ARRAY_MASK]; - else + if (array->page_list[p].page) { + int i = index & (PAGE_SIZE / sizeof (void *) - 1); + return array->page_list[p].page[i]; + } else return NULL; } @@ -138,7 +130,8 @@ int mthca_array_set(struct mthca_array *array, int index, void *value) if (!array->page_list[p].page) return -ENOMEM; - array->page_list[p].page[index & MTHCA_ARRAY_MASK] = value; + array->page_list[p].page[index & (PAGE_SIZE / sizeof (void *) - 1)] = + value; ++array->page_list[p].used; return 0; @@ -151,8 +144,7 @@ void mthca_array_clear(struct mthca_array *array, int index) if (--array->page_list[p].used == 0) { free_page((unsigned long) array->page_list[p].page); array->page_list[p].page = NULL; - } else - array->page_list[p].page[index & MTHCA_ARRAY_MASK] = NULL; + } if (array->page_list[p].used < 0) pr_debug("Array %p index %d page %d with ref count %d < 0\n", diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_av.c b/trunk/drivers/infiniband/hw/mthca/mthca_av.c index 69599455aca2..e215041b2db9 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_av.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_av.c @@ -90,7 +90,7 @@ static enum ib_rate tavor_rate_to_ib(u8 mthca_rate, u8 port_rate) case MTHCA_RATE_TAVOR_1X: return IB_RATE_2_5_GBPS; case MTHCA_RATE_TAVOR_1X_DDR: return IB_RATE_5_GBPS; case MTHCA_RATE_TAVOR_4X: return IB_RATE_10_GBPS; - default: return mult_to_ib_rate(port_rate); + default: return port_rate; } } diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_catas.c b/trunk/drivers/infiniband/hw/mthca/mthca_catas.c index cd044ea2dfa4..c3bec7490f52 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_catas.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_catas.c @@ -34,7 +34,6 @@ #include #include -#include #include "mthca_dev.h" @@ -49,41 +48,9 @@ enum { static DEFINE_SPINLOCK(catas_lock); -static LIST_HEAD(catas_list); -static struct workqueue_struct *catas_wq; -static struct work_struct catas_work; - -static int catas_reset_disable; -module_param_named(catas_reset_disable, catas_reset_disable, int, 0644); -MODULE_PARM_DESC(catas_reset_disable, "disable reset on catastrophic event if nonzero"); - -static void catas_reset(void *work_ptr) -{ - struct mthca_dev *dev, *tmpdev; - LIST_HEAD(tlist); - int ret; - - mutex_lock(&mthca_device_mutex); - - spin_lock_irq(&catas_lock); - list_splice_init(&catas_list, &tlist); - spin_unlock_irq(&catas_lock); - - list_for_each_entry_safe(dev, tmpdev, &tlist, catas_err.list) { - ret = __mthca_restart_one(dev->pdev); - if (ret) - mthca_err(dev, "Reset failed (%d)\n", ret); - else - mthca_dbg(dev, "Reset succeeded\n"); - } - - mutex_unlock(&mthca_device_mutex); -} - static void handle_catas(struct mthca_dev *dev) { struct ib_event event; - unsigned long flags; const char *type; int i; @@ -115,14 +82,6 @@ static void handle_catas(struct mthca_dev *dev) for (i = 0; i < dev->catas_err.size; ++i) mthca_err(dev, " buf[%02x]: %08x\n", i, swab32(readl(dev->catas_err.map + i))); - - if (catas_reset_disable) - return; - - spin_lock_irqsave(&catas_lock, flags); - list_add(&dev->catas_err.list, &catas_list); - queue_work(catas_wq, &catas_work); - spin_unlock_irqrestore(&catas_lock, flags); } static void poll_catas(unsigned long dev_ptr) @@ -176,7 +135,6 @@ void mthca_start_catas_poll(struct mthca_dev *dev) dev->catas_err.timer.data = (unsigned long) dev; dev->catas_err.timer.function = poll_catas; dev->catas_err.timer.expires = jiffies + MTHCA_CATAS_POLL_INTERVAL; - INIT_LIST_HEAD(&dev->catas_err.list); add_timer(&dev->catas_err.timer); } @@ -195,24 +153,4 @@ void mthca_stop_catas_poll(struct mthca_dev *dev) dev->catas_err.addr), dev->catas_err.size * 4); } - - spin_lock_irq(&catas_lock); - list_del(&dev->catas_err.list); - spin_unlock_irq(&catas_lock); -} - -int __init mthca_catas_init(void) -{ - INIT_WORK(&catas_work, catas_reset, NULL); - - catas_wq = create_singlethread_workqueue("mthca_catas"); - if (!catas_wq) - return -ENOMEM; - - return 0; -} - -void mthca_catas_cleanup(void) -{ - destroy_workqueue(catas_wq); } diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c index 99a94d710935..deabc14b4ea4 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -34,7 +34,7 @@ * $Id: mthca_cmd.c 1349 2004-12-16 21:09:43Z roland $ */ -#include +#include #include #include #include diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_cq.c b/trunk/drivers/infiniband/hw/mthca/mthca_cq.c index e393681ba7d4..3e27a084257e 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_cq.c @@ -544,11 +544,11 @@ static inline int mthca_poll_one(struct mthca_dev *dev, wq = &(*cur_qp)->rq; wqe = be32_to_cpu(cqe->wqe); wqe_index = wqe >> wq->wqe_shift; - /* - * WQE addr == base - 1 might be reported in receive completion - * with error instead of (rq size - 1) by Sinai FW 1.0.800 and - * Arbel FW 5.1.400. This bug should be fixed in later FW revs. - */ + /* + * WQE addr == base - 1 might be reported in receive completion + * with error instead of (rq size - 1) by Sinai FW 1.0.800 and + * Arbel FW 5.1.400. This bug should be fixed in later FW revs. + */ if (unlikely(wqe_index < 0)) wqe_index = wq->max - 1; entry->wr_id = (*cur_qp)->wrid[wqe_index]; diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_dev.h b/trunk/drivers/infiniband/hw/mthca/mthca_dev.h index fe5cecf70fed..f8160b8de090 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/trunk/drivers/infiniband/hw/mthca/mthca_dev.h @@ -45,7 +45,6 @@ #include #include #include -#include #include @@ -284,11 +283,8 @@ struct mthca_catas_err { unsigned long stop; u32 size; struct timer_list timer; - struct list_head list; }; -extern struct mutex mthca_device_mutex; - struct mthca_dev { struct ib_device ib_dev; struct pci_dev *pdev; @@ -454,9 +450,6 @@ void mthca_unregister_device(struct mthca_dev *dev); void mthca_start_catas_poll(struct mthca_dev *dev); void mthca_stop_catas_poll(struct mthca_dev *dev); -int __mthca_restart_one(struct pci_dev *pdev); -int mthca_catas_init(void); -void mthca_catas_cleanup(void); int mthca_uar_alloc(struct mthca_dev *dev, struct mthca_uar *uar); void mthca_uar_free(struct mthca_dev *dev, struct mthca_uar *uar); @@ -513,7 +506,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, struct ib_srq_attr *attr, struct mthca_srq *srq); void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq); int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, - enum ib_srq_attr_mask attr_mask, struct ib_udata *udata); + enum ib_srq_attr_mask attr_mask); int mthca_query_srq(struct ib_srq *srq, struct ib_srq_attr *srq_attr); int mthca_max_srq_sge(struct mthca_dev *dev); void mthca_srq_event(struct mthca_dev *dev, u32 srqn, @@ -528,8 +521,7 @@ void mthca_qp_event(struct mthca_dev *dev, u32 qpn, enum ib_event_type event_type); int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr); -int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, - struct ib_udata *udata); +int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask); int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, struct ib_send_wr **bad_wr); int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_mad.c b/trunk/drivers/infiniband/hw/mthca/mthca_mad.c index 45e106f14807..d9bc030bcccc 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_mad.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_mad.c @@ -119,7 +119,7 @@ static void smp_snoop(struct ib_device *ibdev, mthca_update_rate(to_mdev(ibdev), port_num); update_sm_ah(to_mdev(ibdev), port_num, - be16_to_cpu(pinfo->sm_lid), + be16_to_cpu(pinfo->lid), pinfo->neighbormtu_mastersmsl & 0xf); event.device = ibdev; diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_main.c b/trunk/drivers/infiniband/hw/mthca/mthca_main.c index 47ea02148368..557cde3a4563 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_main.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_main.c @@ -80,8 +80,6 @@ static int tune_pci = 0; module_param(tune_pci, int, 0444); MODULE_PARM_DESC(tune_pci, "increase PCI burst from the default set by BIOS if nonzero"); -struct mutex mthca_device_mutex; - static const char mthca_version[] __devinitdata = DRV_NAME ": Mellanox InfiniBand HCA driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; @@ -969,26 +967,39 @@ static struct { } mthca_hca_table[] = { [TAVOR] = { .latest_fw = MTHCA_FW_VER(3, 4, 0), .flags = 0 }, - [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 600), + [ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 7, 400), .flags = MTHCA_FLAG_PCIE }, - [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 400), + [ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 1, 0), .flags = MTHCA_FLAG_MEMFREE | MTHCA_FLAG_PCIE }, - [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 1, 0), + [SINAI] = { .latest_fw = MTHCA_FW_VER(1, 0, 800), .flags = MTHCA_FLAG_MEMFREE | MTHCA_FLAG_PCIE | MTHCA_FLAG_SINAI_OPT } }; -static int __mthca_init_one(struct pci_dev *pdev, int hca_type) +static int __devinit mthca_init_one(struct pci_dev *pdev, + const struct pci_device_id *id) { + static int mthca_version_printed = 0; int ddr_hidden = 0; int err; struct mthca_dev *mdev; + if (!mthca_version_printed) { + printk(KERN_INFO "%s", mthca_version); + ++mthca_version_printed; + } + printk(KERN_INFO PFX "Initializing %s\n", pci_name(pdev)); + if (id->driver_data >= ARRAY_SIZE(mthca_hca_table)) { + printk(KERN_ERR PFX "%s has invalid driver data %lx\n", + pci_name(pdev), id->driver_data); + return -ENODEV; + } + err = pci_enable_device(pdev); if (err) { dev_err(&pdev->dev, "Cannot enable PCI device, " @@ -1054,7 +1065,7 @@ static int __mthca_init_one(struct pci_dev *pdev, int hca_type) mdev->pdev = pdev; - mdev->mthca_flags = mthca_hca_table[hca_type].flags; + mdev->mthca_flags = mthca_hca_table[id->driver_data].flags; if (ddr_hidden) mdev->mthca_flags |= MTHCA_FLAG_DDR_HIDDEN; @@ -1088,13 +1099,13 @@ static int __mthca_init_one(struct pci_dev *pdev, int hca_type) if (err) goto err_cmd; - if (mdev->fw_ver < mthca_hca_table[hca_type].latest_fw) { + if (mdev->fw_ver < mthca_hca_table[id->driver_data].latest_fw) { mthca_warn(mdev, "HCA FW version %d.%d.%d is old (%d.%d.%d is current).\n", (int) (mdev->fw_ver >> 32), (int) (mdev->fw_ver >> 16) & 0xffff, (int) (mdev->fw_ver & 0xffff), - (int) (mthca_hca_table[hca_type].latest_fw >> 32), - (int) (mthca_hca_table[hca_type].latest_fw >> 16) & 0xffff, - (int) (mthca_hca_table[hca_type].latest_fw & 0xffff)); + (int) (mthca_hca_table[id->driver_data].latest_fw >> 32), + (int) (mthca_hca_table[id->driver_data].latest_fw >> 16) & 0xffff, + (int) (mthca_hca_table[id->driver_data].latest_fw & 0xffff)); mthca_warn(mdev, "If you have problems, try updating your HCA FW.\n"); } @@ -1111,7 +1122,6 @@ static int __mthca_init_one(struct pci_dev *pdev, int hca_type) goto err_unregister; pci_set_drvdata(pdev, mdev); - mdev->hca_type = hca_type; return 0; @@ -1156,7 +1166,7 @@ static int __mthca_init_one(struct pci_dev *pdev, int hca_type) return err; } -static void __mthca_remove_one(struct pci_dev *pdev) +static void __devexit mthca_remove_one(struct pci_dev *pdev) { struct mthca_dev *mdev = pci_get_drvdata(pdev); u8 status; @@ -1201,51 +1211,6 @@ static void __mthca_remove_one(struct pci_dev *pdev) } } -int __mthca_restart_one(struct pci_dev *pdev) -{ - struct mthca_dev *mdev; - - mdev = pci_get_drvdata(pdev); - if (!mdev) - return -ENODEV; - __mthca_remove_one(pdev); - return __mthca_init_one(pdev, mdev->hca_type); -} - -static int __devinit mthca_init_one(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - static int mthca_version_printed = 0; - int ret; - - mutex_lock(&mthca_device_mutex); - - if (!mthca_version_printed) { - printk(KERN_INFO "%s", mthca_version); - ++mthca_version_printed; - } - - if (id->driver_data >= ARRAY_SIZE(mthca_hca_table)) { - printk(KERN_ERR PFX "%s has invalid driver data %lx\n", - pci_name(pdev), id->driver_data); - mutex_unlock(&mthca_device_mutex); - return -ENODEV; - } - - ret = __mthca_init_one(pdev, id->driver_data); - - mutex_unlock(&mthca_device_mutex); - - return ret; -} - -static void __devexit mthca_remove_one(struct pci_dev *pdev) -{ - mutex_lock(&mthca_device_mutex); - __mthca_remove_one(pdev); - mutex_unlock(&mthca_device_mutex); -} - static struct pci_device_id mthca_pci_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_TAVOR), .driver_data = TAVOR }, @@ -1283,24 +1248,13 @@ static int __init mthca_init(void) { int ret; - mutex_init(&mthca_device_mutex); - ret = mthca_catas_init(); - if (ret) - return ret; - ret = pci_register_driver(&mthca_driver); - if (ret < 0) { - mthca_catas_cleanup(); - return ret; - } - - return 0; + return ret < 0 ? ret : 0; } static void __exit mthca_cleanup(void) { pci_unregister_driver(&mthca_driver); - mthca_catas_cleanup(); } module_init(mthca_init); diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_provider.c b/trunk/drivers/infiniband/hw/mthca/mthca_provider.c index 981fe2eebdfa..230ae21db8fd 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_provider.c @@ -1287,8 +1287,12 @@ int mthca_register_device(struct mthca_dev *dev) (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | - (1ull << IB_USER_VERBS_CMD_DETACH_MCAST); - dev->ib_dev.node_type = RDMA_NODE_IB_CA; + (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) | + (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | + (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | + (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) | + (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ); + dev->ib_dev.node_type = IB_NODE_CA; dev->ib_dev.phys_port_cnt = dev->limits.num_ports; dev->ib_dev.dma_device = &dev->pdev->dev; dev->ib_dev.class_dev.dev = &dev->pdev->dev; @@ -1312,11 +1316,6 @@ int mthca_register_device(struct mthca_dev *dev) dev->ib_dev.modify_srq = mthca_modify_srq; dev->ib_dev.query_srq = mthca_query_srq; dev->ib_dev.destroy_srq = mthca_destroy_srq; - dev->ib_dev.uverbs_cmd_mask |= - (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | - (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | - (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) | - (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ); if (mthca_is_memfree(dev)) dev->ib_dev.post_srq_recv = mthca_arbel_post_srq_recv; diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_provider.h b/trunk/drivers/infiniband/hw/mthca/mthca_provider.h index 9a5bece3fa5c..8de2887ba15c 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_provider.h +++ b/trunk/drivers/infiniband/hw/mthca/mthca_provider.h @@ -136,8 +136,8 @@ struct mthca_ah { * We have one global lock that protects dev->cq/qp_table. Each * struct mthca_cq/qp also has its own lock. An individual qp lock * may be taken inside of an individual cq lock. Both cqs attached to - * a qp may be locked, with the cq with the lower cqn locked first. - * No other nesting should be done. + * a qp may be locked, with the send cq locked first. No other + * nesting should be done. * * Each struct mthca_cq/qp also has an ref count, protected by the * corresponding table lock. The pointer from the cq/qp_table to the diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_qp.c b/trunk/drivers/infiniband/hw/mthca/mthca_qp.c index 5e5c58b9920b..cd8b6721ac9c 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_qp.c @@ -99,10 +99,6 @@ enum { MTHCA_QP_BIT_RSC = 1 << 3 }; -enum { - MTHCA_SEND_DOORBELL_FENCE = 1 << 5 -}; - struct mthca_qp_path { __be32 port_pkey; u8 rnr_retry; @@ -408,7 +404,7 @@ static void to_ib_ah_attr(struct mthca_dev *dev, struct ib_ah_attr *ib_ah_attr, ib_ah_attr->sl = be32_to_cpu(path->sl_tclass_flowlabel) >> 28; ib_ah_attr->src_path_bits = path->g_mylmc & 0x7f; ib_ah_attr->static_rate = mthca_rate_to_ib(dev, - path->static_rate & 0xf, + path->static_rate & 0x7, ib_ah_attr->port_num); ib_ah_attr->ah_flags = (path->g_mylmc & (1 << 7)) ? IB_AH_GRH : 0; if (ib_ah_attr->ah_flags) { @@ -472,14 +468,10 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m if (qp->transport == RC || qp->transport == UC) { to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path); to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path); - qp_attr->alt_pkey_index = - be32_to_cpu(context->alt_path.port_pkey) & 0x7f; - qp_attr->alt_port_num = qp_attr->alt_ah_attr.port_num; } - qp_attr->pkey_index = be32_to_cpu(context->pri_path.port_pkey) & 0x7f; - qp_attr->port_num = - (be32_to_cpu(context->pri_path.port_pkey) >> 24) & 0x3; + qp_attr->pkey_index = be32_to_cpu(context->pri_path.port_pkey) & 0x7f; + qp_attr->alt_pkey_index = be32_to_cpu(context->alt_path.port_pkey) & 0x7f; /* qp_attr->en_sqd_async_notify is only applicable in modify qp */ qp_attr->sq_draining = mthca_state == MTHCA_QP_STATE_DRAINING; @@ -490,9 +482,11 @@ int mthca_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_m 1 << ((be32_to_cpu(context->params2) >> 21) & 0x7); qp_attr->min_rnr_timer = (be32_to_cpu(context->rnr_nextrecvpsn) >> 24) & 0x1f; + qp_attr->port_num = qp_attr->ah_attr.port_num; qp_attr->timeout = context->pri_path.ackto >> 3; qp_attr->retry_cnt = (be32_to_cpu(context->params1) >> 16) & 0x7; qp_attr->rnr_retry = context->pri_path.rnr_retry >> 5; + qp_attr->alt_port_num = qp_attr->alt_ah_attr.port_num; qp_attr->alt_timeout = context->alt_path.ackto >> 3; qp_init_attr->cap = qp_attr->cap; @@ -529,8 +523,7 @@ static int mthca_path_set(struct mthca_dev *dev, struct ib_ah_attr *ah, return 0; } -int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, - struct ib_udata *udata) +int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) { struct mthca_dev *dev = to_mdev(ibqp->device); struct mthca_qp *qp = to_mqp(ibqp); @@ -845,10 +838,11 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, * entries and reinitialize the QP. */ if (new_state == IB_QPS_RESET && !qp->ibqp.uobject) { - mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn, + mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq), qp->qpn, qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL); if (qp->ibqp.send_cq != qp->ibqp.recv_cq) - mthca_cq_clean(dev, to_mcq(qp->ibqp.send_cq), qp->qpn, NULL); + mthca_cq_clean(dev, to_mcq(qp->ibqp.recv_cq), qp->qpn, + qp->ibqp.srq ? to_msrq(qp->ibqp.srq) : NULL); mthca_wq_reset(&qp->sq); qp->sq.last = get_send_wqe(qp, qp->sq.max - 1); @@ -1265,32 +1259,6 @@ int mthca_alloc_qp(struct mthca_dev *dev, return 0; } -static void mthca_lock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq) -{ - if (send_cq == recv_cq) - spin_lock_irq(&send_cq->lock); - else if (send_cq->cqn < recv_cq->cqn) { - spin_lock_irq(&send_cq->lock); - spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING); - } else { - spin_lock_irq(&recv_cq->lock); - spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING); - } -} - -static void mthca_unlock_cqs(struct mthca_cq *send_cq, struct mthca_cq *recv_cq) -{ - if (send_cq == recv_cq) - spin_unlock_irq(&send_cq->lock); - else if (send_cq->cqn < recv_cq->cqn) { - spin_unlock(&recv_cq->lock); - spin_unlock_irq(&send_cq->lock); - } else { - spin_unlock(&send_cq->lock); - spin_unlock_irq(&recv_cq->lock); - } -} - int mthca_alloc_sqp(struct mthca_dev *dev, struct mthca_pd *pd, struct mthca_cq *send_cq, @@ -1343,13 +1311,17 @@ int mthca_alloc_sqp(struct mthca_dev *dev, * Lock CQs here, so that CQ polling code can do QP lookup * without taking a lock. */ - mthca_lock_cqs(send_cq, recv_cq); + spin_lock_irq(&send_cq->lock); + if (send_cq != recv_cq) + spin_lock(&recv_cq->lock); spin_lock(&dev->qp_table.lock); mthca_array_clear(&dev->qp_table.qp, mqpn); spin_unlock(&dev->qp_table.lock); - mthca_unlock_cqs(send_cq, recv_cq); + if (send_cq != recv_cq) + spin_unlock(&recv_cq->lock); + spin_unlock_irq(&send_cq->lock); err_out: dma_free_coherent(&dev->pdev->dev, sqp->header_buf_size, @@ -1383,7 +1355,9 @@ void mthca_free_qp(struct mthca_dev *dev, * Lock CQs here, so that CQ polling code can do QP lookup * without taking a lock. */ - mthca_lock_cqs(send_cq, recv_cq); + spin_lock_irq(&send_cq->lock); + if (send_cq != recv_cq) + spin_lock(&recv_cq->lock); spin_lock(&dev->qp_table.lock); mthca_array_clear(&dev->qp_table.qp, @@ -1391,7 +1365,9 @@ void mthca_free_qp(struct mthca_dev *dev, --qp->refcount; spin_unlock(&dev->qp_table.lock); - mthca_unlock_cqs(send_cq, recv_cq); + if (send_cq != recv_cq) + spin_unlock(&recv_cq->lock); + spin_unlock_irq(&send_cq->lock); wait_event(qp->wait, !get_qp_refcount(dev, qp)); @@ -1526,7 +1502,7 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, int i; int size; int size0 = 0; - u32 f0; + u32 f0 = 0; int ind; u8 op0 = 0; @@ -1710,8 +1686,6 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, if (!size0) { size0 = size; op0 = mthca_opcode[wr->opcode]; - f0 = wr->send_flags & IB_SEND_FENCE ? - MTHCA_SEND_DOORBELL_FENCE : 0; } ++ind; @@ -1869,7 +1843,7 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, int i; int size; int size0 = 0; - u32 f0; + u32 f0 = 0; int ind; u8 op0 = 0; @@ -2077,8 +2051,6 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, if (!size0) { size0 = size; op0 = mthca_opcode[wr->opcode]; - f0 = wr->send_flags & IB_SEND_FENCE ? - MTHCA_SEND_DOORBELL_FENCE : 0; } ++ind; diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_srq.c b/trunk/drivers/infiniband/hw/mthca/mthca_srq.c index 0f316c87bf64..b60a9d79ae54 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_srq.c @@ -358,7 +358,7 @@ void mthca_free_srq(struct mthca_dev *dev, struct mthca_srq *srq) } int mthca_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, - enum ib_srq_attr_mask attr_mask, struct ib_udata *udata) + enum ib_srq_attr_mask attr_mask) { struct mthca_dev *dev = to_mdev(ibsrq->device); struct mthca_srq *srq = to_msrq(ibsrq); diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_uar.c b/trunk/drivers/infiniband/hw/mthca/mthca_uar.c index 8b728486410d..8e9219842be4 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_uar.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_uar.c @@ -60,7 +60,7 @@ int mthca_init_uar_table(struct mthca_dev *dev) ret = mthca_alloc_init(&dev->uar_table.alloc, dev->limits.num_uars, dev->limits.num_uars - 1, - dev->limits.reserved_uars + 1); + dev->limits.reserved_uars); if (ret) return ret; diff --git a/trunk/drivers/infiniband/ulp/ipoib/Kconfig b/trunk/drivers/infiniband/ulp/ipoib/Kconfig index d74653d7de1c..13d6d01c72c0 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/Kconfig +++ b/trunk/drivers/infiniband/ulp/ipoib/Kconfig @@ -6,7 +6,8 @@ config INFINIBAND_IPOIB transports IP packets over InfiniBand so you can use your IB device as a fancy NIC. - See Documentation/infiniband/ipoib.txt for more information + The IPoIB protocol is defined by the IETF ipoib working + group: . config INFINIBAND_IPOIB_DEBUG bool "IP-over-InfiniBand debugging" if EMBEDDED diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h index 0b8a79d53a00..474aa214ab57 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib.h @@ -336,8 +336,6 @@ static inline void ipoib_unregister_debugfs(void) { } extern int ipoib_sendq_size; extern int ipoib_recvq_size; -extern struct ib_sa_client ipoib_sa_client; - #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG extern int ipoib_debug_level; diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c index f426a69d9a43..5033666b1481 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -169,129 +169,117 @@ static int ipoib_ib_post_receives(struct net_device *dev) return 0; } -static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) +static void ipoib_ib_handle_wc(struct net_device *dev, + struct ib_wc *wc) { struct ipoib_dev_priv *priv = netdev_priv(dev); - unsigned int wr_id = wc->wr_id & ~IPOIB_OP_RECV; - struct sk_buff *skb; - dma_addr_t addr; + unsigned int wr_id = wc->wr_id; - ipoib_dbg_data(priv, "recv completion: id %d, op %d, status: %d\n", + ipoib_dbg_data(priv, "called: id %d, op %d, status: %d\n", wr_id, wc->opcode, wc->status); - if (unlikely(wr_id >= ipoib_recvq_size)) { - ipoib_warn(priv, "recv completion event with wrid %d (> %d)\n", - wr_id, ipoib_recvq_size); - return; - } + if (wr_id & IPOIB_OP_RECV) { + wr_id &= ~IPOIB_OP_RECV; + + if (wr_id < ipoib_recvq_size) { + struct sk_buff *skb = priv->rx_ring[wr_id].skb; + dma_addr_t addr = priv->rx_ring[wr_id].mapping; + + if (unlikely(wc->status != IB_WC_SUCCESS)) { + if (wc->status != IB_WC_WR_FLUSH_ERR) + ipoib_warn(priv, "failed recv event " + "(status=%d, wrid=%d vend_err %x)\n", + wc->status, wr_id, wc->vendor_err); + dma_unmap_single(priv->ca->dma_device, addr, + IPOIB_BUF_SIZE, DMA_FROM_DEVICE); + dev_kfree_skb_any(skb); + priv->rx_ring[wr_id].skb = NULL; + return; + } - skb = priv->rx_ring[wr_id].skb; - addr = priv->rx_ring[wr_id].mapping; + /* + * If we can't allocate a new RX buffer, dump + * this packet and reuse the old buffer. + */ + if (unlikely(ipoib_alloc_rx_skb(dev, wr_id))) { + ++priv->stats.rx_dropped; + goto repost; + } - if (unlikely(wc->status != IB_WC_SUCCESS)) { - if (wc->status != IB_WC_WR_FLUSH_ERR) - ipoib_warn(priv, "failed recv event " - "(status=%d, wrid=%d vend_err %x)\n", - wc->status, wr_id, wc->vendor_err); - dma_unmap_single(priv->ca->dma_device, addr, - IPOIB_BUF_SIZE, DMA_FROM_DEVICE); - dev_kfree_skb_any(skb); - priv->rx_ring[wr_id].skb = NULL; - return; - } + ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n", + wc->byte_len, wc->slid); - /* - * If we can't allocate a new RX buffer, dump - * this packet and reuse the old buffer. - */ - if (unlikely(ipoib_alloc_rx_skb(dev, wr_id))) { - ++priv->stats.rx_dropped; - goto repost; - } + dma_unmap_single(priv->ca->dma_device, addr, + IPOIB_BUF_SIZE, DMA_FROM_DEVICE); - ipoib_dbg_data(priv, "received %d bytes, SLID 0x%04x\n", - wc->byte_len, wc->slid); + skb_put(skb, wc->byte_len); + skb_pull(skb, IB_GRH_BYTES); - dma_unmap_single(priv->ca->dma_device, addr, - IPOIB_BUF_SIZE, DMA_FROM_DEVICE); + if (wc->slid != priv->local_lid || + wc->src_qp != priv->qp->qp_num) { + skb->protocol = ((struct ipoib_header *) skb->data)->proto; + skb->mac.raw = skb->data; + skb_pull(skb, IPOIB_ENCAP_LEN); - skb_put(skb, wc->byte_len); - skb_pull(skb, IB_GRH_BYTES); + dev->last_rx = jiffies; + ++priv->stats.rx_packets; + priv->stats.rx_bytes += skb->len; - if (wc->slid != priv->local_lid || - wc->src_qp != priv->qp->qp_num) { - skb->protocol = ((struct ipoib_header *) skb->data)->proto; - skb->mac.raw = skb->data; - skb_pull(skb, IPOIB_ENCAP_LEN); + skb->dev = dev; + /* XXX get correct PACKET_ type here */ + skb->pkt_type = PACKET_HOST; + netif_rx_ni(skb); + } else { + ipoib_dbg_data(priv, "dropping loopback packet\n"); + dev_kfree_skb_any(skb); + } - dev->last_rx = jiffies; - ++priv->stats.rx_packets; - priv->stats.rx_bytes += skb->len; + repost: + if (unlikely(ipoib_ib_post_receive(dev, wr_id))) + ipoib_warn(priv, "ipoib_ib_post_receive failed " + "for buf %d\n", wr_id); + } else + ipoib_warn(priv, "completion event with wrid %d\n", + wr_id); - skb->dev = dev; - /* XXX get correct PACKET_ type here */ - skb->pkt_type = PACKET_HOST; - netif_rx_ni(skb); } else { - ipoib_dbg_data(priv, "dropping loopback packet\n"); - dev_kfree_skb_any(skb); - } + struct ipoib_tx_buf *tx_req; + unsigned long flags; -repost: - if (unlikely(ipoib_ib_post_receive(dev, wr_id))) - ipoib_warn(priv, "ipoib_ib_post_receive failed " - "for buf %d\n", wr_id); -} - -static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) -{ - struct ipoib_dev_priv *priv = netdev_priv(dev); - unsigned int wr_id = wc->wr_id; - struct ipoib_tx_buf *tx_req; - unsigned long flags; - - ipoib_dbg_data(priv, "send completion: id %d, op %d, status: %d\n", - wr_id, wc->opcode, wc->status); - - if (unlikely(wr_id >= ipoib_sendq_size)) { - ipoib_warn(priv, "send completion event with wrid %d (> %d)\n", - wr_id, ipoib_sendq_size); - return; - } + if (wr_id >= ipoib_sendq_size) { + ipoib_warn(priv, "completion event with wrid %d (> %d)\n", + wr_id, ipoib_sendq_size); + return; + } - tx_req = &priv->tx_ring[wr_id]; + ipoib_dbg_data(priv, "send complete, wrid %d\n", wr_id); - dma_unmap_single(priv->ca->dma_device, - pci_unmap_addr(tx_req, mapping), - tx_req->skb->len, - DMA_TO_DEVICE); + tx_req = &priv->tx_ring[wr_id]; - ++priv->stats.tx_packets; - priv->stats.tx_bytes += tx_req->skb->len; + dma_unmap_single(priv->ca->dma_device, + pci_unmap_addr(tx_req, mapping), + tx_req->skb->len, + DMA_TO_DEVICE); - dev_kfree_skb_any(tx_req->skb); + ++priv->stats.tx_packets; + priv->stats.tx_bytes += tx_req->skb->len; - spin_lock_irqsave(&priv->tx_lock, flags); - ++priv->tx_tail; - if (netif_queue_stopped(dev) && - test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags) && - priv->tx_head - priv->tx_tail <= ipoib_sendq_size >> 1) - netif_wake_queue(dev); - spin_unlock_irqrestore(&priv->tx_lock, flags); + dev_kfree_skb_any(tx_req->skb); - if (wc->status != IB_WC_SUCCESS && - wc->status != IB_WC_WR_FLUSH_ERR) - ipoib_warn(priv, "failed send event " - "(status=%d, wrid=%d vend_err %x)\n", - wc->status, wr_id, wc->vendor_err); -} + spin_lock_irqsave(&priv->tx_lock, flags); + ++priv->tx_tail; + if (netif_queue_stopped(dev) && + test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags) && + priv->tx_head - priv->tx_tail <= ipoib_sendq_size >> 1) + netif_wake_queue(dev); + spin_unlock_irqrestore(&priv->tx_lock, flags); -static void ipoib_ib_handle_wc(struct net_device *dev, struct ib_wc *wc) -{ - if (wc->wr_id & IPOIB_OP_RECV) - ipoib_ib_handle_rx_wc(dev, wc); - else - ipoib_ib_handle_tx_wc(dev, wc); + if (wc->status != IB_WC_SUCCESS && + wc->status != IB_WC_WR_FLUSH_ERR) + ipoib_warn(priv, "failed send event " + "(status=%d, wrid=%d vend_err %x)\n", + wc->status, wr_id, wc->vendor_err); + } } void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr) @@ -332,7 +320,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_tx_buf *tx_req; dma_addr_t addr; - if (unlikely(skb->len > dev->mtu + INFINIBAND_ALEN)) { + if (skb->len > dev->mtu + INFINIBAND_ALEN) { ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n", skb->len, dev->mtu + INFINIBAND_ALEN); ++priv->stats.tx_dropped; @@ -631,10 +619,8 @@ void ipoib_ib_dev_flush(void *_dev) * The device could have been brought down between the start and when * we get here, don't bring it back up if it's not configured up */ - if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) { + if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) ipoib_ib_dev_up(dev); - ipoib_mcast_restart_task(dev); - } mutex_lock(&priv->vlan_mutex); diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c index 1eaf00e9862c..cf71d2a5515c 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -40,6 +40,7 @@ #include #include +#include #include #include /* For ARPHRD_xxx */ @@ -81,8 +82,6 @@ static const u8 ipv4_bcast_addr[] = { struct workqueue_struct *ipoib_workqueue; -struct ib_sa_client ipoib_sa_client; - static void ipoib_add_one(struct ib_device *device); static void ipoib_remove_one(struct ib_device *device); @@ -337,8 +336,7 @@ void ipoib_flush_paths(struct net_device *dev) struct ipoib_path *path, *tp; LIST_HEAD(remove_list); - spin_lock_irq(&priv->tx_lock); - spin_lock(&priv->lock); + spin_lock_irq(&priv->lock); list_splice(&priv->path_list, &remove_list); INIT_LIST_HEAD(&priv->path_list); @@ -349,15 +347,12 @@ void ipoib_flush_paths(struct net_device *dev) list_for_each_entry_safe(path, tp, &remove_list, list) { if (path->query) ib_sa_cancel_query(path->query_id, path->query); - spin_unlock(&priv->lock); - spin_unlock_irq(&priv->tx_lock); + spin_unlock_irq(&priv->lock); wait_for_completion(&path->done); path_free(dev, path); - spin_lock_irq(&priv->tx_lock); - spin_lock(&priv->lock); + spin_lock_irq(&priv->lock); } - spin_unlock(&priv->lock); - spin_unlock_irq(&priv->tx_lock); + spin_unlock_irq(&priv->lock); } static void path_rec_completion(int status, @@ -464,7 +459,7 @@ static int path_rec_start(struct net_device *dev, init_completion(&path->done); path->query_id = - ib_sa_path_rec_get(&ipoib_sa_client, priv->ca, priv->port, + ib_sa_path_rec_get(priv->ca, priv->port, &path->pathrec, IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID | @@ -620,7 +615,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) struct ipoib_neigh *neigh; unsigned long flags; - if (unlikely(!spin_trylock_irqsave(&priv->tx_lock, flags))) + if (!spin_trylock_irqsave(&priv->tx_lock, flags)) return NETDEV_TX_LOCKED; /* @@ -633,7 +628,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_BUSY; } - if (likely(skb->dst && skb->dst->neighbour)) { + if (skb->dst && skb->dst->neighbour) { if (unlikely(!*to_ipoib_neigh(skb->dst->neighbour))) { ipoib_path_lookup(skb, dev); goto out; @@ -1112,16 +1107,13 @@ static void ipoib_add_one(struct ib_device *device) struct ipoib_dev_priv *priv; int s, e, p; - if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) - return; - dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); if (!dev_list) return; INIT_LIST_HEAD(dev_list); - if (device->node_type == RDMA_NODE_IB_SWITCH) { + if (device->node_type == IB_NODE_SWITCH) { s = 0; e = 0; } else { @@ -1145,9 +1137,6 @@ static void ipoib_remove_one(struct ib_device *device) struct ipoib_dev_priv *priv, *tmp; struct list_head *dev_list; - if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) - return; - dev_list = ib_get_client_data(device, &ipoib_client); list_for_each_entry_safe(priv, tmp, dev_list, list) { @@ -1192,16 +1181,13 @@ static int __init ipoib_init_module(void) goto err_fs; } - ib_sa_register_client(&ipoib_sa_client); - ret = ib_register_client(&ipoib_client); if (ret) - goto err_sa; + goto err_wq; return 0; -err_sa: - ib_sa_unregister_client(&ipoib_sa_client); +err_wq: destroy_workqueue(ipoib_workqueue); err_fs: @@ -1213,7 +1199,6 @@ static int __init ipoib_init_module(void) static void __exit ipoib_cleanup_module(void) { ib_unregister_client(&ipoib_client); - ib_sa_unregister_client(&ipoib_sa_client); ipoib_unregister_debugfs(); destroy_workqueue(ipoib_workqueue); } diff --git a/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 3faa1820f0e9..b5e6a7be603d 100644 --- a/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/trunk/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -326,7 +326,6 @@ ipoib_mcast_sendonly_join_complete(int status, /* Clear the busy flag so we try again */ clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags); - mcast->query = NULL; } complete(&mcast->done); @@ -361,7 +360,7 @@ static int ipoib_mcast_sendonly_join(struct ipoib_mcast *mcast) init_completion(&mcast->done); - ret = ib_sa_mcmember_rec_set(&ipoib_sa_client, priv->ca, priv->port, &rec, + ret = ib_sa_mcmember_rec_set(priv->ca, priv->port, &rec, IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID | IB_SA_MCMEMBER_REC_PKEY | @@ -472,32 +471,22 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, if (create) { comp_mask |= - IB_SA_MCMEMBER_REC_QKEY | - IB_SA_MCMEMBER_REC_MTU_SELECTOR | - IB_SA_MCMEMBER_REC_MTU | - IB_SA_MCMEMBER_REC_TRAFFIC_CLASS | - IB_SA_MCMEMBER_REC_RATE_SELECTOR | - IB_SA_MCMEMBER_REC_RATE | - IB_SA_MCMEMBER_REC_SL | - IB_SA_MCMEMBER_REC_FLOW_LABEL | - IB_SA_MCMEMBER_REC_HOP_LIMIT; + IB_SA_MCMEMBER_REC_QKEY | + IB_SA_MCMEMBER_REC_SL | + IB_SA_MCMEMBER_REC_FLOW_LABEL | + IB_SA_MCMEMBER_REC_TRAFFIC_CLASS; rec.qkey = priv->broadcast->mcmember.qkey; - rec.mtu_selector = IB_SA_EQ; - rec.mtu = priv->broadcast->mcmember.mtu; - rec.traffic_class = priv->broadcast->mcmember.traffic_class; - rec.rate_selector = IB_SA_EQ; - rec.rate = priv->broadcast->mcmember.rate; rec.sl = priv->broadcast->mcmember.sl; rec.flow_label = priv->broadcast->mcmember.flow_label; - rec.hop_limit = priv->broadcast->mcmember.hop_limit; + rec.traffic_class = priv->broadcast->mcmember.traffic_class; } init_completion(&mcast->done); - ret = ib_sa_mcmember_rec_set(&ipoib_sa_client, priv->ca, priv->port, - &rec, comp_mask, mcast->backoff * 1000, - GFP_ATOMIC, ipoib_mcast_join_complete, + ret = ib_sa_mcmember_rec_set(priv->ca, priv->port, &rec, comp_mask, + mcast->backoff * 1000, GFP_ATOMIC, + ipoib_mcast_join_complete, mcast, &mcast->query); if (ret < 0) { @@ -538,7 +527,7 @@ void ipoib_mcast_join_task(void *dev_ptr) priv->local_rate = attr.active_speed * ib_width_enum_to_int(attr.active_width); } else - ipoib_warn(priv, "ib_query_port failed\n"); + ipoib_warn(priv, "ib_query_port failed\n"); } if (!priv->broadcast) { @@ -691,7 +680,7 @@ static int ipoib_mcast_leave(struct net_device *dev, struct ipoib_mcast *mcast) * Just make one shot at leaving and don't wait for a reply; * if we fail, too bad. */ - ret = ib_sa_mcmember_rec_delete(&ipoib_sa_client, priv->ca, priv->port, &rec, + ret = ib_sa_mcmember_rec_delete(priv->ca, priv->port, &rec, IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID | IB_SA_MCMEMBER_REC_PKEY | @@ -805,7 +794,7 @@ void ipoib_mcast_dev_flush(struct net_device *dev) } if (priv->broadcast) { - rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree); + rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree); list_add_tail(&priv->broadcast->list, &remove_list); priv->broadcast = NULL; } diff --git a/trunk/drivers/infiniband/ulp/iser/Kconfig b/trunk/drivers/infiniband/ulp/iser/Kconfig index 365a1b5f19e0..fead87d1eff9 100644 --- a/trunk/drivers/infiniband/ulp/iser/Kconfig +++ b/trunk/drivers/infiniband/ulp/iser/Kconfig @@ -1,6 +1,6 @@ config INFINIBAND_ISER tristate "ISCSI RDMA Protocol" - depends on INFINIBAND && SCSI && INET + depends on INFINIBAND && SCSI select SCSI_ISCSI_ATTRS ---help--- Support for the ISCSI RDMA Protocol over InfiniBand. This diff --git a/trunk/drivers/infiniband/ulp/iser/iscsi_iser.c b/trunk/drivers/infiniband/ulp/iser/iscsi_iser.c index e9cf1a9f1e1c..34b0da5cfa0a 100644 --- a/trunk/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/trunk/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -378,6 +378,21 @@ iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn) return iser_conn_set_full_featured_mode(conn); } +static void +iscsi_iser_conn_terminate(struct iscsi_conn *conn) +{ + struct iscsi_iser_conn *iser_conn = conn->dd_data; + struct iser_conn *ib_conn = iser_conn->ib_conn; + + BUG_ON(!ib_conn); + /* starts conn teardown process, waits until all previously * + * posted buffers get flushed, deallocates all conn resources */ + iser_conn_terminate(ib_conn); + iser_conn->ib_conn = NULL; + conn->recv_lock = NULL; +} + + static struct iscsi_transport iscsi_iser_transport; static struct iscsi_cls_session * @@ -540,13 +555,13 @@ iscsi_iser_ep_poll(__u64 ep_handle, int timeout_ms) static void iscsi_iser_ep_disconnect(__u64 ep_handle) { - struct iser_conn *ib_conn; + struct iser_conn *ib_conn = iscsi_iser_ib_conn_lookup(ep_handle); - ib_conn = iscsi_iser_ib_conn_lookup(ep_handle); if (!ib_conn) return; iser_err("ib conn %p state %d\n",ib_conn, ib_conn->state); + iser_conn_terminate(ib_conn); } @@ -555,7 +570,6 @@ static struct scsi_host_template iscsi_iser_sht = { .queuecommand = iscsi_queuecommand, .can_queue = ISCSI_XMIT_CMDS_MAX - 1, .sg_tablesize = ISCSI_ISER_SG_TABLESIZE, - .max_sectors = 1024, .cmd_per_lun = ISCSI_MAX_CMD_PER_LUN, .eh_abort_handler = iscsi_eh_abort, .eh_host_reset_handler = iscsi_eh_host_reset, @@ -600,6 +614,9 @@ static struct iscsi_transport iscsi_iser_transport = { .get_session_param = iscsi_session_get_param, .start_conn = iscsi_iser_conn_start, .stop_conn = iscsi_conn_stop, + /* these are called as part of conn recovery */ + .suspend_conn_recv = NULL, /* FIXME is/how this relvant to iser? */ + .terminate_conn = iscsi_iser_conn_terminate, /* IO */ .send_pdu = iscsi_conn_send_pdu, .get_stats = iscsi_iser_conn_get_stats, diff --git a/trunk/drivers/infiniband/ulp/iser/iscsi_iser.h b/trunk/drivers/infiniband/ulp/iser/iscsi_iser.h index 7e1a411db2a3..3350ba690cfe 100644 --- a/trunk/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/trunk/drivers/infiniband/ulp/iser/iscsi_iser.h @@ -82,12 +82,8 @@ __func__ , ## arg); \ } while (0) -#define SHIFT_4K 12 -#define SIZE_4K (1UL << SHIFT_4K) -#define MASK_4K (~(SIZE_4K-1)) - /* support upto 512KB in one RDMA */ -#define ISCSI_ISER_SG_TABLESIZE (0x80000 >> SHIFT_4K) +#define ISCSI_ISER_SG_TABLESIZE (0x80000 >> PAGE_SHIFT) #define ISCSI_ISER_MAX_LUN 256 #define ISCSI_ISER_MAX_CMD_LEN 16 @@ -175,7 +171,6 @@ struct iser_mem_reg { u64 va; u64 len; void *mem_h; - int is_fmr; }; struct iser_regd_buf { diff --git a/trunk/drivers/infiniband/ulp/iser/iser_memory.c b/trunk/drivers/infiniband/ulp/iser/iser_memory.c index d0b03f426581..31950a522a1c 100644 --- a/trunk/drivers/infiniband/ulp/iser/iser_memory.c +++ b/trunk/drivers/infiniband/ulp/iser/iser_memory.c @@ -42,7 +42,6 @@ #include "iscsi_iser.h" #define ISER_KMALLOC_THRESHOLD 0x20000 /* 128K - kmalloc limit */ - /** * Decrements the reference count for the * registered buffer & releases it @@ -56,7 +55,7 @@ int iser_regd_buff_release(struct iser_regd_buf *regd_buf) if ((atomic_read(®d_buf->ref_count) == 0) || atomic_dec_and_test(®d_buf->ref_count)) { /* if we used the dma mr, unreg is just NOP */ - if (regd_buf->reg.is_fmr) + if (regd_buf->reg.rkey != 0) iser_unreg_mem(®d_buf->reg); if (regd_buf->dma_addr) { @@ -91,9 +90,9 @@ void iser_reg_single(struct iser_device *device, BUG_ON(dma_mapping_error(dma_addr)); regd_buf->reg.lkey = device->mr->lkey; + regd_buf->reg.rkey = 0; /* indicate there's no need to unreg */ regd_buf->reg.len = regd_buf->data_size; regd_buf->reg.va = dma_addr; - regd_buf->reg.is_fmr = 0; regd_buf->dma_addr = dma_addr; regd_buf->direction = direction; @@ -240,7 +239,7 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data, int i; /* compute the offset of first element */ - page_vec->offset = (u64) sg[0].offset & ~MASK_4K; + page_vec->offset = (u64) sg[0].offset; for (i = 0; i < data->dma_nents; i++) { total_sz += sg_dma_len(&sg[i]); @@ -248,30 +247,21 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data, first_addr = sg_dma_address(&sg[i]); last_addr = first_addr + sg_dma_len(&sg[i]); - start_aligned = !(first_addr & ~MASK_4K); - end_aligned = !(last_addr & ~MASK_4K); + start_aligned = !(first_addr & ~PAGE_MASK); + end_aligned = !(last_addr & ~PAGE_MASK); /* continue to collect page fragments till aligned or SG ends */ while (!end_aligned && (i + 1 < data->dma_nents)) { i++; total_sz += sg_dma_len(&sg[i]); last_addr = sg_dma_address(&sg[i]) + sg_dma_len(&sg[i]); - end_aligned = !(last_addr & ~MASK_4K); + end_aligned = !(last_addr & ~PAGE_MASK); } - /* handle the 1st page in the 1st DMA element */ - if (cur_page == 0) { - page = first_addr & MASK_4K; - page_vec->pages[cur_page] = page; - cur_page++; - page += SIZE_4K; - } else - page = first_addr; - - for (; page < last_addr; page += SIZE_4K) { - page_vec->pages[cur_page] = page; - cur_page++; - } + first_addr = first_addr & PAGE_MASK; + + for (page = first_addr; page < last_addr; page += PAGE_SIZE) + page_vec->pages[cur_page++] = page; } page_vec->data_size = total_sz; @@ -279,7 +269,8 @@ static int iser_sg_to_page_vec(struct iser_data_buf *data, return cur_page; } -#define IS_4K_ALIGNED(addr) ((((unsigned long)addr) & ~MASK_4K) == 0) +#define MASK_4K ((1UL << 12) - 1) /* 0xFFF */ +#define IS_4K_ALIGNED(addr) ((((unsigned long)addr) & MASK_4K) == 0) /** * iser_data_buf_aligned_len - Tries to determine the maximal correctly aligned @@ -329,9 +320,9 @@ static void iser_data_buf_dump(struct iser_data_buf *data) struct scatterlist *sg = (struct scatterlist *)data->buf; int i; - for (i = 0; i < data->dma_nents; i++) + for (i = 0; i < data->size; i++) iser_err("sg[%d] dma_addr:0x%lX page:0x%p " - "off:0x%x sz:0x%x dma_len:0x%x\n", + "off:%d sz:%d dma_len:%d\n", i, (unsigned long)sg_dma_address(&sg[i]), sg[i].page, sg[i].offset, sg[i].length,sg_dma_len(&sg[i])); @@ -361,7 +352,7 @@ static void iser_page_vec_build(struct iser_data_buf *data, page_vec->length = page_vec_len; - if (page_vec_len * SIZE_4K < page_vec->data_size) { + if (page_vec_len * PAGE_SIZE < page_vec->data_size) { iser_err("page_vec too short to hold this SG\n"); iser_data_buf_dump(data); iser_dump_page_vec(page_vec); @@ -379,18 +370,15 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask, enum iser_data_dir cmd_dir) { struct iser_conn *ib_conn = iser_ctask->iser_conn->ib_conn; - struct iser_device *device = ib_conn->device; struct iser_data_buf *mem = &iser_ctask->data[cmd_dir]; struct iser_regd_buf *regd_buf; int aligned_len; int err; - int i; - struct scatterlist *sg; regd_buf = &iser_ctask->rdma_regd[cmd_dir]; aligned_len = iser_data_buf_aligned_len(mem); - if (aligned_len != mem->dma_nents) { + if (aligned_len != mem->size) { iser_err("rdma alignment violation %d/%d aligned\n", aligned_len, mem->size); iser_data_buf_dump(mem); @@ -401,38 +389,10 @@ int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask, mem = &iser_ctask->data_copy[cmd_dir]; } - /* if there a single dma entry, FMR is not needed */ - if (mem->dma_nents == 1) { - sg = (struct scatterlist *)mem->buf; - - regd_buf->reg.lkey = device->mr->lkey; - regd_buf->reg.rkey = device->mr->rkey; - regd_buf->reg.len = sg_dma_len(&sg[0]); - regd_buf->reg.va = sg_dma_address(&sg[0]); - regd_buf->reg.is_fmr = 0; - - iser_dbg("PHYSICAL Mem.register: lkey: 0x%08X rkey: 0x%08X " - "va: 0x%08lX sz: %ld]\n", - (unsigned int)regd_buf->reg.lkey, - (unsigned int)regd_buf->reg.rkey, - (unsigned long)regd_buf->reg.va, - (unsigned long)regd_buf->reg.len); - } else { /* use FMR for multiple dma entries */ - iser_page_vec_build(mem, ib_conn->page_vec); - err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, ®d_buf->reg); - if (err) { - iser_data_buf_dump(mem); - iser_err("mem->dma_nents = %d (dlength = 0x%x)\n", mem->dma_nents, - ntoh24(iser_ctask->desc.iscsi_header.dlength)); - iser_err("page_vec: data_size = 0x%x, length = %d, offset = 0x%x\n", - ib_conn->page_vec->data_size, ib_conn->page_vec->length, - ib_conn->page_vec->offset); - for (i=0 ; ipage_vec->length ; i++) - iser_err("page_vec[%d] = 0x%llx\n", i, - (unsigned long long) ib_conn->page_vec->pages[i]); - return err; - } - } + iser_page_vec_build(mem, ib_conn->page_vec); + err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, ®d_buf->reg); + if (err) + return err; /* take a reference on this regd buf such that it will not be released * * (eg in send dto completion) before we get the scsi response */ diff --git a/trunk/drivers/infiniband/ulp/iser/iser_verbs.c b/trunk/drivers/infiniband/ulp/iser/iser_verbs.c index ecdca7fc1e4c..72febf1f8ff8 100644 --- a/trunk/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/trunk/drivers/infiniband/ulp/iser/iser_verbs.c @@ -88,9 +88,8 @@ static int iser_create_device_ib_res(struct iser_device *device) iser_cq_tasklet_fn, (unsigned long)device); - device->mr = ib_get_dma_mr(device->pd, IB_ACCESS_LOCAL_WRITE | - IB_ACCESS_REMOTE_WRITE | - IB_ACCESS_REMOTE_READ); + device->mr = ib_get_dma_mr(device->pd, + IB_ACCESS_LOCAL_WRITE); if (IS_ERR(device->mr)) goto dma_mr_err; @@ -151,7 +150,7 @@ static int iser_create_ib_conn_res(struct iser_conn *ib_conn) } ib_conn->page_vec->pages = (u64 *) (ib_conn->page_vec + 1); - params.page_shift = SHIFT_4K; + params.page_shift = PAGE_SHIFT; /* when the first/last SG element are not start/end * * page aligned, the map whould be of N+1 pages */ params.max_pages_per_fmr = ISCSI_ISER_SG_TABLESIZE + 1; @@ -605,9 +604,8 @@ int iser_reg_page_vec(struct iser_conn *ib_conn, mem_reg->lkey = mem->fmr->lkey; mem_reg->rkey = mem->fmr->rkey; - mem_reg->len = page_vec->length * SIZE_4K; + mem_reg->len = page_vec->length * PAGE_SIZE; mem_reg->va = io_addr; - mem_reg->is_fmr = 1; mem_reg->mem_h = (void *)mem; mem_reg->va += page_vec->offset; diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.c b/trunk/drivers/infiniband/ulp/srp/ib_srp.c index 44b9e5be6687..8f472e7113b4 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.c +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.c @@ -77,14 +77,6 @@ MODULE_PARM_DESC(topspin_workarounds, static const u8 topspin_oui[3] = { 0x00, 0x05, 0xad }; -static int mellanox_workarounds = 1; - -module_param(mellanox_workarounds, int, 0444); -MODULE_PARM_DESC(mellanox_workarounds, - "Enable workarounds for Mellanox SRP target bugs if != 0"); - -static const u8 mellanox_oui[3] = { 0x00, 0x02, 0xc9 }; - static void srp_add_one(struct ib_device *device); static void srp_remove_one(struct ib_device *device); static void srp_completion(struct ib_cq *cq, void *target_ptr); @@ -96,8 +88,6 @@ static struct ib_client srp_client = { .remove = srp_remove_one }; -static struct ib_sa_client srp_sa_client; - static inline struct srp_target_port *host_to_target(struct Scsi_Host *host) { return (struct srp_target_port *) host->hostdata; @@ -269,8 +259,7 @@ static int srp_lookup_path(struct srp_target_port *target) init_completion(&target->done); - target->path_query_id = ib_sa_path_rec_get(&srp_sa_client, - target->srp_host->dev->dev, + target->path_query_id = ib_sa_path_rec_get(target->srp_host->dev->dev, target->srp_host->port, &target->path, IB_SA_PATH_REC_DGID | @@ -333,7 +322,7 @@ static int srp_send_req(struct srp_target_port *target) req->priv.req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT); /* - * In the published SRP specification (draft rev. 16a), the + * In the published SRP specification (draft rev. 16a), the * port identifier format is 8 bytes of ID extension followed * by 8 bytes of GUID. Older drafts put the two halves in the * opposite order, so that the GUID comes first. @@ -537,10 +526,8 @@ static int srp_reconnect_target(struct srp_target_port *target) while (ib_poll_cq(target->cq, 1, &wc) > 0) ; /* nothing */ - spin_lock_irq(target->scsi_host->host_lock); list_for_each_entry_safe(req, tmp, &target->req_queue, list) srp_reset_req(target, req); - spin_unlock_irq(target->scsi_host->host_lock); target->rx_head = 0; target->tx_head = 0; @@ -580,7 +567,7 @@ static int srp_reconnect_target(struct srp_target_port *target) return ret; } -static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat, +static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat, int sg_cnt, struct srp_request *req, struct srp_direct_buf *buf) { @@ -590,15 +577,10 @@ static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat, int page_cnt; int i, j; int ret; - struct srp_device *dev = target->srp_host->dev; if (!dev->fmr_pool) return -ENODEV; - if ((sg_dma_address(&scat[0]) & ~dev->fmr_page_mask) && - mellanox_workarounds && !memcmp(&target->ioc_guid, mellanox_oui, 3)) - return -EINVAL; - len = page_cnt = 0; for (i = 0; i < sg_cnt; ++i) { if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) { @@ -701,7 +683,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target, buf->va = cpu_to_be64(sg_dma_address(scat)); buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey); buf->len = cpu_to_be32(sg_dma_len(scat)); - } else if (srp_map_fmr(target, scat, count, req, + } else if (srp_map_fmr(target->srp_host->dev, scat, count, req, (void *) cmd->add_data)) { /* * FMR mapping failed, and the scatterlist has more @@ -802,6 +784,13 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) spin_unlock_irqrestore(target->scsi_host->host_lock, flags); } +static void srp_reconnect_work(void *target_ptr) +{ + struct srp_target_port *target = target_ptr; + + srp_reconnect_target(target); +} + static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc) { struct srp_iu *iu; @@ -854,6 +843,7 @@ static void srp_completion(struct ib_cq *cq, void *target_ptr) { struct srp_target_port *target = target_ptr; struct ib_wc wc; + unsigned long flags; ib_req_notify_cq(cq, IB_CQ_NEXT_COMP); while (ib_poll_cq(cq, 1, &wc) > 0) { @@ -861,6 +851,10 @@ static void srp_completion(struct ib_cq *cq, void *target_ptr) printk(KERN_ERR PFX "failed %s status %d\n", wc.wr_id & SRP_OP_RECV ? "receive" : "send", wc.status); + spin_lock_irqsave(target->scsi_host->host_lock, flags); + if (target->state == SRP_TARGET_LIVE) + schedule_work(&target->work); + spin_unlock_irqrestore(target->scsi_host->host_lock, flags); break; } @@ -1452,28 +1446,12 @@ static ssize_t show_zero_req_lim(struct class_device *cdev, char *buf) return sprintf(buf, "%d\n", target->zero_req_lim); } -static ssize_t show_local_ib_port(struct class_device *cdev, char *buf) -{ - struct srp_target_port *target = host_to_target(class_to_shost(cdev)); - - return sprintf(buf, "%d\n", target->srp_host->port); -} - -static ssize_t show_local_ib_device(struct class_device *cdev, char *buf) -{ - struct srp_target_port *target = host_to_target(class_to_shost(cdev)); - - return sprintf(buf, "%s\n", target->srp_host->dev->dev->name); -} - -static CLASS_DEVICE_ATTR(id_ext, S_IRUGO, show_id_ext, NULL); -static CLASS_DEVICE_ATTR(ioc_guid, S_IRUGO, show_ioc_guid, NULL); -static CLASS_DEVICE_ATTR(service_id, S_IRUGO, show_service_id, NULL); -static CLASS_DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL); -static CLASS_DEVICE_ATTR(dgid, S_IRUGO, show_dgid, NULL); -static CLASS_DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL); -static CLASS_DEVICE_ATTR(local_ib_port, S_IRUGO, show_local_ib_port, NULL); -static CLASS_DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL); +static CLASS_DEVICE_ATTR(id_ext, S_IRUGO, show_id_ext, NULL); +static CLASS_DEVICE_ATTR(ioc_guid, S_IRUGO, show_ioc_guid, NULL); +static CLASS_DEVICE_ATTR(service_id, S_IRUGO, show_service_id, NULL); +static CLASS_DEVICE_ATTR(pkey, S_IRUGO, show_pkey, NULL); +static CLASS_DEVICE_ATTR(dgid, S_IRUGO, show_dgid, NULL); +static CLASS_DEVICE_ATTR(zero_req_lim, S_IRUGO, show_zero_req_lim, NULL); static struct class_device_attribute *srp_host_attrs[] = { &class_device_attr_id_ext, @@ -1482,8 +1460,6 @@ static struct class_device_attribute *srp_host_attrs[] = { &class_device_attr_pkey, &class_device_attr_dgid, &class_device_attr_zero_req_lim, - &class_device_attr_local_ib_port, - &class_device_attr_local_ib_device, NULL }; @@ -1714,6 +1690,8 @@ static ssize_t srp_create_target(struct class_device *class_dev, target->scsi_host = target_host; target->srp_host = host; + INIT_WORK(&target->work, srp_reconnect_work, target); + INIT_LIST_HEAD(&target->free_reqs); INIT_LIST_HEAD(&target->req_queue); for (i = 0; i < SRP_SQ_SIZE; ++i) { @@ -1902,7 +1880,7 @@ static void srp_add_one(struct ib_device *device) if (IS_ERR(srp_dev->fmr_pool)) srp_dev->fmr_pool = NULL; - if (device->node_type == RDMA_NODE_IB_SWITCH) { + if (device->node_type == IB_NODE_SWITCH) { s = 0; e = 0; } else { @@ -2001,12 +1979,9 @@ static int __init srp_init_module(void) return ret; } - ib_sa_register_client(&srp_sa_client); - ret = ib_register_client(&srp_client); if (ret) { printk(KERN_ERR PFX "couldn't register IB client\n"); - ib_sa_unregister_client(&srp_sa_client); class_unregister(&srp_class); return ret; } @@ -2017,7 +1992,6 @@ static int __init srp_init_module(void) static void __exit srp_cleanup_module(void) { ib_unregister_client(&srp_client); - ib_sa_unregister_client(&srp_sa_client); class_unregister(&srp_class); } diff --git a/trunk/drivers/input/evdev.c b/trunk/drivers/input/evdev.c index 4bf48188cc91..a29d5ceb00cf 100644 --- a/trunk/drivers/input/evdev.c +++ b/trunk/drivers/input/evdev.c @@ -127,10 +127,14 @@ static int evdev_open(struct inode * inode, struct file * file) { struct evdev_list *list; int i = iminor(inode) - EVDEV_MINOR_BASE; + int accept_err; if (i >= EVDEV_MINORS || !evdev_table[i] || !evdev_table[i]->exist) return -ENODEV; + if ((accept_err = input_accept_process(&(evdev_table[i]->handle), file))) + return accept_err; + if (!(list = kzalloc(sizeof(struct evdev_list), GFP_KERNEL))) return -ENOMEM; @@ -256,7 +260,7 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ if (evdev_event_from_user(buffer + retval, &event)) return -EFAULT; - input_inject_event(&list->evdev->handle, event.type, event.code, event.value); + input_event(list->evdev->handle.dev, event.type, event.code, event.value); retval += evdev_event_size(); } @@ -424,8 +428,8 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, if (get_user(v, ip + 1)) return -EFAULT; - input_inject_event(&evdev->handle, EV_REP, REP_DELAY, u); - input_inject_event(&evdev->handle, EV_REP, REP_PERIOD, v); + input_event(dev, EV_REP, REP_DELAY, u); + input_event(dev, EV_REP, REP_PERIOD, v); return 0; diff --git a/trunk/drivers/input/gameport/fm801-gp.c b/trunk/drivers/input/gameport/fm801-gp.c index 90de5afe03c2..47e93daa0fa7 100644 --- a/trunk/drivers/input/gameport/fm801-gp.c +++ b/trunk/drivers/input/gameport/fm801-gp.c @@ -106,10 +106,10 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device gp->gameport = port; gp->res_port = request_region(port->io, 0x10, "FM801 GP"); if (!gp->res_port) { + kfree(gp); + gameport_free_port(port); printk(KERN_DEBUG "fm801-gp: unable to grab region 0x%x-0x%x\n", port->io, port->io + 0x0f); - gameport_free_port(port); - kfree(gp); return -EBUSY; } diff --git a/trunk/drivers/input/gameport/gameport.c b/trunk/drivers/input/gameport/gameport.c index 3f47ae55c6f3..36644bff379d 100644 --- a/trunk/drivers/input/gameport/gameport.c +++ b/trunk/drivers/input/gameport/gameport.c @@ -53,7 +53,6 @@ static LIST_HEAD(gameport_list); static struct bus_type gameport_bus; -static void gameport_add_driver(struct gameport_driver *drv); static void gameport_add_port(struct gameport *gameport); static void gameport_destroy_port(struct gameport *gameport); static void gameport_reconnect_port(struct gameport *gameport); @@ -212,14 +211,8 @@ static void gameport_release_driver(struct gameport *gameport) static void gameport_find_driver(struct gameport *gameport) { - int error; - down_write(&gameport_bus.subsys.rwsem); - error = device_attach(&gameport->dev); - if (error < 0) - printk(KERN_WARNING - "gameport: device_attach() failed for %s (%s), error: %d\n", - gameport->phys, gameport->name, error); + device_attach(&gameport->dev); up_write(&gameport_bus.subsys.rwsem); } @@ -323,6 +316,7 @@ static void gameport_remove_duplicate_events(struct gameport_event *event) spin_unlock_irqrestore(&gameport_event_lock, flags); } + static struct gameport_event *gameport_get_event(void) { struct gameport_event *event; @@ -348,6 +342,7 @@ static struct gameport_event *gameport_get_event(void) static void gameport_handle_event(void) { struct gameport_event *event; + struct gameport_driver *gameport_drv; mutex_lock(&gameport_mutex); @@ -374,7 +369,8 @@ static void gameport_handle_event(void) break; case GAMEPORT_REGISTER_DRIVER: - gameport_add_driver(event->object); + gameport_drv = event->object; + driver_register(&gameport_drv->driver); break; default: @@ -536,7 +532,6 @@ static void gameport_init_port(struct gameport *gameport) if (gameport->parent) gameport->dev.parent = &gameport->parent->dev; - INIT_LIST_HEAD(&gameport->node); spin_lock_init(&gameport->timer_lock); init_timer(&gameport->poll_timer); gameport->poll_timer.function = gameport_run_poll_handler; @@ -549,8 +544,6 @@ static void gameport_init_port(struct gameport *gameport) */ static void gameport_add_port(struct gameport *gameport) { - int error; - if (gameport->parent) gameport->parent->child = gameport; @@ -565,13 +558,8 @@ static void gameport_add_port(struct gameport *gameport) printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n", gameport->name, gameport->phys, gameport->speed); - error = device_add(&gameport->dev); - if (error) - printk(KERN_ERR - "gameport: device_add() failed for %s (%s), error: %d\n", - gameport->phys, gameport->name, error); - else - gameport->registered = 1; + device_add(&gameport->dev); + gameport->registered = 1; } /* @@ -595,11 +583,10 @@ static void gameport_destroy_port(struct gameport *gameport) if (gameport->registered) { device_del(&gameport->dev); + list_del_init(&gameport->node); gameport->registered = 0; } - list_del_init(&gameport->node); - gameport_remove_pending_events(gameport); put_device(&gameport->dev); } @@ -717,22 +704,11 @@ static int gameport_driver_remove(struct device *dev) } static struct bus_type gameport_bus = { - .name = "gameport", - .probe = gameport_driver_probe, - .remove = gameport_driver_remove, + .name = "gameport", + .probe = gameport_driver_probe, + .remove = gameport_driver_remove, }; -static void gameport_add_driver(struct gameport_driver *drv) -{ - int error; - - error = driver_register(&drv->driver); - if (error) - printk(KERN_ERR - "gameport: driver_register() failed for %s, error: %d\n", - drv->driver.name, error); -} - void __gameport_register_driver(struct gameport_driver *drv, struct module *owner) { drv->driver.bus = &gameport_bus; @@ -802,24 +778,16 @@ void gameport_close(struct gameport *gameport) static int __init gameport_init(void) { - int error; + gameport_task = kthread_run(gameport_thread, NULL, "kgameportd"); + if (IS_ERR(gameport_task)) { + printk(KERN_ERR "gameport: Failed to start kgameportd\n"); + return PTR_ERR(gameport_task); + } gameport_bus.dev_attrs = gameport_device_attrs; gameport_bus.drv_attrs = gameport_driver_attrs; gameport_bus.match = gameport_bus_match; - error = bus_register(&gameport_bus); - if (error) { - printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error); - return error; - } - - gameport_task = kthread_run(gameport_thread, NULL, "kgameportd"); - if (IS_ERR(gameport_task)) { - bus_unregister(&gameport_bus); - error = PTR_ERR(gameport_task); - printk(KERN_ERR "gameport: Failed to start kgameportd, error: %d\n", error); - return error; - } + bus_register(&gameport_bus); return 0; } diff --git a/trunk/drivers/input/input.c b/trunk/drivers/input/input.c index 9cb4b9a54f01..a90486f5e491 100644 --- a/trunk/drivers/input/input.c +++ b/trunk/drivers/input/input.c @@ -35,16 +35,6 @@ static LIST_HEAD(input_handler_list); static struct input_handler *input_table[8]; -/** - * input_event() - report new input event - * @handle: device that generated the event - * @type: type of the event - * @code: event code - * @value: value of the event - * - * This function should be used by drivers implementing various input devices - * See also input_inject_event() - */ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { struct input_handle *handle; @@ -193,23 +183,6 @@ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, in } EXPORT_SYMBOL(input_event); -/** - * input_inject_event() - send input event from input handler - * @handle: input handle to send event through - * @type: type of the event - * @code: event code - * @value: value of the event - * - * Similar to input_event() but will ignore event if device is "grabbed" and handle - * injecting event is not the one that owns the device. - */ -void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value) -{ - if (!handle->dev->grab || handle->dev->grab == handle) - input_event(handle->dev, type, code, value); -} -EXPORT_SYMBOL(input_inject_event); - static void input_repeat_key(unsigned long data) { struct input_dev *dev = (void *) data; @@ -224,6 +197,15 @@ static void input_repeat_key(unsigned long data) mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD])); } +int input_accept_process(struct input_handle *handle, struct file *file) +{ + if (handle->dev->accept) + return handle->dev->accept(handle->dev, file); + + return 0; +} +EXPORT_SYMBOL(input_accept_process); + int input_grab_device(struct input_handle *handle) { if (handle->dev->grab) @@ -236,15 +218,8 @@ EXPORT_SYMBOL(input_grab_device); void input_release_device(struct input_handle *handle) { - struct input_dev *dev = handle->dev; - - if (dev->grab == handle) { - dev->grab = NULL; - - list_for_each_entry(handle, &dev->h_list, d_node) - if (handle->handler->start) - handle->handler->start(handle); - } + if (handle->dev->grab == handle) + handle->dev->grab = NULL; } EXPORT_SYMBOL(input_release_device); @@ -988,11 +963,8 @@ int input_register_device(struct input_dev *dev) list_for_each_entry(handler, &input_handler_list, node) if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) if ((id = input_match_device(handler->id_table, dev))) - if ((handle = handler->connect(handler, dev, id))) { + if ((handle = handler->connect(handler, dev, id))) input_link_handle(handle); - if (handler->start) - handler->start(handle); - } input_wakeup_procfs_readers(); @@ -1056,11 +1028,8 @@ void input_register_handler(struct input_handler *handler) list_for_each_entry(dev, &input_dev_list, node) if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) if ((id = input_match_device(handler->id_table, dev))) - if ((handle = handler->connect(handler, dev, id))) { + if ((handle = handler->connect(handler, dev, id))) input_link_handle(handle); - if (handler->start) - handler->start(handle); - } input_wakeup_procfs_readers(); } diff --git a/trunk/drivers/input/joystick/iforce/iforce-main.c b/trunk/drivers/input/joystick/iforce/iforce-main.c index b4914e7231f8..6d99e3c37884 100644 --- a/trunk/drivers/input/joystick/iforce/iforce-main.c +++ b/trunk/drivers/input/joystick/iforce/iforce-main.c @@ -79,7 +79,6 @@ static struct iforce_device iforce_device[] = { { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? - { 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce }, { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } }; @@ -223,22 +222,22 @@ static int iforce_erase_effect(struct input_dev *dev, int effect_id) int err = 0; struct iforce_core_effect* core_effect; - if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX) - return -EINVAL; - - core_effect = &iforce->core_effects[effect_id]; - /* Check who is trying to erase this effect */ - if (core_effect->owner != current->pid) { - printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, core_effect->owner); + if (iforce->core_effects[effect_id].owner != current->pid) { + printk(KERN_WARNING "iforce-main.c: %d tried to erase an effect belonging to %d\n", current->pid, iforce->core_effects[effect_id].owner); return -EACCES; } + if (effect_id < 0 || effect_id >= FF_EFFECTS_MAX) + return -EINVAL; + + core_effect = iforce->core_effects + effect_id; + if (test_bit(FF_MOD1_IS_USED, core_effect->flags)) - err = release_resource(&core_effect->mod1_chunk); + err = release_resource(&(iforce->core_effects[effect_id].mod1_chunk)); if (!err && test_bit(FF_MOD2_IS_USED, core_effect->flags)) - err = release_resource(&core_effect->mod2_chunk); + err = release_resource(&(iforce->core_effects[effect_id].mod2_chunk)); /*TODO: remember to change that if more FF_MOD* bits are added */ core_effect->flags[0] = 0; diff --git a/trunk/drivers/input/joystick/spaceball.c b/trunk/drivers/input/joystick/spaceball.c index 7a19ee052972..75eb5ca59992 100644 --- a/trunk/drivers/input/joystick/spaceball.c +++ b/trunk/drivers/input/joystick/spaceball.c @@ -50,7 +50,7 @@ MODULE_LICENSE("GPL"); */ #define SPACEBALL_MAX_LENGTH 128 -#define SPACEBALL_MAX_ID 9 +#define SPACEBALL_MAX_ID 8 #define SPACEBALL_1003 1 #define SPACEBALL_2003B 3 diff --git a/trunk/drivers/input/keyboard/atkbd.c b/trunk/drivers/input/keyboard/atkbd.c index a86afd0a5ef1..ce1f10e8984b 100644 --- a/trunk/drivers/input/keyboard/atkbd.c +++ b/trunk/drivers/input/keyboard/atkbd.c @@ -482,55 +482,6 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, return IRQ_HANDLED; } -static int atkbd_set_repeat_rate(struct atkbd *atkbd) -{ - const short period[32] = - { 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125, - 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 }; - const short delay[4] = - { 250, 500, 750, 1000 }; - - struct input_dev *dev = atkbd->dev; - unsigned char param; - int i = 0, j = 0; - - while (i < ARRAY_SIZE(period) - 1 && period[i] < dev->rep[REP_PERIOD]) - i++; - dev->rep[REP_PERIOD] = period[i]; - - while (j < ARRAY_SIZE(delay) - 1 && delay[j] < dev->rep[REP_DELAY]) - j++; - dev->rep[REP_DELAY] = delay[j]; - - param = i | (j << 5); - return ps2_command(&atkbd->ps2dev, ¶m, ATKBD_CMD_SETREP); -} - -static int atkbd_set_leds(struct atkbd *atkbd) -{ - struct input_dev *dev = atkbd->dev; - unsigned char param[2]; - - param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0) - | (test_bit(LED_NUML, dev->led) ? 2 : 0) - | (test_bit(LED_CAPSL, dev->led) ? 4 : 0); - if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS)) - return -1; - - if (atkbd->extra) { - param[0] = 0; - param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0) - | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0) - | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0) - | (test_bit(LED_MISC, dev->led) ? 0x10 : 0) - | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0); - if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS)) - return -1; - } - - return 0; -} - /* * atkbd_event_work() is used to complete processing of events that * can not be processed by input_event() which is often called from @@ -539,15 +490,47 @@ static int atkbd_set_leds(struct atkbd *atkbd) static void atkbd_event_work(void *data) { + const short period[32] = + { 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125, + 133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 }; + const short delay[4] = + { 250, 500, 750, 1000 }; + struct atkbd *atkbd = data; + struct input_dev *dev = atkbd->dev; + unsigned char param[2]; + int i, j; mutex_lock(&atkbd->event_mutex); - if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) - atkbd_set_leds(atkbd); + if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask)) { + param[0] = (test_bit(LED_SCROLLL, dev->led) ? 1 : 0) + | (test_bit(LED_NUML, dev->led) ? 2 : 0) + | (test_bit(LED_CAPSL, dev->led) ? 4 : 0); + ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS); + + if (atkbd->extra) { + param[0] = 0; + param[1] = (test_bit(LED_COMPOSE, dev->led) ? 0x01 : 0) + | (test_bit(LED_SLEEP, dev->led) ? 0x02 : 0) + | (test_bit(LED_SUSPEND, dev->led) ? 0x04 : 0) + | (test_bit(LED_MISC, dev->led) ? 0x10 : 0) + | (test_bit(LED_MUTE, dev->led) ? 0x20 : 0); + ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_EX_SETLEDS); + } + } - if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) - atkbd_set_repeat_rate(atkbd); + if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask)) { + i = j = 0; + while (i < 31 && period[i] < dev->rep[REP_PERIOD]) + i++; + while (j < 3 && delay[j] < dev->rep[REP_DELAY]) + j++; + dev->rep[REP_PERIOD] = period[i]; + dev->rep[REP_DELAY] = delay[j]; + param[0] = i | (j << 5); + ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETREP); + } mutex_unlock(&atkbd->event_mutex); } @@ -992,6 +975,7 @@ static int atkbd_reconnect(struct serio *serio) { struct atkbd *atkbd = serio_get_drvdata(serio); struct serio_driver *drv = serio->drv; + unsigned char param[1]; if (!atkbd || !drv) { printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n"); @@ -1001,6 +985,10 @@ static int atkbd_reconnect(struct serio *serio) atkbd_disable(atkbd); if (atkbd->write) { + param[0] = (test_bit(LED_SCROLLL, atkbd->dev->led) ? 1 : 0) + | (test_bit(LED_NUML, atkbd->dev->led) ? 2 : 0) + | (test_bit(LED_CAPSL, atkbd->dev->led) ? 4 : 0); + if (atkbd_probe(atkbd)) return -1; if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra)) @@ -1008,13 +996,8 @@ static int atkbd_reconnect(struct serio *serio) atkbd_activate(atkbd); -/* - * Restore repeat rate and LEDs (that were reset by atkbd_activate) - * to pre-resume state - */ - if (!atkbd->softrepeat) - atkbd_set_repeat_rate(atkbd); - atkbd_set_leds(atkbd); + if (ps2_command(&atkbd->ps2dev, param, ATKBD_CMD_SETLEDS)) + return -1; } atkbd_enable(atkbd); diff --git a/trunk/drivers/input/misc/wistron_btns.c b/trunk/drivers/input/misc/wistron_btns.c index de0f46dd9692..ccf0faeee5c1 100644 --- a/trunk/drivers/input/misc/wistron_btns.c +++ b/trunk/drivers/input/misc/wistron_btns.c @@ -94,7 +94,7 @@ static void call_bios(struct regs *regs) static ssize_t __init locate_wistron_bios(void __iomem *base) { - static unsigned char __initdata signature[] = + static const unsigned char __initdata signature[] = { 0x42, 0x21, 0x55, 0x30 }; ssize_t offset; @@ -343,7 +343,7 @@ static struct key_entry keymap_aopen_1559as[] = { * a list of buttons and their key codes (reported when loading this module * with force=1) and the output of dmidecode to $MODULE_AUTHOR. */ -static struct dmi_system_id dmi_ids[] __initdata = { +static struct dmi_system_id dmi_ids[] = { { .callback = dmi_matched, .ident = "Fujitsu-Siemens Amilo Pro V2000", diff --git a/trunk/drivers/input/mouse/logips2pp.c b/trunk/drivers/input/mouse/logips2pp.c index 54b696cfe1e3..2f0d28840810 100644 --- a/trunk/drivers/input/mouse/logips2pp.c +++ b/trunk/drivers/input/mouse/logips2pp.c @@ -238,7 +238,8 @@ static struct ps2pp_info *get_model_info(unsigned char model) { 100, PS2PP_KIND_MX, /* MX510 */ PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, - { 111, PS2PP_KIND_MX, PS2PP_WHEEL | PS2PP_SIDE_BTN }, /* MX300 reports task button as side */ + { 111, PS2PP_KIND_MX, /* MX300 */ + PS2PP_WHEEL | PS2PP_EXTRA_BTN | PS2PP_TASK_BTN }, { 112, PS2PP_KIND_MX, /* MX500 */ PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN | PS2PP_EXTRA_BTN | PS2PP_NAV_BTN }, diff --git a/trunk/drivers/input/mouse/psmouse-base.c b/trunk/drivers/input/mouse/psmouse-base.c index 343afa38f4c2..8bc9f51ae6c2 100644 --- a/trunk/drivers/input/mouse/psmouse-base.c +++ b/trunk/drivers/input/mouse/psmouse-base.c @@ -485,6 +485,13 @@ static int im_explorer_detect(struct psmouse *psmouse, int set_properties) param[0] = 40; ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); + param[0] = 200; + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); + param[0] = 200; + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); + param[0] = 60; + ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE); + if (set_properties) { set_bit(BTN_MIDDLE, psmouse->dev->keybit); set_bit(REL_WHEEL, psmouse->dev->relbit); diff --git a/trunk/drivers/input/mouse/trackpoint.c b/trunk/drivers/input/mouse/trackpoint.c index ae5871a0e060..6d9ec9ab1b90 100644 --- a/trunk/drivers/input/mouse/trackpoint.c +++ b/trunk/drivers/input/mouse/trackpoint.c @@ -183,26 +183,21 @@ static struct attribute_group trackpoint_attr_group = { .attrs = trackpoint_attrs, }; -static int trackpoint_start_protocol(struct psmouse *psmouse, unsigned char *firmware_id) +static void trackpoint_disconnect(struct psmouse *psmouse) { - unsigned char param[2] = { 0 }; - - if (ps2_command(&psmouse->ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID))) - return -1; - - if (param[0] != TP_MAGIC_IDENT) - return -1; - - if (firmware_id) - *firmware_id = param[1]; + sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group); - return 0; + kfree(psmouse->private); + psmouse->private = NULL; } static int trackpoint_sync(struct psmouse *psmouse) { - struct trackpoint_data *tp = psmouse->private; unsigned char toggle; + struct trackpoint_data *tp = psmouse->private; + + if (!tp) + return -1; /* Disable features that may make device unusable with this driver */ trackpoint_read(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, &toggle); @@ -268,38 +263,27 @@ static void trackpoint_defaults(struct trackpoint_data *tp) tp->ext_dev = TP_DEF_EXT_DEV; } -static void trackpoint_disconnect(struct psmouse *psmouse) -{ - sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group); - - kfree(psmouse->private); - psmouse->private = NULL; -} - -static int trackpoint_reconnect(struct psmouse *psmouse) -{ - if (trackpoint_start_protocol(psmouse, NULL)) - return -1; - - if (trackpoint_sync(psmouse)) - return -1; - - return 0; -} - int trackpoint_detect(struct psmouse *psmouse, int set_properties) { struct trackpoint_data *priv; struct ps2dev *ps2dev = &psmouse->ps2dev; unsigned char firmware_id; unsigned char button_info; + unsigned char param[2]; + + param[0] = param[1] = 0; - if (trackpoint_start_protocol(psmouse, &firmware_id)) + if (ps2_command(ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID))) + return -1; + + if (param[0] != TP_MAGIC_IDENT) return -1; if (!set_properties) return 0; + firmware_id = param[1]; + if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) { printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n"); button_info = 0; @@ -312,7 +296,7 @@ int trackpoint_detect(struct psmouse *psmouse, int set_properties) psmouse->vendor = "IBM"; psmouse->name = "TrackPoint"; - psmouse->reconnect = trackpoint_reconnect; + psmouse->reconnect = trackpoint_sync; psmouse->disconnect = trackpoint_disconnect; trackpoint_defaults(priv); diff --git a/trunk/drivers/input/serio/libps2.c b/trunk/drivers/input/serio/libps2.c index ed202f2f251a..61a6f977846f 100644 --- a/trunk/drivers/input/serio/libps2.c +++ b/trunk/drivers/input/serio/libps2.c @@ -177,11 +177,6 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) return -1; } - if (send && !param) { - WARN_ON(1); - return -1; - } - mutex_lock_nested(&ps2dev->cmd_mutex, SINGLE_DEPTH_NESTING); serio_pause_rx(ps2dev->serio); diff --git a/trunk/drivers/input/serio/serio.c b/trunk/drivers/input/serio/serio.c index 3e76ad71c9a0..6521034bc933 100644 --- a/trunk/drivers/input/serio/serio.c +++ b/trunk/drivers/input/serio/serio.c @@ -62,7 +62,6 @@ static LIST_HEAD(serio_list); static struct bus_type serio_bus; -static void serio_add_driver(struct serio_driver *drv); static void serio_add_port(struct serio *serio); static void serio_destroy_port(struct serio *serio); static void serio_reconnect_port(struct serio *serio); @@ -141,14 +140,8 @@ static void serio_release_driver(struct serio *serio) static void serio_find_driver(struct serio *serio) { - int error; - down_write(&serio_bus.subsys.rwsem); - error = device_attach(&serio->dev); - if (error < 0) - printk(KERN_WARNING - "serio: device_attach() failed for %s (%s), error: %d\n", - serio->phys, serio->name, error); + device_attach(&serio->dev); up_write(&serio_bus.subsys.rwsem); } @@ -279,6 +272,7 @@ static struct serio_event *serio_get_event(void) static void serio_handle_event(void) { struct serio_event *event; + struct serio_driver *serio_drv; mutex_lock(&serio_mutex); @@ -310,7 +304,8 @@ static void serio_handle_event(void) break; case SERIO_REGISTER_DRIVER: - serio_add_driver(event->object); + serio_drv = event->object; + driver_register(&serio_drv->driver); break; default: @@ -530,7 +525,6 @@ static void serio_init_port(struct serio *serio) __module_get(THIS_MODULE); - INIT_LIST_HEAD(&serio->node); spin_lock_init(&serio->lock); mutex_init(&serio->drv_mutex); device_initialize(&serio->dev); @@ -548,8 +542,6 @@ static void serio_init_port(struct serio *serio) */ static void serio_add_port(struct serio *serio) { - int error; - if (serio->parent) { serio_pause_rx(serio->parent); serio->parent->child = serio; @@ -559,19 +551,9 @@ static void serio_add_port(struct serio *serio) list_add_tail(&serio->node, &serio_list); if (serio->start) serio->start(serio); - error = device_add(&serio->dev); - if (error) - printk(KERN_ERR - "serio: device_add() failed for %s (%s), error: %d\n", - serio->phys, serio->name, error); - else { - serio->registered = 1; - error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group); - if (error) - printk(KERN_ERR - "serio: sysfs_create_group() failed for %s (%s), error: %d\n", - serio->phys, serio->name, error); - } + device_add(&serio->dev); + sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group); + serio->registered = 1; } /* @@ -601,10 +583,10 @@ static void serio_destroy_port(struct serio *serio) if (serio->registered) { sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group); device_del(&serio->dev); + list_del_init(&serio->node); serio->registered = 0; } - list_del_init(&serio->node); serio_remove_pending_events(serio); put_device(&serio->dev); } @@ -774,17 +756,6 @@ static struct bus_type serio_bus = { .remove = serio_driver_remove, }; -static void serio_add_driver(struct serio_driver *drv) -{ - int error; - - error = driver_register(&drv->driver); - if (error) - printk(KERN_ERR - "serio: driver_register() failed for %s, error: %d\n", - drv->driver.name, error); -} - void __serio_register_driver(struct serio_driver *drv, struct module *owner) { drv->driver.bus = &serio_bus; @@ -932,26 +903,18 @@ irqreturn_t serio_interrupt(struct serio *serio, static int __init serio_init(void) { - int error; + serio_task = kthread_run(serio_thread, NULL, "kseriod"); + if (IS_ERR(serio_task)) { + printk(KERN_ERR "serio: Failed to start kseriod\n"); + return PTR_ERR(serio_task); + } serio_bus.dev_attrs = serio_device_attrs; serio_bus.drv_attrs = serio_driver_attrs; serio_bus.match = serio_bus_match; serio_bus.uevent = serio_uevent; serio_bus.resume = serio_resume; - error = bus_register(&serio_bus); - if (error) { - printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error); - return error; - } - - serio_task = kthread_run(serio_thread, NULL, "kseriod"); - if (IS_ERR(serio_task)) { - bus_unregister(&serio_bus); - error = PTR_ERR(serio_task); - printk(KERN_ERR "serio: Failed to start kseriod, error: %d\n", error); - return error; - } + bus_register(&serio_bus); return 0; } diff --git a/trunk/drivers/isdn/hardware/eicon/divasync.h b/trunk/drivers/isdn/hardware/eicon/divasync.h index af3eb9e795b5..0a5be7f969f2 100644 --- a/trunk/drivers/isdn/hardware/eicon/divasync.h +++ b/trunk/drivers/isdn/hardware/eicon/divasync.h @@ -256,6 +256,7 @@ typedef struct #define NO_ORDER_CHECK_MASK 0x00000010 #define LOW_CHANNEL_MASK 0x00000020 #define NO_HSCX30_MASK 0x00000040 +#define MODE_MASK 0x00000080 #define SET_BOARD 0x00001000 #define SET_CRC4 0x00030000 #define SET_L1_TRISTATE 0x00040000 diff --git a/trunk/drivers/macintosh/Kconfig b/trunk/drivers/macintosh/Kconfig index d5d649f5ccdb..f5fe7fb4b3ad 100644 --- a/trunk/drivers/macintosh/Kconfig +++ b/trunk/drivers/macintosh/Kconfig @@ -90,15 +90,6 @@ config ADB_PMU_LED and the ide-disk LED trigger and configure appropriately through sysfs. -config ADB_PMU_LED_IDE - bool "Use front LED as IDE LED by default" - depends on ADB_PMU_LED - select LEDS_TRIGGERS - select LEDS_TRIGGER_IDE_DISK - help - This option makes the front LED default to the IDE trigger - so that it blinks on IDE activity. - config PMAC_SMU bool "Support for SMU based PowerMacs" depends on PPC_PMAC64 @@ -109,7 +100,7 @@ config PMAC_SMU config PMAC_APM_EMU tristate "APM emulation" - depends on PPC_PMAC && PPC32 && PM && ADB_PMU + depends on PPC_PMAC && PPC32 && PM config PMAC_MEDIABAY bool "Support PowerBook hotswap media bay" @@ -124,6 +115,8 @@ config PMAC_BACKLIGHT bool "Backlight control for LCD screens" depends on ADB_PMU && FB = y && (BROKEN || !PPC64) select FB_BACKLIGHT + select BACKLIGHT_CLASS_DEVICE + select BACKLIGHT_LCD_SUPPORT help Say Y here to enable Macintosh specific extensions of the generic backlight code. With this enabled, the brightness keys on older diff --git a/trunk/drivers/macintosh/adbhid.c b/trunk/drivers/macintosh/adbhid.c index efd51e01c06e..545be1ed6927 100644 --- a/trunk/drivers/macintosh/adbhid.c +++ b/trunk/drivers/macintosh/adbhid.c @@ -46,10 +46,13 @@ #include #ifdef CONFIG_PPC_PMAC -#include #include #endif +#ifdef CONFIG_PMAC_BACKLIGHT +#include +#endif + MODULE_AUTHOR("Franz Sirl "); #define KEYB_KEYREG 0 /* register # for key up/down data */ @@ -234,6 +237,11 @@ static struct adb_ids keyboard_ids; static struct adb_ids mouse_ids; static struct adb_ids buttons_ids; +#ifdef CONFIG_PMAC_BACKLIGHT +/* Exported to via-pmu.c */ +int disable_kernel_backlight = 0; +#endif /* CONFIG_PMAC_BACKLIGHT */ + /* Kind of keyboard, see Apple technote 1152 */ #define ADB_KEYBOARD_UNKNOWN 0 #define ADB_KEYBOARD_ANSI 0x0100 @@ -519,7 +527,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto case 0xa: /* brightness decrease */ #ifdef CONFIG_PMAC_BACKLIGHT - if (down) + if (!disable_kernel_backlight && down) pmac_backlight_key_down(); #endif input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down); @@ -527,7 +535,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto case 0x9: /* brightness increase */ #ifdef CONFIG_PMAC_BACKLIGHT - if (down) + if (!disable_kernel_backlight && down) pmac_backlight_key_up(); #endif input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down); diff --git a/trunk/drivers/macintosh/macio_asic.c b/trunk/drivers/macintosh/macio_asic.c index d56216067549..82657bc86d19 100644 --- a/trunk/drivers/macintosh/macio_asic.c +++ b/trunk/drivers/macintosh/macio_asic.c @@ -139,9 +139,7 @@ static int macio_uevent(struct device *dev, char **envp, int num_envp, { struct macio_dev * macio_dev; struct of_device * of; - char *scratch; - const char *compat, *compat2; - + char *scratch, *compat, *compat2; int i = 0; int length, cplen, cplen2, seen = 0; @@ -175,7 +173,7 @@ static int macio_uevent(struct device *dev, char **envp, int num_envp, * it's not really legal to split it out with commas. We split it * up using a number of environment variables instead. */ - compat = get_property(of->node, "compatible", &cplen); + compat = (char *) get_property(of->node, "compatible", &cplen); compat2 = compat; cplen2= cplen; while (compat && cplen > 0) { @@ -456,7 +454,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, struct resource *parent_res) { struct macio_dev *dev; - const u32 *reg; + u32 *reg; if (np == NULL) return NULL; @@ -491,7 +489,7 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, #endif MAX_NODE_NAME_SIZE, np->name); } else { - reg = get_property(np, "reg", NULL); + reg = (u32 *)get_property(np, "reg", NULL); sprintf(dev->ofdev.dev.bus_id, "%1d.%08x:%.*s", chip->lbus.index, reg ? *reg : 0, MAX_NODE_NAME_SIZE, np->name); diff --git a/trunk/drivers/macintosh/macio_sysfs.c b/trunk/drivers/macintosh/macio_sysfs.c index 8566bdfdd4b8..cae24a13526a 100644 --- a/trunk/drivers/macintosh/macio_sysfs.c +++ b/trunk/drivers/macintosh/macio_sysfs.c @@ -16,12 +16,12 @@ static ssize_t compatible_show (struct device *dev, struct device_attribute *attr, char *buf) { struct of_device *of; - const char *compat; + char *compat; int cplen; int length = 0; of = &to_macio_device (dev)->ofdev; - compat = get_property(of->node, "compatible", &cplen); + compat = (char *) get_property(of->node, "compatible", &cplen); if (!compat) { *buf = '\0'; return 0; @@ -42,12 +42,12 @@ static ssize_t modalias_show (struct device *dev, struct device_attribute *attr, char *buf) { struct of_device *of; - const char *compat; + char *compat; int cplen; int length; of = &to_macio_device (dev)->ofdev; - compat = get_property(of->node, "compatible", &cplen); + compat = (char *) get_property (of->node, "compatible", &cplen); if (!compat) compat = "", cplen = 1; length = sprintf (buf, "of:N%sT%s", of->node->name, of->node->type); buf += length; diff --git a/trunk/drivers/macintosh/smu.c b/trunk/drivers/macintosh/smu.c index 090e40fc5013..00ef46898147 100644 --- a/trunk/drivers/macintosh/smu.c +++ b/trunk/drivers/macintosh/smu.c @@ -454,7 +454,7 @@ EXPORT_SYMBOL(smu_present); int __init smu_init (void) { struct device_node *np; - const u32 *data; + u32 *data; np = of_find_node_by_type(NULL, "smu"); if (np == NULL) @@ -490,7 +490,7 @@ int __init smu_init (void) printk(KERN_ERR "SMU: Can't find doorbell GPIO !\n"); goto fail; } - data = get_property(smu->db_node, "reg", NULL); + data = (u32 *)get_property(smu->db_node, "reg", NULL); if (data == NULL) { of_node_put(smu->db_node); smu->db_node = NULL; @@ -511,7 +511,7 @@ int __init smu_init (void) smu->msg_node = of_find_node_by_name(NULL, "smu-interrupt"); if (smu->msg_node == NULL) break; - data = get_property(smu->msg_node, "reg", NULL); + data = (u32 *)get_property(smu->msg_node, "reg", NULL); if (data == NULL) { of_node_put(smu->msg_node); smu->msg_node = NULL; @@ -982,11 +982,11 @@ static struct smu_sdbp_header *smu_create_sdb_partition(int id) /* Note: Only allowed to return error code in pointers (using ERR_PTR) * when interruptible is 1 */ -const struct smu_sdbp_header *__smu_get_sdb_partition(int id, - unsigned int *size, int interruptible) +struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, + int interruptible) { char pname[32]; - const struct smu_sdbp_header *part; + struct smu_sdbp_header *part; if (!smu) return NULL; @@ -1003,7 +1003,8 @@ const struct smu_sdbp_header *__smu_get_sdb_partition(int id, } else mutex_lock(&smu_part_access); - part = get_property(smu->of_node, pname, size); + part = (struct smu_sdbp_header *)get_property(smu->of_node, + pname, size); if (part == NULL) { DPRINTK("trying to extract from SMU ...\n"); part = smu_create_sdb_partition(id); @@ -1014,7 +1015,7 @@ const struct smu_sdbp_header *__smu_get_sdb_partition(int id, return part; } -const struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) { return __smu_get_sdb_partition(id, size, 0); } @@ -1093,7 +1094,7 @@ static ssize_t smu_write(struct file *file, const char __user *buf, pp->mode = smu_file_events; return 0; } else if (hdr.cmdtype == SMU_CMDTYPE_GET_PARTITION) { - const struct smu_sdbp_header *part; + struct smu_sdbp_header *part; part = __smu_get_sdb_partition(hdr.cmd, NULL, 1); if (part == NULL) return -EINVAL; diff --git a/trunk/drivers/macintosh/therm_adt746x.c b/trunk/drivers/macintosh/therm_adt746x.c index a0f30d0853ea..7f86478bdd36 100644 --- a/trunk/drivers/macintosh/therm_adt746x.c +++ b/trunk/drivers/macintosh/therm_adt746x.c @@ -47,7 +47,7 @@ static u8 FAN_SPD_SET[2] = {0x30, 0x31}; static u8 default_limits_local[3] = {70, 50, 70}; /* local, sensor1, sensor2 */ static u8 default_limits_chip[3] = {80, 65, 80}; /* local, sensor1, sensor2 */ -static const char *sensor_location[3] = {NULL, NULL, NULL}; +static char *sensor_location[3] = {NULL, NULL, NULL}; static int limit_adjust = 0; static int fan_speed = -1; @@ -553,7 +553,7 @@ static int __init thermostat_init(void) { struct device_node* np; - const u32 *prop; + u32 *prop; int i = 0, offset = 0; np = of_find_node_by_name(NULL, "fan"); @@ -566,13 +566,13 @@ thermostat_init(void) else return -ENODEV; - prop = get_property(np, "hwsensor-params-version", NULL); + prop = (u32 *)get_property(np, "hwsensor-params-version", NULL); printk(KERN_INFO "adt746x: version %d (%ssupported)\n", *prop, (*prop == 1)?"":"un"); if (*prop != 1) return -ENODEV; - prop = get_property(np, "reg", NULL); + prop = (u32 *)get_property(np, "reg", NULL); if (!prop) return -ENODEV; diff --git a/trunk/drivers/macintosh/therm_pm72.c b/trunk/drivers/macintosh/therm_pm72.c index d00c0c37a12e..c1fe0b368f76 100644 --- a/trunk/drivers/macintosh/therm_pm72.c +++ b/trunk/drivers/macintosh/therm_pm72.c @@ -95,17 +95,6 @@ * - Use min/max macros here or there * - Latest darwin updated U3H min fan speed to 20% PWM * - * July. 06, 2006 : 1.3 - * - Fix setting of RPM fans on Xserve G5 (they were going too fast) - * - Add missing slots fan control loop for Xserve G5 - * - Lower fixed slots fan speed from 50% to 40% on desktop G5s. We - * still can't properly implement the control loop for these, so let's - * reduce the noise a little bit, it appears that 40% still gives us - * a pretty good air flow - * - Add code to "tickle" the FCU regulary so it doesn't think that - * we are gone while in fact, the machine just didn't need any fan - * speed change lately - * */ #include @@ -132,7 +121,7 @@ #include "therm_pm72.h" -#define VERSION "1.3" +#define VERSION "1.2b2" #undef DEBUG @@ -157,7 +146,6 @@ static struct basckside_pid_params backside_params; static struct backside_pid_state backside_state; static struct drives_pid_state drives_state; static struct dimm_pid_state dimms_state; -static struct slots_pid_state slots_state; static int state; static int cpu_count; static int cpu_pid_type; @@ -166,8 +154,7 @@ static struct completion ctrl_complete; static int critical_state; static int rackmac; static s32 dimm_output_clamp; -static int fcu_rpm_shift; -static int fcu_tickle_ticks; + static DECLARE_MUTEX(driver_lock); /* @@ -508,20 +495,13 @@ static int start_fcu(void) rc = fan_write_reg(0x2e, &buf, 1); if (rc < 0) return -EIO; - rc = fan_read_reg(0, &buf, 1); - if (rc < 0) - return -EIO; - fcu_rpm_shift = (buf == 1) ? 2 : 3; - printk(KERN_DEBUG "FCU Initialized, RPM fan shift is %d\n", - fcu_rpm_shift); - return 0; } static int set_rpm_fan(int fan_index, int rpm) { unsigned char buf[2]; - int rc, id, min, max; + int rc, id; if (fcu_fans[fan_index].type != FCU_FAN_RPM) return -EINVAL; @@ -529,15 +509,12 @@ static int set_rpm_fan(int fan_index, int rpm) if (id == FCU_FAN_ABSENT_ID) return -EINVAL; - min = 2400 >> fcu_rpm_shift; - max = 56000 >> fcu_rpm_shift; - - if (rpm < min) - rpm = min; - else if (rpm > max) - rpm = max; - buf[0] = rpm >> (8 - fcu_rpm_shift); - buf[1] = rpm << fcu_rpm_shift; + if (rpm < 300) + rpm = 300; + else if (rpm > 8191) + rpm = 8191; + buf[0] = rpm >> 5; + buf[1] = rpm << 3; rc = fan_write_reg(0x10 + (id * 2), buf, 2); if (rc < 0) return -EIO; @@ -574,7 +551,7 @@ static int get_rpm_fan(int fan_index, int programmed) if (rc != 2) return -EIO; - return (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift; + return (buf[0] << 5) | buf[1] >> 3; } static int set_pwm_fan(int fan_index, int pwm) @@ -632,26 +609,6 @@ static int get_pwm_fan(int fan_index) return (buf[0] * 1000) / 2559; } -static void tickle_fcu(void) -{ - int pwm; - - pwm = get_pwm_fan(SLOTS_FAN_PWM_INDEX); - - DBG("FCU Tickle, slots fan is: %d\n", pwm); - if (pwm < 0) - pwm = 100; - - if (!rackmac) { - pwm = SLOTS_FAN_DEFAULT_PWM; - } else if (pwm < SLOTS_PID_OUTPUT_MIN) - pwm = SLOTS_PID_OUTPUT_MIN; - - /* That is hopefully enough to make the FCU happy */ - set_pwm_fan(SLOTS_FAN_PWM_INDEX, pwm); -} - - /* * Utility routine to read the CPU calibration EEPROM data * from the device-tree @@ -660,7 +617,7 @@ static int read_eeprom(int cpu, struct mpu_data *out) { struct device_node *np; char nodename[64]; - const u8 *data; + u8 *data; int len; /* prom.c routine for finding a node by path is a bit brain dead @@ -673,7 +630,7 @@ static int read_eeprom(int cpu, struct mpu_data *out) printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid node from device-tree\n"); return -ENODEV; } - data = get_property(np, "cpuid", &len); + data = (u8 *)get_property(np, "cpuid", &len); if (data == NULL) { printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid property from device-tree\n"); of_node_put(np); @@ -758,9 +715,6 @@ BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm) BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp) BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm) -BUILD_SHOW_FUNC_FIX(slots_temperature, slots_state.last_temp) -BUILD_SHOW_FUNC_INT(slots_fan_pwm, slots_state.pwm) - BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp) static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL); @@ -781,9 +735,6 @@ static DEVICE_ATTR(backside_fan_pwm,S_IRUGO,show_backside_fan_pwm,NULL); static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL); static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL); -static DEVICE_ATTR(slots_temperature,S_IRUGO,show_slots_temperature,NULL); -static DEVICE_ATTR(slots_fan_pwm,S_IRUGO,show_slots_fan_pwm,NULL); - static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL); /* @@ -1125,9 +1076,6 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state) fan_min = dimm_output_clamp; fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan); - DBG(" CPU min mpu = %d, min dimm = %d\n", - state->mpu.rminn_intake_fan, dimm_output_clamp); - state->rpm = max(state->rpm, (int)fan_min); state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan); state->intake_rpm = state->rpm; @@ -1336,7 +1284,7 @@ static int init_backside_state(struct backside_pid_state *state) */ u3 = of_find_node_by_path("/u3@0,f8000000"); if (u3 != NULL) { - const u32 *vers = get_property(u3, "device-rev", NULL); + u32 *vers = (u32 *)get_property(u3, "device-rev", NULL); if (vers) if (((*vers) & 0x3f) < 0x34) u3h = 0; @@ -1426,8 +1374,7 @@ static void do_monitor_drives(struct drives_pid_state *state) DBG(" current rpm: %d\n", state->rpm); /* Get some sensor readings */ - temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, - DS1775_TEMP)) << 8; + temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, DS1775_TEMP)) << 8; state->last_temp = temp; DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp), FIX32TOPRINT(DRIVES_PID_INPUT_TARGET)); @@ -1628,7 +1575,7 @@ static int init_dimms_state(struct dimm_pid_state *state) } /* - * Dispose of the state data for the DIMM control loop + * Dispose of the state data for the drives control loop */ static void dispose_dimms_state(struct dimm_pid_state *state) { @@ -1641,127 +1588,6 @@ static void dispose_dimms_state(struct dimm_pid_state *state) state->monitor = NULL; } -/* - * Slots fan control loop - */ -static void do_monitor_slots(struct slots_pid_state *state) -{ - s32 temp, integral, derivative; - s64 integ_p, deriv_p, prop_p, sum; - int i, rc; - - if (--state->ticks != 0) - return; - state->ticks = SLOTS_PID_INTERVAL; - - DBG("slots:\n"); - - /* Check fan status */ - rc = get_pwm_fan(SLOTS_FAN_PWM_INDEX); - if (rc < 0) { - printk(KERN_WARNING "Error %d reading slots fan !\n", rc); - /* XXX What do we do now ? */ - } else - state->pwm = rc; - DBG(" current pwm: %d\n", state->pwm); - - /* Get some sensor readings */ - temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, - DS1775_TEMP)) << 8; - state->last_temp = temp; - DBG(" temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp), - FIX32TOPRINT(SLOTS_PID_INPUT_TARGET)); - - /* Store temperature and error in history array */ - state->cur_sample = (state->cur_sample + 1) % SLOTS_PID_HISTORY_SIZE; - state->sample_history[state->cur_sample] = temp; - state->error_history[state->cur_sample] = temp - SLOTS_PID_INPUT_TARGET; - - /* If first loop, fill the history table */ - if (state->first) { - for (i = 0; i < (SLOTS_PID_HISTORY_SIZE - 1); i++) { - state->cur_sample = (state->cur_sample + 1) % - SLOTS_PID_HISTORY_SIZE; - state->sample_history[state->cur_sample] = temp; - state->error_history[state->cur_sample] = - temp - SLOTS_PID_INPUT_TARGET; - } - state->first = 0; - } - - /* Calculate the integral term */ - sum = 0; - integral = 0; - for (i = 0; i < SLOTS_PID_HISTORY_SIZE; i++) - integral += state->error_history[i]; - integral *= SLOTS_PID_INTERVAL; - DBG(" integral: %08x\n", integral); - integ_p = ((s64)SLOTS_PID_G_r) * (s64)integral; - DBG(" integ_p: %d\n", (int)(integ_p >> 36)); - sum += integ_p; - - /* Calculate the derivative term */ - derivative = state->error_history[state->cur_sample] - - state->error_history[(state->cur_sample + SLOTS_PID_HISTORY_SIZE - 1) - % SLOTS_PID_HISTORY_SIZE]; - derivative /= SLOTS_PID_INTERVAL; - deriv_p = ((s64)SLOTS_PID_G_d) * (s64)derivative; - DBG(" deriv_p: %d\n", (int)(deriv_p >> 36)); - sum += deriv_p; - - /* Calculate the proportional term */ - prop_p = ((s64)SLOTS_PID_G_p) * (s64)(state->error_history[state->cur_sample]); - DBG(" prop_p: %d\n", (int)(prop_p >> 36)); - sum += prop_p; - - /* Scale sum */ - sum >>= 36; - - DBG(" sum: %d\n", (int)sum); - state->pwm = (s32)sum; - - state->pwm = max(state->pwm, SLOTS_PID_OUTPUT_MIN); - state->pwm = min(state->pwm, SLOTS_PID_OUTPUT_MAX); - - DBG("** DRIVES PWM: %d\n", (int)state->pwm); - set_pwm_fan(SLOTS_FAN_PWM_INDEX, state->pwm); -} - -/* - * Initialize the state structure for the slots bay fan control loop - */ -static int init_slots_state(struct slots_pid_state *state) -{ - state->ticks = 1; - state->first = 1; - state->pwm = 50; - - state->monitor = attach_i2c_chip(XSERVE_SLOTS_LM75, "slots_temp"); - if (state->monitor == NULL) - return -ENODEV; - - device_create_file(&of_dev->dev, &dev_attr_slots_temperature); - device_create_file(&of_dev->dev, &dev_attr_slots_fan_pwm); - - return 0; -} - -/* - * Dispose of the state data for the slots control loop - */ -static void dispose_slots_state(struct slots_pid_state *state) -{ - if (state->monitor == NULL) - return; - - device_remove_file(&of_dev->dev, &dev_attr_slots_temperature); - device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm); - - detach_i2c_chip(state->monitor); - state->monitor = NULL; -} - - static int call_critical_overtemp(void) { char *argv[] = { critical_overtemp_path, NULL }; @@ -1791,17 +1617,14 @@ static int main_control_loop(void *x) goto out; } - /* Set the PCI fan once for now on non-RackMac */ - if (!rackmac) - set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM); + /* Set the PCI fan once for now */ + set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM); /* Initialize ADCs */ initialize_adc(&cpu_state[0]); if (cpu_state[1].monitor != NULL) initialize_adc(&cpu_state[1]); - fcu_tickle_ticks = FCU_TICKLE_TICKS; - up(&driver_lock); while (state == state_attached) { @@ -1811,12 +1634,6 @@ static int main_control_loop(void *x) down(&driver_lock); - /* Tickle the FCU just in case */ - if (--fcu_tickle_ticks < 0) { - fcu_tickle_ticks = FCU_TICKLE_TICKS; - tickle_fcu(); - } - /* First, we always calculate the new DIMMs state on an Xserve */ if (rackmac) do_monitor_dimms(&dimms_state); @@ -1837,9 +1654,7 @@ static int main_control_loop(void *x) } /* Then, the rest */ do_monitor_backside(&backside_state); - if (rackmac) - do_monitor_slots(&slots_state); - else + if (!rackmac) do_monitor_drives(&drives_state); up(&driver_lock); @@ -1881,7 +1696,6 @@ static void dispose_control_loops(void) dispose_cpu_state(&cpu_state[1]); dispose_backside_state(&backside_state); dispose_drives_state(&drives_state); - dispose_slots_state(&slots_state); dispose_dimms_state(&dimms_state); } @@ -1931,8 +1745,6 @@ static int create_control_loops(void) goto fail; if (rackmac && init_dimms_state(&dimms_state)) goto fail; - if (rackmac && init_slots_state(&slots_state)) - goto fail; if (!rackmac && init_drives_state(&drives_state)) goto fail; @@ -2111,8 +1923,8 @@ static void fcu_lookup_fans(struct device_node *fcu_node) while ((np = of_get_next_child(fcu_node, np)) != NULL) { int type = -1; - const char *loc; - const u32 *reg; + char *loc; + u32 *reg; DBG(" control: %s, type: %s\n", np->name, np->type); @@ -2128,8 +1940,8 @@ static void fcu_lookup_fans(struct device_node *fcu_node) continue; /* Lookup for a matching location */ - loc = get_property(np, "location", NULL); - reg = get_property(np, "reg", NULL); + loc = (char *)get_property(np, "location", NULL); + reg = (u32 *)get_property(np, "reg", NULL); if (loc == NULL || reg == NULL) continue; DBG(" matching location: %s, reg: 0x%08x\n", loc, *reg); diff --git a/trunk/drivers/macintosh/therm_pm72.h b/trunk/drivers/macintosh/therm_pm72.h index 393cc9df94e1..fc7e9b7ecaf2 100644 --- a/trunk/drivers/macintosh/therm_pm72.h +++ b/trunk/drivers/macintosh/therm_pm72.h @@ -105,7 +105,6 @@ static char * critical_overtemp_path = "/sbin/critical_overtemp"; #define DRIVES_DALLAS_ID 0x94 #define BACKSIDE_MAX_ID 0x98 #define XSERVE_DIMMS_LM87 0x25a -#define XSERVE_SLOTS_LM75 0x290 /* * Some MAX6690, DS1775, LM87 register definitions @@ -199,7 +198,7 @@ struct drives_pid_state #define SLOTS_FAN_PWM_DEFAULT_ID 2 #define SLOTS_FAN_PWM_INDEX 2 -#define SLOTS_FAN_DEFAULT_PWM 40 /* Do better here ! */ +#define SLOTS_FAN_DEFAULT_PWM 50 /* Do better here ! */ /* @@ -207,7 +206,7 @@ struct drives_pid_state */ #define DIMM_PID_G_d 0 #define DIMM_PID_G_p 0 -#define DIMM_PID_G_r 0x06553600 +#define DIMM_PID_G_r 0x6553600 #define DIMM_PID_INPUT_TARGET 3276800 #define DIMM_PID_INTERVAL 1 #define DIMM_PID_OUTPUT_MAX 14000 @@ -227,31 +226,6 @@ struct dimm_pid_state }; -/* - * PID factors for the Xserve Slots control loop - */ -#define SLOTS_PID_G_d 0 -#define SLOTS_PID_G_p 0 -#define SLOTS_PID_G_r 0x00100000 -#define SLOTS_PID_INPUT_TARGET 3200000 -#define SLOTS_PID_INTERVAL 1 -#define SLOTS_PID_OUTPUT_MAX 100 -#define SLOTS_PID_OUTPUT_MIN 20 -#define SLOTS_PID_HISTORY_SIZE 20 - -struct slots_pid_state -{ - int ticks; - struct i2c_client * monitor; - s32 sample_history[SLOTS_PID_HISTORY_SIZE]; - s32 error_history[SLOTS_PID_HISTORY_SIZE]; - int cur_sample; - s32 last_temp; - int first; - int pwm; -}; - - /* Desktops */ @@ -309,9 +283,6 @@ struct cpu_pid_state s32 pump_max; }; -/* Tickle FCU every 10 seconds */ -#define FCU_TICKLE_TICKS 10 - /* * Driver state */ diff --git a/trunk/drivers/macintosh/therm_windtunnel.c b/trunk/drivers/macintosh/therm_windtunnel.c index 738faab1b22c..c7d1c290cb0c 100644 --- a/trunk/drivers/macintosh/therm_windtunnel.c +++ b/trunk/drivers/macintosh/therm_windtunnel.c @@ -484,14 +484,14 @@ struct apple_thermal_info { static int __init g4fan_init( void ) { - const struct apple_thermal_info *info; + struct apple_thermal_info *info; struct device_node *np; init_MUTEX( &x.lock ); if( !(np=of_find_node_by_name(NULL, "power-mgt")) ) return -ENODEV; - info = get_property(np, "thermal-info", NULL); + info = (struct apple_thermal_info*)get_property(np, "thermal-info", NULL); of_node_put(np); if( !info || !machine_is_compatible("PowerMac3,6") ) diff --git a/trunk/drivers/macintosh/via-cuda.c b/trunk/drivers/macintosh/via-cuda.c index 7512d1c15207..69d5452fd22f 100644 --- a/trunk/drivers/macintosh/via-cuda.c +++ b/trunk/drivers/macintosh/via-cuda.c @@ -123,7 +123,7 @@ int __init find_via_cuda(void) { struct adb_request req; phys_addr_t taddr; - const u32 *reg; + u32 *reg; int err; if (vias != 0) @@ -132,7 +132,7 @@ int __init find_via_cuda(void) if (vias == 0) return 0; - reg = get_property(vias, "reg", NULL); + reg = (u32 *)get_property(vias, "reg", NULL); if (reg == NULL) { printk(KERN_ERR "via-cuda: No \"reg\" property !\n"); goto fail; diff --git a/trunk/drivers/macintosh/via-pmu-backlight.c b/trunk/drivers/macintosh/via-pmu-backlight.c index a82f313d9dc9..b42d05f2aaff 100644 --- a/trunk/drivers/macintosh/via-pmu-backlight.c +++ b/trunk/drivers/macintosh/via-pmu-backlight.c @@ -15,51 +15,19 @@ #define MAX_PMU_LEVEL 0xFF +static struct device_node *vias; static struct backlight_properties pmu_backlight_data; -static spinlock_t pmu_backlight_lock; -static int sleeping; -static u8 bl_curve[FB_BACKLIGHT_LEVELS]; -static void pmu_backlight_init_curve(u8 off, u8 min, u8 max) -{ - unsigned int i, flat, count, range = (max - min); - - bl_curve[0] = off; - - for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat) - bl_curve[flat] = min; - - count = FB_BACKLIGHT_LEVELS * 15 / 16; - for (i = 0; i < count; ++i) - bl_curve[flat + i] = min + (range * (i + 1) / count); -} - -static int pmu_backlight_curve_lookup(int value) -{ - int level = (FB_BACKLIGHT_LEVELS - 1); - int i, max = 0; - - /* Look for biggest value */ - for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) - max = max((int)bl_curve[i], max); - - /* Look for nearest value */ - for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) { - int diff = abs(bl_curve[i] - value); - if (diff < max) { - max = diff; - level = i; - } - } - return level; -} - -static int pmu_backlight_get_level_brightness(int level) +static int pmu_backlight_get_level_brightness(struct fb_info *info, + int level) { int pmulevel; /* Get and convert the value */ - pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; + mutex_lock(&info->bl_mutex); + pmulevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; + mutex_unlock(&info->bl_mutex); + if (pmulevel < 0) pmulevel = 0; else if (pmulevel > MAX_PMU_LEVEL) @@ -70,37 +38,25 @@ static int pmu_backlight_get_level_brightness(int level) static int pmu_backlight_update_status(struct backlight_device *bd) { + struct fb_info *info = class_get_devdata(&bd->class_dev); struct adb_request req; - unsigned long flags; - int level = bd->props->brightness; - - spin_lock_irqsave(&pmu_backlight_lock, flags); + int pmulevel, level = bd->props->brightness; - /* Don't update brightness when sleeping */ - if (sleeping) - goto out; + if (vias == NULL) + return -ENODEV; if (bd->props->power != FB_BLANK_UNBLANK || bd->props->fb_blank != FB_BLANK_UNBLANK) level = 0; - if (level > 0) { - int pmulevel = pmu_backlight_get_level_brightness(level); + pmulevel = pmu_backlight_get_level_brightness(info, level); - pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel); - pmu_wait_complete(&req); - - pmu_request(&req, NULL, 2, PMU_POWER_CTRL, - PMU_POW_BACKLIGHT | PMU_POW_ON); - pmu_wait_complete(&req); - } else { - pmu_request(&req, NULL, 2, PMU_POWER_CTRL, - PMU_POW_BACKLIGHT | PMU_POW_OFF); - pmu_wait_complete(&req); - } + pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel); + pmu_wait_complete(&req); -out: - spin_unlock_irqrestore(&pmu_backlight_lock, flags); + pmu_request(&req, NULL, 2, PMU_POWER_CTRL, + PMU_POW_BACKLIGHT | (level > 0 ? PMU_POW_ON : PMU_POW_OFF)); + pmu_wait_complete(&req); return 0; } @@ -117,23 +73,15 @@ static struct backlight_properties pmu_backlight_data = { .max_brightness = (FB_BACKLIGHT_LEVELS - 1), }; -#ifdef CONFIG_PM -void pmu_backlight_set_sleep(int sleep) -{ - unsigned long flags; - - spin_lock_irqsave(&pmu_backlight_lock, flags); - sleeping = sleep; - spin_unlock_irqrestore(&pmu_backlight_lock, flags); -} -#endif /* CONFIG_PM */ - -void __init pmu_backlight_init() +void __init pmu_backlight_init(struct device_node *in_vias) { struct backlight_device *bd; + struct fb_info *info; char name[10]; int level, autosave; + vias = in_vias; + /* Special case for the old PowerBook since I can't test on it */ autosave = machine_is_compatible("AAPL,3400/2400") || @@ -145,14 +93,27 @@ void __init pmu_backlight_init() !machine_is_compatible("PowerBook1,1")) return; - snprintf(name, sizeof(name), "pmubl"); + /* Actually, this is a hack, but I don't know of a better way + * to get the first framebuffer device. + */ + info = registered_fb[0]; + if (!info) { + printk("pmubl: No framebuffer found\n"); + goto error; + } + + snprintf(name, sizeof(name), "pmubl%d", info->node); - bd = backlight_device_register(name, NULL, &pmu_backlight_data); + bd = backlight_device_register(name, info, &pmu_backlight_data); if (IS_ERR(bd)) { printk("pmubl: Backlight registration failed\n"); goto error; } - pmu_backlight_init_curve(0x7F, 0x46, 0x0E); + + mutex_lock(&info->bl_mutex); + info->bl_dev = bd; + fb_bl_default_curve(info, 0x7F, 0x46, 0x0E); + mutex_unlock(&info->bl_mutex); level = pmu_backlight_data.max_brightness; @@ -162,16 +123,18 @@ void __init pmu_backlight_init() pmu_request(&req, NULL, 2, 0xd9, 0); pmu_wait_complete(&req); - level = pmu_backlight_curve_lookup( + mutex_lock(&info->bl_mutex); + level = pmac_backlight_curve_lookup(info, (req.reply[0] >> 4) * pmu_backlight_data.max_brightness / 15); + mutex_unlock(&info->bl_mutex); } - down(&bd->sem); + up(&bd->sem); bd->props->brightness = level; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - up(&bd->sem); + down(&bd->sem); mutex_lock(&pmac_backlight_mutex); if (!pmac_backlight) diff --git a/trunk/drivers/macintosh/via-pmu-led.c b/trunk/drivers/macintosh/via-pmu-led.c index 179af10105d9..af8375ed0f5e 100644 --- a/trunk/drivers/macintosh/via-pmu-led.c +++ b/trunk/drivers/macintosh/via-pmu-led.c @@ -74,7 +74,7 @@ static void pmu_led_set(struct led_classdev *led_cdev, static struct led_classdev pmu_led = { .name = "pmu-front-led", -#ifdef CONFIG_ADB_PMU_LED_IDE +#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK .default_trigger = "ide-disk", #endif .brightness_set = pmu_led_set, @@ -120,7 +120,7 @@ static int __init via_pmu_led_init(void) dt = of_find_node_by_path("/"); if (dt == NULL) return -ENODEV; - model = get_property(dt, "model", NULL); + model = (const char *)get_property(dt, "model", NULL); if (model == NULL) return -ENODEV; if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 && diff --git a/trunk/drivers/macintosh/via-pmu.c b/trunk/drivers/macintosh/via-pmu.c index dda03985dcf5..06ca80bfd6b9 100644 --- a/trunk/drivers/macintosh/via-pmu.c +++ b/trunk/drivers/macintosh/via-pmu.c @@ -16,6 +16,7 @@ * a sleep or a freq. switch * - Move sleep code out of here to pmac_pm, merge into new * common PM infrastructure + * - Move backlight code out as well * - Save/Restore PCI space properly * */ @@ -59,7 +60,9 @@ #include #include #include +#ifdef CONFIG_PMAC_BACKLIGHT #include +#endif #include "via-pmu-event.h" @@ -174,6 +177,10 @@ static int query_batt_timer = BATTERY_POLLING_COUNT; static struct adb_request batt_req; static struct proc_dir_entry *proc_pmu_batt[PMU_MAX_BATTERIES]; +#if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) +extern int disable_kernel_backlight; +#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ + int __fake_sleep; int asleep; BLOCKING_NOTIFIER_HEAD(sleep_notifier_list); @@ -280,7 +287,7 @@ static char *pbook_type[] = { int __init find_via_pmu(void) { u64 taddr; - const u32 *reg; + u32 *reg; if (via != 0) return 1; @@ -288,7 +295,7 @@ int __init find_via_pmu(void) if (vias == NULL) return 0; - reg = get_property(vias, "reg", NULL); + reg = (u32 *)get_property(vias, "reg", NULL); if (reg == NULL) { printk(KERN_ERR "via-pmu: No \"reg\" property !\n"); goto fail; @@ -330,7 +337,7 @@ int __init find_via_pmu(void) gpiop = of_find_node_by_name(NULL, "gpio"); if (gpiop) { - reg = get_property(gpiop, "reg", NULL); + reg = (u32 *)get_property(gpiop, "reg", NULL); if (reg) gaddr = of_translate_address(gpiop, reg); if (gaddr != OF_BAD_ADDR) @@ -459,7 +466,7 @@ static int __init via_pmu_dev_init(void) #ifdef CONFIG_PMAC_BACKLIGHT /* Initialize backlight */ - pmu_backlight_init(); + pmu_backlight_init(vias); #endif #ifdef CONFIG_PPC32 @@ -479,9 +486,9 @@ static int __init via_pmu_dev_init(void) pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART; } else { struct device_node* prim = find_devices("power-mgt"); - const u32 *prim_info = NULL; + u32 *prim_info = NULL; if (prim) - prim_info = get_property(prim, "prim-info", NULL); + prim_info = (u32 *)get_property(prim, "prim-info", NULL); if (prim_info) { /* Other stuffs here yet unknown */ pmu_battery_count = (prim_info[6] >> 16) & 0xff; @@ -1396,8 +1403,11 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs) else if ((1 << pirq) & PMU_INT_SNDBRT) { #ifdef CONFIG_PMAC_BACKLIGHT if (len == 3) - pmac_backlight_set_legacy_brightness_pmu(data[1] >> 4); -#endif +#ifdef CONFIG_INPUT_ADBHID + if (!disable_kernel_backlight) +#endif /* CONFIG_INPUT_ADBHID */ + pmac_backlight_set_legacy_brightness(data[1] >> 4); +#endif /* CONFIG_PMAC_BACKLIGHT */ } /* Tick interrupt */ else if ((1 << pirq) & PMU_INT_TICK) { @@ -1995,8 +2005,6 @@ restore_via_state(void) out_8(&via[IER], IER_SET | SR_INT | CB1_INT); } -extern void pmu_backlight_set_sleep(int sleep); - static int pmac_suspend_devices(void) { @@ -2034,11 +2042,6 @@ pmac_suspend_devices(void) return -EBUSY; } -#ifdef CONFIG_PMAC_BACKLIGHT - /* Tell backlight code not to muck around with the chip anymore */ - pmu_backlight_set_sleep(1); -#endif - /* Call platform functions marked "on sleep" */ pmac_pfunc_i2c_suspend(); pmac_pfunc_base_suspend(); @@ -2097,11 +2100,6 @@ pmac_wakeup_devices(void) { mdelay(100); -#ifdef CONFIG_PMAC_BACKLIGHT - /* Tell backlight code it can use the chip again */ - pmu_backlight_set_sleep(0); -#endif - /* Power back up system devices (including the PIC) */ device_power_up(); @@ -2416,7 +2414,7 @@ struct pmu_private { spinlock_t lock; #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) int backlight_locker; -#endif +#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ }; static LIST_HEAD(all_pmu_pvt); @@ -2466,7 +2464,7 @@ pmu_open(struct inode *inode, struct file *file) spin_lock_irqsave(&all_pvt_lock, flags); #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) pp->backlight_locker = 0; -#endif +#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ list_add(&pp->list, &all_pmu_pvt); spin_unlock_irqrestore(&all_pvt_lock, flags); file->private_data = pp; @@ -2561,12 +2559,13 @@ pmu_release(struct inode *inode, struct file *file) spin_lock_irqsave(&all_pvt_lock, flags); list_del(&pp->list); spin_unlock_irqrestore(&all_pvt_lock, flags); - #if defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) - if (pp->backlight_locker) - pmac_backlight_enable(); -#endif - + if (pp->backlight_locker) { + spin_lock_irqsave(&pmu_lock, flags); + disable_kernel_backlight--; + spin_unlock_irqrestore(&pmu_lock, flags); + } +#endif /* defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_PMAC_BACKLIGHT) */ kfree(pp); } unlock_kernel(); @@ -2643,18 +2642,18 @@ pmu_ioctl(struct inode * inode, struct file *filp, #ifdef CONFIG_INPUT_ADBHID case PMU_IOC_GRAB_BACKLIGHT: { struct pmu_private *pp = filp->private_data; + unsigned long flags; if (pp->backlight_locker) return 0; - pp->backlight_locker = 1; - pmac_backlight_disable(); - + spin_lock_irqsave(&pmu_lock, flags); + disable_kernel_backlight++; + spin_unlock_irqrestore(&pmu_lock, flags); return 0; } #endif /* CONFIG_INPUT_ADBHID */ #endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */ - case PMU_IOC_GET_MODEL: return put_user(pmu_kind, argp); case PMU_IOC_HAS_ADB: diff --git a/trunk/drivers/macintosh/windfarm_pm81.c b/trunk/drivers/macintosh/windfarm_pm81.c index 2ff546e4c92f..f1df6efcbe68 100644 --- a/trunk/drivers/macintosh/windfarm_pm81.c +++ b/trunk/drivers/macintosh/windfarm_pm81.c @@ -396,7 +396,7 @@ static void wf_smu_sys_fans_tick(struct wf_smu_sys_fans_state *st) static void wf_smu_create_cpu_fans(void) { struct wf_cpu_pid_param pid_param; - const struct smu_sdbp_header *hdr; + struct smu_sdbp_header *hdr; struct smu_sdbp_cpupiddata *piddata; struct smu_sdbp_fvt *fvt; s32 tmax, tdelta, maxpow, powadj; @@ -702,7 +702,7 @@ static struct notifier_block wf_smu_events = { static int wf_init_pm(void) { - const struct smu_sdbp_header *hdr; + struct smu_sdbp_header *hdr; hdr = smu_get_sdb_partition(SMU_SDB_SENSORTREE_ID, NULL); if (hdr != 0) { diff --git a/trunk/drivers/macintosh/windfarm_pm91.c b/trunk/drivers/macintosh/windfarm_pm91.c index 59e9ffe37c39..0d6372e96d32 100644 --- a/trunk/drivers/macintosh/windfarm_pm91.c +++ b/trunk/drivers/macintosh/windfarm_pm91.c @@ -144,7 +144,7 @@ static struct wf_smu_slots_fans_state *wf_smu_slots_fans; static void wf_smu_create_cpu_fans(void) { struct wf_cpu_pid_param pid_param; - const struct smu_sdbp_header *hdr; + struct smu_sdbp_header *hdr; struct smu_sdbp_cpupiddata *piddata; struct smu_sdbp_fvt *fvt; s32 tmax, tdelta, maxpow, powadj; diff --git a/trunk/drivers/macintosh/windfarm_smu_controls.c b/trunk/drivers/macintosh/windfarm_smu_controls.c index bff1f372f188..a9e88edc0c72 100644 --- a/trunk/drivers/macintosh/windfarm_smu_controls.c +++ b/trunk/drivers/macintosh/windfarm_smu_controls.c @@ -159,15 +159,14 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, int pwm_fan) { struct smu_fan_control *fct; - const s32 *v; - const u32 *reg; - const char *l; + s32 *v; u32 *reg; + char *l; fct = kmalloc(sizeof(struct smu_fan_control), GFP_KERNEL); if (fct == NULL) return NULL; fct->ctrl.ops = &smu_fan_ops; - l = get_property(node, "location", NULL); + l = (char *)get_property(node, "location", NULL); if (l == NULL) goto fail; @@ -224,17 +223,17 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node, goto fail; /* Get min & max values*/ - v = get_property(node, "min-value", NULL); + v = (s32 *)get_property(node, "min-value", NULL); if (v == NULL) goto fail; fct->min = *v; - v = get_property(node, "max-value", NULL); + v = (s32 *)get_property(node, "max-value", NULL); if (v == NULL) goto fail; fct->max = *v; /* Get "reg" value */ - reg = get_property(node, "reg", NULL); + reg = (u32 *)get_property(node, "reg", NULL); if (reg == NULL) goto fail; fct->reg = *reg; diff --git a/trunk/drivers/macintosh/windfarm_smu_sat.c b/trunk/drivers/macintosh/windfarm_smu_sat.c index aceb61d9fbc8..e295a07a1ebc 100644 --- a/trunk/drivers/macintosh/windfarm_smu_sat.c +++ b/trunk/drivers/macintosh/windfarm_smu_sat.c @@ -233,15 +233,15 @@ static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) { struct wf_sat *sat; struct wf_sat_sensor *sens; - const u32 *reg; - const char *loc, *type; + u32 *reg; + char *loc, *type; u8 addr, chip, core; struct device_node *child; int shift, cpu, index; char *name; int vsens[2], isens[2]; - reg = get_property(dev, "reg", NULL); + reg = (u32 *) get_property(dev, "reg", NULL); if (reg == NULL) return; addr = *reg; @@ -268,7 +268,7 @@ static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) isens[0] = isens[1] = -1; child = NULL; while ((child = of_get_next_child(dev, child)) != NULL) { - reg = get_property(child, "reg", NULL); + reg = (u32 *) get_property(child, "reg", NULL); type = get_property(child, "device_type", NULL); loc = get_property(child, "location", NULL); if (reg == NULL || loc == NULL) diff --git a/trunk/drivers/macintosh/windfarm_smu_sensors.c b/trunk/drivers/macintosh/windfarm_smu_sensors.c index defe9922ebd1..bed25dcf8a1e 100644 --- a/trunk/drivers/macintosh/windfarm_smu_sensors.c +++ b/trunk/drivers/macintosh/windfarm_smu_sensors.c @@ -198,14 +198,14 @@ static struct wf_sensor_ops smu_slotspow_ops = { static struct smu_ad_sensor *smu_ads_create(struct device_node *node) { struct smu_ad_sensor *ads; - const char *c, *l; - const u32 *v; + char *c, *l; + u32 *v; ads = kmalloc(sizeof(struct smu_ad_sensor), GFP_KERNEL); if (ads == NULL) return NULL; - c = get_property(node, "device_type", NULL); - l = get_property(node, "location", NULL); + c = (char *)get_property(node, "device_type", NULL); + l = (char *)get_property(node, "location", NULL); if (c == NULL || l == NULL) goto fail; @@ -255,7 +255,7 @@ static struct smu_ad_sensor *smu_ads_create(struct device_node *node) } else goto fail; - v = get_property(node, "reg", NULL); + v = (u32 *)get_property(node, "reg", NULL); if (v == NULL) goto fail; ads->reg = *v; @@ -382,7 +382,7 @@ smu_cpu_power_create(struct wf_sensor *volts, struct wf_sensor *amps) static void smu_fetch_param_partitions(void) { - const struct smu_sdbp_header *hdr; + struct smu_sdbp_header *hdr; /* Get CPU voltage/current/power calibration data */ hdr = smu_get_sdb_partition(SMU_SDB_CPUVCP_ID, NULL); diff --git a/trunk/drivers/md/dm-crypt.c b/trunk/drivers/md/dm-crypt.c index bdbd34993a80..6022ed12a795 100644 --- a/trunk/drivers/md/dm-crypt.c +++ b/trunk/drivers/md/dm-crypt.c @@ -5,7 +5,6 @@ * This file is released under the GPL. */ -#include #include #include #include @@ -79,13 +78,11 @@ struct crypt_config { */ struct crypt_iv_operations *iv_gen_ops; char *iv_mode; - struct crypto_cipher *iv_gen_private; + void *iv_gen_private; sector_t iv_offset; unsigned int iv_size; - char cipher[CRYPTO_MAX_ALG_NAME]; - char chainmode[CRYPTO_MAX_ALG_NAME]; - struct crypto_blkcipher *tfm; + struct crypto_tfm *tfm; unsigned int key_size; u8 key[0]; }; @@ -99,12 +96,12 @@ static kmem_cache_t *_crypt_io_pool; /* * Different IV generation algorithms: * - * plain: the initial vector is the 32-bit little-endian version of the sector + * plain: the initial vector is the 32-bit low-endian version of the sector * number, padded with zeros if neccessary. * - * essiv: "encrypted sector|salt initial vector", the sector number is - * encrypted with the bulk cipher using a salt as key. The salt - * should be derived from the bulk cipher's key via hashing. + * ess_iv: "encrypted sector|salt initial vector", the sector number is + * encrypted with the bulk cipher using a salt as key. The salt + * should be derived from the bulk cipher's key via hashing. * * plumb: unimplemented, see: * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454 @@ -121,13 +118,11 @@ static int crypt_iv_plain_gen(struct crypt_config *cc, u8 *iv, sector_t sector) static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, const char *opts) { - struct crypto_cipher *essiv_tfm; - struct crypto_hash *hash_tfm; - struct hash_desc desc; + struct crypto_tfm *essiv_tfm; + struct crypto_tfm *hash_tfm; struct scatterlist sg; unsigned int saltsize; u8 *salt; - int err; if (opts == NULL) { ti->error = "Digest algorithm missing for ESSIV mode"; @@ -135,70 +130,76 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, } /* Hash the cipher key with the given hash algorithm */ - hash_tfm = crypto_alloc_hash(opts, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(hash_tfm)) { + hash_tfm = crypto_alloc_tfm(opts, CRYPTO_TFM_REQ_MAY_SLEEP); + if (hash_tfm == NULL) { ti->error = "Error initializing ESSIV hash"; - return PTR_ERR(hash_tfm); + return -EINVAL; } - saltsize = crypto_hash_digestsize(hash_tfm); + if (crypto_tfm_alg_type(hash_tfm) != CRYPTO_ALG_TYPE_DIGEST) { + ti->error = "Expected digest algorithm for ESSIV hash"; + crypto_free_tfm(hash_tfm); + return -EINVAL; + } + + saltsize = crypto_tfm_alg_digestsize(hash_tfm); salt = kmalloc(saltsize, GFP_KERNEL); if (salt == NULL) { ti->error = "Error kmallocing salt storage in ESSIV"; - crypto_free_hash(hash_tfm); + crypto_free_tfm(hash_tfm); return -ENOMEM; } sg_set_buf(&sg, cc->key, cc->key_size); - desc.tfm = hash_tfm; - desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; - err = crypto_hash_digest(&desc, &sg, cc->key_size, salt); - crypto_free_hash(hash_tfm); - - if (err) { - ti->error = "Error calculating hash in ESSIV"; - return err; - } + crypto_digest_digest(hash_tfm, &sg, 1, salt); + crypto_free_tfm(hash_tfm); /* Setup the essiv_tfm with the given salt */ - essiv_tfm = crypto_alloc_cipher(cc->cipher, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(essiv_tfm)) { + essiv_tfm = crypto_alloc_tfm(crypto_tfm_alg_name(cc->tfm), + CRYPTO_TFM_MODE_ECB | + CRYPTO_TFM_REQ_MAY_SLEEP); + if (essiv_tfm == NULL) { ti->error = "Error allocating crypto tfm for ESSIV"; kfree(salt); - return PTR_ERR(essiv_tfm); + return -EINVAL; } - if (crypto_cipher_blocksize(essiv_tfm) != - crypto_blkcipher_ivsize(cc->tfm)) { + if (crypto_tfm_alg_blocksize(essiv_tfm) + != crypto_tfm_alg_ivsize(cc->tfm)) { ti->error = "Block size of ESSIV cipher does " "not match IV size of block cipher"; - crypto_free_cipher(essiv_tfm); + crypto_free_tfm(essiv_tfm); kfree(salt); return -EINVAL; } - err = crypto_cipher_setkey(essiv_tfm, salt, saltsize); - if (err) { + if (crypto_cipher_setkey(essiv_tfm, salt, saltsize) < 0) { ti->error = "Failed to set key for ESSIV cipher"; - crypto_free_cipher(essiv_tfm); + crypto_free_tfm(essiv_tfm); kfree(salt); - return err; + return -EINVAL; } kfree(salt); - cc->iv_gen_private = essiv_tfm; + cc->iv_gen_private = (void *)essiv_tfm; return 0; } static void crypt_iv_essiv_dtr(struct crypt_config *cc) { - crypto_free_cipher(cc->iv_gen_private); + crypto_free_tfm((struct crypto_tfm *)cc->iv_gen_private); cc->iv_gen_private = NULL; } static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector) { + struct scatterlist sg; + memset(iv, 0, cc->iv_size); *(u64 *)iv = cpu_to_le64(sector); - crypto_cipher_encrypt_one(cc->iv_gen_private, iv, iv); + + sg_set_buf(&sg, iv, cc->iv_size); + crypto_cipher_encrypt((struct crypto_tfm *)cc->iv_gen_private, + &sg, &sg, cc->iv_size); + return 0; } @@ -219,11 +220,6 @@ crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, int write, sector_t sector) { u8 iv[cc->iv_size]; - struct blkcipher_desc desc = { - .tfm = cc->tfm, - .info = iv, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP, - }; int r; if (cc->iv_gen_ops) { @@ -232,14 +228,14 @@ crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, return r; if (write) - r = crypto_blkcipher_encrypt_iv(&desc, out, in, length); + r = crypto_cipher_encrypt_iv(cc->tfm, out, in, length, iv); else - r = crypto_blkcipher_decrypt_iv(&desc, out, in, length); + r = crypto_cipher_decrypt_iv(cc->tfm, out, in, length, iv); } else { if (write) - r = crypto_blkcipher_encrypt(&desc, out, in, length); + r = crypto_cipher_encrypt(cc->tfm, out, in, length); else - r = crypto_blkcipher_decrypt(&desc, out, in, length); + r = crypto_cipher_decrypt(cc->tfm, out, in, length); } return r; @@ -514,12 +510,13 @@ static void crypt_encode_key(char *hex, u8 *key, unsigned int size) static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) { struct crypt_config *cc; - struct crypto_blkcipher *tfm; + struct crypto_tfm *tfm; char *tmp; char *cipher; char *chainmode; char *ivmode; char *ivopts; + unsigned int crypto_flags; unsigned int key_size; unsigned long long tmpll; @@ -559,25 +556,31 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) ivmode = "plain"; } - if (strcmp(chainmode, "ecb") && !ivmode) { - ti->error = "This chaining mode requires an IV mechanism"; + /* Choose crypto_flags according to chainmode */ + if (strcmp(chainmode, "cbc") == 0) + crypto_flags = CRYPTO_TFM_MODE_CBC; + else if (strcmp(chainmode, "ecb") == 0) + crypto_flags = CRYPTO_TFM_MODE_ECB; + else { + ti->error = "Unknown chaining mode"; goto bad1; } - if (snprintf(cc->cipher, CRYPTO_MAX_ALG_NAME, "%s(%s)", chainmode, - cipher) >= CRYPTO_MAX_ALG_NAME) { - ti->error = "Chain mode + cipher name is too long"; + if (crypto_flags != CRYPTO_TFM_MODE_ECB && !ivmode) { + ti->error = "This chaining mode requires an IV mechanism"; goto bad1; } - tfm = crypto_alloc_blkcipher(cc->cipher, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) { + tfm = crypto_alloc_tfm(cipher, crypto_flags | CRYPTO_TFM_REQ_MAY_SLEEP); + if (!tfm) { ti->error = "Error allocating crypto tfm"; goto bad1; } + if (crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER) { + ti->error = "Expected cipher algorithm"; + goto bad2; + } - strcpy(cc->cipher, cipher); - strcpy(cc->chainmode, chainmode); cc->tfm = tfm; /* @@ -600,12 +603,12 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) cc->iv_gen_ops->ctr(cc, ti, ivopts) < 0) goto bad2; - cc->iv_size = crypto_blkcipher_ivsize(tfm); - if (cc->iv_size) + if (tfm->crt_cipher.cit_decrypt_iv && tfm->crt_cipher.cit_encrypt_iv) /* at least a 64 bit sector number should fit in our buffer */ - cc->iv_size = max(cc->iv_size, + cc->iv_size = max(crypto_tfm_alg_ivsize(tfm), (unsigned int)(sizeof(u64) / sizeof(u8))); else { + cc->iv_size = 0; if (cc->iv_gen_ops) { DMWARN("Selected cipher does not support IVs"); if (cc->iv_gen_ops->dtr) @@ -626,7 +629,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad4; } - if (crypto_blkcipher_setkey(tfm, cc->key, key_size) < 0) { + if (tfm->crt_cipher.cit_setkey(tfm, cc->key, key_size) < 0) { ti->error = "Error setting key"; goto bad5; } @@ -672,7 +675,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) cc->iv_gen_ops->dtr(cc); bad2: - crypto_free_blkcipher(tfm); + crypto_free_tfm(tfm); bad1: /* Must zero key material before freeing */ memset(cc, 0, sizeof(*cc) + cc->key_size * sizeof(u8)); @@ -690,7 +693,7 @@ static void crypt_dtr(struct dm_target *ti) kfree(cc->iv_mode); if (cc->iv_gen_ops && cc->iv_gen_ops->dtr) cc->iv_gen_ops->dtr(cc); - crypto_free_blkcipher(cc->tfm); + crypto_free_tfm(cc->tfm); dm_put_device(ti, cc->dev); /* Must zero key material before freeing */ @@ -855,9 +858,18 @@ static int crypt_status(struct dm_target *ti, status_type_t type, break; case STATUSTYPE_TABLE: - cipher = crypto_blkcipher_name(cc->tfm); + cipher = crypto_tfm_alg_name(cc->tfm); - chainmode = cc->chainmode; + switch(cc->tfm->crt_cipher.cit_mode) { + case CRYPTO_TFM_MODE_CBC: + chainmode = "cbc"; + break; + case CRYPTO_TFM_MODE_ECB: + chainmode = "ecb"; + break; + default: + BUG(); + } if (cc->iv_mode) DMEMIT("%s-%s-%s ", cipher, chainmode, cc->iv_mode); diff --git a/trunk/drivers/md/dm-mpath.c b/trunk/drivers/md/dm-mpath.c index 93f701ea87bc..217615b33223 100644 --- a/trunk/drivers/md/dm-mpath.c +++ b/trunk/drivers/md/dm-mpath.c @@ -710,8 +710,6 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, return -EINVAL; } - m->ti = ti; - r = parse_features(&as, m, ti); if (r) goto bad; @@ -753,6 +751,7 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc, } ti->private = m; + m->ti = ti; return 0; diff --git a/trunk/drivers/md/dm-raid1.c b/trunk/drivers/md/dm-raid1.c index c54de989eb00..be48cedf986b 100644 --- a/trunk/drivers/md/dm-raid1.c +++ b/trunk/drivers/md/dm-raid1.c @@ -255,9 +255,7 @@ static struct region *__rh_alloc(struct region_hash *rh, region_t region) struct region *reg, *nreg; read_unlock(&rh->hash_lock); - nreg = mempool_alloc(rh->region_pool, GFP_ATOMIC); - if (unlikely(!nreg)) - nreg = kmalloc(sizeof(struct region), GFP_NOIO); + nreg = mempool_alloc(rh->region_pool, GFP_NOIO); nreg->state = rh->log->type->in_sync(rh->log, region, 1) ? RH_CLEAN : RH_NOSYNC; nreg->rh = rh; diff --git a/trunk/drivers/md/linear.c b/trunk/drivers/md/linear.c index b99c19c7eb22..ff83c9b5979e 100644 --- a/trunk/drivers/md/linear.c +++ b/trunk/drivers/md/linear.c @@ -162,7 +162,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) goto out; } - min_spacing = conf->array_size; + min_spacing = mddev->array_size; sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *)); /* min_spacing is the minimum spacing that will fit the hash @@ -171,7 +171,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) * that is larger than min_spacing as use the size of that as * the actual spacing */ - conf->hash_spacing = conf->array_size; + conf->hash_spacing = mddev->array_size; for (i=0; i < cnt-1 ; i++) { sector_t sz = 0; int j; @@ -228,7 +228,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) curr_offset = 0; i = 0; for (curr_offset = 0; - curr_offset < conf->array_size; + curr_offset < mddev->array_size; curr_offset += conf->hash_spacing) { while (i < mddev->raid_disks-1 && diff --git a/trunk/drivers/md/md.c b/trunk/drivers/md/md.c index 8dbab2ef3885..b6d16022a53e 100644 --- a/trunk/drivers/md/md.c +++ b/trunk/drivers/md/md.c @@ -1597,19 +1597,6 @@ void md_update_sb(mddev_t * mddev) repeat: spin_lock_irq(&mddev->write_lock); - - if (mddev->degraded && mddev->sb_dirty == 3) - /* If the array is degraded, then skipping spares is both - * dangerous and fairly pointless. - * Dangerous because a device that was removed from the array - * might have a event_count that still looks up-to-date, - * so it can be re-added without a resync. - * Pointless because if there are any spares to skip, - * then a recovery will happen and soon that array won't - * be degraded any more and the spare can go back to sleep then. - */ - mddev->sb_dirty = 1; - sync_req = mddev->in_sync; mddev->utime = get_seconds(); if (mddev->sb_dirty == 3) diff --git a/trunk/drivers/md/raid1.c b/trunk/drivers/md/raid1.c index 3b4d69c05623..1efe22a2d041 100644 --- a/trunk/drivers/md/raid1.c +++ b/trunk/drivers/md/raid1.c @@ -930,13 +930,10 @@ static void status(struct seq_file *seq, mddev_t *mddev) seq_printf(seq, " [%d/%d] [", conf->raid_disks, conf->working_disks); - rcu_read_lock(); - for (i = 0; i < conf->raid_disks; i++) { - mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); + for (i = 0; i < conf->raid_disks; i++) seq_printf(seq, "%s", - rdev && test_bit(In_sync, &rdev->flags) ? "U" : "_"); - } - rcu_read_unlock(); + conf->mirrors[i].rdev && + test_bit(In_sync, &conf->mirrors[i].rdev->flags) ? "U" : "_"); seq_printf(seq, "]"); } @@ -978,6 +975,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) static void print_conf(conf_t *conf) { int i; + mirror_info_t *tmp; printk("RAID1 conf printout:\n"); if (!conf) { @@ -987,17 +985,14 @@ static void print_conf(conf_t *conf) printk(" --- wd:%d rd:%d\n", conf->working_disks, conf->raid_disks); - rcu_read_lock(); for (i = 0; i < conf->raid_disks; i++) { char b[BDEVNAME_SIZE]; - mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); - if (rdev) + tmp = conf->mirrors + i; + if (tmp->rdev) printk(" disk %d, wo:%d, o:%d, dev:%s\n", - i, !test_bit(In_sync, &rdev->flags), - !test_bit(Faulty, &rdev->flags), - bdevname(rdev->bdev,b)); + i, !test_bit(In_sync, &tmp->rdev->flags), !test_bit(Faulty, &tmp->rdev->flags), + bdevname(tmp->rdev->bdev,b)); } - rcu_read_unlock(); } static void close_sync(conf_t *conf) @@ -1013,20 +1008,20 @@ static int raid1_spare_active(mddev_t *mddev) { int i; conf_t *conf = mddev->private; + mirror_info_t *tmp; /* * Find all failed disks within the RAID1 configuration - * and mark them readable. - * Called under mddev lock, so rcu protection not needed. + * and mark them readable */ for (i = 0; i < conf->raid_disks; i++) { - mdk_rdev_t *rdev = conf->mirrors[i].rdev; - if (rdev - && !test_bit(Faulty, &rdev->flags) - && !test_bit(In_sync, &rdev->flags)) { + tmp = conf->mirrors + i; + if (tmp->rdev + && !test_bit(Faulty, &tmp->rdev->flags) + && !test_bit(In_sync, &tmp->rdev->flags)) { conf->working_disks++; mddev->degraded--; - set_bit(In_sync, &rdev->flags); + set_bit(In_sync, &tmp->rdev->flags); } } @@ -1242,7 +1237,7 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) /* ouch - failed to read all of that. * Try some synchronous reads of other devices to get * good data, much like with normal read errors. Only - * read into the pages we already have so we don't + * read into the pages we already have so they we don't * need to re-issue the read request. * We don't need to freeze the array, because being in an * active sync request, there is no normal IO, and @@ -1262,10 +1257,6 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) s = PAGE_SIZE >> 9; do { if (r1_bio->bios[d]->bi_end_io == end_sync_read) { - /* No rcu protection needed here devices - * can only be removed when no resync is - * active, and resync is currently active - */ rdev = conf->mirrors[d].rdev; if (sync_page_io(rdev->bdev, sect + rdev->data_offset, @@ -1472,11 +1463,6 @@ static void raid1d(mddev_t *mddev) s = PAGE_SIZE >> 9; do { - /* Note: no rcu protection needed here - * as this is synchronous in the raid1d thread - * which is the thread that might remove - * a device. If raid1d ever becomes multi-threaded.... - */ rdev = conf->mirrors[d].rdev; if (rdev && test_bit(In_sync, &rdev->flags) && @@ -1500,6 +1486,7 @@ static void raid1d(mddev_t *mddev) d = conf->raid_disks; d--; rdev = conf->mirrors[d].rdev; + atomic_add(s, &rdev->corrected_errors); if (rdev && test_bit(In_sync, &rdev->flags)) { if (sync_page_io(rdev->bdev, @@ -1522,11 +1509,9 @@ static void raid1d(mddev_t *mddev) s<<9, conf->tmppage, READ) == 0) /* Well, this device is dead */ md_error(mddev, rdev); - else { - atomic_add(s, &rdev->corrected_errors); + else printk(KERN_INFO "raid1:%s: read error corrected (%d sectors at %llu on %s)\n", mdname(mddev), s, (unsigned long long)(sect + rdev->data_offset), bdevname(rdev->bdev, b)); - } } } } else { @@ -1640,16 +1625,15 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i return 0; } + /* before building a request, check if we can skip these blocks.. + * This call the bitmap_start_sync doesn't actually record anything + */ if (mddev->bitmap == NULL && mddev->recovery_cp == MaxSector && - !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) && conf->fullsync == 0) { *skipped = 1; return max_sector - sector_nr; } - /* before building a request, check if we can skip these blocks.. - * This call the bitmap_start_sync doesn't actually record anything - */ if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) && !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) { /* We can skip this block, and probably several more */ @@ -1802,17 +1786,19 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i for (i=0; iraid_disks; i++) { bio = r1_bio->bios[i]; if (bio->bi_end_io == end_sync_read) { - md_sync_acct(bio->bi_bdev, nr_sectors); + md_sync_acct(conf->mirrors[i].rdev->bdev, nr_sectors); generic_make_request(bio); } } } else { atomic_set(&r1_bio->remaining, 1); bio = r1_bio->bios[r1_bio->read_disk]; - md_sync_acct(bio->bi_bdev, nr_sectors); + md_sync_acct(conf->mirrors[r1_bio->read_disk].rdev->bdev, + nr_sectors); generic_make_request(bio); } + return nr_sectors; } diff --git a/trunk/drivers/media/Kconfig b/trunk/drivers/media/Kconfig index ed4aa4e7912c..ef52e6da01ed 100644 --- a/trunk/drivers/media/Kconfig +++ b/trunk/drivers/media/Kconfig @@ -53,7 +53,7 @@ config VIDEO_V4L1_COMPAT If you are unsure as to whether this is required, answer Y. config VIDEO_V4L2 - bool + tristate default y source "drivers/media/video/Kconfig" diff --git a/trunk/drivers/media/common/saa7146_video.c b/trunk/drivers/media/common/saa7146_video.c index 7e0cedc557df..8393d472d3b8 100644 --- a/trunk/drivers/media/common/saa7146_video.c +++ b/trunk/drivers/media/common/saa7146_video.c @@ -1190,7 +1190,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int } return err; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT case VIDIOCGMBUF: { struct video_mbuf *mbuf = arg; @@ -1219,7 +1218,6 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int mutex_unlock(&q->lock); return 0; } -#endif default: return v4l_compat_translate_ioctl(inode,file,cmd,arg, saa7146_video_do_ioctl); diff --git a/trunk/drivers/media/dvb/b2c2/Kconfig b/trunk/drivers/media/dvb/b2c2/Kconfig index 49a06fc54c51..d7f1fd5b7b02 100644 --- a/trunk/drivers/media/dvb/b2c2/Kconfig +++ b/trunk/drivers/media/dvb/b2c2/Kconfig @@ -1,7 +1,6 @@ config DVB_B2C2_FLEXCOP tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters" depends on DVB_CORE && I2C - select DVB_PLL select DVB_STV0299 select DVB_MT352 select DVB_MT312 diff --git a/trunk/drivers/media/dvb/bt8xx/Kconfig b/trunk/drivers/media/dvb/bt8xx/Kconfig index 7d0ee1ab2903..f394002118f8 100644 --- a/trunk/drivers/media/dvb/bt8xx/Kconfig +++ b/trunk/drivers/media/dvb/bt8xx/Kconfig @@ -1,7 +1,6 @@ config DVB_BT8XX tristate "BT8xx based PCI cards" depends on DVB_CORE && PCI && I2C && VIDEO_BT848 - select DVB_PLL select DVB_MT352 select DVB_SP887X select DVB_NXT6000 diff --git a/trunk/drivers/media/dvb/bt8xx/dst.c b/trunk/drivers/media/dvb/bt8xx/dst.c index 06ac899a9a26..d687a14ec0a7 100644 --- a/trunk/drivers/media/dvb/bt8xx/dst.c +++ b/trunk/drivers/media/dvb/bt8xx/dst.c @@ -393,7 +393,7 @@ static int dst_set_bandwidth(struct dst_state *state, fe_bandwidth_t bandwidth) state->bandwidth = bandwidth; if (state->dst_type != DST_TYPE_IS_TERR) - return -EOPNOTSUPP; + return 0; switch (bandwidth) { case BANDWIDTH_6_MHZ: @@ -462,7 +462,7 @@ static int dst_set_symbolrate(struct dst_state *state, u32 srate) state->symbol_rate = srate; if (state->dst_type == DST_TYPE_IS_TERR) { - return -EOPNOTSUPP; + return 0; } dprintk(verbose, DST_INFO, 1, "set symrate %u", srate); srate /= 1000; @@ -504,7 +504,7 @@ static int dst_set_symbolrate(struct dst_state *state, u32 srate) static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation) { if (state->dst_type != DST_TYPE_IS_CABLE) - return -EOPNOTSUPP; + return 0; state->modulation = modulation; switch (modulation) { @@ -1234,7 +1234,7 @@ int dst_command(struct dst_state *state, u8 *data, u8 len) goto error; } if (write_dst(state, data, len)) { - dprintk(verbose, DST_INFO, 1, "Trying to recover.. "); + dprintk(verbose, DST_INFO, 1, "Tring to recover.. "); if ((dst_error_recovery(state)) < 0) { dprintk(verbose, DST_ERROR, 1, "Recovery Failed."); goto error; @@ -1328,13 +1328,15 @@ static int dst_tone_power_cmd(struct dst_state *state) { u8 paket[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 }; - if (state->dst_type != DST_TYPE_IS_SAT) - return -EOPNOTSUPP; + if (state->dst_type == DST_TYPE_IS_TERR) + return 0; paket[4] = state->tx_tuna[4]; paket[2] = state->tx_tuna[2]; paket[3] = state->tx_tuna[3]; paket[7] = dst_check_sum (paket, 7); - return dst_command(state, paket, 8); + dst_command(state, paket, 8); + + return 0; } static int dst_get_tuna(struct dst_state *state) @@ -1463,7 +1465,7 @@ static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec }; if (state->dst_type != DST_TYPE_IS_SAT) - return -EOPNOTSUPP; + return 0; if (cmd->msg_len > 0 && cmd->msg_len < 5) memcpy(&paket[3], cmd->msg, cmd->msg_len); else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5) @@ -1471,17 +1473,18 @@ static int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd else return -EINVAL; paket[7] = dst_check_sum(&paket[0], 7); - return dst_command(state, paket, 8); + dst_command(state, paket, 8); + return 0; } static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) { - int need_cmd, retval = 0; + int need_cmd; struct dst_state *state = fe->demodulator_priv; state->voltage = voltage; if (state->dst_type != DST_TYPE_IS_SAT) - return -EOPNOTSUPP; + return 0; need_cmd = 0; @@ -1503,9 +1506,9 @@ static int dst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) } if (need_cmd) - retval = dst_tone_power_cmd(state); + dst_tone_power_cmd(state); - return retval; + return 0; } static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) @@ -1514,7 +1517,7 @@ static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) state->tone = tone; if (state->dst_type != DST_TYPE_IS_SAT) - return -EOPNOTSUPP; + return 0; switch (tone) { case SEC_TONE_OFF: @@ -1530,7 +1533,9 @@ static int dst_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) default: return -EINVAL; } - return dst_tone_power_cmd(state); + dst_tone_power_cmd(state); + + return 0; } static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd) @@ -1538,7 +1543,7 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd) struct dst_state *state = fe->demodulator_priv; if (state->dst_type != DST_TYPE_IS_SAT) - return -EOPNOTSUPP; + return 0; state->minicmd = minicmd; switch (minicmd) { case SEC_MINI_A: @@ -1548,7 +1553,9 @@ static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd) state->tx_tuna[3] = 0xff; break; } - return dst_tone_power_cmd(state); + dst_tone_power_cmd(state); + + return 0; } @@ -1601,31 +1608,28 @@ static int dst_read_signal_strength(struct dvb_frontend *fe, u16 *strength) { struct dst_state *state = fe->demodulator_priv; - int retval = dst_get_signal(state); + dst_get_signal(state); *strength = state->decode_strength; - return retval; + return 0; } static int dst_read_snr(struct dvb_frontend *fe, u16 *snr) { struct dst_state *state = fe->demodulator_priv; - int retval = dst_get_signal(state); + dst_get_signal(state); *snr = state->decode_snr; - return retval; + return 0; } static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) { - int retval = -EINVAL; struct dst_state *state = fe->demodulator_priv; if (p != NULL) { - retval = dst_set_freq(state, p->frequency); - if(retval != 0) - return retval; + dst_set_freq(state, p->frequency); dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency); if (state->dst_type == DST_TYPE_IS_SAT) { @@ -1643,10 +1647,10 @@ static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_paramet dst_set_symbolrate(state, p->u.qam.symbol_rate); dst_set_modulation(state, p->u.qam.modulation); } - retval = dst_write_tuna(fe); + dst_write_tuna(fe); } - return retval; + return 0; } static int dst_tune_frontend(struct dvb_frontend* fe, diff --git a/trunk/drivers/media/dvb/dvb-core/Makefile b/trunk/drivers/media/dvb/dvb-core/Makefile index 0b5182835cc8..11054657fdb5 100644 --- a/trunk/drivers/media/dvb/dvb-core/Makefile +++ b/trunk/drivers/media/dvb/dvb-core/Makefile @@ -2,8 +2,8 @@ # Makefile for the kernel DVB device drivers. # -dvb-core-objs := dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ - dvb_ca_en50221.o dvb_frontend.o \ - dvb_net.o dvb_ringbuffer.o dvb_math.o +dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ + dvb_ca_en50221.o dvb_frontend.o \ + dvb_net.o dvb_ringbuffer.o dvb_math.o obj-$(CONFIG_DVB_CORE) += dvb-core.o diff --git a/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c b/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c index 57b34cda99f5..59ac35ddd51e 100644 --- a/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/trunk/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -526,9 +526,7 @@ static int dvb_frontend_thread(void *data) fepriv->delay = 3*HZ; fepriv->status = 0; fepriv->wakeup = 0; - fepriv->reinitialise = 0; - - dvb_frontend_init(fe); + fepriv->reinitialise = 1; while (1) { up(&fepriv->sem); /* is locked when we enter the thread... */ @@ -1015,18 +1013,17 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) return ret; if ((file->f_flags & O_ACCMODE) != O_RDONLY) { - - /* normal tune mode when opened R/W */ - fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; - fepriv->tone = -1; - fepriv->voltage = -1; - ret = dvb_frontend_start (fe); if (ret) dvb_generic_release (inode, file); /* empty event queue */ fepriv->events.eventr = fepriv->events.eventw = 0; + + /* normal tune mode when opened R/W */ + fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; + fepriv->tone = -1; + fepriv->voltage = -1; } return ret; diff --git a/trunk/drivers/media/dvb/dvb-usb/Kconfig b/trunk/drivers/media/dvb/dvb-usb/Kconfig index 75824b77198a..3bc6722a6443 100644 --- a/trunk/drivers/media/dvb/dvb-usb/Kconfig +++ b/trunk/drivers/media/dvb/dvb-usb/Kconfig @@ -2,7 +2,6 @@ config DVB_USB tristate "Support for various USB DVB devices" depends on DVB_CORE && USB && I2C select FW_LOADER - select DVB_PLL help By enabling this you will be able to choose the various supported USB1.1 and USB2.0 DVB devices. diff --git a/trunk/drivers/media/dvb/frontends/Kconfig b/trunk/drivers/media/dvb/frontends/Kconfig index db978555b1eb..0ef361f0309b 100644 --- a/trunk/drivers/media/dvb/frontends/Kconfig +++ b/trunk/drivers/media/dvb/frontends/Kconfig @@ -6,43 +6,43 @@ comment "DVB-S (satellite) frontends" config DVB_STV0299 tristate "ST STV0299 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_CX24110 tristate "Conexant CX24110 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_CX24123 tristate "Conexant CX24123 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_TDA8083 tristate "Philips TDA8083 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_MT312 tristate "Zarlink VP310/MT312 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_VES1X93 tristate "VLSI VES1893 or VES1993 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_S5H1420 tristate "Samsung S5H1420 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-S tuner module. Say Y when you want to support this frontend. @@ -51,7 +51,7 @@ comment "DVB-T (terrestrial) frontends" config DVB_SP8870 tristate "Spase sp8870 based" - depends on DVB_CORE && I2C + depends on DVB_CORE select FW_LOADER help A DVB-T tuner module. Say Y when you want to support this frontend. @@ -63,7 +63,7 @@ config DVB_SP8870 config DVB_SP887X tristate "Spase sp887x based" - depends on DVB_CORE && I2C + depends on DVB_CORE select FW_LOADER help A DVB-T tuner module. Say Y when you want to support this frontend. @@ -75,25 +75,25 @@ config DVB_SP887X config DVB_CX22700 tristate "Conexant CX22700 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_CX22702 tristate "Conexant cx22702 demodulator (OFDM)" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_L64781 tristate "LSI L64781" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_TDA1004X tristate "Philips TDA10045H/TDA10046H based" - depends on DVB_CORE && I2C + depends on DVB_CORE select FW_LOADER help A DVB-T tuner module. Say Y when you want to support this frontend. @@ -106,32 +106,32 @@ config DVB_TDA1004X config DVB_NXT6000 tristate "NxtWave Communications NXT6000 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_MT352 tristate "Zarlink MT352 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_ZL10353 tristate "Zarlink ZL10353 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-T tuner module. Say Y when you want to support this frontend. config DVB_DIB3000MB tristate "DiBcom 3000M-B" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. config DVB_DIB3000MC tristate "DiBcom 3000P/M-C" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-T tuner module. Designed for mobile usage. Say Y when you want to support this frontend. @@ -141,19 +141,19 @@ comment "DVB-C (cable) frontends" config DVB_VES1820 tristate "VLSI VES1820 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-C tuner module. Say Y when you want to support this frontend. config DVB_TDA10021 tristate "Philips TDA10021 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-C tuner module. Say Y when you want to support this frontend. config DVB_STV0297 tristate "ST STV0297 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help A DVB-C tuner module. Say Y when you want to support this frontend. @@ -162,7 +162,7 @@ comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends" config DVB_NXT200X tristate "NxtWave Communications NXT2002/NXT2004 based" - depends on DVB_CORE && I2C + depends on DVB_CORE select FW_LOADER help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want @@ -176,7 +176,7 @@ config DVB_NXT200X config DVB_OR51211 tristate "Oren OR51211 based" - depends on DVB_CORE && I2C + depends on DVB_CORE select FW_LOADER help An ATSC 8VSB tuner module. Say Y when you want to support this frontend. @@ -188,7 +188,7 @@ config DVB_OR51211 config DVB_OR51132 tristate "Oren OR51132 based" - depends on DVB_CORE && I2C + depends on DVB_CORE select FW_LOADER help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want @@ -203,7 +203,7 @@ config DVB_OR51132 config DVB_BCM3510 tristate "Broadcom BCM3510" - depends on DVB_CORE && I2C + depends on DVB_CORE select FW_LOADER help An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to @@ -211,7 +211,7 @@ config DVB_BCM3510 config DVB_LGDT330X tristate "LG Electronics LGDT3302/LGDT3303 based" - depends on DVB_CORE && I2C + depends on DVB_CORE help An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want to support this frontend. @@ -220,19 +220,15 @@ config DVB_LGDT330X comment "Miscellaneous devices" depends on DVB_CORE -config DVB_PLL - tristate - depends on DVB_CORE && I2C - config DVB_LNBP21 tristate "LNBP21 SEC controller" - depends on DVB_CORE && I2C + depends on DVB_CORE help An SEC control chip. config DVB_ISL6421 tristate "ISL6421 SEC controller" - depends on DVB_CORE && I2C + depends on DVB_CORE help An SEC control chip. diff --git a/trunk/drivers/media/dvb/frontends/Makefile b/trunk/drivers/media/dvb/frontends/Makefile index 0e4880b6db14..5222245c7f59 100644 --- a/trunk/drivers/media/dvb/frontends/Makefile +++ b/trunk/drivers/media/dvb/frontends/Makefile @@ -4,7 +4,7 @@ EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -obj-$(CONFIG_DVB_PLL) += dvb-pll.o +obj-$(CONFIG_DVB_CORE) += dvb-pll.o obj-$(CONFIG_DVB_STV0299) += stv0299.o obj-$(CONFIG_DVB_SP8870) += sp8870.o obj-$(CONFIG_DVB_CX22700) += cx22700.o diff --git a/trunk/drivers/media/dvb/frontends/dvb-pll.c b/trunk/drivers/media/dvb/frontends/dvb-pll.c index 2be33f27c69f..a189683454b7 100644 --- a/trunk/drivers/media/dvb/frontends/dvb-pll.c +++ b/trunk/drivers/media/dvb/frontends/dvb-pll.c @@ -194,11 +194,11 @@ struct dvb_pll_desc dvb_pll_tda665x = { { 253834000, 36249333, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ }, { 383834000, 36249333, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ }, { 443834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ }, - { 444000000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, - { 583834000, 36249333, 166667, 0xca, 0x64 /* 011 0 0 1 00 */ }, - { 793834000, 36249333, 166667, 0xca, 0xa4 /* 101 0 0 1 00 */ }, - { 444834000, 36249333, 166667, 0xca, 0xc4 /* 110 0 0 1 00 */ }, - { 861000000, 36249333, 166667, 0xca, 0xe4 /* 111 0 0 1 00 */ }, + { 444000000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ }, + { 583834000, 36249333, 166667, 0xca, 0x63 /* 011 0 0 0 11 */ }, + { 793834000, 36249333, 166667, 0xca, 0xa3 /* 101 0 0 0 11 */ }, + { 444834000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ }, + { 861000000, 36249333, 166667, 0xca, 0xe3 /* 111 0 0 0 11 */ }, } }; EXPORT_SYMBOL(dvb_pll_tda665x); @@ -613,21 +613,7 @@ static struct dvb_tuner_ops dvb_pll_tuner_ops = { int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc) { - u8 b1 [] = { 0 }; - struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .buf = b1, .len = 1 }; struct dvb_pll_priv *priv = NULL; - int ret; - - if (i2c != NULL) { - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - - ret = i2c_transfer (i2c, &msg, 1); - if (ret != 1) - return -1; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); - } priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL); if (priv == NULL) diff --git a/trunk/drivers/media/dvb/pluto2/Kconfig b/trunk/drivers/media/dvb/pluto2/Kconfig index 9b84b1bdc313..7d8e6e87bdbb 100644 --- a/trunk/drivers/media/dvb/pluto2/Kconfig +++ b/trunk/drivers/media/dvb/pluto2/Kconfig @@ -2,7 +2,6 @@ config DVB_PLUTO2 tristate "Pluto2 cards" depends on DVB_CORE && PCI && I2C select I2C_ALGOBIT - select DVB_PLL select DVB_TDA1004X help Support for PCI cards based on the Pluto2 FPGA like the Satelco diff --git a/trunk/drivers/media/dvb/ttpci/Kconfig b/trunk/drivers/media/dvb/ttpci/Kconfig index 5fb097595cfb..987881fa988c 100644 --- a/trunk/drivers/media/dvb/ttpci/Kconfig +++ b/trunk/drivers/media/dvb/ttpci/Kconfig @@ -3,7 +3,6 @@ config DVB_AV7110 depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select FW_LOADER select VIDEO_SAA7146_VV - select DVB_PLL select DVB_VES1820 select DVB_VES1X93 select DVB_STV0299 @@ -62,7 +61,6 @@ config DVB_BUDGET tristate "Budget cards" depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select VIDEO_SAA7146 - select DVB_PLL select DVB_STV0299 select DVB_VES1X93 select DVB_VES1820 @@ -85,7 +83,6 @@ config DVB_BUDGET_CI tristate "Budget cards with onboard CI connector" depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select VIDEO_SAA7146 - select DVB_PLL select DVB_STV0297 select DVB_STV0299 select DVB_TDA1004X @@ -107,7 +104,6 @@ config DVB_BUDGET_AV tristate "Budget cards with analog video inputs" depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select VIDEO_SAA7146_VV - select DVB_PLL select DVB_STV0299 select DVB_TDA1004X select DVB_TDA10021 @@ -126,7 +122,6 @@ config DVB_BUDGET_PATCH tristate "AV7110 cards with Budget Patch" depends on DVB_CORE && DVB_BUDGET && VIDEO_V4L1 select DVB_AV7110 - select DVB_PLL select DVB_STV0299 select DVB_VES1X93 select DVB_TDA8083 diff --git a/trunk/drivers/media/dvb/ttpci/av7110.c b/trunk/drivers/media/dvb/ttpci/av7110.c index 4506165c5de2..500f15c10aaf 100644 --- a/trunk/drivers/media/dvb/ttpci/av7110.c +++ b/trunk/drivers/media/dvb/ttpci/av7110.c @@ -2203,8 +2203,8 @@ static int frontend_init(struct av7110 *av7110) av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params; /* set TDA9819 into DVB mode */ - saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD) - saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF) + saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD) + saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) /* tuner on this needs a slower i2c bus speed */ av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240; diff --git a/trunk/drivers/media/dvb/ttpci/av7110_v4l.c b/trunk/drivers/media/dvb/ttpci/av7110_v4l.c index 6ffe53fdcf57..64055461559d 100644 --- a/trunk/drivers/media/dvb/ttpci/av7110_v4l.c +++ b/trunk/drivers/media/dvb/ttpci/av7110_v4l.c @@ -272,8 +272,8 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh) if (ves1820_writereg(dev, 0x09, 0x0f, 0x60)) dprintk(1, "setting band in demodulator failed.\n"); } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { - saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9819 pin9(STD) - saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9819 pin30(VIF) + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // TDA9198 pin9(STD) + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); // TDA9198 pin30(VIF) } if (i2c_writereg(av7110, 0x48, 0x02, 0xd0) != 1) dprintk(1, "saa7113 write failed @ card %d", av7110->dvb_adapter.num); @@ -308,8 +308,8 @@ static int av7110_dvb_c_switch(struct saa7146_fh *fh) if (ves1820_writereg(dev, 0x09, 0x0f, 0x20)) dprintk(1, "setting band in demodulator failed.\n"); } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { - saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD) - saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF) + saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD) + saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) } } @@ -750,8 +750,8 @@ int av7110_init_analog_module(struct av7110 *av7110) if (ves1820_writereg(av7110->dev, 0x09, 0x0f, 0x20)) dprintk(1, "setting band in demodulator failed.\n"); } else if (av7110->analog_tuner_flags & ANALOG_TUNER_STV0297) { - saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9819 pin9(STD) - saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9819 pin30(VIF) + saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD) + saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF) } /* init the saa7113 */ diff --git a/trunk/drivers/media/dvb/ttpci/budget-av.c b/trunk/drivers/media/dvb/ttpci/budget-av.c index 2d21fec23b4d..5f111d407730 100644 --- a/trunk/drivers/media/dvb/ttpci/budget-av.c +++ b/trunk/drivers/media/dvb/ttpci/budget-av.c @@ -1303,9 +1303,6 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio budget_av->budget.dvb_adapter.priv = budget_av; frontend_init(budget_av); ciintf_init(budget_av); - - ttpci_budget_init_hooks(&budget_av->budget); - return 0; } diff --git a/trunk/drivers/media/dvb/ttpci/budget-ci.c b/trunk/drivers/media/dvb/ttpci/budget-ci.c index ffbbb3e34be4..4b966eea3834 100644 --- a/trunk/drivers/media/dvb/ttpci/budget-ci.c +++ b/trunk/drivers/media/dvb/ttpci/budget-ci.c @@ -1101,8 +1101,6 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio budget_ci->budget.dvb_adapter.priv = budget_ci; frontend_init(budget_ci); - ttpci_budget_init_hooks(&budget_ci->budget); - return 0; } diff --git a/trunk/drivers/media/dvb/ttpci/budget-core.c b/trunk/drivers/media/dvb/ttpci/budget-core.c index e15562f81664..e4cf7775e07f 100644 --- a/trunk/drivers/media/dvb/ttpci/budget-core.c +++ b/trunk/drivers/media/dvb/ttpci/budget-core.c @@ -63,6 +63,9 @@ static int stop_ts_capture(struct budget *budget) { dprintk(2, "budget: %p\n", budget); + if (--budget->feeding) + return budget->feeding; + saa7146_write(budget->dev, MC1, MASK_20); // DMA3 off SAA7146_IER_DISABLE(budget->dev, MASK_10); return 0; @@ -74,8 +77,8 @@ static int start_ts_capture(struct budget *budget) dprintk(2, "budget: %p\n", budget); - if (!budget->feeding || !budget->fe_synced) - return 0; + if (budget->feeding) + return ++budget->feeding; saa7146_write(dev, MC1, MASK_20); // DMA3 off @@ -136,33 +139,7 @@ static int start_ts_capture(struct budget *budget) SAA7146_IER_ENABLE(budget->dev, MASK_10); /* VPE */ saa7146_write(dev, MC1, (MASK_04 | MASK_20)); /* DMA3 on */ - return 0; -} - -static int budget_read_fe_status(struct dvb_frontend *fe, fe_status_t *status) -{ - struct budget *budget = (struct budget *) fe->dvb->priv; - int synced; - int ret; - - if (budget->read_fe_status) - ret = budget->read_fe_status(fe, status); - else - ret = -EINVAL; - - if (!ret) { - synced = (*status & FE_HAS_LOCK); - if (synced != budget->fe_synced) { - budget->fe_synced = synced; - spin_lock(&budget->feedlock); - if (synced) - start_ts_capture(budget); - else - stop_ts_capture(budget); - spin_unlock(&budget->feedlock); - } - } - return ret; + return ++budget->feeding; } static void vpeirq(unsigned long data) @@ -290,7 +267,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; struct budget *budget = (struct budget *) demux->priv; - int status = 0; + int status; dprintk(2, "budget: %p\n", budget); @@ -299,8 +276,7 @@ static int budget_start_feed(struct dvb_demux_feed *feed) spin_lock(&budget->feedlock); feed->pusi_seen = 0; /* have a clean section start */ - if (budget->feeding++ == 0) - status = start_ts_capture(budget); + status = start_ts_capture(budget); spin_unlock(&budget->feedlock); return status; } @@ -309,13 +285,12 @@ static int budget_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; struct budget *budget = (struct budget *) demux->priv; - int status = 0; + int status; dprintk(2, "budget: %p\n", budget); spin_lock(&budget->feedlock); - if (--budget->feeding == 0) - status = stop_ts_capture(budget); + status = stop_ts_capture(budget); spin_unlock(&budget->feedlock); return status; } @@ -495,14 +470,6 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, return ret; } -void ttpci_budget_init_hooks(struct budget *budget) -{ - if (budget->dvb_frontend && !budget->read_fe_status) { - budget->read_fe_status = budget->dvb_frontend->ops.read_status; - budget->dvb_frontend->ops.read_status = budget_read_fe_status; - } -} - int ttpci_budget_deinit(struct budget *budget) { struct saa7146_dev *dev = budget->dev; @@ -541,8 +508,11 @@ void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port) spin_lock(&budget->feedlock); budget->video_port = video_port; if (budget->feeding) { + int oldfeeding = budget->feeding; + budget->feeding = 1; stop_ts_capture(budget); start_ts_capture(budget); + budget->feeding = oldfeeding; } spin_unlock(&budget->feedlock); } @@ -550,7 +520,6 @@ void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port) EXPORT_SYMBOL_GPL(ttpci_budget_debiread); EXPORT_SYMBOL_GPL(ttpci_budget_debiwrite); EXPORT_SYMBOL_GPL(ttpci_budget_init); -EXPORT_SYMBOL_GPL(ttpci_budget_init_hooks); EXPORT_SYMBOL_GPL(ttpci_budget_deinit); EXPORT_SYMBOL_GPL(ttpci_budget_irq10_handler); EXPORT_SYMBOL_GPL(ttpci_budget_set_video_port); diff --git a/trunk/drivers/media/dvb/ttpci/budget-patch.c b/trunk/drivers/media/dvb/ttpci/budget-patch.c index 57227441891e..ee60ce90a400 100644 --- a/trunk/drivers/media/dvb/ttpci/budget-patch.c +++ b/trunk/drivers/media/dvb/ttpci/budget-patch.c @@ -617,8 +617,6 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte budget->dvb_adapter.priv = budget; frontend_init(budget); - ttpci_budget_init_hooks(budget); - return 0; } diff --git a/trunk/drivers/media/dvb/ttpci/budget.c b/trunk/drivers/media/dvb/ttpci/budget.c index 863dffb4ed8e..35761f13c12b 100644 --- a/trunk/drivers/media/dvb/ttpci/budget.c +++ b/trunk/drivers/media/dvb/ttpci/budget.c @@ -375,6 +375,9 @@ static void frontend_init(struct budget *budget) if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; budget->dvb_frontend->tuner_priv = &budget->i2c_adap; + budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; + budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst; + budget->dvb_frontend->ops.set_tone = budget_set_tone; break; } break; @@ -471,8 +474,6 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_ budget->dvb_adapter.priv = budget; frontend_init(budget); - ttpci_budget_init_hooks(budget); - return 0; } diff --git a/trunk/drivers/media/dvb/ttpci/budget.h b/trunk/drivers/media/dvb/ttpci/budget.h index e8a5c79178e1..ecea3a13030e 100644 --- a/trunk/drivers/media/dvb/ttpci/budget.h +++ b/trunk/drivers/media/dvb/ttpci/budget.h @@ -52,6 +52,9 @@ struct budget { struct dmx_frontend hw_frontend; struct dmx_frontend mem_frontend; + int fe_synced; + struct mutex pid_mutex; + int ci_present; int video_port; @@ -71,9 +74,6 @@ struct budget { struct dvb_adapter dvb_adapter; struct dvb_frontend *dvb_frontend; - int (*read_fe_status)(struct dvb_frontend *fe, fe_status_t *status); - int fe_synced; - void *priv; }; @@ -106,7 +106,6 @@ static struct saa7146_pci_extension_data x_var = { \ extern int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev, struct saa7146_pci_extension_data *info, struct module *owner); -extern void ttpci_budget_init_hooks(struct budget *budget); extern int ttpci_budget_deinit(struct budget *budget); extern void ttpci_budget_irq10_handler(struct saa7146_dev *dev, u32 * isr); extern void ttpci_budget_set_video_port(struct saa7146_dev *dev, int video_port); diff --git a/trunk/drivers/media/dvb/ttusb-budget/Kconfig b/trunk/drivers/media/dvb/ttusb-budget/Kconfig index 46a6a60d2ab9..92c7cdcf8981 100644 --- a/trunk/drivers/media/dvb/ttusb-budget/Kconfig +++ b/trunk/drivers/media/dvb/ttusb-budget/Kconfig @@ -1,7 +1,6 @@ config DVB_TTUSB_BUDGET tristate "Technotrend/Hauppauge Nova-USB devices" - depends on DVB_CORE && USB && I2C - select DVB_PLL + depends on DVB_CORE && USB select DVB_CX22700 select DVB_TDA1004X select DVB_VES1820 diff --git a/trunk/drivers/media/radio/Kconfig b/trunk/drivers/media/radio/Kconfig index 220076b1b956..de3128a31de8 100644 --- a/trunk/drivers/media/radio/Kconfig +++ b/trunk/drivers/media/radio/Kconfig @@ -350,15 +350,5 @@ config RADIO_ZOLTRIX_PORT help Enter the I/O port of your Zoltrix radio card. -config USB_DSBR - tristate "D-Link USB FM radio support (EXPERIMENTAL)" - depends on USB && VIDEO_V4L1 && EXPERIMENTAL - ---help--- - Say Y here if you want to connect this type of radio to your - computer's USB port. Note that the audio is not digital, and - you must connect the line out connector to a sound card or a - set of speakers. - - To compile this driver as a module, choose M here: the - module will be called dsbr100. endmenu + diff --git a/trunk/drivers/media/radio/Makefile b/trunk/drivers/media/radio/Makefile index cf55a18e3ddf..e95b6805e002 100644 --- a/trunk/drivers/media/radio/Makefile +++ b/trunk/drivers/media/radio/Makefile @@ -20,6 +20,5 @@ obj-$(CONFIG_RADIO_GEMTEK) += radio-gemtek.o obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o obj-$(CONFIG_RADIO_TRUST) += radio-trust.o obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o -obj-$(CONFIG_USB_DSBR) += dsbr100.o EXTRA_CFLAGS += -Isound diff --git a/trunk/drivers/media/video/Kconfig b/trunk/drivers/media/video/Kconfig index 94d078b77bab..6d532f170ce5 100644 --- a/trunk/drivers/media/video/Kconfig +++ b/trunk/drivers/media/video/Kconfig @@ -145,7 +145,7 @@ config VIDEO_SAA5246A config VIDEO_SAA5249 tristate "SAA5249 Teletext processor" - depends on VIDEO_DEV && I2C && VIDEO_V4L1 + depends on VIDEO_DEV && I2C help Support for I2C bus based teletext using the SAA5249 chip. At the moment this is only useful on some European WinTV cards. @@ -155,7 +155,7 @@ config VIDEO_SAA5249 config TUNER_3036 tristate "SAB3036 tuner" - depends on VIDEO_DEV && I2C && VIDEO_V4L1 + depends on VIDEO_DEV && I2C help Say Y here to include support for Philips SAB3036 compatible tuners. If in doubt, say N. @@ -260,7 +260,7 @@ source "drivers/media/video/saa7134/Kconfig" config VIDEO_MXB tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" - depends on PCI && VIDEO_V4L1 && I2C + depends on PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV select VIDEO_TUNER ---help--- @@ -272,7 +272,7 @@ config VIDEO_MXB config VIDEO_DPC tristate "Philips-Semiconductors 'dpc7146 demonstration board'" - depends on PCI && VIDEO_V4L1 && I2C + depends on PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV select VIDEO_V4L2 ---help--- @@ -287,7 +287,7 @@ config VIDEO_DPC config VIDEO_HEXIUM_ORION tristate "Hexium HV-PCI6 and Orion frame grabber" - depends on PCI && VIDEO_V4L1 && I2C + depends on PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV select VIDEO_V4L2 ---help--- @@ -299,7 +299,7 @@ config VIDEO_HEXIUM_ORION config VIDEO_HEXIUM_GEMINI tristate "Hexium Gemini frame grabber" - depends on PCI && VIDEO_V4L1 && I2C + depends on PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV select VIDEO_V4L2 ---help--- @@ -449,6 +449,18 @@ source "drivers/media/video/pvrusb2/Kconfig" source "drivers/media/video/em28xx/Kconfig" +config USB_DSBR + tristate "D-Link USB FM radio support (EXPERIMENTAL)" + depends on USB && VIDEO_V4L1 && EXPERIMENTAL + ---help--- + Say Y here if you want to connect this type of radio to your + computer's USB port. Note that the audio is not digital, and + you must connect the line out connector to a sound card or a + set of speakers. + + To compile this driver as a module, choose M here: the + module will be called dsbr100. + source "drivers/media/video/usbvideo/Kconfig" source "drivers/media/video/et61x251/Kconfig" diff --git a/trunk/drivers/media/video/Makefile b/trunk/drivers/media/video/Makefile index e82e511f2a72..353d61cfac1b 100644 --- a/trunk/drivers/media/video/Makefile +++ b/trunk/drivers/media/video/Makefile @@ -77,6 +77,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o obj-$(CONFIG_USB_DABUSB) += dabusb.o +obj-$(CONFIG_USB_DSBR) += dsbr100.o obj-$(CONFIG_USB_OV511) += ov511.o obj-$(CONFIG_USB_SE401) += se401.o obj-$(CONFIG_USB_STV680) += stv680.o @@ -90,7 +91,6 @@ obj-$(CONFIG_USB_ZC0301) += zc0301/ obj-$(CONFIG_USB_IBMCAM) += usbvideo/ obj-$(CONFIG_USB_KONICAWC) += usbvideo/ obj-$(CONFIG_USB_VICAM) += usbvideo/ -obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o diff --git a/trunk/drivers/media/video/bt8xx/Kconfig b/trunk/drivers/media/video/bt8xx/Kconfig index cdcf55650714..153f6a4a96c9 100644 --- a/trunk/drivers/media/video/bt8xx/Kconfig +++ b/trunk/drivers/media/video/bt8xx/Kconfig @@ -1,6 +1,6 @@ config VIDEO_BT848 tristate "BT848 Video For Linux" - depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L1 + depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX diff --git a/trunk/drivers/media/video/bt8xx/bttv-driver.c b/trunk/drivers/media/video/bt8xx/bttv-driver.c index 20dff7c316eb..5764a89d3562 100644 --- a/trunk/drivers/media/video/bt8xx/bttv-driver.c +++ b/trunk/drivers/media/video/bt8xx/bttv-driver.c @@ -3923,12 +3923,7 @@ static int __devinit bttv_register_video(struct bttv *btv) goto err; printk(KERN_INFO "bttv%d: registered device video%d\n", btv->c.nr,btv->video_dev->minor & 0x1f); - if (class_device_create_file(&btv->video_dev->class_dev, - &class_device_attr_card)<0) { - printk(KERN_ERR "bttv%d: class_device_create_file 'card' " - "failed\n", btv->c.nr); - goto err; - } + video_device_create_file(btv->video_dev, &class_device_attr_card); /* vbi */ btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi"); @@ -4292,8 +4287,6 @@ static struct pci_driver bttv_pci_driver = { static int bttv_init_module(void) { - int ret; - bttv_num = 0; printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n", @@ -4315,11 +4308,7 @@ static int bttv_init_module(void) bttv_check_chipset(); - ret = bus_register(&bttv_sub_bus_type); - if (ret < 0) { - printk(KERN_WARNING "bttv: bus_register error: %d\n", ret); - return ret; - } + bus_register(&bttv_sub_bus_type); return pci_register_driver(&bttv_pci_driver); } diff --git a/trunk/drivers/media/video/bt8xx/bttv-input.c b/trunk/drivers/media/video/bt8xx/bttv-input.c index 933d6db09acb..b41f81d2372c 100644 --- a/trunk/drivers/media/video/bt8xx/bttv-input.c +++ b/trunk/drivers/media/video/bt8xx/bttv-input.c @@ -303,7 +303,6 @@ int bttv_input_init(struct bttv *btv) ir->mask_keyup = 0x010000; ir->polling = 50; // ms break; - case BTTV_BOARD_PV_M4900: case BTTV_BOARD_PV_BT878P_9B: case BTTV_BOARD_PV_BT878P_PLUS: ir_codes = ir_codes_pixelview; diff --git a/trunk/drivers/media/video/bt8xx/bttv-vbi.c b/trunk/drivers/media/video/bt8xx/bttv-vbi.c index 63676e7bd635..8c9f0f7cf467 100644 --- a/trunk/drivers/media/video/bt8xx/bttv-vbi.c +++ b/trunk/drivers/media/video/bt8xx/bttv-vbi.c @@ -31,16 +31,11 @@ #include #include "bttvp.h" -/* Offset from line sync pulse leading edge (0H) to start of VBI capture, - in fCLKx2 pixels. According to the datasheet, VBI capture starts - VBI_HDELAY fCLKx1 pixels from the tailing edgeof /HRESET, and /HRESET - is 64 fCLKx1 pixels wide. VBI_HDELAY is set to 0, so this should be - (64 + 0) * 2 = 128 fCLKx2 pixels. But it's not! The datasheet is - Just Plain Wrong. The real value appears to be different for - different revisions of the bt8x8 chips, and to be affected by the - horizontal scaling factor. Experimentally, the value is measured - to be about 244. */ -#define VBI_OFFSET 244 +/* Offset from line sync pulse leading edge (0H) in 1 / sampling_rate: + bt8x8 /HRESET pulse starts at 0H and has length 64 / fCLKx1 (E|O_VTC + HSFMT = 0). VBI_HDELAY (always 0) is an offset from the trailing edge + of /HRESET in 1 / fCLKx1, and the sampling_rate tvnorm->Fsc is fCLKx2. */ +#define VBI_OFFSET ((64 + 0) * 2) #define VBI_DEFLINES 16 #define VBI_MAXLINES 32 diff --git a/trunk/drivers/media/video/compat_ioctl32.c b/trunk/drivers/media/video/compat_ioctl32.c index b69ee1194815..353d02b67c33 100644 --- a/trunk/drivers/media/video/compat_ioctl32.c +++ b/trunk/drivers/media/video/compat_ioctl32.c @@ -21,7 +21,7 @@ #ifdef CONFIG_COMPAT -#ifdef CONFIG_VIDEO_V4L1_COMPAT + struct video_tuner32 { compat_int_t tuner; char name[32]; @@ -107,7 +107,6 @@ struct video_window32 { compat_caddr_t clips; compat_int_t clipcount; }; -#endif static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -125,7 +124,6 @@ static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } -#ifdef CONFIG_VIDEO_V4L1_COMPAT /* You get back everything except the clips... */ static int put_video_window32(struct video_window *kp, struct video_window32 __user *up) { @@ -140,7 +138,6 @@ static int put_video_window32(struct video_window *kp, struct video_window32 __u return -EFAULT; return 0; } -#endif struct v4l2_clip32 { @@ -493,24 +490,6 @@ static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user return 0; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT -struct video_code32 -{ - char loadwhat[16]; /* name or tag of file being passed */ - compat_int_t datasize; - unsigned char *data; -}; - -static inline int microcode32(struct video_code *kp, struct video_code32 __user *up) -{ - if(!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) || - copy_from_user(kp->loadwhat, up->loadwhat, sizeof (up->loadwhat)) || - get_user(kp->datasize, &up->datasize) || - copy_from_user(kp->data, up->data, up->datasize)) - return -EFAULT; - return 0; -} - #define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32) #define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32) #define VIDIOCGWIN32 _IOR('v',9, struct video_window32) @@ -519,9 +498,6 @@ static inline int microcode32(struct video_code *kp, struct video_code32 __user #define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32) #define VIDIOCGFREQ32 _IOR('v',14, u32) #define VIDIOCSFREQ32 _IOW('v',15, u32) -#define VIDIOCSMICROCODE32 _IOW('v',27, struct video_code32) - -#endif /* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */ #define VIDIOC_ENUMINPUT32 VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4) @@ -543,7 +519,6 @@ static inline int microcode32(struct video_code *kp, struct video_code32 __user #define VIDIOC_S_INPUT32 _IOWR ('V', 39, compat_int_t) #define VIDIOC_TRY_FMT32 _IOWR ('V', 64, struct v4l2_format32) -#ifdef CONFIG_VIDEO_V4L1_COMPAT enum { MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip) }; @@ -608,17 +583,13 @@ static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg) return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw); } -#endif static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { union { -#ifdef CONFIG_VIDEO_V4L1_COMPAT struct video_tuner vt; struct video_buffer vb; struct video_window vw; - struct video_code vc; -#endif struct v4l2_format v2f; struct v4l2_buffer v2b; struct v4l2_framebuffer v2fb; @@ -634,7 +605,6 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg /* First, convert the command. */ switch(cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break; case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break; case VIDIOCGWIN32: cmd = VIDIOCGWIN; break; @@ -642,8 +612,6 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break; case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break; case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break; - case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break; -#endif case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break; case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break; case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break; @@ -663,7 +631,6 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg }; switch(cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT case VIDIOCSTUNER: case VIDIOCGTUNER: err = get_video_tuner32(&karg.vt, up); @@ -677,7 +644,6 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg break; case VIDIOCSFREQ: -#endif case VIDIOC_S_INPUT: case VIDIOC_OVERLAY: case VIDIOC_STREAMON: @@ -731,21 +697,14 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg compatible_arg = 0; break; -#ifdef CONFIG_VIDEO_V4L1_COMPAT case VIDIOCGWIN: case VIDIOCGFBUF: case VIDIOCGFREQ: -#endif case VIDIOC_G_FBUF: case VIDIOC_G_INPUT: compatible_arg = 0; -#ifdef CONFIG_VIDEO_V4L1_COMPAT - case VIDIOCSMICROCODE: - err = microcode32(&karg.vc, up); - compatible_arg = 0; - break; -#endif }; + if(err) goto out; @@ -760,7 +719,6 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg } if(err == 0) { switch(cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT case VIDIOCGTUNER: err = put_video_tuner32(&karg.vt, up); break; @@ -772,7 +730,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg case VIDIOCGFBUF: err = put_video_buffer32(&karg.vb, up); break; -#endif + case VIDIOC_G_FBUF: err = put_v4l2_framebuffer32(&karg.v2fb, up); break; @@ -810,9 +768,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg err = put_v4l2_input32(&karg.v2i, up); break; -#ifdef CONFIG_VIDEO_V4L1_COMPAT case VIDIOCGFREQ: -#endif case VIDIOC_G_INPUT: err = put_user(((u32)karg.vx), (u32 __user *)up); break; @@ -830,7 +786,6 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) return ret; switch (cmd) { -#ifdef CONFIG_VIDEO_V4L1_COMPAT case VIDIOCSWIN32: ret = do_set_window(file, cmd, arg); break; @@ -841,7 +796,6 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case VIDIOCSFBUF32: case VIDIOCGFREQ32: case VIDIOCSFREQ32: -#endif case VIDIOC_QUERYCAP: case VIDIOC_ENUM_FMT: case VIDIOC_G_FMT32: @@ -873,7 +827,6 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) ret = do_video_ioctl(file, cmd, arg); break; -#ifdef CONFIG_VIDEO_V4L1_COMPAT /* Little v, the video4linux ioctls (conflict?) */ case VIDIOCGCAP: case VIDIOCGCHAN: @@ -902,7 +855,6 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) case _IOR('v' , BASE_VIDIOCPRIVATE+7, int): ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); break; -#endif default: v4l_print_ioctl("compat_ioctl32", cmd); } diff --git a/trunk/drivers/media/video/cpia2/Kconfig b/trunk/drivers/media/video/cpia2/Kconfig index e39a96152004..513cc0927389 100644 --- a/trunk/drivers/media/video/cpia2/Kconfig +++ b/trunk/drivers/media/video/cpia2/Kconfig @@ -1,6 +1,6 @@ config VIDEO_CPIA2 tristate "CPiA2 Video For Linux" - depends on VIDEO_DEV && USB && VIDEO_V4L1 + depends on VIDEO_DEV && USB ---help--- This is the video4linux driver for cameras based on Vision's CPiA2 (Colour Processor Interface ASIC), such as the Digital Blue QX5 diff --git a/trunk/drivers/media/video/cx25840/cx25840-core.c b/trunk/drivers/media/video/cx25840/cx25840-core.c index 7bb7589a07c3..5c2036b40ea1 100644 --- a/trunk/drivers/media/video/cx25840/cx25840-core.c +++ b/trunk/drivers/media/video/cx25840/cx25840-core.c @@ -104,8 +104,8 @@ u32 cx25840_read4(struct i2c_client * client, u16 addr) if (i2c_master_recv(client, buffer, 4) < 4) return 0; - return (buffer[3] << 24) | (buffer[2] << 16) | - (buffer[1] << 8) | buffer[0]; + return (buffer[0] << 24) | (buffer[1] << 16) | + (buffer[2] << 8) | buffer[3]; } int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask, diff --git a/trunk/drivers/media/video/cx88/Kconfig b/trunk/drivers/media/video/cx88/Kconfig index 7a94e6a11927..80e23ee9801c 100644 --- a/trunk/drivers/media/video/cx88/Kconfig +++ b/trunk/drivers/media/video/cx88/Kconfig @@ -51,7 +51,6 @@ config VIDEO_CX88_DVB tristate "DVB/ATSC Support for cx2388x based TV cards" depends on VIDEO_CX88 && DVB_CORE select VIDEO_BUF_DVB - select DVB_PLL ---help--- This adds support for DVB/ATSC cards based on the Conexant 2388x chip. diff --git a/trunk/drivers/media/video/cx88/cx88-input.c b/trunk/drivers/media/video/cx88/cx88-input.c index c25564648993..72b630a91f41 100644 --- a/trunk/drivers/media/video/cx88/cx88-input.c +++ b/trunk/drivers/media/video/cx88/cx88-input.c @@ -89,7 +89,7 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) auxgpio = cx_read(MO_GP1_IO); /* Take out the parity part */ - gpio=(gpio & 0x7fd) + (auxgpio & 0xef); + gpio+=(gpio & 0x7fd) + (auxgpio & 0xef); } else auxgpio = gpio; diff --git a/trunk/drivers/media/video/cx88/cx88-video.c b/trunk/drivers/media/video/cx88/cx88-video.c index 94c92bacc342..2225d4b94140 100644 --- a/trunk/drivers/media/video/cx88/cx88-video.c +++ b/trunk/drivers/media/video/cx88/cx88-video.c @@ -1180,6 +1180,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_VBI_CAPTURE | + V4L2_CAP_VIDEO_OVERLAY | 0; if (UNSET != core->tuner_type) cap->capabilities |= V4L2_CAP_TUNER; @@ -1225,7 +1226,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, struct v4l2_format *f = arg; return cx8800_try_fmt(dev,fh,f); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT +#ifdef HAVE_V4L1 /* --- streaming capture ------------------------------------- */ case VIDIOCGMBUF: { @@ -1584,7 +1585,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, *id = 0; return 0; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT +#ifdef HAVE_V4L1 case VIDIOCSTUNER: { struct video_tuner *v = arg; diff --git a/trunk/drivers/media/radio/dsbr100.c b/trunk/drivers/media/video/dsbr100.c similarity index 100% rename from trunk/drivers/media/radio/dsbr100.c rename to trunk/drivers/media/video/dsbr100.c diff --git a/trunk/drivers/media/video/msp3400-driver.c b/trunk/drivers/media/video/msp3400-driver.c index 56246b8578f3..dbb75a7db199 100644 --- a/trunk/drivers/media/video/msp3400-driver.c +++ b/trunk/drivers/media/video/msp3400-driver.c @@ -362,7 +362,7 @@ int msp_sleep(struct msp_state *state, int timeout) } /* ------------------------------------------------------------------------ */ -#ifdef CONFIG_VIDEO_V4L1 + static int msp_mode_v4l2_to_v4l1(int rxsubchans, int audmode) { if (rxsubchans == V4L2_TUNER_SUB_MONO) @@ -384,7 +384,6 @@ static int msp_mode_v4l1_to_v4l2(int mode) return V4L2_TUNER_MODE_LANG1; return V4L2_TUNER_MODE_MONO; } -#endif static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl) { @@ -510,7 +509,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ -#ifdef CONFIG_VIDEO_V4L1 case VIDIOCGAUDIO: { struct video_audio *va = arg; @@ -579,12 +577,6 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) } case VIDIOCSFREQ: - { - /* new channel -- kick audio carrier scan */ - msp_wake_thread(client); - break; - } -#endif case VIDIOC_S_FREQUENCY: { /* new channel -- kick audio carrier scan */ diff --git a/trunk/drivers/media/video/msp3400-kthreads.c b/trunk/drivers/media/video/msp3400-kthreads.c index ed02ff811388..f2fd9195b3ac 100644 --- a/trunk/drivers/media/video/msp3400-kthreads.c +++ b/trunk/drivers/media/video/msp3400-kthreads.c @@ -961,10 +961,10 @@ int msp34xxg_thread(void *data) /* setup the chip*/ msp34xxg_reset(client); state->std = state->radio ? 0x40 : msp_standard; - /* start autodetect */ - msp_write_dem(client, 0x20, state->std); if (state->std != 1) goto unmute; + /* start autodetect */ + msp_write_dem(client, 0x20, state->std); /* watch autodetect */ v4l_dbg(1, msp_debug, client, "started autodetect, waiting for result\n"); diff --git a/trunk/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/trunk/drivers/media/video/pvrusb2/pvrusb2-hdw.c index be1e5cc78081..9b48abcf6089 100644 --- a/trunk/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/trunk/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -852,6 +852,7 @@ unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw) return hdw->serial_number; } + int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw) { return hdw->unit_number; @@ -2317,6 +2318,7 @@ void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *hdw) } } + /* Return name for this driver instance */ const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw) { @@ -2540,10 +2542,6 @@ static void pvr2_ctl_timeout(unsigned long data) } -/* Issue a command and get a response from the device. This extended - version includes a probe flag (which if set means that device errors - should not be logged or treated as fatal) and a timeout in jiffies. - This can be used to non-lethally probe the health of endpoint 1. */ static int pvr2_send_request_ex(struct pvr2_hdw *hdw, unsigned int timeout,int probe_fl, void *write_data,unsigned int write_len, @@ -2972,7 +2970,6 @@ int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) } -/* Stop / start video stream transport */ static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl) { int status; @@ -3071,7 +3068,6 @@ int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val) } -/* Find I2C address of eeprom */ static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) { int result; diff --git a/trunk/drivers/media/video/pvrusb2/pvrusb2-io.c b/trunk/drivers/media/video/pvrusb2/pvrusb2-io.c index 1e393762546c..681f79c8064e 100644 --- a/trunk/drivers/media/video/pvrusb2/pvrusb2-io.c +++ b/trunk/drivers/media/video/pvrusb2/pvrusb2-io.c @@ -26,8 +26,6 @@ #include #include -static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state); - #define BUFFER_SIG 0x47653271 // #define SANITY_CHECK_BUFFERS @@ -517,10 +515,6 @@ void pvr2_stream_set_callback(struct pvr2_stream *sp, } /* Query / set the nominal buffer count */ -int pvr2_stream_get_buffer_count(struct pvr2_stream *sp) -{ - return sp->buffer_target_count; -} int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt) { @@ -559,6 +553,7 @@ int pvr2_stream_get_ready_count(struct pvr2_stream *sp) return sp->r_count; } + void pvr2_stream_kill(struct pvr2_stream *sp) { struct pvr2_buffer *bp; @@ -612,6 +607,7 @@ int pvr2_buffer_queue(struct pvr2_buffer *bp) return ret; } + int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt) { int ret = 0; @@ -650,6 +646,7 @@ int pvr2_buffer_get_status(struct pvr2_buffer *bp) return bp->status; } + int pvr2_buffer_get_id(struct pvr2_buffer *bp) { return bp->id; diff --git a/trunk/drivers/media/video/pvrusb2/pvrusb2-io.h b/trunk/drivers/media/video/pvrusb2/pvrusb2-io.h index 93279cc2a35e..96285ad234a6 100644 --- a/trunk/drivers/media/video/pvrusb2/pvrusb2-io.h +++ b/trunk/drivers/media/video/pvrusb2/pvrusb2-io.h @@ -47,7 +47,6 @@ void pvr2_stream_set_callback(struct pvr2_stream *, void *data); /* Query / set the nominal buffer count */ -int pvr2_stream_get_buffer_count(struct pvr2_stream *); int pvr2_stream_set_buffer_count(struct pvr2_stream *,unsigned int); /* Get a pointer to a buffer that is either idle, ready, or is specified @@ -59,7 +58,6 @@ struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id); /* Find out how many buffers are idle or ready */ int pvr2_stream_get_ready_count(struct pvr2_stream *); - /* Kill all pending buffers and throw away any ready buffers as well */ void pvr2_stream_kill(struct pvr2_stream *); diff --git a/trunk/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/trunk/drivers/media/video/pvrusb2/pvrusb2-ioread.c index b71f9a961f8a..f7a2e225a002 100644 --- a/trunk/drivers/media/video/pvrusb2/pvrusb2-ioread.c +++ b/trunk/drivers/media/video/pvrusb2/pvrusb2-ioread.c @@ -213,9 +213,7 @@ int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp) " pvr2_ioread_setup (tear-down) id=%p",cp); pvr2_ioread_stop(cp); pvr2_stream_kill(cp->stream); - if (pvr2_stream_get_buffer_count(cp->stream)) { - pvr2_stream_set_buffer_count(cp->stream,0); - } + pvr2_stream_set_buffer_count(cp->stream,0); cp->stream = NULL; } if (sp) { @@ -253,6 +251,7 @@ int pvr2_ioread_set_enabled(struct pvr2_ioread *cp,int fl) return ret; } + static int pvr2_ioread_get_buffer(struct pvr2_ioread *cp) { int stat; diff --git a/trunk/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/trunk/drivers/media/video/pvrusb2/pvrusb2-sysfs.c index d1dda5caf406..6af55a8b6f05 100644 --- a/trunk/drivers/media/video/pvrusb2/pvrusb2-sysfs.c +++ b/trunk/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -44,16 +44,12 @@ struct pvr2_sysfs { struct kobj_type ktype; struct class_device_attribute attr_v4l_minor_number; struct class_device_attribute attr_unit_number; - int v4l_minor_number_created_ok; - int unit_number_created_ok; }; #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC struct pvr2_sysfs_debugifc { struct class_device_attribute attr_debugcmd; struct class_device_attribute attr_debuginfo; - int debugcmd_created_ok; - int debuginfo_created_ok; }; #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ @@ -71,7 +67,6 @@ struct pvr2_sysfs_ctl_item { struct pvr2_sysfs_ctl_item *item_next; struct attribute *attr_gen[7]; struct attribute_group grp; - int created_ok; char name[80]; }; @@ -492,7 +487,6 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) struct pvr2_sysfs_func_set *fp; struct pvr2_ctrl *cptr; unsigned int cnt,acnt; - int ret; if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) { return; @@ -595,13 +589,7 @@ static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) cip->grp.name = cip->name; cip->grp.attrs = cip->attr_gen; - ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); - if (ret) { - printk(KERN_WARNING "%s: sysfs_create_group error: %d\n", - __FUNCTION__, ret); - return; - } - cip->created_ok = !0; + sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); } #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC @@ -612,8 +600,6 @@ static ssize_t debugcmd_store(struct class_device *,const char *,size_t count); static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) { struct pvr2_sysfs_debugifc *dip; - int ret; - dip = kmalloc(sizeof(*dip),GFP_KERNEL); if (!dip) return; memset(dip,0,sizeof(*dip)); @@ -627,34 +613,17 @@ static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) dip->attr_debuginfo.attr.mode = S_IRUGO; dip->attr_debuginfo.show = debuginfo_show; sfp->debugifc = dip; - ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd); - if (ret < 0) { - printk(KERN_WARNING "%s: class_device_create_file error: %d\n", - __FUNCTION__, ret); - } else { - dip->debugcmd_created_ok = !0; - } - ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo); - if (ret < 0) { - printk(KERN_WARNING "%s: class_device_create_file error: %d\n", - __FUNCTION__, ret); - } else { - dip->debuginfo_created_ok = !0; - } + class_device_create_file(sfp->class_dev,&dip->attr_debugcmd); + class_device_create_file(sfp->class_dev,&dip->attr_debuginfo); } static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp) { if (!sfp->debugifc) return; - if (sfp->debugifc->debuginfo_created_ok) { - class_device_remove_file(sfp->class_dev, - &sfp->debugifc->attr_debuginfo); - } - if (sfp->debugifc->debugcmd_created_ok) { - class_device_remove_file(sfp->class_dev, - &sfp->debugifc->attr_debugcmd); - } + class_device_remove_file(sfp->class_dev, + &sfp->debugifc->attr_debuginfo); + class_device_remove_file(sfp->class_dev,&sfp->debugifc->attr_debugcmd); kfree(sfp->debugifc); sfp->debugifc = NULL; } @@ -676,9 +645,7 @@ static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp) struct pvr2_sysfs_ctl_item *cip1,*cip2; for (cip1 = sfp->item_first; cip1; cip1 = cip2) { cip2 = cip1->item_next; - if (cip1->created_ok) { - sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp); - } + sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp); pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1); kfree(cip1); } @@ -708,14 +675,8 @@ static void class_dev_destroy(struct pvr2_sysfs *sfp) pvr2_sysfs_tear_down_debugifc(sfp); #endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ pvr2_sysfs_tear_down_controls(sfp); - if (sfp->v4l_minor_number_created_ok) { - class_device_remove_file(sfp->class_dev, - &sfp->attr_v4l_minor_number); - } - if (sfp->unit_number_created_ok) { - class_device_remove_file(sfp->class_dev, - &sfp->attr_unit_number); - } + class_device_remove_file(sfp->class_dev,&sfp->attr_v4l_minor_number); + class_device_remove_file(sfp->class_dev,&sfp->attr_unit_number); pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); sfp->class_dev->class_data = NULL; class_device_unregister(sfp->class_dev); @@ -748,8 +709,6 @@ static void class_dev_create(struct pvr2_sysfs *sfp, { struct usb_device *usb_dev; struct class_device *class_dev; - int ret; - usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw); if (!usb_dev) return; class_dev = kmalloc(sizeof(*class_dev),GFP_KERNEL); @@ -774,40 +733,20 @@ static void class_dev_create(struct pvr2_sysfs *sfp, sfp->class_dev = class_dev; class_dev->class_data = sfp; - ret = class_device_register(class_dev); - if (ret) { - printk(KERN_ERR "%s: class_device_register failed\n", - __FUNCTION__); - kfree(class_dev); - return; - } + class_device_register(class_dev); sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE; sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number"; sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; sfp->attr_v4l_minor_number.show = v4l_minor_number_show; sfp->attr_v4l_minor_number.store = NULL; - ret = class_device_create_file(sfp->class_dev, - &sfp->attr_v4l_minor_number); - if (ret < 0) { - printk(KERN_WARNING "%s: class_device_create_file error: %d\n", - __FUNCTION__, ret); - } else { - sfp->v4l_minor_number_created_ok = !0; - } - + class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number); sfp->attr_unit_number.attr.owner = THIS_MODULE; sfp->attr_unit_number.attr.name = "unit_number"; sfp->attr_unit_number.attr.mode = S_IRUGO; sfp->attr_unit_number.show = unit_number_show; sfp->attr_unit_number.store = NULL; - ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number); - if (ret < 0) { - printk(KERN_WARNING "%s: class_device_create_file error: %d\n", - __FUNCTION__, ret); - } else { - sfp->unit_number_created_ok = !0; - } + class_device_create_file(sfp->class_dev,&sfp->attr_unit_number); pvr2_sysfs_add_controls(sfp); #ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC diff --git a/trunk/drivers/media/video/pwc/Kconfig b/trunk/drivers/media/video/pwc/Kconfig index 8fdf7101d3bf..697145e0bf15 100644 --- a/trunk/drivers/media/video/pwc/Kconfig +++ b/trunk/drivers/media/video/pwc/Kconfig @@ -30,7 +30,7 @@ config USB_PWC config USB_PWC_DEBUG bool "USB Philips Cameras verbose debug" - depends on USB_PWC + depends USB_PWC help Say Y here in order to have the pwc driver generate verbose debugging messages. diff --git a/trunk/drivers/media/video/pwc/pwc-if.c b/trunk/drivers/media/video/pwc/pwc-if.c index d4703944df9c..47d0d83a0264 100644 --- a/trunk/drivers/media/video/pwc/pwc-if.c +++ b/trunk/drivers/media/video/pwc/pwc-if.c @@ -160,7 +160,6 @@ static struct file_operations pwc_fops = { .poll = pwc_video_poll, .mmap = pwc_video_mmap, .ioctl = pwc_video_ioctl, - .compat_ioctl = v4l_compat_ioctl32, .llseek = no_llseek, }; static struct video_device pwc_template = { diff --git a/trunk/drivers/media/video/saa7134/Kconfig b/trunk/drivers/media/video/saa7134/Kconfig index f5543166d193..e1c1805df1fb 100644 --- a/trunk/drivers/media/video/saa7134/Kconfig +++ b/trunk/drivers/media/video/saa7134/Kconfig @@ -40,7 +40,6 @@ config VIDEO_SAA7134_DVB depends on VIDEO_SAA7134 && DVB_CORE select VIDEO_BUF_DVB select FW_LOADER - select DVB_PLL ---help--- This adds support for DVB cards based on the Philips saa7134 chip. diff --git a/trunk/drivers/media/video/saa7134/saa7134-alsa.c b/trunk/drivers/media/video/saa7134/saa7134-alsa.c index d73cff1970ae..f1fd69e7f119 100644 --- a/trunk/drivers/media/video/saa7134/saa7134-alsa.c +++ b/trunk/drivers/media/video/saa7134/saa7134-alsa.c @@ -997,9 +997,9 @@ static int saa7134_alsa_init(void) struct saa7134_dev *dev = NULL; struct list_head *list; - if (!saa7134_dmasound_init && !saa7134_dmasound_exit) { - saa7134_dmasound_init = alsa_device_init; - saa7134_dmasound_exit = alsa_device_exit; + if (!dmasound_init && !dmasound_exit) { + dmasound_init = alsa_device_init; + dmasound_exit = alsa_device_exit; } else { printk(KERN_WARNING "saa7134 ALSA: can't load, DMA sound handler already assigned (probably to OSS)\n"); return -EBUSY; @@ -1036,8 +1036,8 @@ static void saa7134_alsa_exit(void) snd_card_free(snd_saa7134_cards[idx]); } - saa7134_dmasound_init = NULL; - saa7134_dmasound_exit = NULL; + dmasound_init = NULL; + dmasound_exit = NULL; printk(KERN_INFO "saa7134 ALSA driver for DMA sound unloaded\n"); return; diff --git a/trunk/drivers/media/video/saa7134/saa7134-core.c b/trunk/drivers/media/video/saa7134/saa7134-core.c index be3a81fc90a2..6e97cc84ba89 100644 --- a/trunk/drivers/media/video/saa7134/saa7134-core.c +++ b/trunk/drivers/media/video/saa7134/saa7134-core.c @@ -95,8 +95,8 @@ LIST_HEAD(saa7134_devlist); static LIST_HEAD(mops_list); static unsigned int saa7134_devcount; -int (*saa7134_dmasound_init)(struct saa7134_dev *dev); -int (*saa7134_dmasound_exit)(struct saa7134_dev *dev); +int (*dmasound_init)(struct saa7134_dev *dev); +int (*dmasound_exit)(struct saa7134_dev *dev); #define dprintk(fmt, arg...) if (core_debug) \ printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg) @@ -1008,8 +1008,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* check for signal */ saa7134_irq_video_intl(dev); - if (saa7134_dmasound_init && !dev->dmasound.priv_data) { - saa7134_dmasound_init(dev); + if (dmasound_init && !dev->dmasound.priv_data) { + dmasound_init(dev); } return 0; @@ -1036,8 +1036,8 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev) struct saa7134_mpeg_ops *mops; /* Release DMA sound modules if present */ - if (saa7134_dmasound_exit && dev->dmasound.priv_data) { - saa7134_dmasound_exit(dev); + if (dmasound_exit && dev->dmasound.priv_data) { + dmasound_exit(dev); } /* debugging ... */ @@ -1169,8 +1169,8 @@ EXPORT_SYMBOL(saa7134_boards); /* ----------------- for the DMA sound modules --------------- */ -EXPORT_SYMBOL(saa7134_dmasound_init); -EXPORT_SYMBOL(saa7134_dmasound_exit); +EXPORT_SYMBOL(dmasound_init); +EXPORT_SYMBOL(dmasound_exit); EXPORT_SYMBOL(saa7134_pgtable_free); EXPORT_SYMBOL(saa7134_pgtable_build); EXPORT_SYMBOL(saa7134_pgtable_alloc); diff --git a/trunk/drivers/media/video/saa7134/saa7134-oss.c b/trunk/drivers/media/video/saa7134/saa7134-oss.c index 2e3ba5f31453..3895d05804ae 100644 --- a/trunk/drivers/media/video/saa7134/saa7134-oss.c +++ b/trunk/drivers/media/video/saa7134/saa7134-oss.c @@ -993,9 +993,9 @@ static int saa7134_oss_init(void) struct saa7134_dev *dev = NULL; struct list_head *list; - if (!saa7134_dmasound_init && !saa7134_dmasound_exit) { - saa7134_dmasound_init = oss_device_init; - saa7134_dmasound_exit = oss_device_exit; + if (!dmasound_init && !dmasound_exit) { + dmasound_init = oss_device_init; + dmasound_exit = oss_device_exit; } else { printk(KERN_WARNING "saa7134 OSS: can't load, DMA sound handler already assigned (probably to ALSA)\n"); return -EBUSY; @@ -1037,8 +1037,8 @@ static void saa7134_oss_exit(void) } - saa7134_dmasound_init = NULL; - saa7134_dmasound_exit = NULL; + dmasound_init = NULL; + dmasound_exit = NULL; printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n"); diff --git a/trunk/drivers/media/video/saa7134/saa7134-video.c b/trunk/drivers/media/video/saa7134/saa7134-video.c index 2c171af9a9f2..e4156ec9c6d7 100644 --- a/trunk/drivers/media/video/saa7134/saa7134-video.c +++ b/trunk/drivers/media/video/saa7134/saa7134-video.c @@ -40,7 +40,7 @@ static unsigned int video_debug = 0; static unsigned int gbuffers = 8; -static unsigned int noninterlaced = 1; +static unsigned int noninterlaced = 0; static unsigned int gbufsize = 720*576*4; static unsigned int gbufsize_max = 720*576*4; module_param(video_debug, int, 0644); @@ -48,7 +48,7 @@ MODULE_PARM_DESC(video_debug,"enable debug messages [video]"); module_param(gbuffers, int, 0444); MODULE_PARM_DESC(gbuffers,"number of capture buffers, range 2-32"); module_param(noninterlaced, int, 0644); -MODULE_PARM_DESC(noninterlaced,"capture non interlaced video"); +MODULE_PARM_DESC(noninterlaced,"video input is noninterlaced"); #define dprintk(fmt, arg...) if (video_debug) \ printk(KERN_DEBUG "%s/video: " fmt, dev->name , ## arg) @@ -2087,7 +2087,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, struct v4l2_format *f = arg; return saa7134_try_fmt(dev,fh,f); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT +#ifdef HAVE_V4L1 case VIDIOCGMBUF: { struct video_mbuf *mbuf = arg; diff --git a/trunk/drivers/media/video/saa7134/saa7134.h b/trunk/drivers/media/video/saa7134/saa7134.h index c04ce6152fd5..d5ee99c574cc 100644 --- a/trunk/drivers/media/video/saa7134/saa7134.h +++ b/trunk/drivers/media/video/saa7134/saa7134.h @@ -586,8 +586,8 @@ void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf); int saa7134_set_dmabits(struct saa7134_dev *dev); -extern int (*saa7134_dmasound_init)(struct saa7134_dev *dev); -extern int (*saa7134_dmasound_exit)(struct saa7134_dev *dev); +extern int (*dmasound_init)(struct saa7134_dev *dev); +extern int (*dmasound_exit)(struct saa7134_dev *dev); /* ----------------------------------------------------------- */ diff --git a/trunk/drivers/media/video/stradis.c b/trunk/drivers/media/video/stradis.c index 5686547ba76a..b36ba9fa3a28 100644 --- a/trunk/drivers/media/video/stradis.c +++ b/trunk/drivers/media/video/stradis.c @@ -2181,6 +2181,7 @@ static struct pci_device_id stradis_pci_tbl[] = { { 0 } }; +MODULE_DEVICE_TABLE(pci, stradis_pci_tbl); static struct pci_driver stradis_driver = { .name = "stradis", diff --git a/trunk/drivers/media/video/tuner-core.c b/trunk/drivers/media/video/tuner-core.c index 40590bae5ff7..f7eb402d5f2b 100644 --- a/trunk/drivers/media/video/tuner-core.c +++ b/trunk/drivers/media/video/tuner-core.c @@ -196,6 +196,14 @@ static void set_type(struct i2c_client *c, unsigned int type, i2c_master_send(c, buffer, 4); default_tuner_init(c); break; + case TUNER_LG_TDVS_H06XF: + /* Set the Auxiliary Byte. */ + buffer[2] &= ~0x20; + buffer[2] |= 0x18; + buffer[3] = 0x20; + i2c_master_send(c, buffer, 4); + default_tuner_init(c); + break; case TUNER_PHILIPS_TD1316: buffer[0] = 0x0b; buffer[1] = 0xdc; @@ -590,7 +598,6 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) if (t->standby) t->standby (client); break; -#ifdef CONFIG_VIDEO_V4L1 case VIDIOCSAUDIO: if (check_mode(t, "VIDIOCSAUDIO") == EINVAL) return 0; @@ -600,6 +607,17 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) /* Should be implemented, since bttv calls it */ tuner_dbg("VIDIOCSAUDIO not implemented.\n"); break; + case TDA9887_SET_CONFIG: + if (t->type == TUNER_TDA9887) { + int *i = arg; + + t->tda9887_config = *i; + set_freq(client, t->tv_freq); + } + break; + /* --- v4l ioctls --- */ + /* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ case VIDIOCSCHAN: { static const v4l2_std_id map[] = { @@ -683,18 +701,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO; return 0; } -#endif - case TDA9887_SET_CONFIG: - if (t->type == TUNER_TDA9887) { - int *i = arg; - t->tda9887_config = *i; - set_freq(client, t->tv_freq); - } - break; - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ case VIDIOC_S_STD: { v4l2_std_id *id = arg; diff --git a/trunk/drivers/media/video/tuner-simple.c b/trunk/drivers/media/video/tuner-simple.c index abe37cf632c6..d071c5cbf013 100644 --- a/trunk/drivers/media/video/tuner-simple.c +++ b/trunk/drivers/media/video/tuner-simple.c @@ -339,20 +339,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) if (4 != (rc = i2c_master_send(c,buffer,4))) tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); - switch (t->type) { - case TUNER_LG_TDVS_H06XF: - /* Set the Auxiliary Byte. */ - buffer[0] = buffer[2]; - buffer[0] &= ~0x20; - buffer[0] |= 0x18; - buffer[1] = 0x20; - tuner_dbg("tv 0x%02x 0x%02x\n",buffer[0],buffer[1]); - - if (2 != (rc = i2c_master_send(c,buffer,2))) - tuner_warn("i2c i/o error: rc == %d (should be 2)\n",rc); - break; - case TUNER_MICROTUNE_4042FI5: - { + if (t->type == TUNER_MICROTUNE_4042FI5) { // FIXME - this may also work for other tuners unsigned long timeout = jiffies + msecs_to_jiffies(1); u8 status_byte = 0; @@ -377,12 +364,10 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) buffer[2] = config; buffer[3] = cb; tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", - buffer[0],buffer[1],buffer[2],buffer[3]); + buffer[0],buffer[1],buffer[2],buffer[3]); if (4 != (rc = i2c_master_send(c,buffer,4))) tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); - break; - } } } diff --git a/trunk/drivers/media/video/tuner-types.c b/trunk/drivers/media/video/tuner-types.c index 8b542599ed47..a167e17c6dcd 100644 --- a/trunk/drivers/media/video/tuner-types.c +++ b/trunk/drivers/media/video/tuner-types.c @@ -926,17 +926,11 @@ static struct tuner_params tuner_lg_tdvs_h06xf_params[] = { /* ------------ TUNER_YMEC_TVF66T5_B_DFF - Philips PAL ------------ */ -static struct tuner_range tuner_ymec_tvf66t5_b_dff_pal_ranges[] = { - { 16 * 160.25 /*MHz*/, 0x8e, 0x01, }, - { 16 * 464.25 /*MHz*/, 0x8e, 0x02, }, - { 16 * 999.99 , 0x8e, 0x08, }, -}; - static struct tuner_params tuner_ymec_tvf66t5_b_dff_params[] = { { .type = TUNER_PARAM_TYPE_PAL, - .ranges = tuner_ymec_tvf66t5_b_dff_pal_ranges, - .count = ARRAY_SIZE(tuner_ymec_tvf66t5_b_dff_pal_ranges), + .ranges = tuner_tena_9533_di_pal_ranges, + .count = ARRAY_SIZE(tuner_tena_9533_di_pal_ranges), }, }; @@ -1033,11 +1027,10 @@ static struct tuner_params tuner_tnf_5335mf_params[] = { /* 70-79 */ /* ------------ TUNER_SAMSUNG_TCPN_2121P30A - Samsung NTSC ------------ */ -/* '+ 4' turns on the Low Noise Amplifier */ static struct tuner_range tuner_samsung_tcpn_2121p30a_ntsc_ranges[] = { - { 16 * 130.00 /*MHz*/, 0xce, 0x01 + 4, }, - { 16 * 364.50 /*MHz*/, 0xce, 0x02 + 4, }, - { 16 * 999.99 , 0xce, 0x08 + 4, }, + { 16 * 130.00 /*MHz*/, 0xce, 0x01, }, + { 16 * 364.50 /*MHz*/, 0xce, 0x02, }, + { 16 * 999.99 , 0xce, 0x08, }, }; static struct tuner_params tuner_samsung_tcpn_2121p30a_params[] = { @@ -1067,11 +1060,10 @@ static struct tuner_params tuner_thomson_fe6600_params[] = { /* ------------ TUNER_SAMSUNG_TCPG_6121P30A - Samsung PAL ------------ */ -/* '+ 4' turns on the Low Noise Amplifier */ static struct tuner_range tuner_samsung_tcpg_6121p30a_pal_ranges[] = { - { 16 * 146.25 /*MHz*/, 0xce, 0x01 + 4, }, - { 16 * 428.50 /*MHz*/, 0xce, 0x02 + 4, }, - { 16 * 999.99 , 0xce, 0x08 + 4, }, + { 16 * 146.25 /*MHz*/, 0xce, 0x01, }, + { 16 * 428.50 /*MHz*/, 0xce, 0x02, }, + { 16 * 999.99 , 0xce, 0x08, }, }; static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = { diff --git a/trunk/drivers/media/video/usbvideo/Kconfig b/trunk/drivers/media/video/usbvideo/Kconfig index a0fd82b924f2..59fb899f31f3 100644 --- a/trunk/drivers/media/video/usbvideo/Kconfig +++ b/trunk/drivers/media/video/usbvideo/Kconfig @@ -3,7 +3,7 @@ config VIDEO_USBVIDEO config USB_VICAM tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)" - depends on USB && VIDEO_DEV && VIDEO_V4L1 && EXPERIMENTAL + depends on USB && VIDEO_V4L1 && EXPERIMENTAL select VIDEO_USBVIDEO ---help--- Say Y here if you have 3com homeconnect camera (vicam). @@ -13,7 +13,7 @@ config USB_VICAM config USB_IBMCAM tristate "USB IBM (Xirlink) C-it Camera support" - depends on USB && VIDEO_DEV && VIDEO_V4L1 + depends on USB && VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want to connect a IBM "C-It" camera, also known as @@ -28,7 +28,7 @@ config USB_IBMCAM config USB_KONICAWC tristate "USB Konica Webcam support" - depends on USB && VIDEO_DEV && VIDEO_V4L1 + depends on USB && VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want support for webcams based on a Konica @@ -39,7 +39,7 @@ config USB_KONICAWC config USB_QUICKCAM_MESSENGER tristate "USB Logitech Quickcam Messenger" - depends on USB && VIDEO_DEV && VIDEO_V4L1 + depends on USB && VIDEO_DEV select VIDEO_USBVIDEO ---help--- Say Y or M here to enable support for the USB Logitech Quickcam diff --git a/trunk/drivers/media/video/v4l1-compat.c b/trunk/drivers/media/video/v4l1-compat.c index d7c3fcbc80f7..d83a2c84d233 100644 --- a/trunk/drivers/media/video/v4l1-compat.c +++ b/trunk/drivers/media/video/v4l1-compat.c @@ -599,10 +599,6 @@ v4l_compat_translate_ioctl(struct inode *inode, dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err); break; } - - pict->depth = ((fmt2->fmt.pix.bytesperline<<3) - + (fmt2->fmt.pix.width-1) ) - /fmt2->fmt.pix.width; pict->palette = pixelformat_to_palette( fmt2->fmt.pix.pixelformat); break; diff --git a/trunk/drivers/media/video/v4l2-common.c b/trunk/drivers/media/video/v4l2-common.c index 8d972ffdaf98..f06dc19e504a 100644 --- a/trunk/drivers/media/video/v4l2-common.c +++ b/trunk/drivers/media/video/v4l2-common.c @@ -202,7 +202,7 @@ static char *v4l2_memory_names[] = { /* ------------------------------------------------------------------ */ /* debug help functions */ -#ifdef CONFIG_VIDEO_V4L1_COMPAT +#ifdef HAVE_V4L1 static const char *v4l1_ioctls[] = { [_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP", [_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN", @@ -301,7 +301,7 @@ static const char *v4l2_ioctls[] = { #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) static const char *v4l2_int_ioctls[] = { -#ifdef CONFIG_VIDEO_V4L1_COMPAT +#ifdef HAVE_VIDEO_DECODER [_IOC_NR(DECODER_GET_CAPABILITIES)] = "DECODER_GET_CAPABILITIES", [_IOC_NR(DECODER_GET_STATUS)] = "DECODER_GET_STATUS", [_IOC_NR(DECODER_SET_NORM)] = "DECODER_SET_NORM", @@ -367,7 +367,7 @@ void v4l_printk_ioctl(unsigned int cmd) (_IOC_NR(cmd) < V4L2_INT_IOCTLS) ? v4l2_int_ioctls[_IOC_NR(cmd)] : "UNKNOWN", dir, cmd); break; -#ifdef CONFIG_VIDEO_V4L1_COMPAT +#ifdef HAVE_V4L1 case 'v': printk("v4l1 ioctl %s, dir=%s (0x%08x)\n", (_IOC_NR(cmd) < V4L1_IOCTLS) ? @@ -414,7 +414,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) printk ("%s: tuner type=%d\n", s, *p); break; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT case DECODER_SET_VBI_BYPASS: case DECODER_ENABLE_OUTPUT: case DECODER_GET_STATUS: @@ -425,7 +424,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) case VIDIOCCAPTURE: case VIDIOCSYNC: case VIDIOCSWRITEMODE: -#endif case TUNER_SET_TYPE_ADDR: case TUNER_SET_STANDBY: case TDA9887_SET_CONFIG: @@ -757,7 +755,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) p->afc); break; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT case VIDIOCGVBIFMT: case VIDIOCSVBIFMT: { @@ -927,14 +924,6 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) p->clipcount); break; } - case VIDIOCGFREQ: - case VIDIOCSFREQ: - { - unsigned long *p=arg; - printk ("%s: value=%lu\n", s, *p); - break; - } -#endif case VIDIOC_INT_AUDIO_CLOCK_FREQ: case VIDIOC_INT_I2S_CLOCK_FREQ: case VIDIOC_INT_S_STANDBY: @@ -944,6 +933,13 @@ void v4l_printk_ioctl_arg(char *s,unsigned int cmd, void *arg) printk ("%s: value=%d\n", s, *p); break; } + case VIDIOCGFREQ: + case VIDIOCSFREQ: + { + unsigned long *p=arg; + printk ("%s: value=%lu\n", s, *p); + break; + } case VIDIOC_G_STD: case VIDIOC_S_STD: case VIDIOC_QUERYSTD: diff --git a/trunk/drivers/media/video/videodev.c b/trunk/drivers/media/video/videodev.c index 88bf2af2a0e7..b26ebaff226f 100644 --- a/trunk/drivers/media/video/videodev.c +++ b/trunk/drivers/media/video/videodev.c @@ -760,7 +760,7 @@ static int __video_do_ioctl(struct inode *inode, struct file *file, ret=vfd->vidioc_overlay(file, fh, *i); break; } -#ifdef CONFIG_VIDEO_V4L1_COMPAT +#ifdef HAVE_V4L1 /* --- streaming capture ------------------------------------- */ case VIDIOCGMBUF: { @@ -1512,7 +1512,6 @@ int video_register_device(struct video_device *vfd, int type, int nr) int i=0; int base; int end; - int ret; char *name_base; switch(type) @@ -1538,8 +1537,6 @@ int video_register_device(struct video_device *vfd, int type, int nr) name_base = "radio"; break; default: - printk(KERN_ERR "%s called with unknown type: %d\n", - __FUNCTION__, type); return -1; } @@ -1574,18 +1571,9 @@ int video_register_device(struct video_device *vfd, int type, int nr) vfd->class_dev.class = &video_class; vfd->class_dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); sprintf(vfd->class_dev.class_id, "%s%d", name_base, i - base); - ret = class_device_register(&vfd->class_dev); - if (ret < 0) { - printk(KERN_ERR "%s: class_device_register failed\n", - __FUNCTION__); - goto fail_minor; - } - ret = class_device_create_file(&vfd->class_dev, &class_device_attr_name); - if (ret < 0) { - printk(KERN_ERR "%s: class_device_create_file 'name' failed\n", - __FUNCTION__); - goto fail_classdev; - } + class_device_register(&vfd->class_dev); + class_device_create_file(&vfd->class_dev, + &class_device_attr_name); #if 1 /* needed until all drivers are fixed */ @@ -1595,15 +1583,6 @@ int video_register_device(struct video_device *vfd, int type, int nr) "http://lwn.net/Articles/36850/\n", vfd->name); #endif return 0; - -fail_classdev: - class_device_unregister(&vfd->class_dev); -fail_minor: - mutex_lock(&videodev_lock); - video_device[vfd->minor] = NULL; - vfd->minor = -1; - mutex_unlock(&videodev_lock); - return ret; } /** diff --git a/trunk/drivers/media/video/vivi.c b/trunk/drivers/media/video/vivi.c index 841884af0cc0..41d23c8acbd8 100644 --- a/trunk/drivers/media/video/vivi.c +++ b/trunk/drivers/media/video/vivi.c @@ -986,7 +986,7 @@ static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) file->f_flags & O_NONBLOCK)); } -#ifdef CONFIG_VIDEO_V4L1_COMPAT +#ifdef HAVE_V4L1 static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf) { struct vivi_fh *fh=priv; @@ -1328,7 +1328,7 @@ static struct video_device vivi = { .vidioc_s_ctrl = vidioc_s_ctrl, .vidioc_streamon = vidioc_streamon, .vidioc_streamoff = vidioc_streamoff, -#ifdef CONFIG_VIDEO_V4L1_COMPAT +#ifdef HAVE_V4L1 .vidiocgmbuf = vidiocgmbuf, #endif .tvnorms = tvnorms, diff --git a/trunk/drivers/media/video/zoran.h b/trunk/drivers/media/video/zoran.h index 8fb4a3414e0a..ffcda95ed9d4 100644 --- a/trunk/drivers/media/video/zoran.h +++ b/trunk/drivers/media/video/zoran.h @@ -267,7 +267,7 @@ struct zoran_v4l_settings { }; /* whoops, this one is undeclared if !v4l2 */ -#ifndef CONFIG_VIDEO_V4L2 +#ifndef HAVE_V4L2 struct v4l2_jpegcompression { int quality; int APPn; diff --git a/trunk/drivers/media/video/zoran_driver.c b/trunk/drivers/media/video/zoran_driver.c index 5f90db27892b..d9a5876eb386 100644 --- a/trunk/drivers/media/video/zoran_driver.c +++ b/trunk/drivers/media/video/zoran_driver.c @@ -86,7 +86,7 @@ #include "zoran_device.h" #include "zoran_card.h" -#ifdef CONFIG_VIDEO_V4L2 +#ifdef HAVE_V4L2 /* we declare some card type definitions here, they mean * the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */ #define ZORAN_V4L2_VID_FLAGS ( \ @@ -103,7 +103,7 @@ const struct zoran_format zoran_formats[] = { { .name = "15-bit RGB", .palette = VIDEO_PALETTE_RGB555, -#ifdef CONFIG_VIDEO_V4L2 +#ifdef HAVE_V4L2 #ifdef __LITTLE_ENDIAN .fourcc = V4L2_PIX_FMT_RGB555, #else @@ -117,7 +117,7 @@ const struct zoran_format zoran_formats[] = { }, { .name = "16-bit RGB", .palette = VIDEO_PALETTE_RGB565, -#ifdef CONFIG_VIDEO_V4L2 +#ifdef HAVE_V4L2 #ifdef __LITTLE_ENDIAN .fourcc = V4L2_PIX_FMT_RGB565, #else @@ -131,7 +131,7 @@ const struct zoran_format zoran_formats[] = { }, { .name = "24-bit RGB", .palette = VIDEO_PALETTE_RGB24, -#ifdef CONFIG_VIDEO_V4L2 +#ifdef HAVE_V4L2 #ifdef __LITTLE_ENDIAN .fourcc = V4L2_PIX_FMT_BGR24, #else @@ -145,7 +145,7 @@ const struct zoran_format zoran_formats[] = { }, { .name = "32-bit RGB", .palette = VIDEO_PALETTE_RGB32, -#ifdef CONFIG_VIDEO_V4L2 +#ifdef HAVE_V4L2 #ifdef __LITTLE_ENDIAN .fourcc = V4L2_PIX_FMT_BGR32, #else @@ -159,7 +159,7 @@ const struct zoran_format zoran_formats[] = { }, { .name = "4:2:2, packed, YUYV", .palette = VIDEO_PALETTE_YUV422, -#ifdef CONFIG_VIDEO_V4L2 +#ifdef HAVE_V4L2 .fourcc = V4L2_PIX_FMT_YUYV, .colorspace = V4L2_COLORSPACE_SMPTE170M, #endif @@ -169,7 +169,7 @@ const struct zoran_format zoran_formats[] = { }, { .name = "Hardware-encoded Motion-JPEG", .palette = -1, -#ifdef CONFIG_VIDEO_V4L2 +#ifdef HAVE_V4L2 .fourcc = V4L2_PIX_FMT_MJPEG, .colorspace = V4L2_COLORSPACE_SMPTE170M, #endif @@ -210,7 +210,7 @@ static int lock_norm = 0; /* 1=Don't change TV standard (norm) */ module_param(lock_norm, int, 0); MODULE_PARM_DESC(lock_norm, "Users can't change norm"); -#ifdef CONFIG_VIDEO_V4L2 +#ifdef HAVE_V4L2 /* small helper function for calculating buffersizes for v4l2 * we calculate the nearest higher power-of-two, which * will be the recommended buffersize */ @@ -1761,7 +1761,7 @@ setup_overlay (struct file *file, return wait_grab_pending(zr); } -#ifdef CONFIG_VIDEO_V4L2 +#ifdef HAVE_V4L2 /* get the status of a buffer in the clients buffer queue */ static int zoran_v4l2_buffer_status (struct file *file, @@ -2676,7 +2676,7 @@ zoran_do_ioctl (struct inode *inode, } break; -#ifdef CONFIG_VIDEO_V4L2 +#ifdef HAVE_V4L2 /* The new video4linux2 capture interface - much nicer than video4linux1, since * it allows for integrating the JPEG capturing calls inside standard v4l2 @@ -4689,7 +4689,7 @@ static struct file_operations zoran_fops = { struct video_device zoran_template __devinitdata = { .name = ZORAN_NAME, .type = ZORAN_VID_TYPE, -#ifdef CONFIG_VIDEO_V4L2 +#ifdef HAVE_V4L2 .type2 = ZORAN_V4L2_VID_FLAGS, #endif .hardware = ZORAN_HARDWARE, diff --git a/trunk/drivers/message/fusion/mptbase.h b/trunk/drivers/message/fusion/mptbase.h index c537d71c18e4..d4cb144ab402 100644 --- a/trunk/drivers/message/fusion/mptbase.h +++ b/trunk/drivers/message/fusion/mptbase.h @@ -640,6 +640,7 @@ typedef struct _MPT_ADAPTER struct work_struct fc_setup_reset_work; struct list_head fc_rports; spinlock_t fc_rescan_work_lock; + int fc_rescan_work_count; struct work_struct fc_rescan_work; char fc_rescan_work_q_name[KOBJ_NAME_LEN]; struct workqueue_struct *fc_rescan_work_q; diff --git a/trunk/drivers/message/fusion/mptfc.c b/trunk/drivers/message/fusion/mptfc.c index 85696f34c310..90da7d63b08e 100644 --- a/trunk/drivers/message/fusion/mptfc.c +++ b/trunk/drivers/message/fusion/mptfc.c @@ -669,10 +669,7 @@ mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) * if still doing discovery, * hang loose a while until finished */ - if ((pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) || - (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_ONLINE && - (pp0dest->Flags & MPI_FCPORTPAGE0_FLAGS_ATTACH_TYPE_MASK) - == MPI_FCPORTPAGE0_FLAGS_ATTACH_NO_INIT)) { + if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) { if (count-- > 0) { msleep(100); goto try_again; @@ -898,45 +895,59 @@ mptfc_rescan_devices(void *arg) { MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; int ii; + int work_to_do; u64 pn; + unsigned long flags; struct mptfc_rport_info *ri; - /* start by tagging all ports as missing */ - list_for_each_entry(ri, &ioc->fc_rports, list) { - if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) { - ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING; + do { + /* start by tagging all ports as missing */ + list_for_each_entry(ri, &ioc->fc_rports, list) { + if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) { + ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING; + } } - } - /* - * now rescan devices known to adapter, - * will reregister existing rports - */ - for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { - (void) mptfc_GetFcPortPage0(ioc, ii); - mptfc_init_host_attr(ioc, ii); /* refresh */ - mptfc_GetFcDevPage0(ioc, ii, mptfc_register_dev); - } + /* + * now rescan devices known to adapter, + * will reregister existing rports + */ + for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) { + (void) mptfc_GetFcPortPage0(ioc, ii); + mptfc_init_host_attr(ioc,ii); /* refresh */ + mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev); + } - /* delete devices still missing */ - list_for_each_entry(ri, &ioc->fc_rports, list) { - /* if newly missing, delete it */ - if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) { + /* delete devices still missing */ + list_for_each_entry(ri, &ioc->fc_rports, list) { + /* if newly missing, delete it */ + if (ri->flags & MPT_RPORT_INFO_FLAGS_MISSING) { - ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED| - MPT_RPORT_INFO_FLAGS_MISSING); - fc_remote_port_delete(ri->rport); /* won't sleep */ - ri->rport = NULL; + ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED| + MPT_RPORT_INFO_FLAGS_MISSING); + fc_remote_port_delete(ri->rport); /* won't sleep */ + ri->rport = NULL; - pn = (u64)ri->pg0.WWPN.High << 32 | - (u64)ri->pg0.WWPN.Low; - dfcprintk ((MYIOC_s_INFO_FMT - "mptfc_rescan.%d: %llx deleted\n", - ioc->name, - ioc->sh->host_no, - (unsigned long long)pn)); + pn = (u64)ri->pg0.WWPN.High << 32 | + (u64)ri->pg0.WWPN.Low; + dfcprintk ((MYIOC_s_INFO_FMT + "mptfc_rescan.%d: %llx deleted\n", + ioc->name, + ioc->sh->host_no, + (unsigned long long)pn)); + } } - } + + /* + * allow multiple passes as target state + * might have changed during scan + */ + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + if (ioc->fc_rescan_work_count > 2) /* only need one more */ + ioc->fc_rescan_work_count = 2; + work_to_do = --ioc->fc_rescan_work_count; + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + } while (work_to_do); } static int @@ -1148,6 +1159,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) * by doing it via the workqueue, some locking is eliminated */ + ioc->fc_rescan_work_count = 1; queue_work(ioc->fc_rescan_work_q, &ioc->fc_rescan_work); flush_workqueue(ioc->fc_rescan_work_q); @@ -1190,8 +1202,10 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) case MPI_EVENT_RESCAN: spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); if (ioc->fc_rescan_work_q) { - queue_work(ioc->fc_rescan_work_q, - &ioc->fc_rescan_work); + if (ioc->fc_rescan_work_count++ == 0) { + queue_work(ioc->fc_rescan_work_q, + &ioc->fc_rescan_work); + } } spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); break; @@ -1234,8 +1248,10 @@ mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) mptfc_SetFcPortPage1_defaults(ioc); spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); if (ioc->fc_rescan_work_q) { - queue_work(ioc->fc_rescan_work_q, - &ioc->fc_rescan_work); + if (ioc->fc_rescan_work_count++ == 0) { + queue_work(ioc->fc_rescan_work_q, + &ioc->fc_rescan_work); + } } spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); } diff --git a/trunk/drivers/mmc/imxmmc.c b/trunk/drivers/mmc/imxmmc.c index fb6565b98f32..7ca9e95bdf89 100644 --- a/trunk/drivers/mmc/imxmmc.c +++ b/trunk/drivers/mmc/imxmmc.c @@ -91,8 +91,6 @@ struct imxmci_host { int dma_allocated; unsigned char actual_bus_width; - - int prev_cmd_code; }; #define IMXMCI_PEND_IRQ_b 0 @@ -250,14 +248,16 @@ static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data) * partial FIFO fills and reads. The length has to be rounded up to burst size multiple. * This is required for SCR read at least. */ - if (datasz < 512) { + if (datasz < 64) { host->dma_size = datasz; if (data->flags & MMC_DATA_READ) { host->dma_dir = DMA_FROM_DEVICE; /* Hack to enable read SCR */ - MMC_NOB = 1; - MMC_BLK_LEN = 512; + if(datasz < 16) { + MMC_NOB = 1; + MMC_BLK_LEN = 16; + } } else { host->dma_dir = DMA_TO_DEVICE; } @@ -409,9 +409,6 @@ static void imxmci_finish_request(struct imxmci_host *host, struct mmc_request * spin_unlock_irqrestore(&host->lock, flags); - if(req && req->cmd) - host->prev_cmd_code = req->cmd->opcode; - host->req = NULL; host->cmd = NULL; host->data = NULL; @@ -556,6 +553,7 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) { int i; int burst_len; + int flush_len; int trans_done = 0; unsigned int stat = *pstat; @@ -568,43 +566,44 @@ static int imxmci_cpu_driven_data(struct imxmci_host *host, unsigned int *pstat) dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data running STATUS = 0x%x\n", stat); - udelay(20); /* required for clocks < 8MHz*/ - if(host->dma_dir == DMA_FROM_DEVICE) { imxmci_busy_wait_for_status(host, &stat, STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE, - 50, "imxmci_cpu_driven_data read"); + 20, "imxmci_cpu_driven_data read"); while((stat & (STATUS_APPL_BUFF_FF | STATUS_DATA_TRANS_DONE)) && - (host->data_cnt < 512)) { - - udelay(20); /* required for clocks < 8MHz*/ + (host->data_cnt < host->dma_size)) { + if(burst_len >= host->dma_size - host->data_cnt) { + flush_len = burst_len; + burst_len = host->dma_size - host->data_cnt; + flush_len -= burst_len; + host->data_cnt = host->dma_size; + trans_done = 1; + } else { + flush_len = 0; + host->data_cnt += burst_len; + } for(i = burst_len; i>=2 ; i-=2) { - u16 data; - data = MMC_BUFFER_ACCESS; - udelay(10); /* required for clocks < 8MHz*/ - if(host->data_cnt+2 <= host->dma_size) { - *(host->data_ptr++) = data; - } else { - if(host->data_cnt < host->dma_size) - *(u8*)(host->data_ptr) = data; - } - host->data_cnt += 2; + *(host->data_ptr++) = MMC_BUFFER_ACCESS; + udelay(20); /* required for clocks < 8MHz*/ } - stat = MMC_STATUS; - - dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read %d burst %d STATUS = 0x%x\n", - host->data_cnt, burst_len, stat); - } + if(i == 1) + *(u8*)(host->data_ptr) = MMC_BUFFER_ACCESS; - if((stat & STATUS_DATA_TRANS_DONE) && (host->data_cnt >= 512)) - trans_done = 1; + stat = MMC_STATUS; - if(host->dma_size & 0x1ff) - stat &= ~STATUS_CRC_READ_ERR; + /* Flush extra bytes from FIFO */ + while(flush_len && !(stat & STATUS_DATA_TRANS_DONE)){ + i = MMC_BUFFER_ACCESS; + stat = MMC_STATUS; + stat &= ~STATUS_CRC_READ_ERR; /* Stupid but required there */ + } + dev_dbg(mmc_dev(host->mmc), "imxmci_cpu_driven_data read burst %d STATUS = 0x%x\n", + burst_len, stat); + } } else { imxmci_busy_wait_for_status(host, &stat, STATUS_APPL_BUFF_FE, @@ -693,8 +692,8 @@ static void imxmci_tasklet_fnc(unsigned long data) what, stat, MMC_INT_MASK); dev_err(mmc_dev(host->mmc), "CMD_DAT_CONT = 0x%04x, MMC_BLK_LEN = 0x%04x, MMC_NOB = 0x%04x, DMA_CCR = 0x%08x\n", MMC_CMD_DAT_CONT, MMC_BLK_LEN, MMC_NOB, CCR(host->dma)); - dev_err(mmc_dev(host->mmc), "CMD%d, prevCMD%d, bus %d-bit, dma_size = 0x%x\n", - host->cmd?host->cmd->opcode:0, host->prev_cmd_code, 1<actual_bus_width, host->dma_size); + dev_err(mmc_dev(host->mmc), "CMD%d, bus %d-bit, dma_size = 0x%x\n", + host->cmd?host->cmd->opcode:0, 1<actual_bus_width, host->dma_size); } if(!host->present || timeout) diff --git a/trunk/drivers/mmc/mmc.c b/trunk/drivers/mmc/mmc.c index 74eaaee66de0..33525bdf2ab6 100644 --- a/trunk/drivers/mmc/mmc.c +++ b/trunk/drivers/mmc/mmc.c @@ -247,55 +247,6 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca, EXPORT_SYMBOL(mmc_wait_for_app_cmd); -/** - * mmc_set_data_timeout - set the timeout for a data command - * @data: data phase for command - * @card: the MMC card associated with the data transfer - * @write: flag to differentiate reads from writes - */ -void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card, - int write) -{ - unsigned int mult; - - /* - * SD cards use a 100 multiplier rather than 10 - */ - mult = mmc_card_sd(card) ? 100 : 10; - - /* - * Scale up the multiplier (and therefore the timeout) by - * the r2w factor for writes. - */ - if (write) - mult <<= card->csd.r2w_factor; - - data->timeout_ns = card->csd.tacc_ns * mult; - data->timeout_clks = card->csd.tacc_clks * mult; - - /* - * SD cards also have an upper limit on the timeout. - */ - if (mmc_card_sd(card)) { - unsigned int timeout_us, limit_us; - - timeout_us = data->timeout_ns / 1000; - timeout_us += data->timeout_clks * 1000 / - (card->host->ios.clock / 1000); - - if (write) - limit_us = 250000; - else - limit_us = 100000; - - if (timeout_us > limit_us) { - data->timeout_ns = limit_us * 1000; - data->timeout_clks = 0; - } - } -} -EXPORT_SYMBOL(mmc_set_data_timeout); - static int mmc_select_card(struct mmc_host *host, struct mmc_card *card); /** @@ -957,9 +908,11 @@ static void mmc_read_scrs(struct mmc_host *host) { int err; struct mmc_card *card; + struct mmc_request mrq; struct mmc_command cmd; struct mmc_data data; + struct scatterlist sg; list_for_each_entry(card, &host->cards, node) { @@ -994,8 +947,8 @@ static void mmc_read_scrs(struct mmc_host *host) memset(&data, 0, sizeof(struct mmc_data)); - mmc_set_data_timeout(&data, card, 0); - + data.timeout_ns = card->csd.tacc_ns * 10; + data.timeout_clks = card->csd.tacc_clks * 10; data.blksz_bits = 3; data.blksz = 1 << 3; data.blocks = 1; diff --git a/trunk/drivers/mmc/mmc_block.c b/trunk/drivers/mmc/mmc_block.c index a0e0dad1b419..115cc21094b9 100644 --- a/trunk/drivers/mmc/mmc_block.c +++ b/trunk/drivers/mmc/mmc_block.c @@ -30,7 +30,6 @@ #include #include -#include #include #include @@ -172,6 +171,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) brq.cmd.arg = req->sector << 9; brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + brq.data.timeout_ns = card->csd.tacc_ns * 10; + brq.data.timeout_clks = card->csd.tacc_clks * 10; brq.data.blksz_bits = md->block_bits; brq.data.blksz = 1 << md->block_bits; brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); @@ -179,8 +180,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) brq.stop.arg = 0; brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC; - mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ); - if (rq_data_dir(req) == READ) { brq.cmd.opcode = brq.data.blocks > 1 ? MMC_READ_MULTIPLE_BLOCK : MMC_READ_SINGLE_BLOCK; brq.data.flags |= MMC_DATA_READ; @@ -188,6 +187,12 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) brq.cmd.opcode = MMC_WRITE_BLOCK; brq.data.flags |= MMC_DATA_WRITE; brq.data.blocks = 1; + + /* + * Scale up the timeout by the r2w factor + */ + brq.data.timeout_ns <<= card->csd.r2w_factor; + brq.data.timeout_clks <<= card->csd.r2w_factor; } if (brq.data.blocks > 1) { @@ -319,11 +324,52 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) md->read_only = mmc_blk_readonly(card); /* - * Both SD and MMC specifications state (although a bit - * unclearly in the MMC case) that a block size of 512 - * bytes must always be supported by the card. + * Figure out a workable block size. MMC cards have: + * - two block sizes, one for read and one for write. + * - may support partial reads and/or writes + * (allows block sizes smaller than specified) + */ + md->block_bits = card->csd.read_blkbits; + if (card->csd.write_blkbits != card->csd.read_blkbits) { + if (card->csd.write_blkbits < card->csd.read_blkbits && + card->csd.read_partial) { + /* + * write block size is smaller than read block + * size, but we support partial reads, so choose + * the smaller write block size. + */ + md->block_bits = card->csd.write_blkbits; + } else if (card->csd.write_blkbits > card->csd.read_blkbits && + card->csd.write_partial) { + /* + * read block size is smaller than write block + * size, but we support partial writes. Use read + * block size. + */ + } else { + /* + * We don't support this configuration for writes. + */ + printk(KERN_ERR "%s: unable to select block size for " + "writing (rb%u wb%u rp%u wp%u)\n", + mmc_card_id(card), + 1 << card->csd.read_blkbits, + 1 << card->csd.write_blkbits, + card->csd.read_partial, + card->csd.write_partial); + md->read_only = 1; + } + } + + /* + * Refuse to allow block sizes smaller than 512 bytes. */ - md->block_bits = 9; + if (md->block_bits < 9) { + printk(KERN_ERR "%s: unable to support block size %u\n", + mmc_card_id(card), 1 << md->block_bits); + ret = -EINVAL; + goto err_kfree; + } md->disk = alloc_disk(1 << MMC_SHIFT); if (md->disk == NULL) { diff --git a/trunk/drivers/mmc/mmc_queue.c b/trunk/drivers/mmc/mmc_queue.c index 74f8cdeeff0f..0b9682e9a357 100644 --- a/trunk/drivers/mmc/mmc_queue.c +++ b/trunk/drivers/mmc/mmc_queue.c @@ -79,8 +79,7 @@ static int mmc_queue_thread(void *d) spin_lock_irq(q->queue_lock); set_current_state(TASK_INTERRUPTIBLE); if (!blk_queue_plugged(q)) - req = elv_next_request(q); - mq->req = req; + mq->req = req = elv_next_request(q); spin_unlock_irq(q->queue_lock); if (!req) { diff --git a/trunk/drivers/mmc/wbsd.c b/trunk/drivers/mmc/wbsd.c index c351c6d1a18a..8a30ef3ae419 100644 --- a/trunk/drivers/mmc/wbsd.c +++ b/trunk/drivers/mmc/wbsd.c @@ -41,7 +41,7 @@ #include "wbsd.h" #define DRIVER_NAME "wbsd" -#define DRIVER_VERSION "1.6" +#define DRIVER_VERSION "1.5" #define DBG(x...) \ pr_debug(DRIVER_NAME ": " x) @@ -1439,13 +1439,13 @@ static int __devinit wbsd_scan(struct wbsd_host *host) static int __devinit wbsd_request_region(struct wbsd_host *host, int base) { - if (base & 0x7) + if (io & 0x7) return -EINVAL; if (!request_region(base, 8, DRIVER_NAME)) return -EIO; - host->base = base; + host->base = io; return 0; } @@ -1773,7 +1773,7 @@ static int __devinit wbsd_init(struct device *dev, int base, int irq, int dma, /* * Request resources. */ - ret = wbsd_request_resources(host, base, irq, dma); + ret = wbsd_request_resources(host, io, irq, dma); if (ret) { wbsd_release_resources(host); wbsd_free_mmc(dev); @@ -1861,7 +1861,6 @@ static void __devexit wbsd_shutdown(struct device *dev, int pnp) static int __devinit wbsd_probe(struct platform_device *dev) { - /* Use the module parameters for resources */ return wbsd_init(&dev->dev, io, irq, dma, 0); } diff --git a/trunk/drivers/mtd/Kconfig b/trunk/drivers/mtd/Kconfig index a03e862851db..1344ad7a4b14 100644 --- a/trunk/drivers/mtd/Kconfig +++ b/trunk/drivers/mtd/Kconfig @@ -101,7 +101,7 @@ config MTD_REDBOOT_PARTS_READONLY config MTD_CMDLINE_PARTS bool "Command line partition table parsing" - depends on MTD_PARTITIONS = "y" && MTD = "y" + depends on MTD_PARTITIONS = "y" ---help--- Allow generic configuration of the MTD partition tables via the kernel command line. Multiple flash resources are supported for hardware where @@ -263,14 +263,6 @@ config RFD_FTL http://www.gensw.com/pages/prod/bios/rfd.htm -config SSFDC - tristate "NAND SSFDC (SmartMedia) read only translation layer" - depends on MTD - default n - help - This enables read only access to SmartMedia formatted NAND - flash. You can mount it with FAT file system. - source "drivers/mtd/chips/Kconfig" source "drivers/mtd/maps/Kconfig" diff --git a/trunk/drivers/mtd/Makefile b/trunk/drivers/mtd/Makefile index 1e36b9aed98b..fc9374407c2b 100644 --- a/trunk/drivers/mtd/Makefile +++ b/trunk/drivers/mtd/Makefile @@ -21,7 +21,6 @@ obj-$(CONFIG_FTL) += ftl.o mtd_blkdevs.o obj-$(CONFIG_NFTL) += nftl.o mtd_blkdevs.o obj-$(CONFIG_INFTL) += inftl.o mtd_blkdevs.o obj-$(CONFIG_RFD_FTL) += rfd_ftl.o mtd_blkdevs.o -obj-$(CONFIG_SSFDC) += ssfdc.o mtd_blkdevs.o nftl-objs := nftlcore.o nftlmount.o inftl-objs := inftlcore.o inftlmount.o diff --git a/trunk/drivers/mtd/chips/cfi_cmdset_0001.c b/trunk/drivers/mtd/chips/cfi_cmdset_0001.c index 7ea49a0d5ec3..39edb8250fbc 100644 --- a/trunk/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/trunk/drivers/mtd/chips/cfi_cmdset_0001.c @@ -908,7 +908,7 @@ static void __xipram xip_enable(struct map_info *map, struct flchip *chip, static int __xipram xip_wait_for_operation( struct map_info *map, struct flchip *chip, - unsigned long adr, unsigned int chip_op_time ) + unsigned long adr, int *chip_op_time ) { struct cfi_private *cfi = map->fldrv_priv; struct cfi_pri_intelext *cfip = cfi->cmdset_priv; @@ -917,7 +917,7 @@ static int __xipram xip_wait_for_operation( flstate_t oldstate, newstate; start = xip_currtime(); - usec = chip_op_time * 8; + usec = *chip_op_time * 8; if (usec == 0) usec = 500000; done = 0; @@ -1027,8 +1027,8 @@ static int __xipram xip_wait_for_operation( #define XIP_INVAL_CACHED_RANGE(map, from, size) \ INVALIDATE_CACHED_RANGE(map, from, size) -#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \ - xip_wait_for_operation(map, chip, cmd_adr, usec) +#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, p_usec) \ + xip_wait_for_operation(map, chip, cmd_adr, p_usec) #else @@ -1040,65 +1040,65 @@ static int __xipram xip_wait_for_operation( static int inval_cache_and_wait_for_operation( struct map_info *map, struct flchip *chip, unsigned long cmd_adr, unsigned long inval_adr, int inval_len, - unsigned int chip_op_time) + int *chip_op_time ) { struct cfi_private *cfi = map->fldrv_priv; map_word status, status_OK = CMD(0x80); - int chip_state = chip->state; - unsigned int timeo, sleep_time; + int z, chip_state = chip->state; + unsigned long timeo; spin_unlock(chip->mutex); if (inval_len) INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len); + if (*chip_op_time) + cfi_udelay(*chip_op_time); spin_lock(chip->mutex); - /* set our timeout to 8 times the expected delay */ - timeo = chip_op_time * 8; - if (!timeo) - timeo = 500000; - sleep_time = chip_op_time / 2; + timeo = *chip_op_time * 8 * HZ / 1000000; + if (timeo < HZ/2) + timeo = HZ/2; + timeo += jiffies; + z = 0; for (;;) { + if (chip->state != chip_state) { + /* Someone's suspended the operation: sleep */ + DECLARE_WAITQUEUE(wait, current); + + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + spin_unlock(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + timeo = jiffies + (HZ / 2); /* FIXME */ + spin_lock(chip->mutex); + continue; + } + status = map_read(map, cmd_adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; - if (!timeo) { + /* OK Still waiting */ + if (time_after(jiffies, timeo)) { map_write(map, CMD(0x70), cmd_adr); chip->state = FL_STATUS; return -ETIME; } - /* OK Still waiting. Drop the lock, wait a while and retry. */ + /* Latency issues. Drop the lock, wait a while and retry */ + z++; spin_unlock(chip->mutex); - if (sleep_time >= 1000000/HZ) { - /* - * Half of the normal delay still remaining - * can be performed with a sleeping delay instead - * of busy waiting. - */ - msleep(sleep_time/1000); - timeo -= sleep_time; - sleep_time = 1000000/HZ; - } else { - udelay(1); - cond_resched(); - timeo--; - } + cfi_udelay(1); spin_lock(chip->mutex); - - if (chip->state != chip_state) { - /* Someone's suspended the operation: sleep */ - DECLARE_WAITQUEUE(wait, current); - set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); - spin_unlock(chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); - spin_lock(chip->mutex); - } } + if (!z) { + if (!--(*chip_op_time)) + *chip_op_time = 1; + } else if (z > 1) + ++(*chip_op_time); + /* Done and happy. */ chip->state = FL_STATUS; return 0; @@ -1107,7 +1107,8 @@ static int inval_cache_and_wait_for_operation( #endif #define WAIT_TIMEOUT(map, chip, adr, udelay) \ - INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay); + ({ int __udelay = (udelay); \ + INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, &__udelay); }) static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) @@ -1331,7 +1332,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, ret = INVAL_CACHE_AND_WAIT(map, chip, adr, adr, map_bankwidth(map), - chip->word_write_time); + &chip->word_write_time); if (ret) { xip_enable(map, chip, adr); printk(KERN_ERR "%s: word write error (status timeout)\n", map->name); @@ -1568,7 +1569,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, adr, len, - chip->buffer_write_time); + &chip->buffer_write_time); if (ret) { map_write(map, CMD(0x70), cmd_adr); chip->state = FL_STATUS; @@ -1703,7 +1704,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, ret = INVAL_CACHE_AND_WAIT(map, chip, adr, adr, len, - chip->erase_time); + &chip->erase_time); if (ret) { map_write(map, CMD(0x70), adr); chip->state = FL_STATUS; diff --git a/trunk/drivers/mtd/chips/cfi_cmdset_0002.c b/trunk/drivers/mtd/chips/cfi_cmdset_0002.c index 702ae4cd8691..9885726a16e4 100644 --- a/trunk/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/trunk/drivers/mtd/chips/cfi_cmdset_0002.c @@ -45,11 +45,9 @@ #define MAX_WORD_RETRIES 3 #define MANUFACTURER_AMD 0x0001 -#define MANUFACTURER_ATMEL 0x001F #define MANUFACTURER_SST 0x00BF #define SST49LF004B 0x0060 #define SST49LF008A 0x005a -#define AT49BV6416 0x00d6 static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); @@ -70,9 +68,6 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr); #include "fwh_lock.h" -static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len); -static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len); - static struct mtd_chip_driver cfi_amdstd_chipdrv = { .probe = NULL, /* Not usable directly */ .destroy = cfi_amdstd_destroy, @@ -166,26 +161,6 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param) } } -/* Atmel chips don't use the same PRI format as AMD chips */ -static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param) -{ - struct map_info *map = mtd->priv; - struct cfi_private *cfi = map->fldrv_priv; - struct cfi_pri_amdstd *extp = cfi->cmdset_priv; - struct cfi_pri_atmel atmel_pri; - - memcpy(&atmel_pri, extp, sizeof(atmel_pri)); - memset((char *)extp + 5, 0, sizeof(*extp) - 5); - - if (atmel_pri.Features & 0x02) - extp->EraseSuspend = 2; - - if (atmel_pri.BottomBoot) - extp->TopBottom = 2; - else - extp->TopBottom = 3; -} - static void fixup_use_secsi(struct mtd_info *mtd, void *param) { /* Setup for chips with a secsi area */ @@ -204,17 +179,6 @@ static void fixup_use_erase_chip(struct mtd_info *mtd, void *param) } -/* - * Some Atmel chips (e.g. the AT49BV6416) power-up with all sectors - * locked by default. - */ -static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param) -{ - mtd->lock = cfi_atmel_lock; - mtd->unlock = cfi_atmel_unlock; - mtd->flags |= MTD_STUPID_LOCK; -} - static struct cfi_fixup cfi_fixup_table[] = { #ifdef AMD_BOOTLOC_BUG { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL }, @@ -228,7 +192,6 @@ static struct cfi_fixup cfi_fixup_table[] = { #if !FORCE_WORD_WRITE { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, #endif - { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, { 0, 0, NULL, NULL } }; static struct cfi_fixup jedec_fixup_table[] = { @@ -244,7 +207,6 @@ static struct cfi_fixup fixup_table[] = { * we know that is the case. */ { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL }, - { CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock, NULL }, { 0, 0, NULL, NULL } }; @@ -1645,80 +1607,6 @@ static int cfi_amdstd_erase_chip(struct mtd_info *mtd, struct erase_info *instr) return 0; } -static int do_atmel_lock(struct map_info *map, struct flchip *chip, - unsigned long adr, int len, void *thunk) -{ - struct cfi_private *cfi = map->fldrv_priv; - int ret; - - spin_lock(chip->mutex); - ret = get_chip(map, chip, adr + chip->start, FL_LOCKING); - if (ret) - goto out_unlock; - chip->state = FL_LOCKING; - - DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", - __func__, adr, len); - - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, - cfi->device_type, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, - cfi->device_type, NULL); - cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, - cfi->device_type, NULL); - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, - cfi->device_type, NULL); - cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, - cfi->device_type, NULL); - map_write(map, CMD(0x40), chip->start + adr); - - chip->state = FL_READY; - put_chip(map, chip, adr + chip->start); - ret = 0; - -out_unlock: - spin_unlock(chip->mutex); - return ret; -} - -static int do_atmel_unlock(struct map_info *map, struct flchip *chip, - unsigned long adr, int len, void *thunk) -{ - struct cfi_private *cfi = map->fldrv_priv; - int ret; - - spin_lock(chip->mutex); - ret = get_chip(map, chip, adr + chip->start, FL_UNLOCKING); - if (ret) - goto out_unlock; - chip->state = FL_UNLOCKING; - - DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", - __func__, adr, len); - - cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, - cfi->device_type, NULL); - map_write(map, CMD(0x70), adr); - - chip->state = FL_READY; - put_chip(map, chip, adr + chip->start); - ret = 0; - -out_unlock: - spin_unlock(chip->mutex); - return ret; -} - -static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len) -{ - return cfi_varsize_frob(mtd, do_atmel_lock, ofs, len, NULL); -} - -static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) -{ - return cfi_varsize_frob(mtd, do_atmel_unlock, ofs, len, NULL); -} - static void cfi_amdstd_sync (struct mtd_info *mtd) { diff --git a/trunk/drivers/mtd/chips/jedec_probe.c b/trunk/drivers/mtd/chips/jedec_probe.c index 1154dac715aa..8f39d0a31438 100644 --- a/trunk/drivers/mtd/chips/jedec_probe.c +++ b/trunk/drivers/mtd/chips/jedec_probe.c @@ -111,7 +111,6 @@ #define MX29LV040C 0x004F #define MX29LV160T 0x22C4 #define MX29LV160B 0x2249 -#define MX29F040 0x00A4 #define MX29F016 0x00AD #define MX29F002T 0x00B0 #define MX29F004T 0x0045 @@ -1172,19 +1171,6 @@ static const struct amd_flash_info jedec_table[] = { ERASEINFO(0x10000,31) } }, { - .mfr_id = MANUFACTURER_MACRONIX, - .dev_id = MX29F040, - .name = "Macronix MX29F040", - .uaddr = { - [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ - }, - .DevSize = SIZE_512KiB, - .CmdSet = P_ID_AMD_STD, - .NumEraseRegions= 1, - .regions = { - ERASEINFO(0x10000,8), - } - }, { .mfr_id = MANUFACTURER_MACRONIX, .dev_id = MX29F016, .name = "Macronix MX29F016", diff --git a/trunk/drivers/mtd/devices/block2mtd.c b/trunk/drivers/mtd/devices/block2mtd.c index 401c6a294baa..ede3561be870 100644 --- a/trunk/drivers/mtd/devices/block2mtd.c +++ b/trunk/drivers/mtd/devices/block2mtd.c @@ -18,7 +18,6 @@ #include #include #include -#include #define VERSION "$Revision: 1.30 $" @@ -237,8 +236,6 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, } return 0; } - - static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { @@ -302,19 +299,6 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) /* Get a handle on the device */ bdev = open_bdev_excl(devname, O_RDWR, NULL); -#ifndef MODULE - if (IS_ERR(bdev)) { - - /* We might not have rootfs mounted at this point. Try - to resolve the device name by other means. */ - - dev_t dev = name_to_dev_t(devname); - if (dev != 0) { - bdev = open_by_devnum(dev, FMODE_WRITE | FMODE_READ); - } - } -#endif - if (IS_ERR(bdev)) { ERROR("error: cannot open device %s", devname); goto devinit_err; @@ -409,6 +393,26 @@ static int parse_num(size_t *num, const char *token) } +static int parse_name(char **pname, const char *token, size_t limit) +{ + size_t len; + char *name; + + len = strlen(token) + 1; + if (len > limit) + return -ENOSPC; + + name = kmalloc(len, GFP_KERNEL); + if (!name) + return -ENOMEM; + + strcpy(name, token); + + *pname = name; + return 0; +} + + static inline void kill_final_newline(char *str) { char *newline = strrchr(str, '\n'); @@ -422,15 +426,9 @@ static inline void kill_final_newline(char *str) return 0; \ } while (0) -#ifndef MODULE -static int block2mtd_init_called = 0; -static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ -#endif - - -static int block2mtd_setup2(const char *val) +static int block2mtd_setup(const char *val, struct kernel_param *kp) { - char buf[80 + 12]; /* 80 for device, 12 for erase size */ + char buf[80+12]; /* 80 for device, 12 for erase size */ char *str = buf; char *token[2]; char *name; @@ -452,9 +450,13 @@ static int block2mtd_setup2(const char *val) if (!token[0]) parse_err("no argument"); - name = token[0]; - if (strlen(name) + 1 > 80) - parse_err("device name too long"); + ret = parse_name(&name, token[0], 80); + if (ret == -ENOMEM) + parse_err("out of memory"); + if (ret == -ENOSPC) + parse_err("name too long"); + if (ret) + return 0; if (token[1]) { ret = parse_num(&erase_size, token[1]); @@ -470,48 +472,13 @@ static int block2mtd_setup2(const char *val) } -static int block2mtd_setup(const char *val, struct kernel_param *kp) -{ -#ifdef MODULE - return block2mtd_setup2(val); -#else - /* If more parameters are later passed in via - /sys/module/block2mtd/parameters/block2mtd - and block2mtd_init() has already been called, - we can parse the argument now. */ - - if (block2mtd_init_called) - return block2mtd_setup2(val); - - /* During early boot stage, we only save the parameters - here. We must parse them later: if the param passed - from kernel boot command line, block2mtd_setup() is - called so early that it is not possible to resolve - the device (even kmalloc() fails). Deter that work to - block2mtd_setup2(). */ - - strlcpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); - - return 0; -#endif -} - - module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=[,]\""); static int __init block2mtd_init(void) { - int ret = 0; INFO("version " VERSION); - -#ifndef MODULE - if (strlen(block2mtd_paramline)) - ret = block2mtd_setup2(block2mtd_paramline); - block2mtd_init_called = 1; -#endif - - return ret; + return 0; } diff --git a/trunk/drivers/mtd/devices/m25p80.c b/trunk/drivers/mtd/devices/m25p80.c index ef4a731ca5c2..a8466141e914 100644 --- a/trunk/drivers/mtd/devices/m25p80.c +++ b/trunk/drivers/mtd/devices/m25p80.c @@ -406,13 +406,13 @@ struct flash_info { static struct flash_info __devinitdata m25p_data [] = { /* REVISIT: fill in JEDEC ids, for parts that have them */ - { "m25p05", 0x05, 0x2010, 32 * 1024, 2 }, - { "m25p10", 0x10, 0x2011, 32 * 1024, 4 }, - { "m25p20", 0x11, 0x2012, 64 * 1024, 4 }, - { "m25p40", 0x12, 0x2013, 64 * 1024, 8 }, + { "m25p05", 0x05, 0x0000, 32 * 1024, 2 }, + { "m25p10", 0x10, 0x0000, 32 * 1024, 4 }, + { "m25p20", 0x11, 0x0000, 64 * 1024, 4 }, + { "m25p40", 0x12, 0x0000, 64 * 1024, 8 }, { "m25p80", 0x13, 0x0000, 64 * 1024, 16 }, - { "m25p16", 0x14, 0x2015, 64 * 1024, 32 }, - { "m25p32", 0x15, 0x2016, 64 * 1024, 64 }, + { "m25p16", 0x14, 0x0000, 64 * 1024, 32 }, + { "m25p32", 0x15, 0x0000, 64 * 1024, 64 }, { "m25p64", 0x16, 0x2017, 64 * 1024, 128 }, }; diff --git a/trunk/drivers/mtd/devices/pmc551.c b/trunk/drivers/mtd/devices/pmc551.c index 354e1657cc26..6f9bbf6fee4d 100644 --- a/trunk/drivers/mtd/devices/pmc551.c +++ b/trunk/drivers/mtd/devices/pmc551.c @@ -4,82 +4,82 @@ * PMC551 PCI Mezzanine Ram Device * * Author: - * Mark Ferrell - * Copyright 1999,2000 Nortel Networks + * Mark Ferrell + * Copyright 1999,2000 Nortel Networks * * License: - * As part of this driver was derived from the slram.c driver it - * falls under the same license, which is GNU General Public - * License v2 + * As part of this driver was derived from the slram.c driver it + * falls under the same license, which is GNU General Public + * License v2 * * Description: - * This driver is intended to support the PMC551 PCI Ram device - * from Ramix Inc. The PMC551 is a PMC Mezzanine module for - * cPCI embedded systems. The device contains a single SROM - * that initially programs the V370PDC chipset onboard the - * device, and various banks of DRAM/SDRAM onboard. This driver - * implements this PCI Ram device as an MTD (Memory Technology - * Device) so that it can be used to hold a file system, or for - * added swap space in embedded systems. Since the memory on - * this board isn't as fast as main memory we do not try to hook - * it into main memory as that would simply reduce performance - * on the system. Using it as a block device allows us to use - * it as high speed swap or for a high speed disk device of some - * sort. Which becomes very useful on diskless systems in the - * embedded market I might add. + * This driver is intended to support the PMC551 PCI Ram device + * from Ramix Inc. The PMC551 is a PMC Mezzanine module for + * cPCI embedded systems. The device contains a single SROM + * that initially programs the V370PDC chipset onboard the + * device, and various banks of DRAM/SDRAM onboard. This driver + * implements this PCI Ram device as an MTD (Memory Technology + * Device) so that it can be used to hold a file system, or for + * added swap space in embedded systems. Since the memory on + * this board isn't as fast as main memory we do not try to hook + * it into main memory as that would simply reduce performance + * on the system. Using it as a block device allows us to use + * it as high speed swap or for a high speed disk device of some + * sort. Which becomes very useful on diskless systems in the + * embedded market I might add. * * Notes: - * Due to what I assume is more buggy SROM, the 64M PMC551 I - * have available claims that all 4 of it's DRAM banks have 64M - * of ram configured (making a grand total of 256M onboard). - * This is slightly annoying since the BAR0 size reflects the - * aperture size, not the dram size, and the V370PDC supplies no - * other method for memory size discovery. This problem is - * mostly only relevant when compiled as a module, as the - * unloading of the module with an aperture size smaller then - * the ram will cause the driver to detect the onboard memory - * size to be equal to the aperture size when the module is - * reloaded. Soooo, to help, the module supports an msize - * option to allow the specification of the onboard memory, and - * an asize option, to allow the specification of the aperture - * size. The aperture must be equal to or less then the memory - * size, the driver will correct this if you screw it up. This - * problem is not relevant for compiled in drivers as compiled - * in drivers only init once. + * Due to what I assume is more buggy SROM, the 64M PMC551 I + * have available claims that all 4 of it's DRAM banks have 64M + * of ram configured (making a grand total of 256M onboard). + * This is slightly annoying since the BAR0 size reflects the + * aperture size, not the dram size, and the V370PDC supplies no + * other method for memory size discovery. This problem is + * mostly only relevant when compiled as a module, as the + * unloading of the module with an aperture size smaller then + * the ram will cause the driver to detect the onboard memory + * size to be equal to the aperture size when the module is + * reloaded. Soooo, to help, the module supports an msize + * option to allow the specification of the onboard memory, and + * an asize option, to allow the specification of the aperture + * size. The aperture must be equal to or less then the memory + * size, the driver will correct this if you screw it up. This + * problem is not relevant for compiled in drivers as compiled + * in drivers only init once. * * Credits: - * Saeed Karamooz of Ramix INC. for the - * initial example code of how to initialize this device and for - * help with questions I had concerning operation of the device. + * Saeed Karamooz of Ramix INC. for the + * initial example code of how to initialize this device and for + * help with questions I had concerning operation of the device. * - * Most of the MTD code for this driver was originally written - * for the slram.o module in the MTD drivers package which - * allows the mapping of system memory into an MTD device. - * Since the PMC551 memory module is accessed in the same - * fashion as system memory, the slram.c code became a very nice - * fit to the needs of this driver. All we added was PCI - * detection/initialization to the driver and automatically figure - * out the size via the PCI detection.o, later changes by Corey - * Minyard set up the card to utilize a 1M sliding apature. + * Most of the MTD code for this driver was originally written + * for the slram.o module in the MTD drivers package which + * allows the mapping of system memory into an MTD device. + * Since the PMC551 memory module is accessed in the same + * fashion as system memory, the slram.c code became a very nice + * fit to the needs of this driver. All we added was PCI + * detection/initialization to the driver and automatically figure + * out the size via the PCI detection.o, later changes by Corey + * Minyard set up the card to utilize a 1M sliding apature. * - * Corey Minyard - * * Modified driver to utilize a sliding aperture instead of - * mapping all memory into kernel space which turned out to - * be very wasteful. - * * Located a bug in the SROM's initialization sequence that - * made the memory unusable, added a fix to code to touch up - * the DRAM some. + * Corey Minyard + * * Modified driver to utilize a sliding aperture instead of + * mapping all memory into kernel space which turned out to + * be very wasteful. + * * Located a bug in the SROM's initialization sequence that + * made the memory unusable, added a fix to code to touch up + * the DRAM some. * * Bugs/FIXME's: - * * MUST fix the init function to not spin on a register - * waiting for it to set .. this does not safely handle busted - * devices that never reset the register correctly which will - * cause the system to hang w/ a reboot being the only chance at - * recover. [sort of fixed, could be better] - * * Add I2C handling of the SROM so we can read the SROM's information - * about the aperture size. This should always accurately reflect the - * onboard memory size. - * * Comb the init routine. It's still a bit cludgy on a few things. + * * MUST fix the init function to not spin on a register + * waiting for it to set .. this does not safely handle busted + * devices that never reset the register correctly which will + * cause the system to hang w/ a reboot being the only chance at + * recover. [sort of fixed, could be better] + * * Add I2C handling of the SROM so we can read the SROM's information + * about the aperture size. This should always accurately reflect the + * onboard memory size. + * * Comb the init routine. It's still a bit cludgy on a few things. */ #include @@ -99,83 +99,84 @@ #include #include +#ifndef CONFIG_PCI +#error Enable PCI in your kernel config +#endif + #include #include #include static struct mtd_info *pmc551list; -static int pmc551_erase(struct mtd_info *mtd, struct erase_info *instr) +static int pmc551_erase (struct mtd_info *mtd, struct erase_info *instr) { - struct mypriv *priv = mtd->priv; - u32 soff_hi, soff_lo; /* start address offset hi/lo */ - u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ - unsigned long end; + struct mypriv *priv = mtd->priv; + u32 soff_hi, soff_lo; /* start address offset hi/lo */ + u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ + unsigned long end; u_char *ptr; size_t retlen; #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr, - (long)instr->len); + printk(KERN_DEBUG "pmc551_erase(pos:%ld, len:%ld)\n", (long)instr->addr, (long)instr->len); #endif - end = instr->addr + instr->len - 1; + end = instr->addr + instr->len - 1; - /* Is it past the end? */ - if (end > mtd->size) { + /* Is it past the end? */ + if ( end > mtd->size ) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_erase() out of bounds (%ld > %ld)\n", - (long)end, (long)mtd->size); + printk(KERN_DEBUG "pmc551_erase() out of bounds (%ld > %ld)\n", (long)end, (long)mtd->size); #endif - return -EINVAL; - } - - eoff_hi = end & ~(priv->asize - 1); - soff_hi = instr->addr & ~(priv->asize - 1); - eoff_lo = end & (priv->asize - 1); - soff_lo = instr->addr & (priv->asize - 1); - - pmc551_point(mtd, instr->addr, instr->len, &retlen, &ptr); - - if (soff_hi == eoff_hi || mtd->size == priv->asize) { - /* The whole thing fits within one access, so just one shot - will do it. */ - memset(ptr, 0xff, instr->len); - } else { - /* We have to do multiple writes to get all the data - written. */ - while (soff_hi != eoff_hi) { + return -EINVAL; + } + + eoff_hi = end & ~(priv->asize - 1); + soff_hi = instr->addr & ~(priv->asize - 1); + eoff_lo = end & (priv->asize - 1); + soff_lo = instr->addr & (priv->asize - 1); + + pmc551_point (mtd, instr->addr, instr->len, &retlen, &ptr); + + if ( soff_hi == eoff_hi || mtd->size == priv->asize) { + /* The whole thing fits within one access, so just one shot + will do it. */ + memset(ptr, 0xff, instr->len); + } else { + /* We have to do multiple writes to get all the data + written. */ + while (soff_hi != eoff_hi) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_erase() soff_hi: %ld, " - "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); + printk( KERN_DEBUG "pmc551_erase() soff_hi: %ld, eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); #endif - memset(ptr, 0xff, priv->asize); - if (soff_hi + priv->asize >= mtd->size) { - goto out; - } - soff_hi += priv->asize; - pmc551_point(mtd, (priv->base_map0 | soff_hi), - priv->asize, &retlen, &ptr); - } - memset(ptr, 0xff, eoff_lo); - } - - out: + memset(ptr, 0xff, priv->asize); + if (soff_hi + priv->asize >= mtd->size) { + goto out; + } + soff_hi += priv->asize; + pmc551_point (mtd,(priv->base_map0|soff_hi), + priv->asize, &retlen, &ptr); + } + memset (ptr, 0xff, eoff_lo); + } + +out: instr->state = MTD_ERASE_DONE; #ifdef CONFIG_MTD_PMC551_DEBUG printk(KERN_DEBUG "pmc551_erase() done\n"); #endif - mtd_erase_callback(instr); - return 0; + mtd_erase_callback(instr); + return 0; } -static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len, - size_t * retlen, u_char ** mtdbuf) + +static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) { - struct mypriv *priv = mtd->priv; - u32 soff_hi; - u32 soff_lo; + struct mypriv *priv = mtd->priv; + u32 soff_hi; + u32 soff_lo; #ifdef CONFIG_MTD_PMC551_DEBUG printk(KERN_DEBUG "pmc551_point(%ld, %ld)\n", (long)from, (long)len); @@ -183,19 +184,18 @@ static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len, if (from + len > mtd->size) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_point() out of bounds (%ld > %ld)\n", - (long)from + len, (long)mtd->size); + printk(KERN_DEBUG "pmc551_point() out of bounds (%ld > %ld)\n", (long)from+len, (long)mtd->size); #endif return -EINVAL; } - soff_hi = from & ~(priv->asize - 1); - soff_lo = from & (priv->asize - 1); + soff_hi = from & ~(priv->asize - 1); + soff_lo = from & (priv->asize - 1); /* Cheap hack optimization */ - if (priv->curr_map0 != from) { - pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0, - (priv->base_map0 | soff_hi)); + if( priv->curr_map0 != from ) { + pci_write_config_dword ( priv->dev, PMC551_PCI_MEM_MAP0, + (priv->base_map0 | soff_hi) ); priv->curr_map0 = soff_hi; } @@ -204,144 +204,137 @@ static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len, return 0; } -static void pmc551_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from, - size_t len) + +static void pmc551_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) { #ifdef CONFIG_MTD_PMC551_DEBUG printk(KERN_DEBUG "pmc551_unpoint()\n"); #endif } -static int pmc551_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t * retlen, u_char * buf) + +static int pmc551_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { - struct mypriv *priv = mtd->priv; - u32 soff_hi, soff_lo; /* start address offset hi/lo */ - u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ - unsigned long end; + struct mypriv *priv = mtd->priv; + u32 soff_hi, soff_lo; /* start address offset hi/lo */ + u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ + unsigned long end; u_char *ptr; - u_char *copyto = buf; + u_char *copyto = buf; #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n", - (long)from, (long)len, (long)priv->asize); + printk(KERN_DEBUG "pmc551_read(pos:%ld, len:%ld) asize: %ld\n", (long)from, (long)len, (long)priv->asize); #endif - end = from + len - 1; + end = from + len - 1; - /* Is it past the end? */ - if (end > mtd->size) { + /* Is it past the end? */ + if (end > mtd->size) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_read() out of bounds (%ld > %ld)\n", - (long)end, (long)mtd->size); + printk(KERN_DEBUG "pmc551_read() out of bounds (%ld > %ld)\n", (long) end, (long)mtd->size); #endif - return -EINVAL; - } - - soff_hi = from & ~(priv->asize - 1); - eoff_hi = end & ~(priv->asize - 1); - soff_lo = from & (priv->asize - 1); - eoff_lo = end & (priv->asize - 1); - - pmc551_point(mtd, from, len, retlen, &ptr); - - if (soff_hi == eoff_hi) { - /* The whole thing fits within one access, so just one shot - will do it. */ - memcpy(copyto, ptr, len); - copyto += len; - } else { - /* We have to do multiple writes to get all the data - written. */ - while (soff_hi != eoff_hi) { + return -EINVAL; + } + + soff_hi = from & ~(priv->asize - 1); + eoff_hi = end & ~(priv->asize - 1); + soff_lo = from & (priv->asize - 1); + eoff_lo = end & (priv->asize - 1); + + pmc551_point (mtd, from, len, retlen, &ptr); + + if (soff_hi == eoff_hi) { + /* The whole thing fits within one access, so just one shot + will do it. */ + memcpy(copyto, ptr, len); + copyto += len; + } else { + /* We have to do multiple writes to get all the data + written. */ + while (soff_hi != eoff_hi) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_read() soff_hi: %ld, " - "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); + printk( KERN_DEBUG "pmc551_read() soff_hi: %ld, eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); #endif - memcpy(copyto, ptr, priv->asize); - copyto += priv->asize; - if (soff_hi + priv->asize >= mtd->size) { - goto out; - } - soff_hi += priv->asize; - pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr); - } - memcpy(copyto, ptr, eoff_lo); - copyto += eoff_lo; - } - - out: + memcpy(copyto, ptr, priv->asize); + copyto += priv->asize; + if (soff_hi + priv->asize >= mtd->size) { + goto out; + } + soff_hi += priv->asize; + pmc551_point (mtd, soff_hi, priv->asize, retlen, &ptr); + } + memcpy(copyto, ptr, eoff_lo); + copyto += eoff_lo; + } + +out: #ifdef CONFIG_MTD_PMC551_DEBUG printk(KERN_DEBUG "pmc551_read() done\n"); #endif - *retlen = copyto - buf; - return 0; + *retlen = copyto - buf; + return 0; } -static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t * retlen, const u_char * buf) +static int pmc551_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { - struct mypriv *priv = mtd->priv; - u32 soff_hi, soff_lo; /* start address offset hi/lo */ - u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ - unsigned long end; + struct mypriv *priv = mtd->priv; + u32 soff_hi, soff_lo; /* start address offset hi/lo */ + u32 eoff_hi, eoff_lo; /* end address offset hi/lo */ + unsigned long end; u_char *ptr; - const u_char *copyfrom = buf; + const u_char *copyfrom = buf; + #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n", - (long)to, (long)len, (long)priv->asize); + printk(KERN_DEBUG "pmc551_write(pos:%ld, len:%ld) asize:%ld\n", (long)to, (long)len, (long)priv->asize); #endif - end = to + len - 1; - /* Is it past the end? or did the u32 wrap? */ - if (end > mtd->size) { + end = to + len - 1; + /* Is it past the end? or did the u32 wrap? */ + if (end > mtd->size ) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_write() out of bounds (end: %ld, " - "size: %ld, to: %ld)\n", (long)end, (long)mtd->size, - (long)to); + printk(KERN_DEBUG "pmc551_write() out of bounds (end: %ld, size: %ld, to: %ld)\n", (long) end, (long)mtd->size, (long)to); #endif - return -EINVAL; - } - - soff_hi = to & ~(priv->asize - 1); - eoff_hi = end & ~(priv->asize - 1); - soff_lo = to & (priv->asize - 1); - eoff_lo = end & (priv->asize - 1); - - pmc551_point(mtd, to, len, retlen, &ptr); - - if (soff_hi == eoff_hi) { - /* The whole thing fits within one access, so just one shot - will do it. */ - memcpy(ptr, copyfrom, len); - copyfrom += len; - } else { - /* We have to do multiple writes to get all the data - written. */ - while (soff_hi != eoff_hi) { + return -EINVAL; + } + + soff_hi = to & ~(priv->asize - 1); + eoff_hi = end & ~(priv->asize - 1); + soff_lo = to & (priv->asize - 1); + eoff_lo = end & (priv->asize - 1); + + pmc551_point (mtd, to, len, retlen, &ptr); + + if (soff_hi == eoff_hi) { + /* The whole thing fits within one access, so just one shot + will do it. */ + memcpy(ptr, copyfrom, len); + copyfrom += len; + } else { + /* We have to do multiple writes to get all the data + written. */ + while (soff_hi != eoff_hi) { #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551_write() soff_hi: %ld, " - "eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); + printk( KERN_DEBUG "pmc551_write() soff_hi: %ld, eoff_hi: %ld\n", (long)soff_hi, (long)eoff_hi); #endif - memcpy(ptr, copyfrom, priv->asize); - copyfrom += priv->asize; - if (soff_hi >= mtd->size) { - goto out; - } - soff_hi += priv->asize; - pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr); - } - memcpy(ptr, copyfrom, eoff_lo); - copyfrom += eoff_lo; - } - - out: + memcpy(ptr, copyfrom, priv->asize); + copyfrom += priv->asize; + if (soff_hi >= mtd->size) { + goto out; + } + soff_hi += priv->asize; + pmc551_point (mtd, soff_hi, priv->asize, retlen, &ptr); + } + memcpy(ptr, copyfrom, eoff_lo); + copyfrom += eoff_lo; + } + +out: #ifdef CONFIG_MTD_PMC551_DEBUG printk(KERN_DEBUG "pmc551_write() done\n"); #endif - *retlen = copyfrom - buf; - return 0; + *retlen = copyfrom - buf; + return 0; } /* @@ -356,58 +349,58 @@ static int pmc551_write(struct mtd_info *mtd, loff_t to, size_t len, * mechanism * returns the size of the memory region found. */ -static u32 fixup_pmc551(struct pci_dev *dev) +static u32 fixup_pmc551 (struct pci_dev *dev) { #ifdef CONFIG_MTD_PMC551_BUGFIX - u32 dram_data; + u32 dram_data; #endif - u32 size, dcmd, cfg, dtmp; - u16 cmd, tmp, i; + u32 size, dcmd, cfg, dtmp; + u16 cmd, tmp, i; u8 bcmd, counter; - /* Sanity Check */ - if (!dev) { - return -ENODEV; - } + /* Sanity Check */ + if(!dev) { + return -ENODEV; + } /* * Attempt to reset the card * FIXME: Stop Spinning registers */ - counter = 0; + counter=0; /* unlock registers */ - pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5); + pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5 ); /* read in old data */ - pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd); + pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); /* bang the reset line up and down for a few */ - for (i = 0; i < 10; i++) { - counter = 0; + for(i=0;i<10;i++) { + counter=0; bcmd &= ~0x80; - while (counter++ < 100) { + while(counter++ < 100) { pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); } - counter = 0; + counter=0; bcmd |= 0x80; - while (counter++ < 100) { + while(counter++ < 100) { pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); } } - bcmd |= (0x40 | 0x20); + bcmd |= (0x40|0x20); pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); - /* + /* * Take care and turn off the memory on the device while we * tweak the configurations */ - pci_read_config_word(dev, PCI_COMMAND, &cmd); - tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - pci_write_config_word(dev, PCI_COMMAND, tmp); + pci_read_config_word(dev, PCI_COMMAND, &cmd); + tmp = cmd & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, tmp); /* * Disable existing aperture before probing memory size */ pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd); - dtmp = (dcmd | PMC551_PCI_MEM_MAP_ENABLE | PMC551_PCI_MEM_MAP_REG_EN); + dtmp=(dcmd|PMC551_PCI_MEM_MAP_ENABLE|PMC551_PCI_MEM_MAP_REG_EN); pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp); /* * Grab old BAR0 config so that we can figure out memory size @@ -418,230 +411,220 @@ static u32 fixup_pmc551(struct pci_dev *dev) * then write all 1's to the memory space, read back the result into * "size", and then write back all the old config. */ - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &cfg); + pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &cfg ); #ifndef CONFIG_MTD_PMC551_BUGFIX - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, ~0); - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &size); - size = (size & PCI_BASE_ADDRESS_MEM_MASK); - size &= ~(size - 1); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, cfg); + pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, ~0 ); + pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &size ); + size = (size&PCI_BASE_ADDRESS_MEM_MASK); + size &= ~(size-1); + pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); #else - /* - * Get the size of the memory by reading all the DRAM size values - * and adding them up. - * - * KLUDGE ALERT: the boards we are using have invalid column and - * row mux values. We fix them here, but this will break other - * memory configurations. - */ - pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data); - size = PMC551_DRAM_BLK_GET_SIZE(dram_data); - dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); - dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); - pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data); - - pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data); - size += PMC551_DRAM_BLK_GET_SIZE(dram_data); - dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); - dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); - pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data); - - pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data); - size += PMC551_DRAM_BLK_GET_SIZE(dram_data); - dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); - dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); - pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data); - - pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data); - size += PMC551_DRAM_BLK_GET_SIZE(dram_data); - dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); - dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); - pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data); - - /* - * Oops .. something went wrong - */ - if ((size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) { - return -ENODEV; - } -#endif /* CONFIG_MTD_PMC551_BUGFIX */ - - if ((cfg & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { - return -ENODEV; + /* + * Get the size of the memory by reading all the DRAM size values + * and adding them up. + * + * KLUDGE ALERT: the boards we are using have invalid column and + * row mux values. We fix them here, but this will break other + * memory configurations. + */ + pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data); + size = PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK0, dram_data); + + pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dram_data); + size += PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK1, dram_data); + + pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dram_data); + size += PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK2, dram_data); + + pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dram_data); + size += PMC551_DRAM_BLK_GET_SIZE(dram_data); + dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); + dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); + pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data); + + /* + * Oops .. something went wrong + */ + if( (size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) { + return -ENODEV; + } +#endif /* CONFIG_MTD_PMC551_BUGFIX */ + + if ((cfg&PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { + return -ENODEV; } - /* - * Precharge Dram - */ - pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0400); - pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x00bf); - - /* - * Wait until command has gone through - * FIXME: register spinning issue - */ - do { - pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); - if (counter++ > 100) - break; - } while ((PCI_COMMAND_IO) & cmd); - - /* + /* + * Precharge Dram + */ + pci_write_config_word( dev, PMC551_SDRAM_MA, 0x0400 ); + pci_write_config_word( dev, PMC551_SDRAM_CMD, 0x00bf ); + + /* + * Wait until command has gone through + * FIXME: register spinning issue + */ + do { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd ); + if(counter++ > 100)break; + } while ( (PCI_COMMAND_IO) & cmd ); + + /* * Turn on auto refresh * The loop is taken directly from Ramix's example code. I assume that * this must be held high for some duration of time, but I can find no * documentation refrencing the reasons why. - */ - for (i = 1; i <= 8; i++) { - pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0df); - - /* - * Make certain command has gone through - * FIXME: register spinning issue - */ - counter = 0; - do { - pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); - if (counter++ > 100) - break; - } while ((PCI_COMMAND_IO) & cmd); - } - - pci_write_config_word(dev, PMC551_SDRAM_MA, 0x0020); - pci_write_config_word(dev, PMC551_SDRAM_CMD, 0x0ff); - - /* - * Wait until command completes - * FIXME: register spinning issue - */ - counter = 0; - do { - pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); - if (counter++ > 100) - break; - } while ((PCI_COMMAND_IO) & cmd); - - pci_read_config_dword(dev, PMC551_DRAM_CFG, &dcmd); - dcmd |= 0x02000000; - pci_write_config_dword(dev, PMC551_DRAM_CFG, dcmd); - - /* - * Check to make certain fast back-to-back, if not - * then set it so - */ - pci_read_config_word(dev, PCI_STATUS, &cmd); - if ((cmd & PCI_COMMAND_FAST_BACK) == 0) { - cmd |= PCI_COMMAND_FAST_BACK; - pci_write_config_word(dev, PCI_STATUS, cmd); - } - - /* - * Check to make certain the DEVSEL is set correctly, this device - * has a tendancy to assert DEVSEL and TRDY when a write is performed - * to the memory when memory is read-only - */ - if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) { - cmd &= ~PCI_STATUS_DEVSEL_MASK; - pci_write_config_word(dev, PCI_STATUS, cmd); - } - /* - * Set to be prefetchable and put everything back based on old cfg. + */ + for ( i = 1; i<=8 ; i++) { + pci_write_config_word (dev, PMC551_SDRAM_CMD, 0x0df); + + /* + * Make certain command has gone through + * FIXME: register spinning issue + */ + counter=0; + do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); + if(counter++ > 100)break; + } while ( (PCI_COMMAND_IO) & cmd ); + } + + pci_write_config_word ( dev, PMC551_SDRAM_MA, 0x0020); + pci_write_config_word ( dev, PMC551_SDRAM_CMD, 0x0ff); + + /* + * Wait until command completes + * FIXME: register spinning issue + */ + counter=0; + do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd); + if(counter++ > 100)break; + } while ( (PCI_COMMAND_IO) & cmd ); + + pci_read_config_dword ( dev, PMC551_DRAM_CFG, &dcmd); + dcmd |= 0x02000000; + pci_write_config_dword ( dev, PMC551_DRAM_CFG, dcmd); + + /* + * Check to make certain fast back-to-back, if not + * then set it so + */ + pci_read_config_word( dev, PCI_STATUS, &cmd); + if((cmd&PCI_COMMAND_FAST_BACK) == 0) { + cmd |= PCI_COMMAND_FAST_BACK; + pci_write_config_word( dev, PCI_STATUS, cmd); + } + + /* + * Check to make certain the DEVSEL is set correctly, this device + * has a tendancy to assert DEVSEL and TRDY when a write is performed + * to the memory when memory is read-only + */ + if((cmd&PCI_STATUS_DEVSEL_MASK) != 0x0) { + cmd &= ~PCI_STATUS_DEVSEL_MASK; + pci_write_config_word( dev, PCI_STATUS, cmd ); + } + /* + * Set to be prefetchable and put everything back based on old cfg. * it's possible that the reset of the V370PDC nuked the original * setup - */ - /* - cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH; - pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); - */ - + */ /* - * Turn PCI memory and I/O bus access back on - */ - pci_write_config_word(dev, PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_IO); + cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH; + pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); + */ + + /* + * Turn PCI memory and I/O bus access back on + */ + pci_write_config_word( dev, PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_IO ); #ifdef CONFIG_MTD_PMC551_DEBUG - /* - * Some screen fun - */ - printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at " - "0x%llx\n", (size < 1024) ? size : (size < 1048576) ? - size >> 10 : size >> 20, - (size < 1024) ? 'B' : (size < 1048576) ? 'K' : 'M', size, - ((dcmd & (0x1 << 3)) == 0) ? "non-" : "", - (unsigned long long)pci_resource_start(dev, 0)); - - /* - * Check to see the state of the memory - */ - pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dcmd); - printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n" - "pmc551: DRAM_BLK0 Size: %d at %d\n" - "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n", - (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO", - (((0x1 << 0) & dcmd) == 0) ? "Off" : "On", - PMC551_DRAM_BLK_GET_SIZE(dcmd), - ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7), - ((dcmd >> 9) & 0xF)); - - pci_read_config_dword(dev, PMC551_DRAM_BLK1, &dcmd); - printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n" - "pmc551: DRAM_BLK1 Size: %d at %d\n" - "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n", - (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO", - (((0x1 << 0) & dcmd) == 0) ? "Off" : "On", - PMC551_DRAM_BLK_GET_SIZE(dcmd), - ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7), - ((dcmd >> 9) & 0xF)); - - pci_read_config_dword(dev, PMC551_DRAM_BLK2, &dcmd); - printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n" - "pmc551: DRAM_BLK2 Size: %d at %d\n" - "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n", - (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO", - (((0x1 << 0) & dcmd) == 0) ? "Off" : "On", - PMC551_DRAM_BLK_GET_SIZE(dcmd), - ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7), - ((dcmd >> 9) & 0xF)); - - pci_read_config_dword(dev, PMC551_DRAM_BLK3, &dcmd); - printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n" - "pmc551: DRAM_BLK3 Size: %d at %d\n" - "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n", - (((0x1 << 1) & dcmd) == 0) ? "RW" : "RO", - (((0x1 << 0) & dcmd) == 0) ? "Off" : "On", - PMC551_DRAM_BLK_GET_SIZE(dcmd), - ((dcmd >> 20) & 0x7FF), ((dcmd >> 13) & 0x7), - ((dcmd >> 9) & 0xF)); - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - printk(KERN_DEBUG "pmc551: Memory Access %s\n", - (((0x1 << 1) & cmd) == 0) ? "off" : "on"); - printk(KERN_DEBUG "pmc551: I/O Access %s\n", - (((0x1 << 0) & cmd) == 0) ? "off" : "on"); - - pci_read_config_word(dev, PCI_STATUS, &cmd); - printk(KERN_DEBUG "pmc551: Devsel %s\n", - ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x000) ? "Fast" : - ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x200) ? "Medium" : - ((PCI_STATUS_DEVSEL_MASK & cmd) == 0x400) ? "Slow" : "Invalid"); - - printk(KERN_DEBUG "pmc551: %sFast Back-to-Back\n", - ((PCI_COMMAND_FAST_BACK & cmd) == 0) ? "Not " : ""); - - pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd); - printk(KERN_DEBUG "pmc551: EEPROM is under %s control\n" - "pmc551: System Control Register is %slocked to PCI access\n" - "pmc551: System Control Register is %slocked to EEPROM access\n", - (bcmd & 0x1) ? "software" : "hardware", - (bcmd & 0x20) ? "" : "un", (bcmd & 0x40) ? "" : "un"); + /* + * Some screen fun + */ + printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at 0x%llx\n", + (size<1024)?size:(size<1048576)?size>>10:size>>20, + (size<1024)?'B':(size<1048576)?'K':'M', + size, ((dcmd&(0x1<<3)) == 0)?"non-":"", + (unsigned long long)((dev->resource[0].start)&PCI_BASE_ADDRESS_MEM_MASK)); + + /* + * Check to see the state of the memory + */ + pci_read_config_dword( dev, PMC551_DRAM_BLK0, &dcmd ); + printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n" + "pmc551: DRAM_BLK0 Size: %d at %d\n" + "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n", + (((0x1<<1)&dcmd) == 0)?"RW":"RO", + (((0x1<<0)&dcmd) == 0)?"Off":"On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); + + pci_read_config_dword( dev, PMC551_DRAM_BLK1, &dcmd ); + printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n" + "pmc551: DRAM_BLK1 Size: %d at %d\n" + "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n", + (((0x1<<1)&dcmd) == 0)?"RW":"RO", + (((0x1<<0)&dcmd) == 0)?"Off":"On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); + + pci_read_config_dword( dev, PMC551_DRAM_BLK2, &dcmd ); + printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n" + "pmc551: DRAM_BLK2 Size: %d at %d\n" + "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n", + (((0x1<<1)&dcmd) == 0)?"RW":"RO", + (((0x1<<0)&dcmd) == 0)?"Off":"On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); + + pci_read_config_dword( dev, PMC551_DRAM_BLK3, &dcmd ); + printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n" + "pmc551: DRAM_BLK3 Size: %d at %d\n" + "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n", + (((0x1<<1)&dcmd) == 0)?"RW":"RO", + (((0x1<<0)&dcmd) == 0)?"Off":"On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); + + pci_read_config_word( dev, PCI_COMMAND, &cmd ); + printk( KERN_DEBUG "pmc551: Memory Access %s\n", + (((0x1<<1)&cmd) == 0)?"off":"on" ); + printk( KERN_DEBUG "pmc551: I/O Access %s\n", + (((0x1<<0)&cmd) == 0)?"off":"on" ); + + pci_read_config_word( dev, PCI_STATUS, &cmd ); + printk( KERN_DEBUG "pmc551: Devsel %s\n", + ((PCI_STATUS_DEVSEL_MASK&cmd)==0x000)?"Fast": + ((PCI_STATUS_DEVSEL_MASK&cmd)==0x200)?"Medium": + ((PCI_STATUS_DEVSEL_MASK&cmd)==0x400)?"Slow":"Invalid" ); + + printk( KERN_DEBUG "pmc551: %sFast Back-to-Back\n", + ((PCI_COMMAND_FAST_BACK&cmd) == 0)?"Not ":"" ); + + pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); + printk( KERN_DEBUG "pmc551: EEPROM is under %s control\n" + "pmc551: System Control Register is %slocked to PCI access\n" + "pmc551: System Control Register is %slocked to EEPROM access\n", + (bcmd&0x1)?"software":"hardware", + (bcmd&0x20)?"":"un", (bcmd&0x40)?"":"un"); #endif - return size; + return size; } /* * Kernel version specific module stuffages */ + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Mark Ferrell "); MODULE_DESCRIPTION(PMC551_VERSION); @@ -649,11 +632,11 @@ MODULE_DESCRIPTION(PMC551_VERSION); /* * Stuff these outside the ifdef so as to not bust compiled in driver support */ -static int msize = 0; +static int msize=0; #if defined(CONFIG_MTD_PMC551_APERTURE_SIZE) -static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE +static int asize=CONFIG_MTD_PMC551_APERTURE_SIZE #else -static int asize = 0; +static int asize=0; #endif module_param(msize, int, 0); @@ -666,174 +649,164 @@ MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]"); */ static int __init init_pmc551(void) { - struct pci_dev *PCI_Device = NULL; - struct mypriv *priv; - int count, found = 0; - struct mtd_info *mtd; - u32 length = 0; - - if (msize) { - msize = (1 << (ffs(msize) - 1)) << 20; - if (msize > (1 << 30)) { - printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n", - msize); + struct pci_dev *PCI_Device = NULL; + struct mypriv *priv; + int count, found=0; + struct mtd_info *mtd; + u32 length = 0; + + if(msize) { + msize = (1 << (ffs(msize) - 1))<<20; + if (msize > (1<<30)) { + printk(KERN_NOTICE "pmc551: Invalid memory size [%d]\n", msize); return -EINVAL; } } - if (asize) { - asize = (1 << (ffs(asize) - 1)) << 20; - if (asize > (1 << 30)) { - printk(KERN_NOTICE "pmc551: Invalid aperture size " - "[%d]\n", asize); + if(asize) { + asize = (1 << (ffs(asize) - 1))<<20; + if (asize > (1<<30) ) { + printk(KERN_NOTICE "pmc551: Invalid aperture size [%d]\n", asize); return -EINVAL; } } - printk(KERN_INFO PMC551_VERSION); - - /* - * PCU-bus chipset probe. - */ - for (count = 0; count < MAX_MTD_DEVICES; count++) { - - if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI, - PCI_DEVICE_ID_V3_SEMI_V370PDC, - PCI_Device)) == NULL) { - break; - } - - printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n", - (unsigned long long)pci_resource_start(PCI_Device, 0)); - - /* - * The PMC551 device acts VERY weird if you don't init it - * first. i.e. it will not correctly report devsel. If for - * some reason the sdram is in a wrote-protected state the - * device will DEVSEL when it is written to causing problems - * with the oldproc.c driver in - * some kernels (2.2.*) - */ - if ((length = fixup_pmc551(PCI_Device)) <= 0) { - printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n"); - break; - } + printk(KERN_INFO PMC551_VERSION); + + /* + * PCU-bus chipset probe. + */ + for( count = 0; count < MAX_MTD_DEVICES; count++ ) { + + if ((PCI_Device = pci_find_device(PCI_VENDOR_ID_V3_SEMI, + PCI_DEVICE_ID_V3_SEMI_V370PDC, + PCI_Device ) ) == NULL) { + break; + } + + printk(KERN_NOTICE "pmc551: Found PCI V370PDC at 0x%llx\n", + (unsigned long long)PCI_Device->resource[0].start); + + /* + * The PMC551 device acts VERY weird if you don't init it + * first. i.e. it will not correctly report devsel. If for + * some reason the sdram is in a wrote-protected state the + * device will DEVSEL when it is written to causing problems + * with the oldproc.c driver in + * some kernels (2.2.*) + */ + if((length = fixup_pmc551(PCI_Device)) <= 0) { + printk(KERN_NOTICE "pmc551: Cannot init SDRAM\n"); + break; + } /* * This is needed until the driver is capable of reading the * onboard I2C SROM to discover the "real" memory size. */ - if (msize) { + if(msize) { length = msize; - printk(KERN_NOTICE "pmc551: Using specified memory " - "size 0x%x\n", length); + printk(KERN_NOTICE "pmc551: Using specified memory size 0x%x\n", length); } else { msize = length; } - mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); - if (!mtd) { - printk(KERN_NOTICE "pmc551: Cannot allocate new MTD " - "device.\n"); - break; - } - - priv = kzalloc(sizeof(struct mypriv), GFP_KERNEL); - if (!priv) { - printk(KERN_NOTICE "pmc551: Cannot allocate new MTD " - "device.\n"); - kfree(mtd); - break; - } - mtd->priv = priv; - priv->dev = PCI_Device; - - if (asize > length) { - printk(KERN_NOTICE "pmc551: reducing aperture size to " - "fit %dM\n", length >> 20); + mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); + if (!mtd) { + printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); + break; + } + + memset(mtd, 0, sizeof(struct mtd_info)); + + priv = kmalloc (sizeof(struct mypriv), GFP_KERNEL); + if (!priv) { + printk(KERN_NOTICE "pmc551: Cannot allocate new MTD device.\n"); + kfree(mtd); + break; + } + memset(priv, 0, sizeof(*priv)); + mtd->priv = priv; + priv->dev = PCI_Device; + + if(asize > length) { + printk(KERN_NOTICE "pmc551: reducing aperture size to fit %dM\n",length>>20); priv->asize = asize = length; } else if (asize == 0 || asize == length) { - printk(KERN_NOTICE "pmc551: Using existing aperture " - "size %dM\n", length >> 20); + printk(KERN_NOTICE "pmc551: Using existing aperture size %dM\n", length>>20); priv->asize = asize = length; } else { - printk(KERN_NOTICE "pmc551: Using specified aperture " - "size %dM\n", asize >> 20); + printk(KERN_NOTICE "pmc551: Using specified aperture size %dM\n", asize>>20); priv->asize = asize; } - priv->start = pci_iomap(PCI_Device, 0, priv->asize); + priv->start = ioremap(((PCI_Device->resource[0].start) + & PCI_BASE_ADDRESS_MEM_MASK), + priv->asize); if (!priv->start) { printk(KERN_NOTICE "pmc551: Unable to map IO space\n"); - kfree(mtd->priv); - kfree(mtd); + kfree(mtd->priv); + kfree(mtd); break; } + #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551: setting aperture to %d\n", - ffs(priv->asize >> 20) - 1); + printk( KERN_DEBUG "pmc551: setting aperture to %d\n", + ffs(priv->asize>>20)-1); #endif - priv->base_map0 = (PMC551_PCI_MEM_MAP_REG_EN - | PMC551_PCI_MEM_MAP_ENABLE - | (ffs(priv->asize >> 20) - 1) << 4); - priv->curr_map0 = priv->base_map0; - pci_write_config_dword(priv->dev, PMC551_PCI_MEM_MAP0, - priv->curr_map0); + priv->base_map0 = ( PMC551_PCI_MEM_MAP_REG_EN + | PMC551_PCI_MEM_MAP_ENABLE + | (ffs(priv->asize>>20)-1)<<4 ); + priv->curr_map0 = priv->base_map0; + pci_write_config_dword ( priv->dev, PMC551_PCI_MEM_MAP0, + priv->curr_map0 ); #ifdef CONFIG_MTD_PMC551_DEBUG - printk(KERN_DEBUG "pmc551: aperture set to %d\n", - (priv->base_map0 & 0xF0) >> 4); + printk( KERN_DEBUG "pmc551: aperture set to %d\n", + (priv->base_map0 & 0xF0)>>4 ); #endif - mtd->size = msize; - mtd->flags = MTD_CAP_RAM; - mtd->erase = pmc551_erase; - mtd->read = pmc551_read; - mtd->write = pmc551_write; - mtd->point = pmc551_point; - mtd->unpoint = pmc551_unpoint; - mtd->type = MTD_RAM; - mtd->name = "PMC551 RAM board"; - mtd->erasesize = 0x10000; - mtd->writesize = 1; - mtd->owner = THIS_MODULE; - - if (add_mtd_device(mtd)) { - printk(KERN_NOTICE "pmc551: Failed to register new " - "device\n"); - pci_iounmap(PCI_Device, priv->start); - kfree(mtd->priv); - kfree(mtd); - break; - } - - /* Keep a reference as the add_mtd_device worked */ - pci_dev_get(PCI_Device); - - printk(KERN_NOTICE "Registered pmc551 memory device.\n"); - printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n", - priv->asize >> 20, - priv->start, priv->start + priv->asize); - printk(KERN_NOTICE "Total memory is %d%c\n", - (length < 1024) ? length : - (length < 1048576) ? length >> 10 : length >> 20, - (length < 1024) ? 'B' : (length < 1048576) ? 'K' : 'M'); + mtd->size = msize; + mtd->flags = MTD_CAP_RAM; + mtd->erase = pmc551_erase; + mtd->read = pmc551_read; + mtd->write = pmc551_write; + mtd->point = pmc551_point; + mtd->unpoint = pmc551_unpoint; + mtd->type = MTD_RAM; + mtd->name = "PMC551 RAM board"; + mtd->erasesize = 0x10000; + mtd->writesize = 1; + mtd->owner = THIS_MODULE; + + if (add_mtd_device(mtd)) { + printk(KERN_NOTICE "pmc551: Failed to register new device\n"); + iounmap(priv->start); + kfree(mtd->priv); + kfree(mtd); + break; + } + printk(KERN_NOTICE "Registered pmc551 memory device.\n"); + printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n", + priv->asize>>20, + priv->start, + priv->start + priv->asize); + printk(KERN_NOTICE "Total memory is %d%c\n", + (length<1024)?length: + (length<1048576)?length>>10:length>>20, + (length<1024)?'B':(length<1048576)?'K':'M'); priv->nextpmc551 = pmc551list; pmc551list = mtd; found++; - } - - /* Exited early, reference left over */ - if (PCI_Device) - pci_dev_put(PCI_Device); + } - if (!pmc551list) { - printk(KERN_NOTICE "pmc551: not detected\n"); - return -ENODEV; - } else { + if( !pmc551list ) { + printk(KERN_NOTICE "pmc551: not detected\n"); + return -ENODEV; + } else { printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found); - return 0; + return 0; } } @@ -842,24 +815,23 @@ static int __init init_pmc551(void) */ static void __exit cleanup_pmc551(void) { - int found = 0; - struct mtd_info *mtd; + int found=0; + struct mtd_info *mtd; struct mypriv *priv; - while ((mtd = pmc551list)) { + while((mtd=pmc551list)) { priv = mtd->priv; pmc551list = priv->nextpmc551; - if (priv->start) { - printk(KERN_DEBUG "pmc551: unmapping %dM starting at " - "0x%p\n", priv->asize >> 20, priv->start); - pci_iounmap(priv->dev, priv->start); + if(priv->start) { + printk (KERN_DEBUG "pmc551: unmapping %dM starting at 0x%p\n", + priv->asize>>20, priv->start); + iounmap (priv->start); } - pci_dev_put(priv->dev); - kfree(mtd->priv); - del_mtd_device(mtd); - kfree(mtd); + kfree (mtd->priv); + del_mtd_device (mtd); + kfree (mtd); found++; } diff --git a/trunk/drivers/mtd/maps/Kconfig b/trunk/drivers/mtd/maps/Kconfig index 24747bdc3e19..83d0b2a52527 100644 --- a/trunk/drivers/mtd/maps/Kconfig +++ b/trunk/drivers/mtd/maps/Kconfig @@ -13,13 +13,13 @@ config MTD_COMPLEX_MAPPINGS config MTD_PHYSMAP tristate "CFI Flash device in physical memory map" - depends on MTD_CFI || MTD_JEDECPROBE || MTD_ROM + depends on MTD_CFI help - This provides a 'mapping' driver which allows the NOR Flash and - ROM driver code to communicate with chips which are mapped - physically into the CPU's memory. You will need to configure - the physical address and size of the flash chips on your - particular board as well as the bus width, either statically + This provides a 'mapping' driver which allows the CFI probe and + command set driver code to communicate with flash chips which + are mapped physically into the CPU's memory. You will need to + configure the physical address and size of the flash chips on + your particular board as well as the bus width, either statically with config options or at run-time. config MTD_PHYSMAP_START @@ -447,6 +447,14 @@ config MTD_DC21285 21285 bridge used with Intel's StrongARM processors. More info at . +config MTD_IQ80310 + tristate "CFI Flash device mapped on the XScale IQ80310 board" + depends on MTD_CFI && ARCH_IQ80310 + help + This enables access routines for the flash chips on the Intel XScale + IQ80310 evaluation board. If you have one of these boards and would + like to use the flash chips on it, say 'Y'. + config MTD_IXP4XX tristate "CFI Flash device mapped on Intel IXP4xx based systems" depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP4XX diff --git a/trunk/drivers/mtd/maps/Makefile b/trunk/drivers/mtd/maps/Makefile index 191c1928bbec..ab71f172eb77 100644 --- a/trunk/drivers/mtd/maps/Makefile +++ b/trunk/drivers/mtd/maps/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o obj-$(CONFIG_MTD_CSTM_MIPS_IXX) += cstm_mips_ixx.o obj-$(CONFIG_MTD_DC21285) += dc21285.o obj-$(CONFIG_MTD_DILNETPC) += dilnetpc.o +obj-$(CONFIG_MTD_IQ80310) += iq80310.o obj-$(CONFIG_MTD_L440GX) += l440gx.o obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom.o obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o diff --git a/trunk/drivers/mtd/maps/amd76xrom.c b/trunk/drivers/mtd/maps/amd76xrom.c index 797caffb20b1..447955be18af 100644 --- a/trunk/drivers/mtd/maps/amd76xrom.c +++ b/trunk/drivers/mtd/maps/amd76xrom.c @@ -57,7 +57,6 @@ static void amd76xrom_cleanup(struct amd76xrom_window *window) /* Disable writes through the rom window */ pci_read_config_byte(window->pdev, 0x40, &byte); pci_write_config_byte(window->pdev, 0x40, byte & ~1); - pci_dev_put(window->pdev); } /* Free all of the mtd devices */ @@ -92,7 +91,7 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev, struct amd76xrom_map_info *map = NULL; unsigned long map_top; - /* Remember the pci dev I find the window in - already have a ref */ + /* Remember the pci dev I find the window in */ window->pdev = pdev; /* Assume the rom window is properly setup, and find it's size */ @@ -303,7 +302,7 @@ static int __init init_amd76xrom(void) struct pci_device_id *id; pdev = NULL; for(id = amd76xrom_pci_tbl; id->vendor; id++) { - pdev = pci_get_device(id->vendor, id->device, NULL); + pdev = pci_find_device(id->vendor, id->device, NULL); if (pdev) { break; } diff --git a/trunk/drivers/mtd/maps/arctic-mtd.c b/trunk/drivers/mtd/maps/arctic-mtd.c index 642d96bc8919..d95ae582fbe9 100644 --- a/trunk/drivers/mtd/maps/arctic-mtd.c +++ b/trunk/drivers/mtd/maps/arctic-mtd.c @@ -96,8 +96,6 @@ static struct mtd_partition arctic_partitions[PARTITIONS] = { static int __init init_arctic_mtd(void) { - int err = 0; - printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); arctic_mtd_map.virt = ioremap(PADDR, SIZE); @@ -111,20 +109,12 @@ init_arctic_mtd(void) printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8); arctic_mtd = do_map_probe("cfi_probe", &arctic_mtd_map); - if (!arctic_mtd) { - iounmap((void *) arctic_mtd_map.virt); + if (!arctic_mtd) return -ENXIO; - } arctic_mtd->owner = THIS_MODULE; - err = add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS); - if (err) { - printk("%s: add_mtd_partitions failed\n", NAME); - iounmap((void *) arctic_mtd_map.virt); - } - - return err; + return add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS); } static void __exit diff --git a/trunk/drivers/mtd/maps/beech-mtd.c b/trunk/drivers/mtd/maps/beech-mtd.c index a64b1a5ab316..5df7361d1407 100644 --- a/trunk/drivers/mtd/maps/beech-mtd.c +++ b/trunk/drivers/mtd/maps/beech-mtd.c @@ -72,8 +72,6 @@ static struct mtd_partition beech_partitions[2] = { static int __init init_beech_mtd(void) { - int err = 0; - printk("%s: 0x%08x at 0x%08x\n", NAME, SIZE, PADDR); beech_mtd_map.virt = ioremap(PADDR, SIZE); @@ -88,20 +86,12 @@ init_beech_mtd(void) printk("%s: probing %d-bit flash bus\n", NAME, BUSWIDTH * 8); beech_mtd = do_map_probe("cfi_probe", &beech_mtd_map); - if (!beech_mtd) { - iounmap((void *) beech_mtd_map.virt); + if (!beech_mtd) return -ENXIO; - } beech_mtd->owner = THIS_MODULE; - err = add_mtd_partitions(beech_mtd, beech_partitions, 2); - if (err) { - printk("%s: add_mtd_partitions failed\n", NAME); - iounmap((void *) beech_mtd_map.virt); - } - - return err; + return add_mtd_partitions(beech_mtd, beech_partitions, 2); } static void __exit diff --git a/trunk/drivers/mtd/maps/cstm_mips_ixx.c b/trunk/drivers/mtd/maps/cstm_mips_ixx.c index d6bef100d69a..aa56defb94c8 100644 --- a/trunk/drivers/mtd/maps/cstm_mips_ixx.c +++ b/trunk/drivers/mtd/maps/cstm_mips_ixx.c @@ -171,14 +171,7 @@ int __init init_cstm_mips_ixx(void) cstm_mips_ixx_map[i].phys = cstm_mips_ixx_board_desc[i].window_addr; cstm_mips_ixx_map[i].virt = ioremap(cstm_mips_ixx_board_desc[i].window_addr, cstm_mips_ixx_board_desc[i].window_size); if (!cstm_mips_ixx_map[i].virt) { - int j = 0; printk(KERN_WARNING "Failed to ioremap\n"); - for (j = 0; j < i; j++) { - if (cstm_mips_ixx_map[j].virt) { - iounmap((void *)cstm_mips_ixx_map[j].virt); - cstm_mips_ixx_map[j].virt = 0; - } - } return -EIO; } cstm_mips_ixx_map[i].name = cstm_mips_ixx_board_desc[i].name; @@ -211,15 +204,8 @@ int __init init_cstm_mips_ixx(void) cstm_mips_ixx_map[i].map_priv_2 = (unsigned long)mymtd; add_mtd_partitions(mymtd, parts, cstm_mips_ixx_board_desc[i].num_partitions); } - else { - for (i = 0; i < PHYSMAP_NUMBER; i++) { - if (cstm_mips_ixx_map[i].virt) { - iounmap((void *)cstm_mips_ixx_map[i].virt); - cstm_mips_ixx_map[i].virt = 0; - } - } - return -ENXIO; - } + else + return -ENXIO; } return 0; } diff --git a/trunk/drivers/mtd/maps/ebony.c b/trunk/drivers/mtd/maps/ebony.c index 1488bb92f26f..641e1dd8479e 100644 --- a/trunk/drivers/mtd/maps/ebony.c +++ b/trunk/drivers/mtd/maps/ebony.c @@ -108,7 +108,6 @@ int __init init_ebony(void) ARRAY_SIZE(ebony_small_partitions)); } else { printk("map probe failed for flash\n"); - iounmap(ebony_small_map.virt); return -ENXIO; } @@ -118,7 +117,6 @@ int __init init_ebony(void) if (!ebony_large_map.virt) { printk("Failed to ioremap flash\n"); - iounmap(ebony_small_map.virt); return -EIO; } @@ -131,8 +129,6 @@ int __init init_ebony(void) ARRAY_SIZE(ebony_large_partitions)); } else { printk("map probe failed for flash\n"); - iounmap(ebony_small_map.virt); - iounmap(ebony_large_map.virt); return -ENXIO; } diff --git a/trunk/drivers/mtd/maps/fortunet.c b/trunk/drivers/mtd/maps/fortunet.c index 7c50c271651c..c6bf4e1219ef 100644 --- a/trunk/drivers/mtd/maps/fortunet.c +++ b/trunk/drivers/mtd/maps/fortunet.c @@ -218,11 +218,8 @@ int __init init_fortunet(void) map_regions[ix].map_info.size); if(!map_regions[ix].map_info.virt) { - int j = 0; printk(MTD_FORTUNET_PK "%s flash failed to ioremap!\n", map_regions[ix].map_info.name); - for (j = 0 ; j < ix; j++) - iounmap(map_regions[j].map_info.virt); return -ENXIO; } simple_map_init(&map_regions[ix].map_info); diff --git a/trunk/drivers/mtd/maps/ichxrom.c b/trunk/drivers/mtd/maps/ichxrom.c index 2bb3e63606e5..db4b570d874a 100644 --- a/trunk/drivers/mtd/maps/ichxrom.c +++ b/trunk/drivers/mtd/maps/ichxrom.c @@ -61,7 +61,6 @@ static void ichxrom_cleanup(struct ichxrom_window *window) /* Disable writes through the rom window */ pci_read_config_word(window->pdev, BIOS_CNTL, &word); pci_write_config_word(window->pdev, BIOS_CNTL, word & ~1); - pci_dev_put(window->pdev); /* Free all of the mtd devices */ list_for_each_entry_safe(map, scratch, &window->maps, list) { @@ -356,7 +355,7 @@ static int __init init_ichxrom(void) pdev = NULL; for (id = ichxrom_pci_tbl; id->vendor; id++) { - pdev = pci_get_device(id->vendor, id->device, NULL); + pdev = pci_find_device(id->vendor, id->device, NULL); if (pdev) { break; } diff --git a/trunk/drivers/mtd/maps/iq80310.c b/trunk/drivers/mtd/maps/iq80310.c new file mode 100644 index 000000000000..62d9e87d84e2 --- /dev/null +++ b/trunk/drivers/mtd/maps/iq80310.c @@ -0,0 +1,118 @@ +/* + * $Id: iq80310.c,v 1.21 2005/11/07 11:14:27 gleixner Exp $ + * + * Mapping for the Intel XScale IQ80310 evaluation board + * + * Author: Nicolas Pitre + * Copyright: (C) 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define WINDOW_ADDR 0 +#define WINDOW_SIZE 8*1024*1024 +#define BUSWIDTH 1 + +static struct mtd_info *mymtd; + +static struct map_info iq80310_map = { + .name = "IQ80310 flash", + .size = WINDOW_SIZE, + .bankwidth = BUSWIDTH, + .phys = WINDOW_ADDR +}; + +static struct mtd_partition iq80310_partitions[4] = { + { + .name = "Firmware", + .size = 0x00080000, + .offset = 0, + .mask_flags = MTD_WRITEABLE /* force read-only */ + },{ + .name = "Kernel", + .size = 0x000a0000, + .offset = 0x00080000, + },{ + .name = "Filesystem", + .size = 0x00600000, + .offset = 0x00120000 + },{ + .name = "RedBoot", + .size = 0x000e0000, + .offset = 0x00720000, + .mask_flags = MTD_WRITEABLE + } +}; + +static struct mtd_info *mymtd; +static struct mtd_partition *parsed_parts; +static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; + +static int __init init_iq80310(void) +{ + struct mtd_partition *parts; + int nb_parts = 0; + int parsed_nr_parts = 0; + int ret; + + iq80310_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); + if (!iq80310_map.virt) { + printk("Failed to ioremap\n"); + return -EIO; + } + simple_map_init(&iq80310_map); + + mymtd = do_map_probe("cfi_probe", &iq80310_map); + if (!mymtd) { + iounmap((void *)iq80310_map.virt); + return -ENXIO; + } + mymtd->owner = THIS_MODULE; + + ret = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0); + + if (ret > 0) + parsed_nr_parts = ret; + + if (parsed_nr_parts > 0) { + parts = parsed_parts; + nb_parts = parsed_nr_parts; + } else { + parts = iq80310_partitions; + nb_parts = ARRAY_SIZE(iq80310_partitions); + } + add_mtd_partitions(mymtd, parts, nb_parts); + return 0; +} + +static void __exit cleanup_iq80310(void) +{ + if (mymtd) { + del_mtd_partitions(mymtd); + map_destroy(mymtd); + kfree(parsed_parts); + } + if (iq80310_map.virt) + iounmap((void *)iq80310_map.virt); +} + +module_init(init_iq80310); +module_exit(cleanup_iq80310); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Nicolas Pitre "); +MODULE_DESCRIPTION("MTD map driver for Intel XScale IQ80310 evaluation board"); diff --git a/trunk/drivers/mtd/maps/ixp4xx.c b/trunk/drivers/mtd/maps/ixp4xx.c index 7a828e3e6446..986c58628390 100644 --- a/trunk/drivers/mtd/maps/ixp4xx.c +++ b/trunk/drivers/mtd/maps/ixp4xx.c @@ -253,7 +253,7 @@ static int ixp4xx_flash_probe(struct platform_device *dev) /* Use the fast version */ info->map.write = ixp4xx_write16, - err = parse_mtd_partitions(info->mtd, probes, &info->partitions, dev->resource->start); + err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0); if (err > 0) { err = add_mtd_partitions(info->mtd, info->partitions, err); if(err) diff --git a/trunk/drivers/mtd/maps/l440gx.c b/trunk/drivers/mtd/maps/l440gx.c index 67620adf4811..6b784ef5ee70 100644 --- a/trunk/drivers/mtd/maps/l440gx.c +++ b/trunk/drivers/mtd/maps/l440gx.c @@ -61,17 +61,14 @@ static int __init init_l440gx(void) struct resource *pm_iobase; __u16 word; - dev = pci_get_device(PCI_VENDOR_ID_INTEL, + dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, NULL); - pm_dev = pci_get_device(PCI_VENDOR_ID_INTEL, + pm_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL); - pci_dev_put(dev); - if (!dev || !pm_dev) { printk(KERN_NOTICE "L440GX flash mapping: failed to find PIIX4 ISA bridge, cannot continue\n"); - pci_dev_put(pm_dev); return -ENODEV; } @@ -79,7 +76,6 @@ static int __init init_l440gx(void) if (!l440gx_map.virt) { printk(KERN_WARNING "Failed to ioremap L440GX flash region\n"); - pci_dev_put(pm_dev); return -ENOMEM; } simple_map_init(&l440gx_map); @@ -103,12 +99,8 @@ static int __init init_l440gx(void) pm_iobase->start += iobase & ~1; pm_iobase->end += iobase & ~1; - pci_dev_put(pm_dev); - /* Allocate the resource region */ if (pci_assign_resource(pm_dev, PIIXE_IOBASE_RESOURCE) != 0) { - pci_dev_put(dev); - pci_dev_put(pm_dev); printk(KERN_WARNING "Could not allocate pm iobase resource\n"); iounmap(l440gx_map.virt); return -ENXIO; diff --git a/trunk/drivers/mtd/maps/lasat.c b/trunk/drivers/mtd/maps/lasat.c index e34376321050..1c13d2dc0cdf 100644 --- a/trunk/drivers/mtd/maps/lasat.c +++ b/trunk/drivers/mtd/maps/lasat.c @@ -79,7 +79,6 @@ static int __init init_lasat(void) return 0; } - iounmap(lasat_map.virt); return -ENXIO; } @@ -90,7 +89,6 @@ static void __exit cleanup_lasat(void) map_destroy(lasat_mtd); } if (lasat_map.virt) { - iounmap(lasat_map.virt); lasat_map.virt = 0; } } diff --git a/trunk/drivers/mtd/maps/nettel.c b/trunk/drivers/mtd/maps/nettel.c index 198e840ff6db..0994b5b2e331 100644 --- a/trunk/drivers/mtd/maps/nettel.c +++ b/trunk/drivers/mtd/maps/nettel.c @@ -277,7 +277,6 @@ int __init nettel_init(void) nettel_amd_map.virt = ioremap_nocache(amdaddr, maxsize); if (!nettel_amd_map.virt) { printk("SNAPGEAR: failed to ioremap() BOOTCS\n"); - iounmap(nettel_mmcrp); return(-EIO); } simple_map_init(&nettel_amd_map); @@ -338,8 +337,7 @@ int __init nettel_init(void) nettel_amd_map.virt = NULL; #else /* Only AMD flash supported */ - rc = -ENXIO; - goto out_unmap2; + return(-ENXIO); #endif } @@ -363,15 +361,14 @@ int __init nettel_init(void) nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); if (!nettel_intel_map.virt) { printk("SNAPGEAR: failed to ioremap() ROMCS1\n"); - rc = -EIO; - goto out_unmap2; + return(-EIO); } simple_map_init(&nettel_intel_map); intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); if (!intel_mtd) { - rc = -ENXIO; - goto out_unmap1; + iounmap(nettel_intel_map.virt); + return(-ENXIO); } /* Set PAR to the detected size */ @@ -397,14 +394,13 @@ int __init nettel_init(void) nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); if (!nettel_intel_map.virt) { printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n"); - rc = -EIO; - goto out_unmap2; + return(-EIO); } intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); if (! intel_mtd) { - rc = -ENXIO; - goto out_unmap1; + iounmap((void *) nettel_intel_map.virt); + return(-ENXIO); } intel1size = intel_mtd->size - intel0size; @@ -460,18 +456,6 @@ int __init nettel_init(void) #endif return(rc); - -#ifdef CONFIG_MTD_CFI_INTELEXT -out_unmap1: - iounmap((void *) nettel_intel_map.virt); -#endif - -out_unmap2: - iounmap(nettel_mmcrp); - iounmap(nettel_amd_map.virt); - - return(rc); - } /****************************************************************************/ @@ -485,10 +469,6 @@ void __exit nettel_cleanup(void) del_mtd_partitions(amd_mtd); map_destroy(amd_mtd); } - if (nettel_mmcrp) { - iounmap(nettel_mmcrp); - nettel_mmcrp = NULL; - } if (nettel_amd_map.virt) { iounmap(nettel_amd_map.virt); nettel_amd_map.virt = NULL; diff --git a/trunk/drivers/mtd/maps/ocotea.c b/trunk/drivers/mtd/maps/ocotea.c index 5522eac8c980..2f07602ba940 100644 --- a/trunk/drivers/mtd/maps/ocotea.c +++ b/trunk/drivers/mtd/maps/ocotea.c @@ -97,7 +97,6 @@ int __init init_ocotea(void) ARRAY_SIZE(ocotea_small_partitions)); } else { printk("map probe failed for flash\n"); - iounmap(ocotea_small_map.virt); return -ENXIO; } @@ -107,7 +106,6 @@ int __init init_ocotea(void) if (!ocotea_large_map.virt) { printk("Failed to ioremap flash\n"); - iounmap(ocotea_small_map.virt); return -EIO; } @@ -120,8 +118,6 @@ int __init init_ocotea(void) ARRAY_SIZE(ocotea_large_partitions)); } else { printk("map probe failed for flash\n"); - iounmap(ocotea_small_map.virt); - iounmap(ocotea_large_map.virt); return -ENXIO; } diff --git a/trunk/drivers/mtd/maps/pcmciamtd.c b/trunk/drivers/mtd/maps/pcmciamtd.c index 995347b1beba..c861134cbc48 100644 --- a/trunk/drivers/mtd/maps/pcmciamtd.c +++ b/trunk/drivers/mtd/maps/pcmciamtd.c @@ -602,10 +602,6 @@ static int pcmciamtd_config(struct pcmcia_device *link) ret = pcmcia_request_configuration(link, &link->conf); if(ret != CS_SUCCESS) { cs_error(link, RequestConfiguration, ret); - if (dev->win_base) { - iounmap(dev->win_base); - dev->win_base = NULL; - } return -ENODEV; } diff --git a/trunk/drivers/mtd/maps/physmap.c b/trunk/drivers/mtd/maps/physmap.c index bc7cc71788bc..7799a25a7f2a 100644 --- a/trunk/drivers/mtd/maps/physmap.c +++ b/trunk/drivers/mtd/maps/physmap.c @@ -158,42 +158,9 @@ static int physmap_flash_probe(struct platform_device *dev) return err; } -#ifdef CONFIG_PM -static int physmap_flash_suspend(struct platform_device *dev, pm_message_t state) -{ - struct physmap_flash_info *info = platform_get_drvdata(dev); - int ret = 0; - - if (info) - ret = info->mtd->suspend(info->mtd); - - return ret; -} - -static int physmap_flash_resume(struct platform_device *dev) -{ - struct physmap_flash_info *info = platform_get_drvdata(dev); - if (info) - info->mtd->resume(info->mtd); - return 0; -} - -static void physmap_flash_shutdown(struct platform_device *dev) -{ - struct physmap_flash_info *info = platform_get_drvdata(dev); - if (info && info->mtd->suspend(info->mtd) == 0) - info->mtd->resume(info->mtd); -} -#endif - static struct platform_driver physmap_flash_driver = { .probe = physmap_flash_probe, .remove = physmap_flash_remove, -#ifdef CONFIG_PM - .suspend = physmap_flash_suspend, - .resume = physmap_flash_resume, - .shutdown = physmap_flash_shutdown, -#endif .driver = { .name = "physmap-flash", }, diff --git a/trunk/drivers/mtd/maps/redwood.c b/trunk/drivers/mtd/maps/redwood.c index 2257d2b500c0..ec8fdae1dd99 100644 --- a/trunk/drivers/mtd/maps/redwood.c +++ b/trunk/drivers/mtd/maps/redwood.c @@ -126,8 +126,6 @@ static struct mtd_info *redwood_mtd; int __init init_redwood_flash(void) { - int err = 0; - printk(KERN_NOTICE "redwood: flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); @@ -143,18 +141,11 @@ int __init init_redwood_flash(void) if (redwood_mtd) { redwood_mtd->owner = THIS_MODULE; - err = add_mtd_partitions(redwood_mtd, + return add_mtd_partitions(redwood_mtd, redwood_flash_partitions, NUM_REDWOOD_FLASH_PARTITIONS); - if (err) { - printk("init_redwood_flash: add_mtd_partitions failed\n"); - iounmap(redwood_flash_map.virt); - } - return err; - } - iounmap(redwood_flash_map.virt); return -ENXIO; } diff --git a/trunk/drivers/mtd/maps/sbc8240.c b/trunk/drivers/mtd/maps/sbc8240.c index b8c1331b7a04..7d0fcf8f4f33 100644 --- a/trunk/drivers/mtd/maps/sbc8240.c +++ b/trunk/drivers/mtd/maps/sbc8240.c @@ -156,7 +156,7 @@ int __init init_sbc8240_mtd (void) }; int devicesfound = 0; - int i,j; + int i; for (i = 0; i < NUM_FLASH_BANKS; i++) { printk (KERN_NOTICE MSG_PREFIX @@ -166,10 +166,6 @@ int __init init_sbc8240_mtd (void) (unsigned long) ioremap (pt[i].addr, pt[i].size); if (!sbc8240_map[i].map_priv_1) { printk (MSG_PREFIX "failed to ioremap\n"); - for (j = 0; j < i; j++) { - iounmap((void *) sbc8240_map[j].map_priv_1); - sbc8240_map[j].map_priv_1 = 0; - } return -EIO; } simple_map_init(&sbc8240_mtd[i]); @@ -179,11 +175,6 @@ int __init init_sbc8240_mtd (void) if (sbc8240_mtd[i]) { sbc8240_mtd[i]->module = THIS_MODULE; devicesfound++; - } else { - if (sbc8240_map[i].map_priv_1) { - iounmap((void *) sbc8240_map[i].map_priv_1); - sbc8240_map[i].map_priv_1 = 0; - } } } diff --git a/trunk/drivers/mtd/maps/scx200_docflash.c b/trunk/drivers/mtd/maps/scx200_docflash.c index 5e2bce22f37c..7391fd544e86 100644 --- a/trunk/drivers/mtd/maps/scx200_docflash.c +++ b/trunk/drivers/mtd/maps/scx200_docflash.c @@ -87,23 +87,19 @@ static int __init init_scx200_docflash(void) printk(KERN_DEBUG NAME ": NatSemi SCx200 DOCCS Flash Driver\n"); - if ((bridge = pci_get_device(PCI_VENDOR_ID_NS, + if ((bridge = pci_find_device(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE, NULL)) == NULL) return -ENODEV; /* check that we have found the configuration block */ - if (!scx200_cb_present()) { - pci_dev_put(bridge); + if (!scx200_cb_present()) return -ENODEV; - } if (probe) { /* Try to use the present flash mapping if any */ pci_read_config_dword(bridge, SCx200_DOCCS_BASE, &base); pci_read_config_dword(bridge, SCx200_DOCCS_CTRL, &ctrl); - pci_dev_put(bridge); - pmr = inl(scx200_cb_base + SCx200_PMR); if (base == 0 @@ -131,7 +127,6 @@ static int __init init_scx200_docflash(void) return -ENOMEM; } } else { - pci_dev_put(bridge); for (u = size; u > 1; u >>= 1) ; if (u != 1) { diff --git a/trunk/drivers/mtd/maps/walnut.c b/trunk/drivers/mtd/maps/walnut.c index ca932122fb64..ec80eec376bf 100644 --- a/trunk/drivers/mtd/maps/walnut.c +++ b/trunk/drivers/mtd/maps/walnut.c @@ -68,7 +68,6 @@ int __init init_walnut(void) if (WALNUT_FLASH_ONBD_N(fpga_brds1)) { printk("The on-board flash is disabled (U79 sw 5)!"); - iounmap(fpga_status_adr); return -EIO; } if (WALNUT_FLASH_SRAM_SEL(fpga_brds1)) @@ -82,7 +81,6 @@ int __init init_walnut(void) if (!walnut_map.virt) { printk("Failed to ioremap flash.\n"); - iounmap(fpga_status_adr); return -EIO; } @@ -95,11 +93,9 @@ int __init init_walnut(void) ARRAY_SIZE(walnut_partitions)); } else { printk("map probe failed for flash\n"); - iounmap(fpga_status_adr); return -ENXIO; } - iounmap(fpga_status_adr); return 0; } diff --git a/trunk/drivers/mtd/mtdchar.c b/trunk/drivers/mtd/mtdchar.c index 5b6acfcb2b88..fb8b4f7e48d3 100644 --- a/trunk/drivers/mtd/mtdchar.c +++ b/trunk/drivers/mtd/mtdchar.c @@ -62,12 +62,15 @@ static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) struct mtd_info *mtd = mfi->mtd; switch (orig) { - case SEEK_SET: + case 0: + /* SEEK_SET */ break; - case SEEK_CUR: + case 1: + /* SEEK_CUR */ offset += file->f_pos; break; - case SEEK_END: + case 2: + /* SEEK_END */ offset += mtd->size; break; default: diff --git a/trunk/drivers/mtd/mtdcore.c b/trunk/drivers/mtd/mtdcore.c index c4d26de74349..168d3ba063c3 100644 --- a/trunk/drivers/mtd/mtdcore.c +++ b/trunk/drivers/mtd/mtdcore.c @@ -57,16 +57,6 @@ int add_mtd_device(struct mtd_info *mtd) mtd->index = i; mtd->usecount = 0; - /* Some chips always power up locked. Unlock them now */ - if ((mtd->flags & MTD_WRITEABLE) - && (mtd->flags & MTD_STUPID_LOCK) && mtd->unlock) { - if (mtd->unlock(mtd, 0, mtd->size)) - printk(KERN_WARNING - "%s: unlock failed, " - "writes may not work\n", - mtd->name); - } - DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name); /* No need to get a refcount on the module containing the notifier, since we hold the mtd_table_mutex */ diff --git a/trunk/drivers/mtd/nand/Kconfig b/trunk/drivers/mtd/nand/Kconfig index c99302ed3823..3db77eec0ed2 100644 --- a/trunk/drivers/mtd/nand/Kconfig +++ b/trunk/drivers/mtd/nand/Kconfig @@ -11,7 +11,7 @@ config MTD_NAND help This enables support for accessing all type of NAND flash devices. For further information see - . + . config MTD_NAND_VERIFY_WRITE bool "Verify NAND page writes" diff --git a/trunk/drivers/mtd/nand/ams-delta.c b/trunk/drivers/mtd/nand/ams-delta.c index a0ba07c36ee9..d7897dc6b3c8 100644 --- a/trunk/drivers/mtd/nand/ams-delta.c +++ b/trunk/drivers/mtd/nand/ams-delta.c @@ -130,13 +130,11 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd, if (ctrl & NAND_CTRL_CHANGE) { unsigned long bits; - bits = (~ctrl & NAND_NCE) ? AMS_DELTA_LATCH2_NAND_NCE : 0; - bits |= (ctrl & NAND_CLE) ? AMS_DELTA_LATCH2_NAND_CLE : 0; - bits |= (ctrl & NAND_ALE) ? AMS_DELTA_LATCH2_NAND_ALE : 0; + bits = (~ctrl & NAND_NCE) << 2; + bits |= (ctrl & NAND_CLE) << 7; + bits |= (ctrl & NAND_ALE) << 6; - ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE | - AMS_DELTA_LATCH2_NAND_ALE | - AMS_DELTA_LATCH2_NAND_NCE, bits); + ams_delta_latch2_write(0xC2, bits); } if (cmd != NAND_CMD_NONE) diff --git a/trunk/drivers/mtd/nand/au1550nd.c b/trunk/drivers/mtd/nand/au1550nd.c index 09e421a96893..31228334da12 100644 --- a/trunk/drivers/mtd/nand/au1550nd.c +++ b/trunk/drivers/mtd/nand/au1550nd.c @@ -21,7 +21,18 @@ #include #include +/* fixme: this is ugly */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0) #include +#else +#include +#ifdef CONFIG_MIPS_PB1550 +#include +#endif +#ifdef CONFIG_MIPS_DB1550 +#include +#endif +#endif /* * MTD structure for NAND controller diff --git a/trunk/drivers/mtd/nand/edb7312.c b/trunk/drivers/mtd/nand/edb7312.c index 12017f3c6bd6..516c0e5e564c 100644 --- a/trunk/drivers/mtd/nand/edb7312.c +++ b/trunk/drivers/mtd/nand/edb7312.c @@ -198,9 +198,6 @@ static void __exit ep7312_cleanup(void) /* Release resources, unregister device */ nand_release(ap7312_mtd); - /* Release io resource */ - iounmap((void *)this->IO_ADDR_R); - /* Free the MTD device structure */ kfree(ep7312_mtd); } diff --git a/trunk/drivers/mtd/nand/nand_base.c b/trunk/drivers/mtd/nand/nand_base.c index 975b2ef61121..62b861304e03 100644 --- a/trunk/drivers/mtd/nand/nand_base.c +++ b/trunk/drivers/mtd/nand/nand_base.c @@ -1093,10 +1093,9 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len, ret = nand_do_read_ops(mtd, from, &chip->ops); - *retlen = chip->ops.retlen; - nand_release_device(mtd); + *retlen = chip->ops.retlen; return ret; } @@ -1204,7 +1203,7 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd, pos = steps * (eccsize + chunk); steps = 0; } else - pos = eccsize; + pos = eccsize + chunk; chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page); for (i = 0; i < steps; i++) { @@ -1567,7 +1566,7 @@ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, bytes = min_t(size_t, len, free->length); boffs = free->offset; } - memcpy(chip->oob_poi + boffs, oob, bytes); + memcpy(chip->oob_poi + woffs, oob, bytes); oob += bytes; } return oob; @@ -1692,10 +1691,9 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len, ret = nand_do_write_ops(mtd, to, &chip->ops); - *retlen = chip->ops.retlen; - nand_release_device(mtd); + *retlen = chip->ops.retlen; return ret; } @@ -2224,7 +2222,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, } /* Try to identify manufacturer */ - for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) { + for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) { if (nand_manuf_ids[maf_idx].id == *maf_id) break; } diff --git a/trunk/drivers/mtd/nand/ndfc.c b/trunk/drivers/mtd/nand/ndfc.c index 039c759cfbfc..e5bd88f2d560 100644 --- a/trunk/drivers/mtd/nand/ndfc.c +++ b/trunk/drivers/mtd/nand/ndfc.c @@ -168,7 +168,7 @@ static void ndfc_chip_init(struct ndfc_nand_mtd *mtd) chip->ecc.mode = NAND_ECC_HW; chip->ecc.size = 256; chip->ecc.bytes = 3; - chip->ecclayout = chip->ecc.layout = mtd->pl_chip->ecclayout; + chip->ecclayout = mtd->pl_chip->ecclayout; mtd->mtd.priv = chip; mtd->mtd.owner = THIS_MODULE; } diff --git a/trunk/drivers/mtd/nand/ppchameleonevb.c b/trunk/drivers/mtd/nand/ppchameleonevb.c index eb7d4d443deb..22fa65c12ab9 100644 --- a/trunk/drivers/mtd/nand/ppchameleonevb.c +++ b/trunk/drivers/mtd/nand/ppchameleonevb.c @@ -276,7 +276,6 @@ static int __init ppchameleonevb_init(void) /* Scan to find existence of the device (it could not be mounted) */ if (nand_scan(ppchameleon_mtd, 1)) { iounmap((void *)ppchameleon_fio_base); - ppchameleon_fio_base = NULL; kfree(ppchameleon_mtd); goto nand_evb_init; } @@ -315,8 +314,6 @@ static int __init ppchameleonevb_init(void) ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!ppchameleonevb_mtd) { printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n"); - if (ppchameleon_fio_base) - iounmap(ppchameleon_fio_base); return -ENOMEM; } @@ -325,8 +322,6 @@ static int __init ppchameleonevb_init(void) if (!ppchameleonevb_fio_base) { printk("ioremap PPChameleonEVB NAND flash failed\n"); kfree(ppchameleonevb_mtd); - if (ppchameleon_fio_base) - iounmap(ppchameleon_fio_base); return -EIO; } @@ -383,8 +378,6 @@ static int __init ppchameleonevb_init(void) if (nand_scan(ppchameleonevb_mtd, 1)) { iounmap((void *)ppchameleonevb_fio_base); kfree(ppchameleonevb_mtd); - if (ppchameleon_fio_base) - iounmap(ppchameleon_fio_base); return -ENXIO; } #ifdef CONFIG_MTD_PARTITIONS diff --git a/trunk/drivers/mtd/nand/sharpsl.c b/trunk/drivers/mtd/nand/sharpsl.c index 51c7288ab49a..fbeedc3184e9 100644 --- a/trunk/drivers/mtd/nand/sharpsl.c +++ b/trunk/drivers/mtd/nand/sharpsl.c @@ -78,7 +78,7 @@ static struct mtd_partition sharpsl_nand_default_partition_info[] = { /* * hardware specific access to control-lines * ctrl: - * NAND_CNE: bit 0 -> ! bit 0 & 4 + * NAND_CNE: bit 0 -> bit 0 & 4 * NAND_CLE: bit 1 -> bit 1 * NAND_ALE: bit 2 -> bit 2 * @@ -92,10 +92,7 @@ static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned char bits = ctrl & 0x07; bits |= (ctrl & 0x01) << 4; - - bits ^= 0x11; - - writeb((readb(FLASHCTL) & ~0x17) | bits, FLASHCTL); + writeb((readb(FLASHCTL) & 0x17) | bits, FLASHCTL); } if (cmd != NAND_CMD_NONE) diff --git a/trunk/drivers/mtd/ssfdc.c b/trunk/drivers/mtd/ssfdc.c deleted file mode 100644 index 79d3bb659bfe..000000000000 --- a/trunk/drivers/mtd/ssfdc.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Linux driver for SSFDC Flash Translation Layer (Read only) - * (c) 2005 Eptar srl - * Author: Claudio Lanconelli - * - * Based on NTFL and MTDBLOCK_RO drivers - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -struct ssfdcr_record { - struct mtd_blktrans_dev mbd; - int usecount; - unsigned char heads; - unsigned char sectors; - unsigned short cylinders; - int cis_block; /* block n. containing CIS/IDI */ - int erase_size; /* phys_block_size */ - unsigned short *logic_block_map; /* all zones (max 8192 phys blocks on - the 128MiB) */ - int map_len; /* n. phys_blocks on the card */ -}; - -#define SSFDCR_MAJOR 257 -#define SSFDCR_PARTN_BITS 3 - -#define SECTOR_SIZE 512 -#define SECTOR_SHIFT 9 -#define OOB_SIZE 16 - -#define MAX_LOGIC_BLK_PER_ZONE 1000 -#define MAX_PHYS_BLK_PER_ZONE 1024 - -#define KiB(x) ( (x) * 1024L ) -#define MiB(x) ( KiB(x) * 1024L ) - -/** CHS Table - 1MiB 2MiB 4MiB 8MiB 16MiB 32MiB 64MiB 128MiB -NCylinder 125 125 250 250 500 500 500 500 -NHead 4 4 4 4 4 8 8 16 -NSector 4 8 8 16 16 16 32 32 -SumSector 2,000 4,000 8,000 16,000 32,000 64,000 128,000 256,000 -SectorSize 512 512 512 512 512 512 512 512 -**/ - -typedef struct { - unsigned long size; - unsigned short cyl; - unsigned char head; - unsigned char sec; -} chs_entry_t; - -/* Must be ordered by size */ -static const chs_entry_t chs_table[] = { - { MiB( 1), 125, 4, 4 }, - { MiB( 2), 125, 4, 8 }, - { MiB( 4), 250, 4, 8 }, - { MiB( 8), 250, 4, 16 }, - { MiB( 16), 500, 4, 16 }, - { MiB( 32), 500, 8, 16 }, - { MiB( 64), 500, 8, 32 }, - { MiB(128), 500, 16, 32 }, - { 0 }, -}; - -static int get_chs(unsigned long size, unsigned short *cyl, unsigned char *head, - unsigned char *sec) -{ - int k; - int found = 0; - - k = 0; - while (chs_table[k].size > 0 && size > chs_table[k].size) - k++; - - if (chs_table[k].size > 0) { - if (cyl) - *cyl = chs_table[k].cyl; - if (head) - *head = chs_table[k].head; - if (sec) - *sec = chs_table[k].sec; - found = 1; - } - - return found; -} - -/* These bytes are the signature for the CIS/IDI sector */ -static const uint8_t cis_numbers[] = { - 0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02, 0xDF, 0x01, 0x20 -}; - -/* Read and check for a valid CIS sector */ -static int get_valid_cis_sector(struct mtd_info *mtd) -{ - int ret, k, cis_sector; - size_t retlen; - loff_t offset; - uint8_t *sect_buf; - - cis_sector = -1; - - sect_buf = kmalloc(SECTOR_SIZE, GFP_KERNEL); - if (!sect_buf) - goto out; - - /* - * Look for CIS/IDI sector on the first GOOD block (give up after 4 bad - * blocks). If the first good block doesn't contain CIS number the flash - * is not SSFDC formatted - */ - for (k = 0, offset = 0; k < 4; k++, offset += mtd->erasesize) { - if (!mtd->block_isbad(mtd, offset)) { - ret = mtd->read(mtd, offset, SECTOR_SIZE, &retlen, - sect_buf); - - /* CIS pattern match on the sector buffer */ - if (ret < 0 || retlen != SECTOR_SIZE) { - printk(KERN_WARNING - "SSFDC_RO:can't read CIS/IDI sector\n"); - } else if (!memcmp(sect_buf, cis_numbers, - sizeof(cis_numbers))) { - /* Found */ - cis_sector = (int)(offset >> SECTOR_SHIFT); - } else { - DEBUG(MTD_DEBUG_LEVEL1, - "SSFDC_RO: CIS/IDI sector not found" - " on %s (mtd%d)\n", mtd->name, - mtd->index); - } - break; - } - } - - kfree(sect_buf); - out: - return cis_sector; -} - -/* Read physical sector (wrapper to MTD_READ) */ -static int read_physical_sector(struct mtd_info *mtd, uint8_t *sect_buf, - int sect_no) -{ - int ret; - size_t retlen; - loff_t offset = (loff_t)sect_no << SECTOR_SHIFT; - - ret = mtd->read(mtd, offset, SECTOR_SIZE, &retlen, sect_buf); - if (ret < 0 || retlen != SECTOR_SIZE) - return -1; - - return 0; -} - -/* Read redundancy area (wrapper to MTD_READ_OOB */ -static int read_raw_oob(struct mtd_info *mtd, loff_t offs, uint8_t *buf) -{ - struct mtd_oob_ops ops; - int ret; - - ops.mode = MTD_OOB_RAW; - ops.ooboffs = 0; - ops.ooblen = mtd->oobsize; - ops.len = OOB_SIZE; - ops.oobbuf = buf; - ops.datbuf = NULL; - - ret = mtd->read_oob(mtd, offs, &ops); - if (ret < 0 || ops.retlen != OOB_SIZE) - return -1; - - return 0; -} - -/* Parity calculator on a word of n bit size */ -static int get_parity(int number, int size) -{ - int k; - int parity; - - parity = 1; - for (k = 0; k < size; k++) { - parity += (number >> k); - parity &= 1; - } - return parity; -} - -/* Read and validate the logical block address field stored in the OOB */ -static int get_logical_address(uint8_t *oob_buf) -{ - int block_address, parity; - int offset[2] = {6, 11}; /* offset of the 2 address fields within OOB */ - int j; - int ok = 0; - - /* - * Look for the first valid logical address - * Valid address has fixed pattern on most significant bits and - * parity check - */ - for (j = 0; j < ARRAY_SIZE(offset); j++) { - block_address = ((int)oob_buf[offset[j]] << 8) | - oob_buf[offset[j]+1]; - - /* Check for the signature bits in the address field (MSBits) */ - if ((block_address & ~0x7FF) == 0x1000) { - parity = block_address & 0x01; - block_address &= 0x7FF; - block_address >>= 1; - - if (get_parity(block_address, 10) != parity) { - DEBUG(MTD_DEBUG_LEVEL0, - "SSFDC_RO: logical address field%d" - "parity error(0x%04X)\n", j+1, - block_address); - } else { - ok = 1; - break; - } - } - } - - if (!ok) - block_address = -2; - - DEBUG(MTD_DEBUG_LEVEL3, "SSFDC_RO: get_logical_address() %d\n", - block_address); - - return block_address; -} - -/* Build the logic block map */ -static int build_logical_block_map(struct ssfdcr_record *ssfdc) -{ - unsigned long offset; - uint8_t oob_buf[OOB_SIZE]; - int ret, block_address, phys_block; - struct mtd_info *mtd = ssfdc->mbd.mtd; - - DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: build_block_map() nblks=%d (%luK)\n", - ssfdc->map_len, - (unsigned long)ssfdc->map_len * ssfdc->erase_size / 1024); - - /* Scan every physical block, skip CIS block */ - for (phys_block = ssfdc->cis_block + 1; phys_block < ssfdc->map_len; - phys_block++) { - offset = (unsigned long)phys_block * ssfdc->erase_size; - if (mtd->block_isbad(mtd, offset)) - continue; /* skip bad blocks */ - - ret = read_raw_oob(mtd, offset, oob_buf); - if (ret < 0) { - DEBUG(MTD_DEBUG_LEVEL0, - "SSFDC_RO: mtd read_oob() failed at %lu\n", - offset); - return -1; - } - block_address = get_logical_address(oob_buf); - - /* Skip invalid addresses */ - if (block_address >= 0 && - block_address < MAX_LOGIC_BLK_PER_ZONE) { - int zone_index; - - zone_index = phys_block / MAX_PHYS_BLK_PER_ZONE; - block_address += zone_index * MAX_LOGIC_BLK_PER_ZONE; - ssfdc->logic_block_map[block_address] = - (unsigned short)phys_block; - - DEBUG(MTD_DEBUG_LEVEL2, - "SSFDC_RO: build_block_map() phys_block=%d," - "logic_block_addr=%d, zone=%d\n", - phys_block, block_address, zone_index); - } - } - return 0; -} - -static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) -{ - struct ssfdcr_record *ssfdc; - int cis_sector; - - /* Check for small page NAND flash */ - if (mtd->type != MTD_NANDFLASH || mtd->oobsize != OOB_SIZE) - return; - - /* Check for SSDFC format by reading CIS/IDI sector */ - cis_sector = get_valid_cis_sector(mtd); - if (cis_sector == -1) - return; - - ssfdc = kzalloc(sizeof(struct ssfdcr_record), GFP_KERNEL); - if (!ssfdc) { - printk(KERN_WARNING - "SSFDC_RO: out of memory for data structures\n"); - return; - } - - ssfdc->mbd.mtd = mtd; - ssfdc->mbd.devnum = -1; - ssfdc->mbd.blksize = SECTOR_SIZE; - ssfdc->mbd.tr = tr; - ssfdc->mbd.readonly = 1; - - ssfdc->cis_block = cis_sector / (mtd->erasesize >> SECTOR_SHIFT); - ssfdc->erase_size = mtd->erasesize; - ssfdc->map_len = mtd->size / mtd->erasesize; - - DEBUG(MTD_DEBUG_LEVEL1, - "SSFDC_RO: cis_block=%d,erase_size=%d,map_len=%d,n_zones=%d\n", - ssfdc->cis_block, ssfdc->erase_size, ssfdc->map_len, - (ssfdc->map_len + MAX_PHYS_BLK_PER_ZONE - 1) / - MAX_PHYS_BLK_PER_ZONE); - - /* Set geometry */ - ssfdc->heads = 16; - ssfdc->sectors = 32; - get_chs(mtd->size, NULL, &ssfdc->heads, &ssfdc->sectors); - ssfdc->cylinders = (unsigned short)((mtd->size >> SECTOR_SHIFT) / - ((long)ssfdc->sectors * (long)ssfdc->heads)); - - DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: using C:%d H:%d S:%d == %ld sects\n", - ssfdc->cylinders, ssfdc->heads , ssfdc->sectors, - (long)ssfdc->cylinders * (long)ssfdc->heads * - (long)ssfdc->sectors); - - ssfdc->mbd.size = (long)ssfdc->heads * (long)ssfdc->cylinders * - (long)ssfdc->sectors; - - /* Allocate logical block map */ - ssfdc->logic_block_map = kmalloc(sizeof(ssfdc->logic_block_map[0]) * - ssfdc->map_len, GFP_KERNEL); - if (!ssfdc->logic_block_map) { - printk(KERN_WARNING - "SSFDC_RO: out of memory for data structures\n"); - goto out_err; - } - memset(ssfdc->logic_block_map, 0xff, sizeof(ssfdc->logic_block_map[0]) * - ssfdc->map_len); - - /* Build logical block map */ - if (build_logical_block_map(ssfdc) < 0) - goto out_err; - - /* Register device + partitions */ - if (add_mtd_blktrans_dev(&ssfdc->mbd)) - goto out_err; - - printk(KERN_INFO "SSFDC_RO: Found ssfdc%c on mtd%d (%s)\n", - ssfdc->mbd.devnum + 'a', mtd->index, mtd->name); - return; - -out_err: - kfree(ssfdc->logic_block_map); - kfree(ssfdc); -} - -static void ssfdcr_remove_dev(struct mtd_blktrans_dev *dev) -{ - struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev; - - DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: remove_dev (i=%d)\n", dev->devnum); - - del_mtd_blktrans_dev(dev); - kfree(ssfdc->logic_block_map); - kfree(ssfdc); -} - -static int ssfdcr_readsect(struct mtd_blktrans_dev *dev, - unsigned long logic_sect_no, char *buf) -{ - struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev; - int sectors_per_block, offset, block_address; - - sectors_per_block = ssfdc->erase_size >> SECTOR_SHIFT; - offset = (int)(logic_sect_no % sectors_per_block); - block_address = (int)(logic_sect_no / sectors_per_block); - - DEBUG(MTD_DEBUG_LEVEL3, - "SSFDC_RO: ssfdcr_readsect(%lu) sec_per_blk=%d, ofst=%d," - " block_addr=%d\n", logic_sect_no, sectors_per_block, offset, - block_address); - - if (block_address >= ssfdc->map_len) - BUG(); - - block_address = ssfdc->logic_block_map[block_address]; - - DEBUG(MTD_DEBUG_LEVEL3, - "SSFDC_RO: ssfdcr_readsect() phys_block_addr=%d\n", - block_address); - - if (block_address < 0xffff) { - unsigned long sect_no; - - sect_no = (unsigned long)block_address * sectors_per_block + - offset; - - DEBUG(MTD_DEBUG_LEVEL3, - "SSFDC_RO: ssfdcr_readsect() phys_sect_no=%lu\n", - sect_no); - - if (read_physical_sector(ssfdc->mbd.mtd, buf, sect_no) < 0) - return -EIO; - } else { - memset(buf, 0xff, SECTOR_SIZE); - } - - return 0; -} - -static int ssfdcr_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) -{ - struct ssfdcr_record *ssfdc = (struct ssfdcr_record *)dev; - - DEBUG(MTD_DEBUG_LEVEL1, "SSFDC_RO: ssfdcr_getgeo() C=%d, H=%d, S=%d\n", - ssfdc->cylinders, ssfdc->heads, ssfdc->sectors); - - geo->heads = ssfdc->heads; - geo->sectors = ssfdc->sectors; - geo->cylinders = ssfdc->cylinders; - - return 0; -} - -/**************************************************************************** - * - * Module stuff - * - ****************************************************************************/ - -static struct mtd_blktrans_ops ssfdcr_tr = { - .name = "ssfdc", - .major = SSFDCR_MAJOR, - .part_bits = SSFDCR_PARTN_BITS, - .getgeo = ssfdcr_getgeo, - .readsect = ssfdcr_readsect, - .add_mtd = ssfdcr_add_mtd, - .remove_dev = ssfdcr_remove_dev, - .owner = THIS_MODULE, -}; - -static int __init init_ssfdcr(void) -{ - printk(KERN_INFO "SSFDC read-only Flash Translation layer\n"); - - return register_mtd_blktrans(&ssfdcr_tr); -} - -static void __exit cleanup_ssfdcr(void) -{ - deregister_mtd_blktrans(&ssfdcr_tr); -} - -module_init(init_ssfdcr); -module_exit(cleanup_ssfdcr); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Claudio Lanconelli "); -MODULE_DESCRIPTION("Flash Translation Layer for read-only SSFDC SmartMedia card"); diff --git a/trunk/drivers/net/3c515.c b/trunk/drivers/net/3c515.c index aedfddf20cb3..4532b17e40ea 100644 --- a/trunk/drivers/net/3c515.c +++ b/trunk/drivers/net/3c515.c @@ -1003,8 +1003,7 @@ static int corkscrew_start_xmit(struct sk_buff *skb, /* Calculate the next Tx descriptor entry. */ int entry = vp->cur_tx % TX_RING_SIZE; struct boom_tx_desc *prev_entry; - unsigned long flags; - int i; + unsigned long flags, i; if (vp->tx_full) /* No room to transmit with */ return 1; diff --git a/trunk/drivers/net/3c59x.c b/trunk/drivers/net/3c59x.c index 29dede2eaa85..80e8ca013e44 100644 --- a/trunk/drivers/net/3c59x.c +++ b/trunk/drivers/net/3c59x.c @@ -2077,7 +2077,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) vp->tx_ring[entry].next = 0; #if DO_ZEROCOPY - if (skb->ip_summed != CHECKSUM_PARTIAL) + if (skb->ip_summed != CHECKSUM_HW) vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded); else vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum | AddUDPChksum); diff --git a/trunk/drivers/net/8139cp.c b/trunk/drivers/net/8139cp.c index a48b211c489d..1428bb7715af 100644 --- a/trunk/drivers/net/8139cp.c +++ b/trunk/drivers/net/8139cp.c @@ -813,7 +813,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) if (mss) flags |= LargeSend | ((mss & MSSMask) << MSSShift); - else if (skb->ip_summed == CHECKSUM_PARTIAL) { + else if (skb->ip_summed == CHECKSUM_HW) { const struct iphdr *ip = skb->nh.iph; if (ip->protocol == IPPROTO_TCP) flags |= IPCS | TCPCS; @@ -867,7 +867,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) if (mss) ctrl |= LargeSend | ((mss & MSSMask) << MSSShift); - else if (skb->ip_summed == CHECKSUM_PARTIAL) { + else if (skb->ip_summed == CHECKSUM_HW) { if (ip->protocol == IPPROTO_TCP) ctrl |= IPCS | TCPCS; else if (ip->protocol == IPPROTO_UDP) @@ -898,7 +898,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) txd->addr = cpu_to_le64(first_mapping); wmb(); - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { if (ip->protocol == IPPROTO_TCP) txd->opts1 = cpu_to_le32(first_eor | first_len | FirstFrag | DescOwn | diff --git a/trunk/drivers/net/82596.c b/trunk/drivers/net/82596.c index 257d3bce3993..7e2ca9571467 100644 --- a/trunk/drivers/net/82596.c +++ b/trunk/drivers/net/82596.c @@ -899,7 +899,7 @@ static inline int i596_rx(struct net_device *dev) } -static void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp) +static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp) { struct i596_cmd *ptr; @@ -932,8 +932,7 @@ static void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp) lp->scb.cmd = I596_NULL; } -static void i596_reset(struct net_device *dev, struct i596_private *lp, - int ioaddr) +static inline void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr) { unsigned long flags; @@ -1579,7 +1578,7 @@ static int debug = -1; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "i82596 debug mask"); -int __init init_module(void) +int init_module(void) { if (debug >= 0) i596_debug = debug; @@ -1589,7 +1588,7 @@ int __init init_module(void) return 0; } -void __exit cleanup_module(void) +void cleanup_module(void) { unregister_netdev(dev_82596); #ifdef __mc68000__ diff --git a/trunk/drivers/net/Kconfig b/trunk/drivers/net/Kconfig index a2bd8119270e..39189903e355 100644 --- a/trunk/drivers/net/Kconfig +++ b/trunk/drivers/net/Kconfig @@ -1724,20 +1724,6 @@ config VIA_RHINE_MMIO If unsure, say Y. -config VIA_RHINE_NAPI - bool "Use Rx Polling (NAPI)" - depends on VIA_RHINE - help - NAPI is a new driver API designed to reduce CPU and interrupt load - when the driver is receiving lots of packets from the card. - - If your estimated Rx load is 10kpps or more, or if the card will be - deployed on potentially unfriendly networks (e.g. in a firewall), - then say Y here. - - See for more - information. - config LAN_SAA9730 bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)" depends on NET_PCI && EXPERIMENTAL && MIPS @@ -2233,33 +2219,6 @@ config GFAR_NAPI bool "NAPI Support" depends on GIANFAR -config UCC_GETH - tristate "Freescale QE UCC GETH" - depends on QUICC_ENGINE && UCC_FAST - help - This driver supports the Gigabit Ethernet mode of QE UCC. - QE can be found on MPC836x CPUs. - -config UGETH_NAPI - bool "NAPI Support" - depends on UCC_GETH - -config UGETH_MAGIC_PACKET - bool "Magic Packet detection support" - depends on UCC_GETH - -config UGETH_FILTERING - bool "Mac address filtering support" - depends on UCC_GETH - -config UGETH_TX_ON_DEMOND - bool "Transmit on Demond support" - depends on UCC_GETH - -config UGETH_HAS_GIGA - bool - depends on UCC_GETH && MPC836x - config MV643XX_ETH tristate "MV-643XX Ethernet support" depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MOMENCO_OCELOT_3 || PPC_MULTIPLATFORM @@ -2393,7 +2352,7 @@ config MYRI10GE you will need a newer firmware image. You may get this image or more information, at: - + To compile this driver as a module, choose M here and read . The module diff --git a/trunk/drivers/net/Makefile b/trunk/drivers/net/Makefile index 8427bf9dec9d..c91e95126f78 100644 --- a/trunk/drivers/net/Makefile +++ b/trunk/drivers/net/Makefile @@ -18,9 +18,6 @@ gianfar_driver-objs := gianfar.o \ gianfar_mii.o \ gianfar_sysfs.o -obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o -ucc_geth_driver-objs := ucc_geth.o ucc_geth_phy.o - # # link order important here # diff --git a/trunk/drivers/net/ac3200.c b/trunk/drivers/net/ac3200.c index 0fbbcb75af69..7952dc6d77e3 100644 --- a/trunk/drivers/net/ac3200.c +++ b/trunk/drivers/net/ac3200.c @@ -370,7 +370,8 @@ MODULE_PARM_DESC(mem, "Memory base address(es)"); MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver"); MODULE_LICENSE("GPL"); -int __init init_module(void) +int +init_module(void) { struct net_device *dev; int this_dev, found = 0; diff --git a/trunk/drivers/net/acenic.c b/trunk/drivers/net/acenic.c index 826548644d7b..1c01e9b3d07c 100644 --- a/trunk/drivers/net/acenic.c +++ b/trunk/drivers/net/acenic.c @@ -2040,7 +2040,7 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm) */ if (bd_flags & BD_FLG_TCP_UDP_SUM) { skb->csum = htons(csum); - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_HW; } else { skb->ip_summed = CHECKSUM_NONE; } @@ -2511,7 +2511,7 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) mapping = ace_map_tx_skb(ap, skb, skb, idx); flagsize = (skb->len << 16) | (BD_FLG_END); - if (skb->ip_summed == CHECKSUM_PARTIAL) + if (skb->ip_summed == CHECKSUM_HW) flagsize |= BD_FLG_TCP_UDP_SUM; #if ACENIC_DO_VLAN if (vlan_tx_tag_present(skb)) { @@ -2534,7 +2534,7 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) mapping = ace_map_tx_skb(ap, skb, NULL, idx); flagsize = (skb_headlen(skb) << 16); - if (skb->ip_summed == CHECKSUM_PARTIAL) + if (skb->ip_summed == CHECKSUM_HW) flagsize |= BD_FLG_TCP_UDP_SUM; #if ACENIC_DO_VLAN if (vlan_tx_tag_present(skb)) { @@ -2560,7 +2560,7 @@ static int ace_start_xmit(struct sk_buff *skb, struct net_device *dev) PCI_DMA_TODEVICE); flagsize = (frag->size << 16); - if (skb->ip_summed == CHECKSUM_PARTIAL) + if (skb->ip_summed == CHECKSUM_HW) flagsize |= BD_FLG_TCP_UDP_SUM; idx = (idx + 1) % ACE_TX_RING_ENTRIES(ap); diff --git a/trunk/drivers/net/appletalk/Kconfig b/trunk/drivers/net/appletalk/Kconfig index 0a0e0cd81a23..b14e89004c3a 100644 --- a/trunk/drivers/net/appletalk/Kconfig +++ b/trunk/drivers/net/appletalk/Kconfig @@ -29,7 +29,7 @@ config ATALK even politically correct people are allowed to say Y here. config DEV_APPLETALK - tristate "Appletalk interfaces support" + bool "Appletalk interfaces support" depends on ATALK help AppleTalk is the protocol that Apple computers can use to communicate diff --git a/trunk/drivers/net/appletalk/cops.c b/trunk/drivers/net/appletalk/cops.c index ae7f828344d9..1d01ac0000e4 100644 --- a/trunk/drivers/net/appletalk/cops.c +++ b/trunk/drivers/net/appletalk/cops.c @@ -1030,7 +1030,7 @@ module_param(io, int, 0); module_param(irq, int, 0); module_param(board_type, int, 0); -int __init init_module(void) +int init_module(void) { if (io == 0) printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n", diff --git a/trunk/drivers/net/arcnet/com20020-pci.c b/trunk/drivers/net/arcnet/com20020-pci.c index 96d8a694d433..979a33df0a8c 100644 --- a/trunk/drivers/net/arcnet/com20020-pci.c +++ b/trunk/drivers/net/arcnet/com20020-pci.c @@ -161,7 +161,6 @@ static struct pci_device_id com20020pci_id_table[] = { { 0x1571, 0xa204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, { 0x1571, 0xa205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, { 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, - { 0x10B5, 0x9030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, { 0x10B5, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, {0,} }; diff --git a/trunk/drivers/net/at1700.c b/trunk/drivers/net/at1700.c index 4ca061c2d5b2..5d7929c79bce 100644 --- a/trunk/drivers/net/at1700.c +++ b/trunk/drivers/net/at1700.c @@ -901,7 +901,7 @@ MODULE_PARM_DESC(io, "AT1700/FMV18X I/O base address"); MODULE_PARM_DESC(irq, "AT1700/FMV18X IRQ number"); MODULE_PARM_DESC(net_debug, "AT1700/FMV18X debug level (0-6)"); -int __init init_module(void) +int init_module(void) { if (io == 0) printk("at1700: You should not use auto-probing with insmod!\n"); diff --git a/trunk/drivers/net/bmac.c b/trunk/drivers/net/bmac.c index 711609665632..6fad83f24c4f 100644 --- a/trunk/drivers/net/bmac.c +++ b/trunk/drivers/net/bmac.c @@ -1264,8 +1264,7 @@ static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_i { int j, rev, ret; struct bmac_data *bp; - const unsigned char *prop_addr; - unsigned char addr[6]; + unsigned char *addr; struct net_device *dev; int is_bmac_plus = ((int)match->data) != 0; @@ -1273,16 +1272,14 @@ static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_i printk(KERN_ERR "BMAC: can't use, need 3 addrs and 3 intrs\n"); return -ENODEV; } - prop_addr = get_property(macio_get_of_node(mdev), "mac-address", NULL); - if (prop_addr == NULL) { - prop_addr = get_property(macio_get_of_node(mdev), - "local-mac-address", NULL); - if (prop_addr == NULL) { + addr = get_property(macio_get_of_node(mdev), "mac-address", NULL); + if (addr == NULL) { + addr = get_property(macio_get_of_node(mdev), "local-mac-address", NULL); + if (addr == NULL) { printk(KERN_ERR "BMAC: Can't get mac-address\n"); return -ENODEV; } } - memcpy(addr, prop_addr, sizeof(addr)); dev = alloc_etherdev(PRIV_BYTES); if (!dev) { diff --git a/trunk/drivers/net/bnx2.c b/trunk/drivers/net/bnx2.c index 7857b4630124..db73de0d2511 100644 --- a/trunk/drivers/net/bnx2.c +++ b/trunk/drivers/net/bnx2.c @@ -56,8 +56,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4.44" -#define DRV_MODULE_RELDATE "August 10, 2006" +#define DRV_MODULE_VERSION "1.4.43" +#define DRV_MODULE_RELDATE "June 28, 2006" #define RUN_AT(x) (jiffies + (x)) @@ -209,10 +209,8 @@ MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl); static inline u32 bnx2_tx_avail(struct bnx2 *bp) { - u32 diff; + u32 diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons); - smp_mb(); - diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons); if (diff > MAX_TX_DESC_CNT) diff = (diff & MAX_TX_DESC_CNT) - 1; return (bp->tx_ring_size - diff); @@ -1571,7 +1569,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index) struct rx_bd *rxbd = &bp->rx_desc_ring[RX_RING(index)][RX_IDX(index)]; unsigned long align; - skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size); + skb = dev_alloc_skb(bp->rx_buf_size); if (skb == NULL) { return -ENOMEM; } @@ -1580,6 +1578,7 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index) skb_reserve(skb, 8 - align); } + skb->dev = bp->dev; mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size, PCI_DMA_FROMDEVICE); @@ -1687,20 +1686,15 @@ bnx2_tx_int(struct bnx2 *bp) } bp->tx_cons = sw_cons; - /* Need to make the tx_cons update visible to bnx2_start_xmit() - * before checking for netif_queue_stopped(). Without the - * memory barrier, there is a small possibility that bnx2_start_xmit() - * will miss it and cause the queue to be stopped forever. - */ - smp_mb(); - if (unlikely(netif_queue_stopped(bp->dev)) && - (bnx2_tx_avail(bp) > bp->tx_wake_thresh)) { - netif_tx_lock(bp->dev); + if (unlikely(netif_queue_stopped(bp->dev))) { + spin_lock(&bp->tx_lock); if ((netif_queue_stopped(bp->dev)) && - (bnx2_tx_avail(bp) > bp->tx_wake_thresh)) + (bnx2_tx_avail(bp) > MAX_SKB_FRAGS)) { + netif_wake_queue(bp->dev); - netif_tx_unlock(bp->dev); + } + spin_unlock(&bp->tx_lock); } } @@ -1792,7 +1786,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget) if ((bp->dev->mtu > 1500) && (len <= RX_COPY_THRESH)) { struct sk_buff *new_skb; - new_skb = netdev_alloc_skb(bp->dev, len + 2); + new_skb = dev_alloc_skb(len + 2); if (new_skb == NULL) goto reuse_rx; @@ -1803,6 +1797,7 @@ bnx2_rx_int(struct bnx2 *bp, int budget) skb_reserve(new_skb, 2); skb_put(new_skb, len); + new_skb->dev = bp->dev; bnx2_reuse_rx_skb(bp, skb, sw_ring_cons, sw_ring_prod); @@ -3508,8 +3503,6 @@ bnx2_init_tx_ring(struct bnx2 *bp) struct tx_bd *txbd; u32 val; - bp->tx_wake_thresh = bp->tx_ring_size / 2; - txbd = &bp->tx_desc_ring[MAX_TX_DESC_CNT]; txbd->tx_bd_haddr_hi = (u64) bp->tx_desc_mapping >> 32; @@ -3959,7 +3952,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) return -EINVAL; pkt_size = 1514; - skb = netdev_alloc_skb(bp->dev, pkt_size); + skb = dev_alloc_skb(pkt_size); if (!skb) return -ENOMEM; packet = skb_put(skb, pkt_size); @@ -4397,8 +4390,10 @@ bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) #endif /* Called with netif_tx_lock. - * bnx2_tx_int() runs without netif_tx_lock unless it needs to call - * netif_wake_queue(). + * hard_start_xmit is pseudo-lockless - a lock is only required when + * the tx queue is full. This way, we get the benefit of lockless + * operations most of the time without the complexities to handle + * netif_stop_queue/wake_queue race conditions. */ static int bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) @@ -4423,7 +4418,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) ring_prod = TX_RING_IDX(prod); vlan_tag_flags = 0; - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM; } @@ -4517,9 +4512,12 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; if (unlikely(bnx2_tx_avail(bp) <= MAX_SKB_FRAGS)) { + spin_lock(&bp->tx_lock); netif_stop_queue(dev); - if (bnx2_tx_avail(bp) > bp->tx_wake_thresh) + + if (bnx2_tx_avail(bp) > MAX_SKB_FRAGS) netif_wake_queue(dev); + spin_unlock(&bp->tx_lock); } return NETDEV_TX_OK; @@ -5630,6 +5628,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->pdev = pdev; spin_lock_init(&bp->phy_lock); + spin_lock_init(&bp->tx_lock); INIT_WORK(&bp->reset_task, bnx2_reset_task, bp); dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0); @@ -5752,7 +5751,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->mac_addr[5] = (u8) reg; bp->tx_ring_size = MAX_TX_DESC_CNT; - bnx2_set_rx_ring_size(bp, 255); + bnx2_set_rx_ring_size(bp, 100); bp->rx_csum = 1; diff --git a/trunk/drivers/net/bnx2.h b/trunk/drivers/net/bnx2.h index fe804763c607..658c5ee95c73 100644 --- a/trunk/drivers/net/bnx2.h +++ b/trunk/drivers/net/bnx2.h @@ -3890,6 +3890,10 @@ struct bnx2 { u32 tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES))); u16 tx_prod; + struct tx_bd *tx_desc_ring; + struct sw_bd *tx_buf_ring; + int tx_ring_size; + u16 tx_cons __attribute__((aligned(L1_CACHE_BYTES))); u16 hw_tx_cons; @@ -3912,11 +3916,9 @@ struct bnx2 { struct sw_bd *rx_buf_ring; struct rx_bd *rx_desc_ring[MAX_RX_RINGS]; - /* TX constants */ - struct tx_bd *tx_desc_ring; - struct sw_bd *tx_buf_ring; - int tx_ring_size; - u32 tx_wake_thresh; + /* Only used to synchronize netif_stop_queue/wake_queue when tx */ + /* ring is full */ + spinlock_t tx_lock; /* End of fields used in the performance code paths. */ diff --git a/trunk/drivers/net/cassini.c b/trunk/drivers/net/cassini.c index 558fdb8ad2dc..a31544ccb3c4 100644 --- a/trunk/drivers/net/cassini.c +++ b/trunk/drivers/net/cassini.c @@ -2167,7 +2167,7 @@ static int cas_rx_process_pkt(struct cas *cp, struct cas_rx_comp *rxc, cas_page_unmap(addr); } skb->csum = ntohs(i ^ 0xffff); - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_HW; skb->protocol = eth_type_trans(skb, cp->dev); return len; } @@ -2821,7 +2821,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, } ctrl = 0; - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { u64 csum_start_off, csum_stuff_off; csum_start_off = (u64) (skb->h.raw - skb->data); diff --git a/trunk/drivers/net/chelsio/sge.c b/trunk/drivers/net/chelsio/sge.c index ddd0bdb498f4..61b3754f50ff 100644 --- a/trunk/drivers/net/chelsio/sge.c +++ b/trunk/drivers/net/chelsio/sge.c @@ -1470,9 +1470,9 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) } if (!(adapter->flags & UDP_CSUM_CAPABLE) && - skb->ip_summed == CHECKSUM_PARTIAL && + skb->ip_summed == CHECKSUM_HW && skb->nh.iph->protocol == IPPROTO_UDP) - if (unlikely(skb_checksum_help(skb))) { + if (unlikely(skb_checksum_help(skb, 0))) { dev_kfree_skb_any(skb); return NETDEV_TX_OK; } @@ -1495,11 +1495,11 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) cpl = (struct cpl_tx_pkt *)__skb_push(skb, sizeof(*cpl)); cpl->opcode = CPL_TX_PKT; cpl->ip_csum_dis = 1; /* SW calculates IP csum */ - cpl->l4_csum_dis = skb->ip_summed == CHECKSUM_PARTIAL ? 0 : 1; + cpl->l4_csum_dis = skb->ip_summed == CHECKSUM_HW ? 0 : 1; /* the length field isn't used so don't bother setting it */ - st->tx_cso += (skb->ip_summed == CHECKSUM_PARTIAL); - sge->stats.tx_do_cksum += (skb->ip_summed == CHECKSUM_PARTIAL); + st->tx_cso += (skb->ip_summed == CHECKSUM_HW); + sge->stats.tx_do_cksum += (skb->ip_summed == CHECKSUM_HW); sge->stats.tx_reg_pkts++; } cpl->iff = dev->if_port; diff --git a/trunk/drivers/net/cs89x0.c b/trunk/drivers/net/cs89x0.c index 2dcca79b1f6a..47eecce35fa4 100644 --- a/trunk/drivers/net/cs89x0.c +++ b/trunk/drivers/net/cs89x0.c @@ -1905,7 +1905,8 @@ MODULE_LICENSE("GPL"); */ -int __init init_module(void) +int +init_module(void) { struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); struct net_local *lp; diff --git a/trunk/drivers/net/dl2k.c b/trunk/drivers/net/dl2k.c index b74e67654764..402961e68c89 100644 --- a/trunk/drivers/net/dl2k.c +++ b/trunk/drivers/net/dl2k.c @@ -611,7 +611,7 @@ start_xmit (struct sk_buff *skb, struct net_device *dev) txdesc = &np->tx_ring[entry]; #if 0 - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { txdesc->status |= cpu_to_le64 (TCPChecksumEnable | UDPChecksumEnable | IPChecksumEnable); diff --git a/trunk/drivers/net/dm9000.c b/trunk/drivers/net/dm9000.c index a860ebbbf815..1b758b707134 100644 --- a/trunk/drivers/net/dm9000.c +++ b/trunk/drivers/net/dm9000.c @@ -339,17 +339,6 @@ static void dm9000_timeout(struct net_device *dev) spin_unlock_irqrestore(&db->lock,flags); } -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - *Used by netconsole - */ -static void dm9000_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - dm9000_interrupt(dev->irq,dev,NULL); - enable_irq(dev->irq); -} -#endif /* dm9000_release_board * @@ -377,8 +366,8 @@ dm9000_release_board(struct platform_device *pdev, struct board_info *db) kfree(db->data_req); } - if (db->addr_req != NULL) { - release_resource(db->addr_req); + if (db->addr_res != NULL) { + release_resource(db->addr_res); kfree(db->addr_req); } } @@ -549,9 +538,6 @@ dm9000_probe(struct platform_device *pdev) ndev->stop = &dm9000_stop; ndev->get_stats = &dm9000_get_stats; ndev->set_multicast_list = &dm9000_hash_table; -#ifdef CONFIG_NET_POLL_CONTROLLER - ndev->poll_controller = &dm9000_poll_controller; -#endif #ifdef DM9000_PROGRAM_EEPROM program_eeprom(db); diff --git a/trunk/drivers/net/e100.c b/trunk/drivers/net/e100.c index ce850f1078b5..91ef5f2fd768 100644 --- a/trunk/drivers/net/e100.c +++ b/trunk/drivers/net/e100.c @@ -173,11 +173,8 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); static int debug = 3; -static int eeprom_bad_csum_allow = 0; module_param(debug, int, 0); -module_param(eeprom_bad_csum_allow, int, 0); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -MODULE_PARM_DESC(eeprom_bad_csum_allow, "Allow bad eeprom checksums"); #define DPRINTK(nlevel, klevel, fmt, args...) \ (void)((NETIF_MSG_##nlevel & nic->msg_enable) && \ printk(KERN_##klevel PFX "%s: %s: " fmt, nic->netdev->name, \ @@ -759,8 +756,7 @@ static int e100_eeprom_load(struct nic *nic) checksum = le16_to_cpu(0xBABA - checksum); if(checksum != nic->eeprom[nic->eeprom_wc - 1]) { DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); - if (!eeprom_bad_csum_allow) - return -EAGAIN; + return -EAGAIN; } return 0; diff --git a/trunk/drivers/net/e1000/e1000_hw.c b/trunk/drivers/net/e1000/e1000_hw.c index b3b919116e0f..583518ae49ce 100644 --- a/trunk/drivers/net/e1000/e1000_hw.c +++ b/trunk/drivers/net/e1000/e1000_hw.c @@ -105,33 +105,6 @@ static int32_t e1000_configure_kmrn_for_10_100(struct e1000_hw *hw, uint16_t duplex); static int32_t e1000_configure_kmrn_for_1000(struct e1000_hw *hw); -static int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw, - uint32_t segment); -static int32_t e1000_get_software_flag(struct e1000_hw *hw); -static int32_t e1000_get_software_semaphore(struct e1000_hw *hw); -static int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw); -static int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw); -static int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, - uint16_t words, uint16_t *data); -static int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, - uint8_t* data); -static int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, - uint16_t *data); -static int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, - uint16_t *data); -static void e1000_release_software_flag(struct e1000_hw *hw); -static void e1000_release_software_semaphore(struct e1000_hw *hw); -static int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, - uint32_t no_snoop); -static int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw, - uint32_t index, uint8_t byte); -static int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, - uint16_t words, uint16_t *data); -static int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, - uint8_t data); -static int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, - uint16_t data); - /* IGP cable length table */ static const uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = @@ -3260,7 +3233,7 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw) return data; } -static int32_t +int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask) { uint32_t swfw_sync = 0; @@ -3304,7 +3277,7 @@ e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask) return E1000_SUCCESS; } -static void +void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask) { uint32_t swfw_sync; @@ -3602,7 +3575,7 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw, return E1000_SUCCESS; } -static int32_t +int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *data) @@ -3635,7 +3608,7 @@ e1000_read_kmrn_reg(struct e1000_hw *hw, return E1000_SUCCESS; } -static int32_t +int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data) @@ -3866,7 +3839,7 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw) * * hw - struct containing variables accessed by shared code ******************************************************************************/ -static int32_t +int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw) { int32_t ret_val; @@ -4113,7 +4086,7 @@ e1000_phy_igp_get_info(struct e1000_hw *hw, * hw - Struct containing variables accessed by shared code * phy_info - PHY information structure ******************************************************************************/ -static int32_t +int32_t e1000_phy_ife_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) { @@ -5670,7 +5643,6 @@ e1000_init_rx_addrs(struct e1000_hw *hw) * for the first 15 multicast addresses, and hashes the rest into the * multicast table. *****************************************************************************/ -#if 0 void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t *mc_addr_list, @@ -5747,7 +5719,6 @@ e1000_mc_addr_list_update(struct e1000_hw *hw, } DEBUGOUT("MC Update Complete\n"); } -#endif /* 0 */ /****************************************************************************** * Hashes an address to determine its location in the multicast table @@ -6616,7 +6587,6 @@ e1000_get_bus_info(struct e1000_hw *hw) * hw - Struct containing variables accessed by shared code * offset - offset to read from *****************************************************************************/ -#if 0 uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset) @@ -6627,7 +6597,6 @@ e1000_read_reg_io(struct e1000_hw *hw, e1000_io_write(hw, io_addr, offset); return e1000_io_read(hw, io_data); } -#endif /* 0 */ /****************************************************************************** * Writes a value to one of the devices registers using port I/O (as opposed to @@ -7940,7 +7909,6 @@ e1000_set_pci_express_master_disable(struct e1000_hw *hw) * returns: - none. * ***************************************************************************/ -#if 0 void e1000_enable_pciex_master(struct e1000_hw *hw) { @@ -7955,7 +7923,6 @@ e1000_enable_pciex_master(struct e1000_hw *hw) ctrl &= ~E1000_CTRL_GIO_MASTER_DISABLE; E1000_WRITE_REG(hw, CTRL, ctrl); } -#endif /* 0 */ /******************************************************************************* * @@ -8181,7 +8148,7 @@ e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw) * E1000_SUCCESS at any other case. * ***************************************************************************/ -static int32_t +int32_t e1000_get_software_semaphore(struct e1000_hw *hw) { int32_t timeout = hw->eeprom.word_size + 1; @@ -8216,7 +8183,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw) * hw: Struct containing variables accessed by shared code * ***************************************************************************/ -static void +void e1000_release_software_semaphore(struct e1000_hw *hw) { uint32_t swsm; @@ -8298,7 +8265,7 @@ e1000_arc_subsystem_valid(struct e1000_hw *hw) * returns: E1000_SUCCESS * *****************************************************************************/ -static int32_t +int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop) { uint32_t gcr_reg = 0; @@ -8339,7 +8306,7 @@ e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop) * hw: Struct containing variables accessed by shared code * ***************************************************************************/ -static int32_t +int32_t e1000_get_software_flag(struct e1000_hw *hw) { int32_t timeout = PHY_CFG_TIMEOUT; @@ -8378,7 +8345,7 @@ e1000_get_software_flag(struct e1000_hw *hw) * hw: Struct containing variables accessed by shared code * ***************************************************************************/ -static void +void e1000_release_software_flag(struct e1000_hw *hw) { uint32_t extcnf_ctrl; @@ -8402,7 +8369,6 @@ e1000_release_software_flag(struct e1000_hw *hw) * hw: Struct containing variables accessed by shared code * ***************************************************************************/ -#if 0 int32_t e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw) { @@ -8422,7 +8388,6 @@ e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw) return ret_val; } -#endif /* 0 */ /*************************************************************************** * @@ -8432,7 +8397,6 @@ e1000_ife_disable_dynamic_power_down(struct e1000_hw *hw) * hw: Struct containing variables accessed by shared code * ***************************************************************************/ -#if 0 int32_t e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw) { @@ -8452,7 +8416,6 @@ e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw) return ret_val; } -#endif /* 0 */ /****************************************************************************** * Reads a 16 bit word or words from the EEPROM using the ICH8's flash access @@ -8463,7 +8426,7 @@ e1000_ife_enable_dynamic_power_down(struct e1000_hw *hw) * data - word read from the EEPROM * words - number of words to read *****************************************************************************/ -static int32_t +int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data) { @@ -8519,7 +8482,7 @@ e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words, * words - number of words to write * data - words to write to the EEPROM *****************************************************************************/ -static int32_t +int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data) { @@ -8566,7 +8529,7 @@ e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, uint16_t words, * * hw - The pointer to the hw structure ****************************************************************************/ -static int32_t +int32_t e1000_ich8_cycle_init(struct e1000_hw *hw) { union ich8_hws_flash_status hsfsts; @@ -8633,7 +8596,7 @@ e1000_ich8_cycle_init(struct e1000_hw *hw) * * hw - The pointer to the hw structure ****************************************************************************/ -static int32_t +int32_t e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout) { union ich8_hws_flash_ctrl hsflctl; @@ -8668,7 +8631,7 @@ e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout) * size - Size of data to read, 1=byte 2=word * data - Pointer to the word to store the value read. *****************************************************************************/ -static int32_t +int32_t e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size, uint16_t* data) { @@ -8747,7 +8710,7 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index, * size - Size of data to read, 1=byte 2=word * data - The byte(s) to write to the NVM. *****************************************************************************/ -static int32_t +int32_t e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size, uint16_t data) { @@ -8822,7 +8785,7 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size, * index - The index of the byte to read. * data - Pointer to a byte to store the value read. *****************************************************************************/ -static int32_t +int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data) { int32_t status = E1000_SUCCESS; @@ -8845,7 +8808,7 @@ e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t* data) * index - The index of the byte to write. * byte - The byte to write to the NVM. *****************************************************************************/ -static int32_t +int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte) { int32_t error = E1000_SUCCESS; @@ -8876,7 +8839,7 @@ e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t byte) * index - The index of the byte to read. * data - The byte to write to the NVM. *****************************************************************************/ -static int32_t +int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data) { int32_t status = E1000_SUCCESS; @@ -8894,7 +8857,7 @@ e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, uint8_t data) * index - The starting byte index of the word to read. * data - Pointer to a word to store the value read. *****************************************************************************/ -static int32_t +int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data) { int32_t status = E1000_SUCCESS; @@ -8909,7 +8872,6 @@ e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t *data) * index - The starting byte index of the word to read. * data - The word to write to the NVM. *****************************************************************************/ -#if 0 int32_t e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data) { @@ -8917,7 +8879,6 @@ e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data) status = e1000_write_ich8_data(hw, index, 2, data); return status; } -#endif /* 0 */ /****************************************************************************** * Erases the bank specified. Each bank is a 4k block. Segments are 0 based. @@ -8926,7 +8887,7 @@ e1000_write_ich8_word(struct e1000_hw *hw, uint32_t index, uint16_t data) * hw - pointer to e1000_hw structure * segment - 0 for first segment, 1 for second segment, etc. *****************************************************************************/ -static int32_t +int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment) { union ich8_hws_flash_status hsfsts; @@ -9023,7 +8984,6 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment) * hw: Struct containing variables accessed by shared code * *****************************************************************************/ -#if 0 int32_t e1000_duplex_reversal(struct e1000_hw *hw) { @@ -9052,9 +9012,8 @@ e1000_duplex_reversal(struct e1000_hw *hw) return ret_val; } -#endif /* 0 */ -static int32_t +int32_t e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size) { @@ -9088,7 +9047,7 @@ e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, } -static int32_t +int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw) { uint32_t reg_data, cnf_base_addr, cnf_size, ret_val, loop; diff --git a/trunk/drivers/net/e1000/e1000_hw.h b/trunk/drivers/net/e1000/e1000_hw.h index 375b95518c31..f9341e3276b3 100644 --- a/trunk/drivers/net/e1000/e1000_hw.h +++ b/trunk/drivers/net/e1000/e1000_hw.h @@ -323,8 +323,13 @@ int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t dat int32_t e1000_phy_hw_reset(struct e1000_hw *hw); int32_t e1000_phy_reset(struct e1000_hw *hw); void e1000_phy_powerdown_workaround(struct e1000_hw *hw); +int32_t e1000_kumeran_lock_loss_workaround(struct e1000_hw *hw); +int32_t e1000_init_lcd_from_nvm_config_region(struct e1000_hw *hw, uint32_t cnf_base_addr, uint32_t cnf_size); +int32_t e1000_init_lcd_from_nvm(struct e1000_hw *hw); int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); int32_t e1000_validate_mdi_setting(struct e1000_hw *hw); +int32_t e1000_read_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *data); +int32_t e1000_write_kmrn_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data); /* EEPROM Functions */ int32_t e1000_init_eeprom_params(struct e1000_hw *hw); @@ -395,8 +400,13 @@ int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw); int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data); int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num); int32_t e1000_read_mac_addr(struct e1000_hw * hw); +int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask); +void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask); +void e1000_release_software_flag(struct e1000_hw *hw); +int32_t e1000_get_software_flag(struct e1000_hw *hw); /* Filters (multicast, vlan, receive) */ +void e1000_mc_addr_list_update(struct e1000_hw *hw, uint8_t * mc_addr_list, uint32_t mc_addr_count, uint32_t pad, uint32_t rar_used_count); uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, uint8_t * mc_addr); void e1000_mta_set(struct e1000_hw *hw, uint32_t hash_value); void e1000_rar_set(struct e1000_hw *hw, uint8_t * mc_addr, uint32_t rar_index); @@ -421,9 +431,31 @@ void e1000_pci_clear_mwi(struct e1000_hw *hw); void e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); void e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t * value); /* Port I/O is only supported on 82544 and newer */ +uint32_t e1000_io_read(struct e1000_hw *hw, unsigned long port); +uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset); void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value); +void e1000_enable_pciex_master(struct e1000_hw *hw); int32_t e1000_disable_pciex_master(struct e1000_hw *hw); +int32_t e1000_get_software_semaphore(struct e1000_hw *hw); +void e1000_release_software_semaphore(struct e1000_hw *hw); int32_t e1000_check_phy_reset_block(struct e1000_hw *hw); +int32_t e1000_set_pci_ex_no_snoop(struct e1000_hw *hw, uint32_t no_snoop); + +int32_t e1000_read_ich8_byte(struct e1000_hw *hw, uint32_t index, + uint8_t *data); +int32_t e1000_verify_write_ich8_byte(struct e1000_hw *hw, uint32_t index, + uint8_t byte); +int32_t e1000_write_ich8_byte(struct e1000_hw *hw, uint32_t index, + uint8_t byte); +int32_t e1000_read_ich8_word(struct e1000_hw *hw, uint32_t index, + uint16_t *data); +int32_t e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index, + uint32_t size, uint16_t *data); +int32_t e1000_read_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, + uint16_t words, uint16_t *data); +int32_t e1000_write_eeprom_ich8(struct e1000_hw *hw, uint16_t offset, + uint16_t words, uint16_t *data); +int32_t e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t segment); #define E1000_READ_REG_IO(a, reg) \ diff --git a/trunk/drivers/net/e1000/e1000_main.c b/trunk/drivers/net/e1000/e1000_main.c index 2ab9f96f5dab..da62db897426 100644 --- a/trunk/drivers/net/e1000/e1000_main.c +++ b/trunk/drivers/net/e1000/e1000_main.c @@ -1433,8 +1433,8 @@ e1000_configure_tx(struct e1000_adapter *adapter) E1000_WRITE_REG(hw, TDBAL, (tdba & 0x00000000ffffffffULL)); E1000_WRITE_REG(hw, TDT, 0); E1000_WRITE_REG(hw, TDH, 0); - adapter->tx_ring[0].tdh = ((hw->mac_type >= e1000_82543) ? E1000_TDH : E1000_82542_TDH); - adapter->tx_ring[0].tdt = ((hw->mac_type >= e1000_82543) ? E1000_TDT : E1000_82542_TDT); + adapter->tx_ring[0].tdh = E1000_TDH; + adapter->tx_ring[0].tdt = E1000_TDT; break; } @@ -1840,8 +1840,8 @@ e1000_configure_rx(struct e1000_adapter *adapter) E1000_WRITE_REG(hw, RDBAL, (rdba & 0x00000000ffffffffULL)); E1000_WRITE_REG(hw, RDT, 0); E1000_WRITE_REG(hw, RDH, 0); - adapter->rx_ring[0].rdh = ((hw->mac_type >= e1000_82543) ? E1000_RDH : E1000_82542_RDH); - adapter->rx_ring[0].rdt = ((hw->mac_type >= e1000_82543) ? E1000_RDT : E1000_82542_RDT); + adapter->rx_ring[0].rdh = E1000_RDH; + adapter->rx_ring[0].rdt = E1000_RDT; break; } @@ -2600,7 +2600,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, unsigned int i; uint8_t css; - if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { + if (likely(skb->ip_summed == CHECKSUM_HW)) { css = skb->h.raw - skb->data; i = tx_ring->next_to_use; @@ -2927,11 +2927,11 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) } /* reserve a descriptor for the offload context */ - if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL)) + if ((mss) || (skb->ip_summed == CHECKSUM_HW)) count++; count++; #else - if (skb->ip_summed == CHECKSUM_PARTIAL) + if (skb->ip_summed == CHECKSUM_HW) count++; #endif @@ -3127,7 +3127,7 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu) break; } - /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN + /* NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN * means we reserve 2 more, this pushes us to allocate from the next * larger slab size * i.e. RXBUFFER_2048 --> size-4096 slab */ @@ -3608,7 +3608,7 @@ e1000_rx_checksum(struct e1000_adapter *adapter, */ csum = ntohl(csum ^ 0xFFFF); skb->csum = csum; - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_HW; } adapter->hw_csum_good++; } @@ -3708,7 +3708,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, #define E1000_CB_LENGTH 256 if (length < E1000_CB_LENGTH) { struct sk_buff *new_skb = - netdev_alloc_skb(netdev, length + NET_IP_ALIGN); + dev_alloc_skb(length + NET_IP_ALIGN); if (new_skb) { skb_reserve(new_skb, NET_IP_ALIGN); new_skb->dev = netdev; @@ -3979,7 +3979,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter, while (cleaned_count--) { if (!(skb = buffer_info->skb)) - skb = netdev_alloc_skb(netdev, bufsz); + skb = dev_alloc_skb(bufsz); else { skb_trim(skb, 0); goto map_skb; @@ -3997,7 +3997,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter, DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes " "at %p\n", bufsz, skb->data); /* Try again, without freeing the previous */ - skb = netdev_alloc_skb(netdev, bufsz); + skb = dev_alloc_skb(bufsz); /* Failed allocation, critical failure */ if (!skb) { dev_kfree_skb(oldskb); @@ -4121,8 +4121,7 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, rx_desc->read.buffer_addr[j+1] = ~0; } - skb = netdev_alloc_skb(netdev, - adapter->rx_ps_bsize0 + NET_IP_ALIGN); + skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN); if (unlikely(!skb)) { adapter->alloc_rx_buff_failed++; @@ -4386,13 +4385,11 @@ e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) pci_write_config_word(adapter->pdev, reg, *value); } -#if 0 uint32_t e1000_io_read(struct e1000_hw *hw, unsigned long port) { return inl(port); } -#endif /* 0 */ void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value) diff --git a/trunk/drivers/net/e2100.c b/trunk/drivers/net/e2100.c index e4e733a380e3..e5c5cd2a2712 100644 --- a/trunk/drivers/net/e2100.c +++ b/trunk/drivers/net/e2100.c @@ -425,8 +425,8 @@ MODULE_LICENSE("GPL"); /* This is set up so that only a single autoprobe takes place per call. ISA device autoprobes on a running machine are not recommended. */ - -int __init init_module(void) +int +init_module(void) { struct net_device *dev; int this_dev, found = 0; diff --git a/trunk/drivers/net/eepro.c b/trunk/drivers/net/eepro.c index 8dc61d65dd23..20d31430c74f 100644 --- a/trunk/drivers/net/eepro.c +++ b/trunk/drivers/net/eepro.c @@ -1807,7 +1807,8 @@ MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)"); MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)"); MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)"); -int __init init_module(void) +int +init_module(void) { struct net_device *dev; int i; diff --git a/trunk/drivers/net/eexpress.c b/trunk/drivers/net/eexpress.c index 0701c1d810ca..33291bcf6d4c 100644 --- a/trunk/drivers/net/eexpress.c +++ b/trunk/drivers/net/eexpress.c @@ -1698,7 +1698,7 @@ MODULE_LICENSE("GPL"); * are specified, we verify and then use them. If no parameters are given, we * autoprobe for one card only. */ -int __init init_module(void) +int init_module(void) { struct net_device *dev; int this_dev, found = 0; diff --git a/trunk/drivers/net/es3210.c b/trunk/drivers/net/es3210.c index fd7b32a24ea4..6b0ab1eac3fb 100644 --- a/trunk/drivers/net/es3210.c +++ b/trunk/drivers/net/es3210.c @@ -421,7 +421,8 @@ MODULE_PARM_DESC(mem, "memory base address(es)"); MODULE_DESCRIPTION("Racal-Interlan ES3210 EISA ethernet driver"); MODULE_LICENSE("GPL"); -int __init init_module(void) +int +init_module(void) { struct net_device *dev; int this_dev, found = 0; diff --git a/trunk/drivers/net/eth16i.c b/trunk/drivers/net/eth16i.c index ca42efa9143c..4bf76f86d8e9 100644 --- a/trunk/drivers/net/eth16i.c +++ b/trunk/drivers/net/eth16i.c @@ -1434,7 +1434,7 @@ MODULE_PARM_DESC(mediatype, "eth16i media type of interface(s) (bnc,tp,dix,auto, module_param(debug, int, 0); MODULE_PARM_DESC(debug, "eth16i debug level (0-6)"); -int __init init_module(void) +int init_module(void) { int this_dev, found = 0; struct net_device *dev; diff --git a/trunk/drivers/net/fealnx.c b/trunk/drivers/net/fealnx.c index 567e27413cfd..97d34fee8c1f 100644 --- a/trunk/drivers/net/fealnx.c +++ b/trunk/drivers/net/fealnx.c @@ -92,7 +92,7 @@ static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 }; #include /* These identify the driver base version and may not be removed. */ -static char version[] = +static char version[] __devinitdata = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "\n"; diff --git a/trunk/drivers/net/forcedeth.c b/trunk/drivers/net/forcedeth.c index 32cacf115f75..11b8f1b43dd5 100644 --- a/trunk/drivers/net/forcedeth.c +++ b/trunk/drivers/net/forcedeth.c @@ -1503,8 +1503,7 @@ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT); else #endif - tx_flags_extra = skb->ip_summed == CHECKSUM_PARTIAL ? - NV_TX2_CHECKSUM_L3 | NV_TX2_CHECKSUM_L4 : 0; + tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0); /* vlan tag */ if (np->vlangrp && vlan_tx_tag_present(skb)) { diff --git a/trunk/drivers/net/fs_enet/Makefile b/trunk/drivers/net/fs_enet/Makefile index 02d4dc18ba69..d6dd3f2fb43e 100644 --- a/trunk/drivers/net/fs_enet/Makefile +++ b/trunk/drivers/net/fs_enet/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_FS_ENET) += fs_enet.o -obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o mii-fec.o -obj-$(CONFIG_CPM2) += mac-fcc.o mii-bitbang.o +obj-$(CONFIG_8xx) += mac-fec.o mac-scc.o +obj-$(CONFIG_8260) += mac-fcc.o -fs_enet-objs := fs_enet-main.o +fs_enet-objs := fs_enet-main.o fs_enet-mii.o mii-bitbang.o mii-fixed.o diff --git a/trunk/drivers/net/fs_enet/fec.h b/trunk/drivers/net/fs_enet/fec.h deleted file mode 100644 index e980527e2b99..000000000000 --- a/trunk/drivers/net/fs_enet/fec.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef FS_ENET_FEC_H -#define FS_ENET_FEC_H - -/* CRC polynomium used by the FEC for the multicast group filtering */ -#define FEC_CRC_POLY 0x04C11DB7 - -#define FEC_MAX_MULTICAST_ADDRS 64 - -/* Interrupt events/masks. -*/ -#define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */ -#define FEC_ENET_BABR 0x40000000U /* Babbling receiver */ -#define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */ -#define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */ -#define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */ -#define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */ -#define FEC_ENET_RXF 0x02000000U /* Full frame received */ -#define FEC_ENET_RXB 0x01000000U /* A buffer was received */ -#define FEC_ENET_MII 0x00800000U /* MII interrupt */ -#define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */ - -#define FEC_ECNTRL_PINMUX 0x00000004 -#define FEC_ECNTRL_ETHER_EN 0x00000002 -#define FEC_ECNTRL_RESET 0x00000001 - -#define FEC_RCNTRL_BC_REJ 0x00000010 -#define FEC_RCNTRL_PROM 0x00000008 -#define FEC_RCNTRL_MII_MODE 0x00000004 -#define FEC_RCNTRL_DRT 0x00000002 -#define FEC_RCNTRL_LOOP 0x00000001 - -#define FEC_TCNTRL_FDEN 0x00000004 -#define FEC_TCNTRL_HBC 0x00000002 -#define FEC_TCNTRL_GTS 0x00000001 - - - -/* - * Delay to wait for FEC reset command to complete (in us) - */ -#define FEC_RESET_DELAY 50 -#endif diff --git a/trunk/drivers/net/fs_enet/fs_enet-main.c b/trunk/drivers/net/fs_enet/fs_enet-main.c index df62506a1787..f6abff5846b3 100644 --- a/trunk/drivers/net/fs_enet/fs_enet-main.c +++ b/trunk/drivers/net/fs_enet/fs_enet-main.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include @@ -683,6 +682,35 @@ static void fs_free_irq(struct net_device *dev, int irq) (*fep->ops->post_free_irq)(dev, irq); } +/**********************************************************************************/ + +/* This interrupt occurs when the PHY detects a link change. */ +static irqreturn_t +fs_mii_link_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + struct fs_enet_private *fep; + const struct fs_platform_info *fpi; + + fep = netdev_priv(dev); + fpi = fep->fpi; + + /* + * Acknowledge the interrupt if possible. If we have not + * found the PHY yet we can't process or acknowledge the + * interrupt now. Instead we ignore this interrupt for now, + * which we can do since it is edge triggered. It will be + * acknowledged later by fs_enet_open(). + */ + if (!fep->phy) + return IRQ_NONE; + + fs_mii_ack_int(dev); + fs_mii_link_status_change_check(dev, 0); + + return IRQ_HANDLED; +} + static void fs_timeout(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); @@ -694,13 +722,10 @@ static void fs_timeout(struct net_device *dev) spin_lock_irqsave(&fep->lock, flags); if (dev->flags & IFF_UP) { - phy_stop(fep->phydev); (*fep->ops->stop)(dev); (*fep->ops->restart)(dev); - phy_start(fep->phydev); } - phy_start(fep->phydev); wake = fep->tx_free && !(CBDR_SC(fep->cur_tx) & BD_ENET_TX_READY); spin_unlock_irqrestore(&fep->lock, flags); @@ -708,112 +733,35 @@ static void fs_timeout(struct net_device *dev) netif_wake_queue(dev); } -/*----------------------------------------------------------------------------- - * generic link-change handler - should be sufficient for most cases - *-----------------------------------------------------------------------------*/ -static void generic_adjust_link(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct phy_device *phydev = fep->phydev; - int new_state = 0; - - if (phydev->link) { - - /* adjust to duplex mode */ - if (phydev->duplex != fep->oldduplex){ - new_state = 1; - fep->oldduplex = phydev->duplex; - } - - if (phydev->speed != fep->oldspeed) { - new_state = 1; - fep->oldspeed = phydev->speed; - } - - if (!fep->oldlink) { - new_state = 1; - fep->oldlink = 1; - netif_schedule(dev); - netif_carrier_on(dev); - netif_start_queue(dev); - } - - if (new_state) - fep->ops->restart(dev); - - } else if (fep->oldlink) { - new_state = 1; - fep->oldlink = 0; - fep->oldspeed = 0; - fep->oldduplex = -1; - netif_carrier_off(dev); - netif_stop_queue(dev); - } - - if (new_state && netif_msg_link(fep)) - phy_print_status(phydev); -} - - -static void fs_adjust_link(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&fep->lock, flags); - - if(fep->ops->adjust_link) - fep->ops->adjust_link(dev); - else - generic_adjust_link(dev); - - spin_unlock_irqrestore(&fep->lock, flags); -} - -static int fs_init_phy(struct net_device *dev) -{ - struct fs_enet_private *fep = netdev_priv(dev); - struct phy_device *phydev; - - fep->oldlink = 0; - fep->oldspeed = 0; - fep->oldduplex = -1; - if(fep->fpi->bus_id) - phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0); - else { - printk("No phy bus ID specified in BSP code\n"); - return -EINVAL; - } - if (IS_ERR(phydev)) { - printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); - return PTR_ERR(phydev); - } - - fep->phydev = phydev; - - return 0; -} - - static int fs_enet_open(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); + const struct fs_platform_info *fpi = fep->fpi; int r; - int err; /* Install our interrupt handler. */ r = fs_request_irq(dev, fep->interrupt, "fs_enet-mac", fs_enet_interrupt); if (r != 0) { printk(KERN_ERR DRV_MODULE_NAME - ": %s Could not allocate FS_ENET IRQ!", dev->name); + ": %s Could not allocate FEC IRQ!", dev->name); return -EINVAL; } - err = fs_init_phy(dev); - if(err) - return err; + /* Install our phy interrupt handler */ + if (fpi->phy_irq != -1) { + + r = fs_request_irq(dev, fpi->phy_irq, "fs_enet-phy", fs_mii_link_interrupt); + if (r != 0) { + printk(KERN_ERR DRV_MODULE_NAME + ": %s Could not allocate PHY IRQ!", dev->name); + fs_free_irq(dev, fep->interrupt); + return -EINVAL; + } + } - phy_start(fep->phydev); + fs_mii_startup(dev); + netif_carrier_off(dev); + fs_mii_link_status_change_check(dev, 1); return 0; } @@ -821,19 +769,20 @@ static int fs_enet_open(struct net_device *dev) static int fs_enet_close(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); + const struct fs_platform_info *fpi = fep->fpi; unsigned long flags; netif_stop_queue(dev); netif_carrier_off(dev); - phy_stop(fep->phydev); + fs_mii_shutdown(dev); spin_lock_irqsave(&fep->lock, flags); (*fep->ops->stop)(dev); spin_unlock_irqrestore(&fep->lock, flags); /* release any irqs */ - phy_disconnect(fep->phydev); - fep->phydev = NULL; + if (fpi->phy_irq != -1) + fs_free_irq(dev, fpi->phy_irq); fs_free_irq(dev, fep->interrupt); return 0; @@ -881,19 +830,33 @@ static void fs_get_regs(struct net_device *dev, struct ethtool_regs *regs, static int fs_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct fs_enet_private *fep = netdev_priv(dev); - return phy_ethtool_gset(fep->phydev, cmd); + unsigned long flags; + int rc; + + spin_lock_irqsave(&fep->lock, flags); + rc = mii_ethtool_gset(&fep->mii_if, cmd); + spin_unlock_irqrestore(&fep->lock, flags); + + return rc; } static int fs_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) { struct fs_enet_private *fep = netdev_priv(dev); - phy_ethtool_sset(fep->phydev, cmd); - return 0; + unsigned long flags; + int rc; + + spin_lock_irqsave(&fep->lock, flags); + rc = mii_ethtool_sset(&fep->mii_if, cmd); + spin_unlock_irqrestore(&fep->lock, flags); + + return rc; } static int fs_nway_reset(struct net_device *dev) { - return 0; + struct fs_enet_private *fep = netdev_priv(dev); + return mii_nway_restart(&fep->mii_if); } static u32 fs_get_msglevel(struct net_device *dev) @@ -935,7 +898,7 @@ static int fs_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return -EINVAL; spin_lock_irqsave(&fep->lock, flags); - rc = phy_mii_ioctl(fep->phydev, mii, cmd); + rc = generic_mii_ioctl(&fep->mii_if, mii, cmd, NULL); spin_unlock_irqrestore(&fep->lock, flags); return rc; } @@ -1067,6 +1030,12 @@ static struct net_device *fs_init_instance(struct device *dev, } registered = 1; + err = fs_mii_connect(ndev); + if (err != 0) { + printk(KERN_ERR DRV_MODULE_NAME + ": %s fs_mii_connect failed.\n", ndev->name); + goto err; + } return ndev; @@ -1104,6 +1073,8 @@ static int fs_cleanup_instance(struct net_device *ndev) fpi = fep->fpi; + fs_mii_disconnect(ndev); + unregister_netdev(ndev); dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring) * sizeof(cbd_t), @@ -1225,39 +1196,17 @@ static int __init fs_init(void) r = setup_immap(); if (r != 0) return r; - -#ifdef CONFIG_FS_ENET_HAS_FCC - /* let's insert mii stuff */ - r = fs_enet_mdio_bb_init(); - - if (r != 0) { - printk(KERN_ERR DRV_MODULE_NAME - "BB PHY init failed.\n"); - return r; - } - r = driver_register(&fs_enet_fcc_driver); + r = driver_register(&fs_enet_fec_driver); if (r != 0) goto err; -#endif -#ifdef CONFIG_FS_ENET_HAS_FEC - r = fs_enet_mdio_fec_init(); - if (r != 0) { - printk(KERN_ERR DRV_MODULE_NAME - "FEC PHY init failed.\n"); - return r; - } - - r = driver_register(&fs_enet_fec_driver); + r = driver_register(&fs_enet_fcc_driver); if (r != 0) goto err; -#endif -#ifdef CONFIG_FS_ENET_HAS_SCC r = driver_register(&fs_enet_scc_driver); if (r != 0) goto err; -#endif return 0; err: diff --git a/trunk/drivers/net/fs_enet/fs_enet-mii.c b/trunk/drivers/net/fs_enet/fs_enet-mii.c new file mode 100644 index 000000000000..b7e6e21725cb --- /dev/null +++ b/trunk/drivers/net/fs_enet/fs_enet-mii.c @@ -0,0 +1,505 @@ +/* + * Combined Ethernet driver for Motorola MPC8xx and MPC82xx. + * + * Copyright (c) 2003 Intracom S.A. + * by Pantelis Antoniou + * + * 2005 (c) MontaVista Software, Inc. + * Vitaly Bordug + * + * Heavily based on original FEC driver by Dan Malek + * and modifications by Joakim Tjernlund + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "fs_enet.h" + +/*************************************************/ + +/* + * Generic PHY support. + * Should work for all PHYs, but link change is detected by polling + */ + +static void generic_timer_callback(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + struct fs_enet_private *fep = netdev_priv(dev); + + fep->phy_timer_list.expires = jiffies + HZ / 2; + + add_timer(&fep->phy_timer_list); + + fs_mii_link_status_change_check(dev, 0); +} + +static void generic_startup(struct net_device *dev) +{ + struct fs_enet_private *fep = netdev_priv(dev); + + fep->phy_timer_list.expires = jiffies + HZ / 2; /* every 500ms */ + fep->phy_timer_list.data = (unsigned long)dev; + fep->phy_timer_list.function = generic_timer_callback; + add_timer(&fep->phy_timer_list); +} + +static void generic_shutdown(struct net_device *dev) +{ + struct fs_enet_private *fep = netdev_priv(dev); + + del_timer_sync(&fep->phy_timer_list); +} + +/* ------------------------------------------------------------------------- */ +/* The Davicom DM9161 is used on the NETTA board */ + +/* register definitions */ + +#define MII_DM9161_ANAR 4 /* Aux. Config Register */ +#define MII_DM9161_ACR 16 /* Aux. Config Register */ +#define MII_DM9161_ACSR 17 /* Aux. Config/Status Register */ +#define MII_DM9161_10TCSR 18 /* 10BaseT Config/Status Reg. */ +#define MII_DM9161_INTR 21 /* Interrupt Register */ +#define MII_DM9161_RECR 22 /* Receive Error Counter Reg. */ +#define MII_DM9161_DISCR 23 /* Disconnect Counter Register */ + +static void dm9161_startup(struct net_device *dev) +{ + struct fs_enet_private *fep = netdev_priv(dev); + + fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0000); + /* Start autonegotiation */ + fs_mii_write(dev, fep->mii_if.phy_id, MII_BMCR, 0x1200); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ*8); +} + +static void dm9161_ack_int(struct net_device *dev) +{ + struct fs_enet_private *fep = netdev_priv(dev); + + fs_mii_read(dev, fep->mii_if.phy_id, MII_DM9161_INTR); +} + +static void dm9161_shutdown(struct net_device *dev) +{ + struct fs_enet_private *fep = netdev_priv(dev); + + fs_mii_write(dev, fep->mii_if.phy_id, MII_DM9161_INTR, 0x0f00); +} + +/**********************************************************************************/ + +static const struct phy_info phy_info[] = { + { + .id = 0x00181b88, + .name = "DM9161", + .startup = dm9161_startup, + .ack_int = dm9161_ack_int, + .shutdown = dm9161_shutdown, + }, { + .id = 0, + .name = "GENERIC", + .startup = generic_startup, + .shutdown = generic_shutdown, + }, +}; + +/**********************************************************************************/ + +static int phy_id_detect(struct net_device *dev) +{ + struct fs_enet_private *fep = netdev_priv(dev); + const struct fs_platform_info *fpi = fep->fpi; + struct fs_enet_mii_bus *bus = fep->mii_bus; + int i, r, start, end, phytype, physubtype; + const struct phy_info *phy; + int phy_hwid, phy_id; + + phy_hwid = -1; + fep->phy = NULL; + + /* auto-detect? */ + if (fpi->phy_addr == -1) { + start = 1; + end = 32; + } else { /* direct */ + start = fpi->phy_addr; + end = start + 1; + } + + for (phy_id = start; phy_id < end; phy_id++) { + /* skip already used phy addresses on this bus */ + if (bus->usage_map & (1 << phy_id)) + continue; + r = fs_mii_read(dev, phy_id, MII_PHYSID1); + if (r == -1 || (phytype = (r & 0xffff)) == 0xffff) + continue; + r = fs_mii_read(dev, phy_id, MII_PHYSID2); + if (r == -1 || (physubtype = (r & 0xffff)) == 0xffff) + continue; + phy_hwid = (phytype << 16) | physubtype; + if (phy_hwid != -1) + break; + } + + if (phy_hwid == -1) { + printk(KERN_ERR DRV_MODULE_NAME + ": %s No PHY detected! range=0x%02x-0x%02x\n", + dev->name, start, end); + return -1; + } + + for (i = 0, phy = phy_info; i < ARRAY_SIZE(phy_info); i++, phy++) + if (phy->id == (phy_hwid >> 4) || phy->id == 0) + break; + + if (i >= ARRAY_SIZE(phy_info)) { + printk(KERN_ERR DRV_MODULE_NAME + ": %s PHY id 0x%08x is not supported!\n", + dev->name, phy_hwid); + return -1; + } + + fep->phy = phy; + + /* mark this address as used */ + bus->usage_map |= (1 << phy_id); + + printk(KERN_INFO DRV_MODULE_NAME + ": %s Phy @ 0x%x, type %s (0x%08x)%s\n", + dev->name, phy_id, fep->phy->name, phy_hwid, + fpi->phy_addr == -1 ? " (auto-detected)" : ""); + + return phy_id; +} + +void fs_mii_startup(struct net_device *dev) +{ + struct fs_enet_private *fep = netdev_priv(dev); + + if (fep->phy->startup) + (*fep->phy->startup) (dev); +} + +void fs_mii_shutdown(struct net_device *dev) +{ + struct fs_enet_private *fep = netdev_priv(dev); + + if (fep->phy->shutdown) + (*fep->phy->shutdown) (dev); +} + +void fs_mii_ack_int(struct net_device *dev) +{ + struct fs_enet_private *fep = netdev_priv(dev); + + if (fep->phy->ack_int) + (*fep->phy->ack_int) (dev); +} + +#define MII_LINK 0x0001 +#define MII_HALF 0x0002 +#define MII_FULL 0x0004 +#define MII_BASE4 0x0008 +#define MII_10M 0x0010 +#define MII_100M 0x0020 +#define MII_1G 0x0040 +#define MII_10G 0x0080 + +/* return full mii info at one gulp, with a usable form */ +static unsigned int mii_full_status(struct mii_if_info *mii) +{ + unsigned int status; + int bmsr, adv, lpa, neg; + struct fs_enet_private* fep = netdev_priv(mii->dev); + + /* first, a dummy read, needed to latch some MII phys */ + (void)mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); + bmsr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); + + /* no link */ + if ((bmsr & BMSR_LSTATUS) == 0) + return 0; + + status = MII_LINK; + + /* Lets look what ANEG says if it's supported - otherwize we shall + take the right values from the platform info*/ + if(!mii->force_media) { + /* autoneg not completed; don't bother */ + if ((bmsr & BMSR_ANEGCOMPLETE) == 0) + return 0; + + adv = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_ADVERTISE); + lpa = (*mii->mdio_read)(mii->dev, mii->phy_id, MII_LPA); + + neg = lpa & adv; + } else { + neg = fep->fpi->bus_info->lpa; + } + + if (neg & LPA_100FULL) + status |= MII_FULL | MII_100M; + else if (neg & LPA_100BASE4) + status |= MII_FULL | MII_BASE4 | MII_100M; + else if (neg & LPA_100HALF) + status |= MII_HALF | MII_100M; + else if (neg & LPA_10FULL) + status |= MII_FULL | MII_10M; + else + status |= MII_HALF | MII_10M; + + return status; +} + +void fs_mii_link_status_change_check(struct net_device *dev, int init_media) +{ + struct fs_enet_private *fep = netdev_priv(dev); + struct mii_if_info *mii = &fep->mii_if; + unsigned int mii_status; + int ok_to_print, link, duplex, speed; + unsigned long flags; + + ok_to_print = netif_msg_link(fep); + + mii_status = mii_full_status(mii); + + if (!init_media && mii_status == fep->last_mii_status) + return; + + fep->last_mii_status = mii_status; + + link = !!(mii_status & MII_LINK); + duplex = !!(mii_status & MII_FULL); + speed = (mii_status & MII_100M) ? 100 : 10; + + if (link == 0) { + netif_carrier_off(mii->dev); + netif_stop_queue(dev); + if (!init_media) { + spin_lock_irqsave(&fep->lock, flags); + (*fep->ops->stop)(dev); + spin_unlock_irqrestore(&fep->lock, flags); + } + + if (ok_to_print) + printk(KERN_INFO "%s: link down\n", mii->dev->name); + + } else { + + mii->full_duplex = duplex; + + netif_carrier_on(mii->dev); + + spin_lock_irqsave(&fep->lock, flags); + fep->duplex = duplex; + fep->speed = speed; + (*fep->ops->restart)(dev); + spin_unlock_irqrestore(&fep->lock, flags); + + netif_start_queue(dev); + + if (ok_to_print) + printk(KERN_INFO "%s: link up, %dMbps, %s-duplex\n", + dev->name, speed, duplex ? "full" : "half"); + } +} + +/**********************************************************************************/ + +int fs_mii_read(struct net_device *dev, int phy_id, int location) +{ + struct fs_enet_private *fep = netdev_priv(dev); + struct fs_enet_mii_bus *bus = fep->mii_bus; + + unsigned long flags; + int ret; + + spin_lock_irqsave(&bus->mii_lock, flags); + ret = (*bus->mii_read)(bus, phy_id, location); + spin_unlock_irqrestore(&bus->mii_lock, flags); + + return ret; +} + +void fs_mii_write(struct net_device *dev, int phy_id, int location, int value) +{ + struct fs_enet_private *fep = netdev_priv(dev); + struct fs_enet_mii_bus *bus = fep->mii_bus; + unsigned long flags; + + spin_lock_irqsave(&bus->mii_lock, flags); + (*bus->mii_write)(bus, phy_id, location, value); + spin_unlock_irqrestore(&bus->mii_lock, flags); +} + +/*****************************************************************************/ + +/* list of all registered mii buses */ +static LIST_HEAD(fs_mii_bus_list); + +static struct fs_enet_mii_bus *lookup_bus(int method, int id) +{ + struct list_head *ptr; + struct fs_enet_mii_bus *bus; + + list_for_each(ptr, &fs_mii_bus_list) { + bus = list_entry(ptr, struct fs_enet_mii_bus, list); + if (bus->bus_info->method == method && + bus->bus_info->id == id) + return bus; + } + return NULL; +} + +static struct fs_enet_mii_bus *create_bus(const struct fs_mii_bus_info *bi) +{ + struct fs_enet_mii_bus *bus; + int ret = 0; + + bus = kmalloc(sizeof(*bus), GFP_KERNEL); + if (bus == NULL) { + ret = -ENOMEM; + goto err; + } + memset(bus, 0, sizeof(*bus)); + spin_lock_init(&bus->mii_lock); + bus->bus_info = bi; + bus->refs = 0; + bus->usage_map = 0; + + /* perform initialization */ + switch (bi->method) { + + case fsmii_fixed: + ret = fs_mii_fixed_init(bus); + if (ret != 0) + goto err; + break; + + case fsmii_bitbang: + ret = fs_mii_bitbang_init(bus); + if (ret != 0) + goto err; + break; +#ifdef CONFIG_FS_ENET_HAS_FEC + case fsmii_fec: + ret = fs_mii_fec_init(bus); + if (ret != 0) + goto err; + break; +#endif + default: + ret = -EINVAL; + goto err; + } + + list_add(&bus->list, &fs_mii_bus_list); + + return bus; + +err: + kfree(bus); + return ERR_PTR(ret); +} + +static void destroy_bus(struct fs_enet_mii_bus *bus) +{ + /* remove from bus list */ + list_del(&bus->list); + + /* nothing more needed */ + kfree(bus); +} + +int fs_mii_connect(struct net_device *dev) +{ + struct fs_enet_private *fep = netdev_priv(dev); + const struct fs_platform_info *fpi = fep->fpi; + struct fs_enet_mii_bus *bus = NULL; + + /* check method validity */ + switch (fpi->bus_info->method) { + case fsmii_fixed: + case fsmii_bitbang: + break; +#ifdef CONFIG_FS_ENET_HAS_FEC + case fsmii_fec: + break; +#endif + default: + printk(KERN_ERR DRV_MODULE_NAME + ": %s Unknown MII bus method (%d)!\n", + dev->name, fpi->bus_info->method); + return -EINVAL; + } + + bus = lookup_bus(fpi->bus_info->method, fpi->bus_info->id); + + /* if not found create new bus */ + if (bus == NULL) { + bus = create_bus(fpi->bus_info); + if (IS_ERR(bus)) { + printk(KERN_ERR DRV_MODULE_NAME + ": %s MII bus creation failure!\n", dev->name); + return PTR_ERR(bus); + } + } + + bus->refs++; + + fep->mii_bus = bus; + + fep->mii_if.dev = dev; + fep->mii_if.phy_id_mask = 0x1f; + fep->mii_if.reg_num_mask = 0x1f; + fep->mii_if.mdio_read = fs_mii_read; + fep->mii_if.mdio_write = fs_mii_write; + fep->mii_if.force_media = fpi->bus_info->disable_aneg; + fep->mii_if.phy_id = phy_id_detect(dev); + + return 0; +} + +void fs_mii_disconnect(struct net_device *dev) +{ + struct fs_enet_private *fep = netdev_priv(dev); + struct fs_enet_mii_bus *bus = NULL; + + bus = fep->mii_bus; + fep->mii_bus = NULL; + + if (--bus->refs <= 0) + destroy_bus(bus); +} diff --git a/trunk/drivers/net/fs_enet/fs_enet.h b/trunk/drivers/net/fs_enet/fs_enet.h index 95022c005f75..e7ec96c964a9 100644 --- a/trunk/drivers/net/fs_enet/fs_enet.h +++ b/trunk/drivers/net/fs_enet/fs_enet.h @@ -5,7 +5,6 @@ #include #include #include -#include #include @@ -13,30 +12,12 @@ #ifdef CONFIG_CPM1 #include - -struct fec_info { - fec_t* fecp; - u32 mii_speed; -}; #endif #ifdef CONFIG_CPM2 #include #endif -/* This is used to operate with pins. - Note that the actual port size may - be different; cpm(s) handle it OK */ -struct bb_info { - u8 mdio_dat_msk; - u8 mdio_dir_msk; - u8 *mdio_dir; - u8 *mdio_dat; - u8 mdc_msk; - u8 *mdc_dat; - int delay; -}; - /* hw driver ops */ struct fs_ops { int (*setup_data)(struct net_device *dev); @@ -44,7 +25,6 @@ struct fs_ops { void (*free_bd)(struct net_device *dev); void (*cleanup_data)(struct net_device *dev); void (*set_multicast_list)(struct net_device *dev); - void (*adjust_link)(struct net_device *dev); void (*restart)(struct net_device *dev); void (*stop)(struct net_device *dev); void (*pre_request_irq)(struct net_device *dev, int irq); @@ -120,6 +100,10 @@ struct fs_enet_mii_bus { }; }; +int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus); +int fs_mii_fixed_init(struct fs_enet_mii_bus *bus); +int fs_mii_fec_init(struct fs_enet_mii_bus *bus); + struct fs_enet_private { struct device *dev; /* pointer back to the device (must be initialized first) */ spinlock_t lock; /* during all ops except TX pckt processing */ @@ -146,8 +130,7 @@ struct fs_enet_private { struct fs_enet_mii_bus *mii_bus; int interrupt; - struct phy_device *phydev; - int oldduplex, oldspeed, oldlink; /* current settings */ + int duplex, speed; /* current settings */ /* event masks */ u32 ev_napi_rx; /* mask of NAPI rx events */ @@ -185,9 +168,15 @@ struct fs_enet_private { }; /***************************************************************************/ -int fs_enet_mdio_bb_init(void); -int fs_mii_fixed_init(struct fs_enet_mii_bus *bus); -int fs_enet_mdio_fec_init(void); + +int fs_mii_read(struct net_device *dev, int phy_id, int location); +void fs_mii_write(struct net_device *dev, int phy_id, int location, int value); + +void fs_mii_startup(struct net_device *dev); +void fs_mii_shutdown(struct net_device *dev); +void fs_mii_ack_int(struct net_device *dev); + +void fs_mii_link_status_change_check(struct net_device *dev, int init_media); void fs_init_bds(struct net_device *dev); void fs_cleanup_bds(struct net_device *dev); @@ -205,6 +194,7 @@ int fs_enet_platform_init(void); void fs_enet_platform_cleanup(void); /***************************************************************************/ + /* buffer descriptor access macros */ /* access macros */ diff --git a/trunk/drivers/net/fs_enet/mac-fcc.c b/trunk/drivers/net/fs_enet/mac-fcc.c index 1ff2597b8495..64e20982c1fe 100644 --- a/trunk/drivers/net/fs_enet/mac-fcc.c +++ b/trunk/drivers/net/fs_enet/mac-fcc.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -123,32 +122,22 @@ static int do_pd_setup(struct fs_enet_private *fep) /* Attach the memory for the FCC Parameter RAM */ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_pram"); - fep->fcc.ep = (void *)ioremap(r->start, r->end - r->start + 1); + fep->fcc.ep = (void *)r->start; + if (fep->fcc.ep == NULL) return -EINVAL; r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fcc_regs"); - fep->fcc.fccp = (void *)ioremap(r->start, r->end - r->start + 1); + fep->fcc.fccp = (void *)r->start; + if (fep->fcc.fccp == NULL) return -EINVAL; - if (fep->fpi->fcc_regs_c) { - - fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c; - } else { - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, - "fcc_regs_c"); - fep->fcc.fcccp = (void *)ioremap(r->start, - r->end - r->start + 1); - } + fep->fcc.fcccp = (void *)fep->fpi->fcc_regs_c; if (fep->fcc.fcccp == NULL) return -EINVAL; - fep->fcc.mem = (void *)fep->fpi->mem_offset; - if (fep->fcc.mem == NULL) - return -EINVAL; - return 0; } @@ -166,6 +155,8 @@ static int setup_data(struct net_device *dev) if ((unsigned int)fep->fcc.idx >= 3) /* max 3 FCCs */ return -EINVAL; + fep->fcc.mem = (void *)fpi->mem_offset; + if (do_pd_setup(fep) != 0) return -EINVAL; @@ -403,7 +394,7 @@ static void restart(struct net_device *dev) /* adjust to speed (for RMII mode) */ if (fpi->use_rmii) { - if (fep->phydev->speed == 100) + if (fep->speed == 100) C8(fcccp, fcc_gfemr, 0x20); else S8(fcccp, fcc_gfemr, 0x20); @@ -429,7 +420,7 @@ static void restart(struct net_device *dev) S32(fccp, fcc_fpsmr, FCC_PSMR_RMII); /* adjust to duplex mode */ - if (fep->phydev->duplex) + if (fep->duplex) S32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB); else C32(fccp, fcc_fpsmr, FCC_PSMR_FDE | FCC_PSMR_LPB); @@ -495,10 +486,7 @@ static void rx_bd_done(struct net_device *dev) static void tx_kickstart(struct net_device *dev) { - struct fs_enet_private *fep = netdev_priv(dev); - fcc_t *fccp = fep->fcc.fccp; - - S32(fccp, fcc_ftodr, 0x80); + /* nothing */ } static u32 get_int_events(struct net_device *dev) diff --git a/trunk/drivers/net/fs_enet/mac-fec.c b/trunk/drivers/net/fs_enet/mac-fec.c index c2c5fd419bd0..e09547077529 100644 --- a/trunk/drivers/net/fs_enet/mac-fec.c +++ b/trunk/drivers/net/fs_enet/mac-fec.c @@ -46,7 +46,6 @@ #endif #include "fs_enet.h" -#include "fec.h" /*************************************************/ @@ -76,8 +75,50 @@ /* clear bits */ #define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v)) + +/* CRC polynomium used by the FEC for the multicast group filtering */ +#define FEC_CRC_POLY 0x04C11DB7 + +#define FEC_MAX_MULTICAST_ADDRS 64 + +/* Interrupt events/masks. +*/ +#define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */ +#define FEC_ENET_BABR 0x40000000U /* Babbling receiver */ +#define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */ +#define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */ +#define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */ +#define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */ +#define FEC_ENET_RXF 0x02000000U /* Full frame received */ +#define FEC_ENET_RXB 0x01000000U /* A buffer was received */ +#define FEC_ENET_MII 0x00800000U /* MII interrupt */ +#define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */ + +#define FEC_ECNTRL_PINMUX 0x00000004 +#define FEC_ECNTRL_ETHER_EN 0x00000002 +#define FEC_ECNTRL_RESET 0x00000001 + +#define FEC_RCNTRL_BC_REJ 0x00000010 +#define FEC_RCNTRL_PROM 0x00000008 +#define FEC_RCNTRL_MII_MODE 0x00000004 +#define FEC_RCNTRL_DRT 0x00000002 +#define FEC_RCNTRL_LOOP 0x00000001 + +#define FEC_TCNTRL_FDEN 0x00000004 +#define FEC_TCNTRL_HBC 0x00000002 +#define FEC_TCNTRL_GTS 0x00000001 + + +/* Make MII read/write commands for the FEC. +*/ +#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) +#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff)) +#define mk_mii_end 0 + +#define FEC_MII_LOOPS 10000 + /* - * Delay to wait for FEC reset command to complete (in us) + * Delay to wait for FEC reset command to complete (in us) */ #define FEC_RESET_DELAY 50 @@ -262,15 +303,13 @@ static void restart(struct net_device *dev) int r; u32 addrhi, addrlo; - struct mii_bus* mii = fep->phydev->bus; - struct fec_info* fec_inf = mii->priv; - r = whack_reset(fep->fec.fecp); if (r != 0) printk(KERN_ERR DRV_MODULE_NAME ": %s FEC Reset FAILED!\n", dev->name); + /* - * Set station address. + * Set station address. */ addrhi = ((u32) dev->dev_addr[0] << 24) | ((u32) dev->dev_addr[1] << 16) | @@ -311,12 +350,12 @@ static void restart(struct net_device *dev) FW(fecp, fun_code, 0x78000000); /* - * Set MII speed. + * Set MII speed. */ - FW(fecp, mii_speed, fec_inf->mii_speed); + FW(fecp, mii_speed, fep->mii_bus->fec.mii_speed); /* - * Clear any outstanding interrupt. + * Clear any outstanding interrupt. */ FW(fecp, ievent, 0xffc0); FW(fecp, ivec, (fep->interrupt / 2) << 29); @@ -351,12 +390,11 @@ static void restart(struct net_device *dev) } #endif - FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ /* - * adjust to duplex mode + * adjust to duplex mode */ - if (fep->phydev->duplex) { + if (fep->duplex) { FC(fecp, r_cntrl, FEC_RCNTRL_DRT); FS(fecp, x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */ } else { @@ -380,11 +418,9 @@ static void restart(struct net_device *dev) static void stop(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); - const struct fs_platform_info *fpi = fep->fpi; fec_t *fecp = fep->fec.fecp; - - struct fec_info* feci= fep->phydev->bus->priv; - + struct fs_enet_mii_bus *bus = fep->mii_bus; + const struct fs_mii_bus_info *bi = bus->bus_info; int i; if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0) @@ -408,11 +444,11 @@ static void stop(struct net_device *dev) fs_cleanup_bds(dev); /* shut down FEC1? that's where the mii bus is */ - if (fpi->has_phy) { + if (fep->fec.idx == 0 && bus->refs > 1 && bi->method == fsmii_fec) { FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); FW(fecp, ievent, FEC_ENET_MII); - FW(fecp, mii_speed, feci->mii_speed); + FW(fecp, mii_speed, bus->fec.mii_speed); } } @@ -547,3 +583,73 @@ const struct fs_ops fs_fec_ops = { .free_bd = free_bd, }; +/***********************************************************************/ + +static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location) +{ + fec_t *fecp = bus->fec.fecp; + int i, ret = -1; + + if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) + BUG(); + + /* Add PHY address to register command. */ + FW(fecp, mii_data, (phy_id << 23) | mk_mii_read(location)); + + for (i = 0; i < FEC_MII_LOOPS; i++) + if ((FR(fecp, ievent) & FEC_ENET_MII) != 0) + break; + + if (i < FEC_MII_LOOPS) { + FW(fecp, ievent, FEC_ENET_MII); + ret = FR(fecp, mii_data) & 0xffff; + } + + return ret; +} + +static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int value) +{ + fec_t *fecp = bus->fec.fecp; + int i; + + /* this must never happen */ + if ((FR(fecp, r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) + BUG(); + + /* Add PHY address to register command. */ + FW(fecp, mii_data, (phy_id << 23) | mk_mii_write(location, value)); + + for (i = 0; i < FEC_MII_LOOPS; i++) + if ((FR(fecp, ievent) & FEC_ENET_MII) != 0) + break; + + if (i < FEC_MII_LOOPS) + FW(fecp, ievent, FEC_ENET_MII); +} + +int fs_mii_fec_init(struct fs_enet_mii_bus *bus) +{ + bd_t *bd = (bd_t *)__res; + const struct fs_mii_bus_info *bi = bus->bus_info; + fec_t *fecp; + + if (bi->id != 0) + return -1; + + bus->fec.fecp = &((immap_t *)fs_enet_immap)->im_cpm.cp_fec; + bus->fec.mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) + & 0x3F) << 1; + + fecp = bus->fec.fecp; + + FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ + FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); + FW(fecp, ievent, FEC_ENET_MII); + FW(fecp, mii_speed, bus->fec.mii_speed); + + bus->mii_read = mii_read; + bus->mii_write = mii_write; + + return 0; +} diff --git a/trunk/drivers/net/fs_enet/mac-scc.c b/trunk/drivers/net/fs_enet/mac-scc.c index 95ec5872c507..eaa24fab645f 100644 --- a/trunk/drivers/net/fs_enet/mac-scc.c +++ b/trunk/drivers/net/fs_enet/mac-scc.c @@ -369,7 +369,7 @@ static void restart(struct net_device *dev) W16(sccp, scc_psmr, SCC_PSMR_ENCRC | SCC_PSMR_NIB22); /* Set full duplex mode if needed */ - if (fep->phydev->duplex) + if (fep->duplex) S16(sccp, scc_psmr, SCC_PSMR_LPB | SCC_PSMR_FDE); S32(sccp, scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT); @@ -500,8 +500,6 @@ static void tx_restart(struct net_device *dev) scc_cr_cmd(fep, CPM_CR_RESTART_TX); } - - /*************************************************************************/ const struct fs_ops fs_scc_ops = { diff --git a/trunk/drivers/net/fs_enet/mii-bitbang.c b/trunk/drivers/net/fs_enet/mii-bitbang.c index 0b9b8b5c847c..48f9cf83ab6f 100644 --- a/trunk/drivers/net/fs_enet/mii-bitbang.c +++ b/trunk/drivers/net/fs_enet/mii-bitbang.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -41,25 +40,129 @@ #include "fs_enet.h" -static int bitbang_prep_bit(u8 **datp, u8 *mskp, - struct fs_mii_bit *mii_bit) +#ifdef CONFIG_8xx +static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit) { - void *dat; + immap_t *im = (immap_t *)fs_enet_immap; + void *dir, *dat, *ppar; int adv; u8 msk; - dat = (void*) mii_bit->offset; + switch (port) { + case fsiop_porta: + dir = &im->im_ioport.iop_padir; + dat = &im->im_ioport.iop_padat; + ppar = &im->im_ioport.iop_papar; + break; + + case fsiop_portb: + dir = &im->im_cpm.cp_pbdir; + dat = &im->im_cpm.cp_pbdat; + ppar = &im->im_cpm.cp_pbpar; + break; + + case fsiop_portc: + dir = &im->im_ioport.iop_pcdir; + dat = &im->im_ioport.iop_pcdat; + ppar = &im->im_ioport.iop_pcpar; + break; + + case fsiop_portd: + dir = &im->im_ioport.iop_pddir; + dat = &im->im_ioport.iop_pddat; + ppar = &im->im_ioport.iop_pdpar; + break; + + case fsiop_porte: + dir = &im->im_cpm.cp_pedir; + dat = &im->im_cpm.cp_pedat; + ppar = &im->im_cpm.cp_pepar; + break; + + default: + printk(KERN_ERR DRV_MODULE_NAME + "Illegal port value %d!\n", port); + return -EINVAL; + } + + adv = bit >> 3; + dir = (char *)dir + adv; + dat = (char *)dat + adv; + ppar = (char *)ppar + adv; + + msk = 1 << (7 - (bit & 7)); + if ((in_8(ppar) & msk) != 0) { + printk(KERN_ERR DRV_MODULE_NAME + "pin %d on port %d is not general purpose!\n", bit, port); + return -EINVAL; + } + + *dirp = dir; + *datp = dat; + *mskp = msk; + + return 0; +} +#endif + +#ifdef CONFIG_8260 +static int bitbang_prep_bit(u8 **dirp, u8 **datp, u8 *mskp, int port, int bit) +{ + iop_cpm2_t *io = &((cpm2_map_t *)fs_enet_immap)->im_ioport; + void *dir, *dat, *ppar; + int adv; + u8 msk; + + switch (port) { + case fsiop_porta: + dir = &io->iop_pdira; + dat = &io->iop_pdata; + ppar = &io->iop_ppara; + break; + + case fsiop_portb: + dir = &io->iop_pdirb; + dat = &io->iop_pdatb; + ppar = &io->iop_pparb; + break; + + case fsiop_portc: + dir = &io->iop_pdirc; + dat = &io->iop_pdatc; + ppar = &io->iop_pparc; + break; + + case fsiop_portd: + dir = &io->iop_pdird; + dat = &io->iop_pdatd; + ppar = &io->iop_ppard; + break; + + default: + printk(KERN_ERR DRV_MODULE_NAME + "Illegal port value %d!\n", port); + return -EINVAL; + } - adv = mii_bit->bit >> 3; + adv = bit >> 3; + dir = (char *)dir + adv; dat = (char *)dat + adv; + ppar = (char *)ppar + adv; - msk = 1 << (7 - (mii_bit->bit & 7)); + msk = 1 << (7 - (bit & 7)); + if ((in_8(ppar) & msk) != 0) { + printk(KERN_ERR DRV_MODULE_NAME + "pin %d on port %d is not general purpose!\n", bit, port); + return -EINVAL; + } + *dirp = dir; *datp = dat; *mskp = msk; return 0; } +#endif static inline void bb_set(u8 *p, u8 m) { @@ -76,44 +179,44 @@ static inline int bb_read(u8 *p, u8 m) return (in_8(p) & m) != 0; } -static inline void mdio_active(struct bb_info *bitbang) +static inline void mdio_active(struct fs_enet_mii_bus *bus) { - bb_set(bitbang->mdio_dir, bitbang->mdio_dir_msk); + bb_set(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk); } -static inline void mdio_tristate(struct bb_info *bitbang ) +static inline void mdio_tristate(struct fs_enet_mii_bus *bus) { - bb_clr(bitbang->mdio_dir, bitbang->mdio_dir_msk); + bb_clr(bus->bitbang.mdio_dir, bus->bitbang.mdio_msk); } -static inline int mdio_read(struct bb_info *bitbang ) +static inline int mdio_read(struct fs_enet_mii_bus *bus) { - return bb_read(bitbang->mdio_dat, bitbang->mdio_dat_msk); + return bb_read(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); } -static inline void mdio(struct bb_info *bitbang , int what) +static inline void mdio(struct fs_enet_mii_bus *bus, int what) { if (what) - bb_set(bitbang->mdio_dat, bitbang->mdio_dat_msk); + bb_set(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); else - bb_clr(bitbang->mdio_dat, bitbang->mdio_dat_msk); + bb_clr(bus->bitbang.mdio_dat, bus->bitbang.mdio_msk); } -static inline void mdc(struct bb_info *bitbang , int what) +static inline void mdc(struct fs_enet_mii_bus *bus, int what) { if (what) - bb_set(bitbang->mdc_dat, bitbang->mdc_msk); + bb_set(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk); else - bb_clr(bitbang->mdc_dat, bitbang->mdc_msk); + bb_clr(bus->bitbang.mdc_dat, bus->bitbang.mdc_msk); } -static inline void mii_delay(struct bb_info *bitbang ) +static inline void mii_delay(struct fs_enet_mii_bus *bus) { - udelay(bitbang->delay); + udelay(bus->bus_info->i.bitbang.delay); } /* Utility to send the preamble, address, and register (common to read and write). */ -static void bitbang_pre(struct bb_info *bitbang , int read, u8 addr, u8 reg) +static void bitbang_pre(struct fs_enet_mii_bus *bus, int read, u8 addr, u8 reg) { int j; @@ -125,284 +228,177 @@ static void bitbang_pre(struct bb_info *bitbang , int read, u8 addr, u8 reg) * but it is safer and will be much more robust. */ - mdio_active(bitbang); - mdio(bitbang, 1); + mdio_active(bus); + mdio(bus, 1); for (j = 0; j < 32; j++) { - mdc(bitbang, 0); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); + mdc(bus, 0); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); } /* send the start bit (01) and the read opcode (10) or write (10) */ - mdc(bitbang, 0); - mdio(bitbang, 0); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); - mdc(bitbang, 0); - mdio(bitbang, 1); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); - mdc(bitbang, 0); - mdio(bitbang, read); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); - mdc(bitbang, 0); - mdio(bitbang, !read); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); + mdc(bus, 0); + mdio(bus, 0); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); + mdc(bus, 0); + mdio(bus, 1); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); + mdc(bus, 0); + mdio(bus, read); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); + mdc(bus, 0); + mdio(bus, !read); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); /* send the PHY address */ for (j = 0; j < 5; j++) { - mdc(bitbang, 0); - mdio(bitbang, (addr & 0x10) != 0); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); + mdc(bus, 0); + mdio(bus, (addr & 0x10) != 0); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); addr <<= 1; } /* send the register address */ for (j = 0; j < 5; j++) { - mdc(bitbang, 0); - mdio(bitbang, (reg & 0x10) != 0); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); + mdc(bus, 0); + mdio(bus, (reg & 0x10) != 0); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); reg <<= 1; } } -static int fs_enet_mii_bb_read(struct mii_bus *bus , int phy_id, int location) +static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location) { u16 rdreg; int ret, j; u8 addr = phy_id & 0xff; u8 reg = location & 0xff; - struct bb_info* bitbang = bus->priv; - bitbang_pre(bitbang, 1, addr, reg); + bitbang_pre(bus, 1, addr, reg); /* tri-state our MDIO I/O pin so we can read */ - mdc(bitbang, 0); - mdio_tristate(bitbang); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); + mdc(bus, 0); + mdio_tristate(bus); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); /* check the turnaround bit: the PHY should be driving it to zero */ - if (mdio_read(bitbang) != 0) { + if (mdio_read(bus) != 0) { /* PHY didn't drive TA low */ for (j = 0; j < 32; j++) { - mdc(bitbang, 0); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); + mdc(bus, 0); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); } ret = -1; goto out; } - mdc(bitbang, 0); - mii_delay(bitbang); + mdc(bus, 0); + mii_delay(bus); /* read 16 bits of register data, MSB first */ rdreg = 0; for (j = 0; j < 16; j++) { - mdc(bitbang, 1); - mii_delay(bitbang); + mdc(bus, 1); + mii_delay(bus); rdreg <<= 1; - rdreg |= mdio_read(bitbang); - mdc(bitbang, 0); - mii_delay(bitbang); + rdreg |= mdio_read(bus); + mdc(bus, 0); + mii_delay(bus); } - mdc(bitbang, 1); - mii_delay(bitbang); - mdc(bitbang, 0); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); + mdc(bus, 1); + mii_delay(bus); + mdc(bus, 0); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); ret = rdreg; out: return ret; } -static int fs_enet_mii_bb_write(struct mii_bus *bus, int phy_id, int location, u16 val) +static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val) { int j; - struct bb_info* bitbang = bus->priv; - u8 addr = phy_id & 0xff; u8 reg = location & 0xff; u16 value = val & 0xffff; - bitbang_pre(bitbang, 0, addr, reg); + bitbang_pre(bus, 0, addr, reg); /* send the turnaround (10) */ - mdc(bitbang, 0); - mdio(bitbang, 1); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); - mdc(bitbang, 0); - mdio(bitbang, 0); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); + mdc(bus, 0); + mdio(bus, 1); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); + mdc(bus, 0); + mdio(bus, 0); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); /* write 16 bits of register data, MSB first */ for (j = 0; j < 16; j++) { - mdc(bitbang, 0); - mdio(bitbang, (value & 0x8000) != 0); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); + mdc(bus, 0); + mdio(bus, (value & 0x8000) != 0); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); value <<= 1; } /* * Tri-state the MDIO line. */ - mdio_tristate(bitbang); - mdc(bitbang, 0); - mii_delay(bitbang); - mdc(bitbang, 1); - mii_delay(bitbang); - return 0; + mdio_tristate(bus); + mdc(bus, 0); + mii_delay(bus); + mdc(bus, 1); + mii_delay(bus); } -static int fs_enet_mii_bb_reset(struct mii_bus *bus) -{ - /*nothing here - dunno how to reset it*/ - return 0; -} - -static int fs_mii_bitbang_init(struct bb_info *bitbang, struct fs_mii_bb_platform_info* fmpi) +int fs_mii_bitbang_init(struct fs_enet_mii_bus *bus) { + const struct fs_mii_bus_info *bi = bus->bus_info; int r; - bitbang->delay = fmpi->delay; - - r = bitbang_prep_bit(&bitbang->mdio_dir, - &bitbang->mdio_dir_msk, - &fmpi->mdio_dir); + r = bitbang_prep_bit(&bus->bitbang.mdio_dir, + &bus->bitbang.mdio_dat, + &bus->bitbang.mdio_msk, + bi->i.bitbang.mdio_port, + bi->i.bitbang.mdio_bit); if (r != 0) return r; - r = bitbang_prep_bit(&bitbang->mdio_dat, - &bitbang->mdio_dat_msk, - &fmpi->mdio_dat); + r = bitbang_prep_bit(&bus->bitbang.mdc_dir, + &bus->bitbang.mdc_dat, + &bus->bitbang.mdc_msk, + bi->i.bitbang.mdc_port, + bi->i.bitbang.mdc_bit); if (r != 0) return r; - r = bitbang_prep_bit(&bitbang->mdc_dat, - &bitbang->mdc_msk, - &fmpi->mdc_dat); - if (r != 0) - return r; + bus->mii_read = mii_read; + bus->mii_write = mii_write; return 0; } - - -static int __devinit fs_enet_mdio_probe(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct fs_mii_bb_platform_info *pdata; - struct mii_bus *new_bus; - struct bb_info *bitbang; - int err = 0; - - if (NULL == dev) - return -EINVAL; - - new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); - - if (NULL == new_bus) - return -ENOMEM; - - bitbang = kzalloc(sizeof(struct bb_info), GFP_KERNEL); - - if (NULL == bitbang) - return -ENOMEM; - - new_bus->name = "BB MII Bus", - new_bus->read = &fs_enet_mii_bb_read, - new_bus->write = &fs_enet_mii_bb_write, - new_bus->reset = &fs_enet_mii_bb_reset, - new_bus->id = pdev->id; - - new_bus->phy_mask = ~0x9; - pdata = (struct fs_mii_bb_platform_info *)pdev->dev.platform_data; - - if (NULL == pdata) { - printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id); - return -ENODEV; - } - - /*set up workspace*/ - fs_mii_bitbang_init(bitbang, pdata); - - new_bus->priv = bitbang; - - new_bus->irq = pdata->irq; - - new_bus->dev = dev; - dev_set_drvdata(dev, new_bus); - - err = mdiobus_register(new_bus); - - if (0 != err) { - printk (KERN_ERR "%s: Cannot register as MDIO bus\n", - new_bus->name); - goto bus_register_fail; - } - - return 0; - -bus_register_fail: - kfree(bitbang); - kfree(new_bus); - - return err; -} - - -static int fs_enet_mdio_remove(struct device *dev) -{ - struct mii_bus *bus = dev_get_drvdata(dev); - - mdiobus_unregister(bus); - - dev_set_drvdata(dev, NULL); - - iounmap((void *) (&bus->priv)); - bus->priv = NULL; - kfree(bus); - - return 0; -} - -static struct device_driver fs_enet_bb_mdio_driver = { - .name = "fsl-bb-mdio", - .bus = &platform_bus_type, - .probe = fs_enet_mdio_probe, - .remove = fs_enet_mdio_remove, -}; - -int fs_enet_mdio_bb_init(void) -{ - return driver_register(&fs_enet_bb_mdio_driver); -} - -void fs_enet_mdio_bb_exit(void) -{ - driver_unregister(&fs_enet_bb_mdio_driver); -} - diff --git a/trunk/drivers/net/fs_enet/mii-fec.c b/trunk/drivers/net/fs_enet/mii-fec.c deleted file mode 100644 index 1328e10caa35..000000000000 --- a/trunk/drivers/net/fs_enet/mii-fec.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Combined Ethernet driver for Motorola MPC8xx and MPC82xx. - * - * Copyright (c) 2003 Intracom S.A. - * by Pantelis Antoniou - * - * 2005 (c) MontaVista Software, Inc. - * Vitaly Bordug - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "fs_enet.h" -#include "fec.h" - -/* Make MII read/write commands for the FEC. -*/ -#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) -#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff)) -#define mk_mii_end 0 - -#define FEC_MII_LOOPS 10000 - -static int match_has_phy (struct device *dev, void* data) -{ - struct platform_device* pdev = container_of(dev, struct platform_device, dev); - struct fs_platform_info* fpi; - if(strcmp(pdev->name, (char*)data)) - { - return 0; - } - - fpi = pdev->dev.platform_data; - if((fpi)&&(fpi->has_phy)) - return 1; - return 0; -} - -static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info *fmpi) -{ - struct resource *r; - fec_t *fecp; - char* name = "fsl-cpm-fec"; - - /* we need fec in order to be useful */ - struct platform_device *fec_pdev = - container_of(bus_find_device(&platform_bus_type, NULL, name, match_has_phy), - struct platform_device, dev); - - if(fec_pdev == NULL) { - printk(KERN_ERR"Unable to find PHY for %s", name); - return -ENODEV; - } - - r = platform_get_resource_byname(fec_pdev, IORESOURCE_MEM, "regs"); - - fec->fecp = fecp = (fec_t*)ioremap(r->start,sizeof(fec_t)); - fec->mii_speed = fmpi->mii_speed; - - setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ - setbits32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); - out_be32(&fecp->fec_ievent, FEC_ENET_MII); - out_be32(&fecp->fec_mii_speed, fec->mii_speed); - - return 0; -} - -static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) -{ - struct fec_info* fec = bus->priv; - fec_t *fecp = fec->fecp; - int i, ret = -1; - - if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) - BUG(); - - /* Add PHY address to register command. */ - out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location)); - - for (i = 0; i < FEC_MII_LOOPS; i++) - if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0) - break; - - if (i < FEC_MII_LOOPS) { - out_be32(&fecp->fec_ievent, FEC_ENET_MII); - ret = in_be32(&fecp->fec_mii_data) & 0xffff; - } - - return ret; - -} - -static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val) -{ - struct fec_info* fec = bus->priv; - fec_t *fecp = fec->fecp; - int i; - - /* this must never happen */ - if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) - BUG(); - - /* Add PHY address to register command. */ - out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val)); - - for (i = 0; i < FEC_MII_LOOPS; i++) - if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0) - break; - - if (i < FEC_MII_LOOPS) - out_be32(&fecp->fec_ievent, FEC_ENET_MII); - - return 0; - -} - -static int fs_enet_fec_mii_reset(struct mii_bus *bus) -{ - /* nothing here - for now */ - return 0; -} - -static int __devinit fs_enet_fec_mdio_probe(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct fs_mii_fec_platform_info *pdata; - struct mii_bus *new_bus; - struct fec_info *fec; - int err = 0; - if (NULL == dev) - return -EINVAL; - new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); - - if (NULL == new_bus) - return -ENOMEM; - - fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL); - - if (NULL == fec) - return -ENOMEM; - - new_bus->name = "FEC MII Bus", - new_bus->read = &fs_enet_fec_mii_read, - new_bus->write = &fs_enet_fec_mii_write, - new_bus->reset = &fs_enet_fec_mii_reset, - new_bus->id = pdev->id; - - pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data; - - if (NULL == pdata) { - printk(KERN_ERR "fs_enet FEC mdio %d: Missing platform data!\n", pdev->id); - return -ENODEV; - } - - /*set up workspace*/ - - fs_mii_fec_init(fec, pdata); - new_bus->priv = fec; - - new_bus->irq = pdata->irq; - - new_bus->dev = dev; - dev_set_drvdata(dev, new_bus); - - err = mdiobus_register(new_bus); - - if (0 != err) { - printk (KERN_ERR "%s: Cannot register as MDIO bus\n", - new_bus->name); - goto bus_register_fail; - } - - return 0; - -bus_register_fail: - kfree(new_bus); - - return err; -} - - -static int fs_enet_fec_mdio_remove(struct device *dev) -{ - struct mii_bus *bus = dev_get_drvdata(dev); - - mdiobus_unregister(bus); - - dev_set_drvdata(dev, NULL); - kfree(bus->priv); - - bus->priv = NULL; - kfree(bus); - - return 0; -} - -static struct device_driver fs_enet_fec_mdio_driver = { - .name = "fsl-cpm-fec-mdio", - .bus = &platform_bus_type, - .probe = fs_enet_fec_mdio_probe, - .remove = fs_enet_fec_mdio_remove, -}; - -int fs_enet_mdio_fec_init(void) -{ - return driver_register(&fs_enet_fec_mdio_driver); -} - -void fs_enet_mdio_fec_exit(void) -{ - driver_unregister(&fs_enet_fec_mdio_driver); -} - diff --git a/trunk/drivers/net/fs_enet/mii-fixed.c b/trunk/drivers/net/fs_enet/mii-fixed.c new file mode 100644 index 000000000000..ae4a9c3bb393 --- /dev/null +++ b/trunk/drivers/net/fs_enet/mii-fixed.c @@ -0,0 +1,91 @@ +/* + * Combined Ethernet driver for Motorola MPC8xx and MPC82xx. + * + * Copyright (c) 2003 Intracom S.A. + * by Pantelis Antoniou + * + * 2005 (c) MontaVista Software, Inc. + * Vitaly Bordug + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "fs_enet.h" + +static const u16 mii_regs[7] = { + 0x3100, + 0x786d, + 0x0fff, + 0x0fff, + 0x01e1, + 0x45e1, + 0x0003, +}; + +static int mii_read(struct fs_enet_mii_bus *bus, int phy_id, int location) +{ + int ret = 0; + + if ((unsigned int)location >= ARRAY_SIZE(mii_regs)) + return -1; + + if (location != 5) + ret = mii_regs[location]; + else + ret = bus->fixed.lpa; + + return ret; +} + +static void mii_write(struct fs_enet_mii_bus *bus, int phy_id, int location, int val) +{ + /* do nothing */ +} + +int fs_mii_fixed_init(struct fs_enet_mii_bus *bus) +{ + const struct fs_mii_bus_info *bi = bus->bus_info; + + bus->fixed.lpa = 0x45e1; /* default 100Mb, full duplex */ + + /* if speed is fixed at 10Mb, remove 100Mb modes */ + if (bi->i.fixed.speed == 10) + bus->fixed.lpa &= ~LPA_100; + + /* if duplex is half, remove full duplex modes */ + if (bi->i.fixed.duplex == 0) + bus->fixed.lpa &= ~LPA_DUPLEX; + + bus->mii_read = mii_read; + bus->mii_write = mii_write; + + return 0; +} diff --git a/trunk/drivers/net/gianfar.c b/trunk/drivers/net/gianfar.c index ba960913c034..ebbbd6ca6204 100644 --- a/trunk/drivers/net/gianfar.c +++ b/trunk/drivers/net/gianfar.c @@ -947,7 +947,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Set up checksumming */ if (likely((dev->features & NETIF_F_IP_CSUM) - && (CHECKSUM_PARTIAL == skb->ip_summed))) { + && (CHECKSUM_HW == skb->ip_summed))) { fcb = gfar_add_fcb(skb, txbdp); status |= TXBD_TOE; gfar_tx_checksum(skb, fcb); diff --git a/trunk/drivers/net/hamachi.c b/trunk/drivers/net/hamachi.c index 763373ae9666..409c6aab0411 100644 --- a/trunk/drivers/net/hamachi.c +++ b/trunk/drivers/net/hamachi.c @@ -1648,7 +1648,7 @@ static int hamachi_rx(struct net_device *dev) * could do the pseudo myself and return * CHECKSUM_UNNECESSARY */ - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_HW; } } } diff --git a/trunk/drivers/net/ibm_emac/ibm_emac_core.c b/trunk/drivers/net/ibm_emac/ibm_emac_core.c index 57e214d85e9a..82468e2dc799 100644 --- a/trunk/drivers/net/ibm_emac/ibm_emac_core.c +++ b/trunk/drivers/net/ibm_emac/ibm_emac_core.c @@ -1036,7 +1036,7 @@ static inline u16 emac_tx_csum(struct ocp_enet_private *dev, struct sk_buff *skb) { #if defined(CONFIG_IBM_EMAC_TAH) - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { ++dev->stats.tx_packets_csum; return EMAC_TX_CTRL_TAH_CSUM; } diff --git a/trunk/drivers/net/ibmveth.c b/trunk/drivers/net/ibmveth.c index e56eac88b809..0464e78f733a 100644 --- a/trunk/drivers/net/ibmveth.c +++ b/trunk/drivers/net/ibmveth.c @@ -702,8 +702,7 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev) desc[3].desc, desc[4].desc, desc[5].desc, - correlator, - &correlator); + correlator); } while ((lpar_rc == H_BUSY) && (retry_count--)); if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) { diff --git a/trunk/drivers/net/ibmveth.h b/trunk/drivers/net/ibmveth.h index f5b25bff1540..8385bf836507 100644 --- a/trunk/drivers/net/ibmveth.h +++ b/trunk/drivers/net/ibmveth.h @@ -41,6 +41,16 @@ #define IbmVethMcastRemoveFilter 0x2UL #define IbmVethMcastClearFilterTable 0x3UL +/* hcall numbers */ +#define H_VIO_SIGNAL 0x104 +#define H_REGISTER_LOGICAL_LAN 0x114 +#define H_FREE_LOGICAL_LAN 0x118 +#define H_ADD_LOGICAL_LAN_BUFFER 0x11C +#define H_SEND_LOGICAL_LAN 0x120 +#define H_MULTICAST_CTRL 0x130 +#define H_CHANGE_LOGICAL_LAN_MAC 0x14C +#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4 + /* hcall macros */ #define h_register_logical_lan(ua, buflst, rxq, fltlst, mac) \ plpar_hcall_norets(H_REGISTER_LOGICAL_LAN, ua, buflst, rxq, fltlst, mac) @@ -51,21 +61,8 @@ #define h_add_logical_lan_buffer(ua, buf) \ plpar_hcall_norets(H_ADD_LOGICAL_LAN_BUFFER, ua, buf) -static inline long h_send_logical_lan(unsigned long unit_address, - unsigned long desc1, unsigned long desc2, unsigned long desc3, - unsigned long desc4, unsigned long desc5, unsigned long desc6, - unsigned long corellator_in, unsigned long *corellator_out) -{ - long rc; - unsigned long retbuf[PLPAR_HCALL9_BUFSIZE]; - - rc = plpar_hcall9(H_SEND_LOGICAL_LAN, retbuf, unit_address, desc1, - desc2, desc3, desc4, desc5, desc6, corellator_in); - - *corellator_out = retbuf[0]; - - return rc; -} +#define h_send_logical_lan(ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator) \ + plpar_hcall_8arg_2ret(H_SEND_LOGICAL_LAN, ua, buf1, buf2, buf3, buf4, buf5, buf6, correlator, &correlator) #define h_multicast_ctrl(ua, cmd, mac) \ plpar_hcall_norets(H_MULTICAST_CTRL, ua, cmd, mac) diff --git a/trunk/drivers/net/ioc3-eth.c b/trunk/drivers/net/ioc3-eth.c index 65f897ddb920..68d8af7df08e 100644 --- a/trunk/drivers/net/ioc3-eth.c +++ b/trunk/drivers/net/ioc3-eth.c @@ -1387,7 +1387,7 @@ static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev) * MAC header which should not be summed and the TCP/UDP pseudo headers * manually. */ - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { int proto = ntohs(skb->nh.iph->protocol); unsigned int csoff; struct iphdr *ih = skb->nh.iph; diff --git a/trunk/drivers/net/irda/ali-ircc.c b/trunk/drivers/net/irda/ali-ircc.c index 68d4c418cb98..e3c8cd5eca67 100644 --- a/trunk/drivers/net/irda/ali-ircc.c +++ b/trunk/drivers/net/irda/ali-ircc.c @@ -249,7 +249,7 @@ static void __exit ali_ircc_cleanup(void) IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); - for (i=0; i < ARRAY_SIZE(dev_self); i++) { + for (i=0; i < 4; i++) { if (dev_self[i]) ali_ircc_close(dev_self[i]); } @@ -273,12 +273,6 @@ static int ali_ircc_open(int i, chipio_t *info) int err; IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__); - - if (i >= ARRAY_SIZE(dev_self)) { - IRDA_ERROR("%s(), maximum number of supported chips reached!\n", - __FUNCTION__); - return -ENOMEM; - } /* Set FIR FIFO and DMA Threshold */ if ((ali_ircc_setup(info)) == -1) diff --git a/trunk/drivers/net/irda/irport.c b/trunk/drivers/net/irda/irport.c index ba4f3eb988b3..44efd49bf4a9 100644 --- a/trunk/drivers/net/irda/irport.c +++ b/trunk/drivers/net/irda/irport.c @@ -1090,7 +1090,7 @@ static int __init irport_init(void) { int i; - for (i=0; (io[i] < 2000) && (i < ARRAY_SIZE(dev_self)); i++) { + for (i=0; (io[i] < 2000) && (i < 4); i++) { if (irport_open(i, io[i], irq[i]) != NULL) return 0; } @@ -1112,7 +1112,7 @@ static void __exit irport_cleanup(void) IRDA_DEBUG( 4, "%s()\n", __FUNCTION__); - for (i=0; i < ARRAY_SIZE(dev_self); i++) { + for (i=0; i < 4; i++) { if (dev_self[i]) irport_close(dev_self[i]); } diff --git a/trunk/drivers/net/irda/via-ircc.c b/trunk/drivers/net/irda/via-ircc.c index 79b85f327500..8bafb455c102 100644 --- a/trunk/drivers/net/irda/via-ircc.c +++ b/trunk/drivers/net/irda/via-ircc.c @@ -279,7 +279,7 @@ static void via_ircc_clean(void) IRDA_DEBUG(3, "%s()\n", __FUNCTION__); - for (i=0; i < ARRAY_SIZE(dev_self); i++) { + for (i=0; i < 4; i++) { if (dev_self[i]) via_ircc_close(dev_self[i]); } @@ -327,9 +327,6 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) IRDA_DEBUG(3, "%s()\n", __FUNCTION__); - if (i >= ARRAY_SIZE(dev_self)) - return -ENOMEM; - /* Allocate new instance of the driver */ dev = alloc_irdadev(sizeof(struct via_ircc_cb)); if (dev == NULL) diff --git a/trunk/drivers/net/irda/w83977af_ir.c b/trunk/drivers/net/irda/w83977af_ir.c index 8421597072a7..0ea65c4c6f85 100644 --- a/trunk/drivers/net/irda/w83977af_ir.c +++ b/trunk/drivers/net/irda/w83977af_ir.c @@ -117,7 +117,7 @@ static int __init w83977af_init(void) IRDA_DEBUG(0, "%s()\n", __FUNCTION__ ); - for (i=0; (io[i] < 2000) && (i < ARRAY_SIZE(dev_self)); i++) { + for (i=0; (io[i] < 2000) && (i < 4); i++) { if (w83977af_open(i, io[i], irq[i], dma[i]) == 0) return 0; } @@ -136,7 +136,7 @@ static void __exit w83977af_cleanup(void) IRDA_DEBUG(4, "%s()\n", __FUNCTION__ ); - for (i=0; i < ARRAY_SIZE(dev_self); i++) { + for (i=0; i < 4; i++) { if (dev_self[i]) w83977af_close(dev_self[i]); } diff --git a/trunk/drivers/net/ixgb/ixgb_main.c b/trunk/drivers/net/ixgb/ixgb_main.c index 9405b44f3214..7bbd447289b5 100644 --- a/trunk/drivers/net/ixgb/ixgb_main.c +++ b/trunk/drivers/net/ixgb/ixgb_main.c @@ -1232,7 +1232,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb) unsigned int i; uint8_t css, cso; - if(likely(skb->ip_summed == CHECKSUM_PARTIAL)) { + if(likely(skb->ip_summed == CHECKSUM_HW)) { css = skb->h.raw - skb->data; cso = (skb->h.raw + skb->csum) - skb->data; diff --git a/trunk/drivers/net/lance.c b/trunk/drivers/net/lance.c index 5b4dbfe5fb77..c1c3452c90ca 100644 --- a/trunk/drivers/net/lance.c +++ b/trunk/drivers/net/lance.c @@ -326,7 +326,7 @@ MODULE_PARM_DESC(dma, "LANCE/PCnet ISA DMA channel (ignored for some devices)"); MODULE_PARM_DESC(irq, "LANCE/PCnet IRQ number (ignored for some devices)"); MODULE_PARM_DESC(lance_debug, "LANCE/PCnet debug level (0-7)"); -int __init init_module(void) +int init_module(void) { struct net_device *dev; int this_dev, found = 0; diff --git a/trunk/drivers/net/lne390.c b/trunk/drivers/net/lne390.c index c0ec7f6abcb2..646e89fc3562 100644 --- a/trunk/drivers/net/lne390.c +++ b/trunk/drivers/net/lne390.c @@ -406,7 +406,7 @@ MODULE_PARM_DESC(mem, "memory base address(es)"); MODULE_DESCRIPTION("Mylex LNE390A/B EISA Ethernet driver"); MODULE_LICENSE("GPL"); -int __init init_module(void) +int init_module(void) { struct net_device *dev; int this_dev, found = 0; diff --git a/trunk/drivers/net/lp486e.c b/trunk/drivers/net/lp486e.c index 393aba95cf12..b783a6984abc 100644 --- a/trunk/drivers/net/lp486e.c +++ b/trunk/drivers/net/lp486e.c @@ -442,16 +442,16 @@ init_rx_bufs(struct net_device *dev, int num) { if (rbd) { rbd->pad = 0; rbd->count = 0; - rbd->skb = dev_alloc_skb(RX_SKBSIZE); + rbd->skb = dev_alloc_skb(RX_SKB_SIZE); if (!rbd->skb) { printk("dev_alloc_skb failed"); } rbd->next = rfd->rbd; if (i) { rfd->rbd->prev = rbd; - rbd->size = RX_SKBSIZE; + rbd->size = RX_SKB_SIZE; } else { - rbd->size = (RX_SKBSIZE | RBD_EL); + rbd->size = (RX_SKB_SIZE | RBD_EL); lp->rbd_tail = rbd; } diff --git a/trunk/drivers/net/mace.c b/trunk/drivers/net/mace.c index 5d80e0e6a8e9..29e4b5aa6ead 100644 --- a/trunk/drivers/net/mace.c +++ b/trunk/drivers/net/mace.c @@ -113,7 +113,7 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i struct device_node *mace = macio_get_of_node(mdev); struct net_device *dev; struct mace_data *mp; - const unsigned char *addr; + unsigned char *addr; int j, rev, rc = -EBUSY; if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) { diff --git a/trunk/drivers/net/mv643xx_eth.c b/trunk/drivers/net/mv643xx_eth.c index d4dcc856b3cd..760c61b98867 100644 --- a/trunk/drivers/net/mv643xx_eth.c +++ b/trunk/drivers/net/mv643xx_eth.c @@ -385,8 +385,6 @@ static int mv643xx_eth_receive_queue(struct net_device *dev, int budget) struct pkt_info pkt_info; while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) { - dma_unmap_single(NULL, pkt_info.buf_ptr, ETH_RX_SKB_SIZE, - DMA_FROM_DEVICE); mp->rx_desc_count--; received_packets++; @@ -1147,7 +1145,7 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, desc->byte_cnt = length; desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { BUG_ON(skb->protocol != ETH_P_IP); cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM | diff --git a/trunk/drivers/net/myri10ge/myri10ge.c b/trunk/drivers/net/myri10ge/myri10ge.c index 9f16681d0e7e..07ca9480a6fe 100644 --- a/trunk/drivers/net/myri10ge/myri10ge.c +++ b/trunk/drivers/net/myri10ge/myri10ge.c @@ -177,7 +177,6 @@ struct myri10ge_priv { struct work_struct watchdog_work; struct timer_list watchdog_timer; int watchdog_tx_done; - int watchdog_tx_req; int watchdog_resets; int tx_linearized; int pause; @@ -449,7 +448,6 @@ static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size) struct mcp_gen_header *hdr; size_t hdr_offset; int status; - unsigned i; if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) { dev_err(dev, "Unable to load %s firmware image via hotplug\n", @@ -481,12 +479,18 @@ static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size) goto abort_with_fw; crc = crc32(~0, fw->data, fw->size); - for (i = 0; i < fw->size; i += 256) { - myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET + i, - fw->data + i, - min(256U, (unsigned)(fw->size - i))); - mb(); - readb(mgp->sram); + if (mgp->tx.boundary == 2048) { + /* Avoid PCI burst on chipset with unaligned completions. */ + int i; + __iomem u32 *ptr = (__iomem u32 *) (mgp->sram + + MYRI10GE_FW_OFFSET); + for (i = 0; i < fw->size / 4; i++) { + __raw_writel(((u32 *) fw->data)[i], ptr + i); + wmb(); + } + } else { + myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET, fw->data, + fw->size); } /* corruption checking is good for parity recovery and buggy chipset */ memcpy_fromio(fw->data, mgp->sram + MYRI10GE_FW_OFFSET, fw->size); @@ -616,7 +620,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) return -ENXIO; } dev_info(&mgp->pdev->dev, "handoff confirmed\n"); - myri10ge_dummy_rdma(mgp, 1); + myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096); return 0; } @@ -930,7 +934,7 @@ static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, u16 hw_csum) (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) || vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) { skb->csum = hw_csum; - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_HW; } } @@ -973,7 +977,7 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, if ((skb->protocol == ntohs(ETH_P_IP)) || (skb->protocol == ntohs(ETH_P_IPV6))) { skb->csum = ntohs((u16) csum); - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_HW; } else myri10ge_vlan_ip_csum(skb, ntohs((u16) csum)); } @@ -1897,13 +1901,13 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) pseudo_hdr_offset = 0; odd_flag = 0; flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST); - if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { + if (likely(skb->ip_summed == CHECKSUM_HW)) { cksum_offset = (skb->h.raw - skb->data); pseudo_hdr_offset = (skb->h.raw + skb->csum) - skb->data; /* If the headers are excessively large, then we must * fall back to a software checksum */ if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) { - if (skb_checksum_help(skb)) + if (skb_checksum_help(skb, 0)) goto drop; cksum_offset = 0; pseudo_hdr_offset = 0; @@ -2425,7 +2429,7 @@ static int myri10ge_resume(struct pci_dev *pdev) } myri10ge_reset(mgp); - myri10ge_dummy_rdma(mgp, 1); + myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096); /* Save configuration space to be restored if the * nic resets due to a parity error */ @@ -2543,8 +2547,7 @@ static void myri10ge_watchdog_timer(unsigned long arg) mgp = (struct myri10ge_priv *)arg; if (mgp->tx.req != mgp->tx.done && - mgp->tx.done == mgp->watchdog_tx_done && - mgp->watchdog_tx_req != mgp->watchdog_tx_done) + mgp->tx.done == mgp->watchdog_tx_done) /* nic seems like it might be stuck.. */ schedule_work(&mgp->watchdog_work); else @@ -2553,7 +2556,6 @@ static void myri10ge_watchdog_timer(unsigned long arg) jiffies + myri10ge_watchdog_timeout * HZ); mgp->watchdog_tx_done = mgp->tx.done; - mgp->watchdog_tx_req = mgp->tx.req; } static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) diff --git a/trunk/drivers/net/ni52.c b/trunk/drivers/net/ni52.c index 4d52ecf8af56..fa854c8fde75 100644 --- a/trunk/drivers/net/ni52.c +++ b/trunk/drivers/net/ni52.c @@ -1323,7 +1323,7 @@ MODULE_PARM_DESC(irq, "NI5210 IRQ number,required"); MODULE_PARM_DESC(memstart, "NI5210 memory base address,required"); MODULE_PARM_DESC(memend, "NI5210 memory end address,required"); -int __init init_module(void) +int init_module(void) { if(io <= 0x0 || !memend || !memstart || irq < 2) { printk("ni52: Autoprobing not allowed for modules.\nni52: Set symbols 'io' 'irq' 'memstart' and 'memend'\n"); diff --git a/trunk/drivers/net/ni65.c b/trunk/drivers/net/ni65.c index 810cc572f5f7..bb42ff218484 100644 --- a/trunk/drivers/net/ni65.c +++ b/trunk/drivers/net/ni65.c @@ -1253,7 +1253,7 @@ MODULE_PARM_DESC(irq, "ni6510 IRQ number (ignored for some cards)"); MODULE_PARM_DESC(io, "ni6510 I/O base address"); MODULE_PARM_DESC(dma, "ni6510 ISA DMA channel (ignored for some cards)"); -int __init init_module(void) +int init_module(void) { dev_ni65 = ni65_probe(-1); return IS_ERR(dev_ni65) ? PTR_ERR(dev_ni65) : 0; diff --git a/trunk/drivers/net/ns83820.c b/trunk/drivers/net/ns83820.c index 5143f5dbb2e5..0e76859c90a2 100644 --- a/trunk/drivers/net/ns83820.c +++ b/trunk/drivers/net/ns83820.c @@ -1153,7 +1153,7 @@ static int ns83820_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) if (!nr_frags) frag = NULL; extsts = 0; - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { extsts |= EXTSTS_IPPKT; if (IPPROTO_TCP == skb->nh.iph->protocol) extsts |= EXTSTS_TCPPKT; diff --git a/trunk/drivers/net/pcmcia/xirc2ps_cs.c b/trunk/drivers/net/pcmcia/xirc2ps_cs.c index 4122bb46f5ff..9bae77ce1314 100644 --- a/trunk/drivers/net/pcmcia/xirc2ps_cs.c +++ b/trunk/drivers/net/pcmcia/xirc2ps_cs.c @@ -345,7 +345,6 @@ typedef struct local_info_t { void __iomem *dingo_ccr; /* only used for CEM56 cards */ unsigned last_ptr_value; /* last packets transmitted value */ const char *manf_str; - struct work_struct tx_timeout_task; } local_info_t; /**************** @@ -353,7 +352,6 @@ typedef struct local_info_t { */ static int do_start_xmit(struct sk_buff *skb, struct net_device *dev); static void do_tx_timeout(struct net_device *dev); -static void xirc2ps_tx_timeout_task(void *data); static struct net_device_stats *do_get_stats(struct net_device *dev); static void set_addresses(struct net_device *dev); static void set_multicast_list(struct net_device *dev); @@ -591,7 +589,6 @@ xirc2ps_probe(struct pcmcia_device *link) #ifdef HAVE_TX_TIMEOUT dev->tx_timeout = do_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; - INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task, dev); #endif return xirc2ps_config(link); @@ -1344,24 +1341,17 @@ xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) /*====================================================================*/ static void -xirc2ps_tx_timeout_task(void *data) +do_tx_timeout(struct net_device *dev) { - struct net_device *dev = data; + local_info_t *lp = netdev_priv(dev); + printk(KERN_NOTICE "%s: transmit timed out\n", dev->name); + lp->stats.tx_errors++; /* reset the card */ do_reset(dev,1); dev->trans_start = jiffies; netif_wake_queue(dev); } -static void -do_tx_timeout(struct net_device *dev) -{ - local_info_t *lp = netdev_priv(dev); - lp->stats.tx_errors++; - printk(KERN_NOTICE "%s: transmit timed out\n", dev->name); - schedule_work(&lp->tx_timeout_task); -} - static int do_start_xmit(struct sk_buff *skb, struct net_device *dev) { diff --git a/trunk/drivers/net/pcnet32.c b/trunk/drivers/net/pcnet32.c index d50bcb89dd28..4daafe303358 100644 --- a/trunk/drivers/net/pcnet32.c +++ b/trunk/drivers/net/pcnet32.c @@ -202,8 +202,6 @@ static int homepna[MAX_UNITS]; #define CSR15 15 #define PCNET32_MC_FILTER 8 -#define PCNET32_79C970A 0x2621 - /* The PCNET32 Rx and Tx ring descriptors. */ struct pcnet32_rx_head { u32 base; @@ -291,7 +289,6 @@ struct pcnet32_private { /* each bit indicates an available PHY */ u32 phymask; - unsigned short chip_version; /* which variant this is */ }; static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *); @@ -727,11 +724,9 @@ static u32 pcnet32_get_link(struct net_device *dev) spin_lock_irqsave(&lp->lock, flags); if (lp->mii) { r = mii_link_ok(&lp->mii_if); - } else if (lp->chip_version >= PCNET32_79C970A) { + } else { ulong ioaddr = dev->base_addr; /* card base I/O address */ r = (lp->a.read_bcr(ioaddr, 4) != 0xc0); - } else { /* can not detect link on really old chips */ - r = 1; } spin_unlock_irqrestore(&lp->lock, flags); @@ -1096,10 +1091,6 @@ static int pcnet32_suspend(struct net_device *dev, unsigned long *flags, ulong ioaddr = dev->base_addr; int ticks; - /* really old chips have to be stopped. */ - if (lp->chip_version < PCNET32_79C970A) - return 0; - /* set SUSPEND (SPND) - CSR5 bit 0 */ csr5 = a->read_csr(ioaddr, CSR5); a->write_csr(ioaddr, CSR5, csr5 | CSR5_SUSPEND); @@ -1538,7 +1529,6 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) lp->mii_if.reg_num_mask = 0x1f; lp->dxsuflo = dxsuflo; lp->mii = mii; - lp->chip_version = chip_version; lp->msg_enable = pcnet32_debug; if ((cards_found >= MAX_UNITS) || (options[cards_found] > sizeof(options_mapping))) @@ -1849,7 +1839,10 @@ static int pcnet32_open(struct net_device *dev) val |= 2; } else if (lp->options & PCNET32_PORT_ASEL) { /* workaround of xSeries250, turn on for 79C975 only */ - if (lp->chip_version == 0x2627) + i = ((lp->a.read_csr(ioaddr, 88) | + (lp->a. + read_csr(ioaddr, 89) << 16)) >> 12) & 0xffff; + if (i == 0x2627) val |= 3; } lp->a.write_bcr(ioaddr, 9, val); @@ -1993,11 +1986,9 @@ static int pcnet32_open(struct net_device *dev) netif_start_queue(dev); - if (lp->chip_version >= PCNET32_79C970A) { - /* Print the link status and start the watchdog */ - pcnet32_check_media(dev, 1); - mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); - } + /* Print the link status and start the watchdog */ + pcnet32_check_media(dev, 1); + mod_timer(&(lp->watchdog_timer), PCNET32_WATCHDOG_TIMEOUT); i = 0; while (i++ < 100) diff --git a/trunk/drivers/net/phy/Kconfig b/trunk/drivers/net/phy/Kconfig index b79ec0d7480f..2ba6d3a40e2e 100644 --- a/trunk/drivers/net/phy/Kconfig +++ b/trunk/drivers/net/phy/Kconfig @@ -56,22 +56,5 @@ config SMSC_PHY ---help--- Currently supports the LAN83C185 PHY -config FIXED_PHY - tristate "Drivers for PHY emulation on fixed speed/link" - depends on PHYLIB - ---help--- - Adds the driver to PHY layer to cover the boards that do not have any PHY bound, - but with the ability to manipulate with speed/link in software. The relavant MII - speed/duplex parameters could be effectively handled in user-specified fuction. - Currently tested with mpc866ads. - -config FIXED_MII_10_FDX - bool "Emulation for 10M Fdx fixed PHY behavior" - depends on FIXED_PHY - -config FIXED_MII_100_FDX - bool "Emulation for 100M Fdx fixed PHY behavior" - depends on FIXED_PHY - endmenu diff --git a/trunk/drivers/net/phy/Makefile b/trunk/drivers/net/phy/Makefile index 320f8323123f..a00e61942525 100644 --- a/trunk/drivers/net/phy/Makefile +++ b/trunk/drivers/net/phy/Makefile @@ -10,4 +10,3 @@ obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_SMSC_PHY) += smsc.o obj-$(CONFIG_VITESSE_PHY) += vitesse.o -obj-$(CONFIG_FIXED_PHY) += fixed.o diff --git a/trunk/drivers/net/phy/fixed.c b/trunk/drivers/net/phy/fixed.c deleted file mode 100644 index 341036df4710..000000000000 --- a/trunk/drivers/net/phy/fixed.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * drivers/net/phy/fixed.c - * - * Driver for fixed PHYs, when transceiver is able to operate in one fixed mode. - * - * Author: Vitaly Bordug - * - * Copyright (c) 2006 MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define MII_REGS_NUM 7 - -/* - The idea is to emulate normal phy behavior by responding with - pre-defined values to mii BMCR read, so that read_status hook could - take all the needed info. -*/ - -struct fixed_phy_status { - u8 link; - u16 speed; - u8 duplex; -}; - -/*----------------------------------------------------------------------------- - * Private information hoder for mii_bus - *-----------------------------------------------------------------------------*/ -struct fixed_info { - u16 *regs; - u8 regs_num; - struct fixed_phy_status phy_status; - struct phy_device *phydev; /* pointer to the container */ - /* link & speed cb */ - int(*link_update)(struct net_device*, struct fixed_phy_status*); - -}; - -/*----------------------------------------------------------------------------- - * If something weird is required to be done with link/speed, - * network driver is able to assign a function to implement this. - * May be useful for PHY's that need to be software-driven. - *-----------------------------------------------------------------------------*/ -int fixed_mdio_set_link_update(struct phy_device* phydev, - int(*link_update)(struct net_device*, struct fixed_phy_status*)) -{ - struct fixed_info *fixed; - - if(link_update == NULL) - return -EINVAL; - - if(phydev) { - if(phydev->bus) { - fixed = phydev->bus->priv; - fixed->link_update = link_update; - return 0; - } - } - return -EINVAL; -} -EXPORT_SYMBOL(fixed_mdio_set_link_update); - -/*----------------------------------------------------------------------------- - * This is used for updating internal mii regs from the status - *-----------------------------------------------------------------------------*/ -static int fixed_mdio_update_regs(struct fixed_info *fixed) -{ - u16 *regs = fixed->regs; - u16 bmsr = 0; - u16 bmcr = 0; - - if(!regs) { - printk(KERN_ERR "%s: regs not set up", __FUNCTION__); - return -EINVAL; - } - - if(fixed->phy_status.link) - bmsr |= BMSR_LSTATUS; - - if(fixed->phy_status.duplex) { - bmcr |= BMCR_FULLDPLX; - - switch ( fixed->phy_status.speed ) { - case 100: - bmsr |= BMSR_100FULL; - bmcr |= BMCR_SPEED100; - break; - - case 10: - bmsr |= BMSR_10FULL; - break; - } - } else { - switch ( fixed->phy_status.speed ) { - case 100: - bmsr |= BMSR_100HALF; - bmcr |= BMCR_SPEED100; - break; - - case 10: - bmsr |= BMSR_100HALF; - break; - } - } - - regs[MII_BMCR] = bmcr; - regs[MII_BMSR] = bmsr | 0x800; /*we are always capable of 10 hdx*/ - - return 0; -} - -static int fixed_mii_read(struct mii_bus *bus, int phy_id, int location) -{ - struct fixed_info *fixed = bus->priv; - - /* if user has registered link update callback, use it */ - if(fixed->phydev) - if(fixed->phydev->attached_dev) { - if(fixed->link_update) { - fixed->link_update(fixed->phydev->attached_dev, - &fixed->phy_status); - fixed_mdio_update_regs(fixed); - } - } - - if ((unsigned int)location >= fixed->regs_num) - return -1; - return fixed->regs[location]; -} - -static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val) -{ - /* do nothing for now*/ - return 0; -} - -static int fixed_mii_reset(struct mii_bus *bus) -{ - /*nothing here - no way/need to reset it*/ - return 0; -} - -static int fixed_config_aneg(struct phy_device *phydev) -{ - /* :TODO:03/13/2006 09:45:37 PM:: - The full autoneg funcionality can be emulated, - but no need to have anything here for now - */ - return 0; -} - -/*----------------------------------------------------------------------------- - * the manual bind will do the magic - with phy_id_mask == 0 - * match will never return true... - *-----------------------------------------------------------------------------*/ -static struct phy_driver fixed_mdio_driver = { - .name = "Fixed PHY", - .features = PHY_BASIC_FEATURES, - .config_aneg = fixed_config_aneg, - .read_status = genphy_read_status, - .driver = { .owner = THIS_MODULE,}, -}; - -/*----------------------------------------------------------------------------- - * This func is used to create all the necessary stuff, bind - * the fixed phy driver and register all it on the mdio_bus_type. - * speed is either 10 or 100, duplex is boolean. - * number is used to create multiple fixed PHYs, so that several devices can - * utilize them simultaneously. - *-----------------------------------------------------------------------------*/ -static int fixed_mdio_register_device(int number, int speed, int duplex) -{ - struct mii_bus *new_bus; - struct fixed_info *fixed; - struct phy_device *phydev; - int err = 0; - - struct device* dev = kzalloc(sizeof(struct device), GFP_KERNEL); - - if (NULL == dev) - return -ENOMEM; - - new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); - - if (NULL == new_bus) { - kfree(dev); - return -ENOMEM; - } - fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL); - - if (NULL == fixed) { - kfree(dev); - kfree(new_bus); - return -ENOMEM; - } - - fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL); - fixed->regs_num = MII_REGS_NUM; - fixed->phy_status.speed = speed; - fixed->phy_status.duplex = duplex; - fixed->phy_status.link = 1; - - new_bus->name = "Fixed MII Bus", - new_bus->read = &fixed_mii_read, - new_bus->write = &fixed_mii_write, - new_bus->reset = &fixed_mii_reset, - - /*set up workspace*/ - fixed_mdio_update_regs(fixed); - new_bus->priv = fixed; - - new_bus->dev = dev; - dev_set_drvdata(dev, new_bus); - - /* create phy_device and register it on the mdio bus */ - phydev = phy_device_create(new_bus, 0, 0); - - /* - Put the phydev pointer into the fixed pack so that bus read/write code could - be able to access for instance attached netdev. Well it doesn't have to do - so, only in case of utilizing user-specified link-update... - */ - fixed->phydev = phydev; - - if(NULL == phydev) { - err = -ENOMEM; - goto device_create_fail; - } - - phydev->irq = -1; - phydev->dev.bus = &mdio_bus_type; - - if(number) - snprintf(phydev->dev.bus_id, BUS_ID_SIZE, - "fixed_%d@%d:%d", number, speed, duplex); - else - snprintf(phydev->dev.bus_id, BUS_ID_SIZE, - "fixed@%d:%d", speed, duplex); - phydev->bus = new_bus; - - err = device_register(&phydev->dev); - if(err) { - printk(KERN_ERR "Phy %s failed to register\n", - phydev->dev.bus_id); - goto bus_register_fail; - } - - /* - the mdio bus has phy_id match... In order not to do it - artificially, we are binding the driver here by hand; - it will be the same for all the fixed phys anyway. - */ - down_write(&phydev->dev.bus->subsys.rwsem); - - phydev->dev.driver = &fixed_mdio_driver.driver; - - err = phydev->dev.driver->probe(&phydev->dev); - if(err < 0) { - printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id); - up_write(&phydev->dev.bus->subsys.rwsem); - goto probe_fail; - } - - device_bind_driver(&phydev->dev); - up_write(&phydev->dev.bus->subsys.rwsem); - - return 0; - -probe_fail: - device_unregister(&phydev->dev); -bus_register_fail: - kfree(phydev); -device_create_fail: - kfree(dev); - kfree(new_bus); - kfree(fixed); - - return err; -} - - -MODULE_DESCRIPTION("Fixed PHY device & driver for PAL"); -MODULE_AUTHOR("Vitaly Bordug"); -MODULE_LICENSE("GPL"); - -static int __init fixed_init(void) -{ - int ret; - int duplex = 0; - - /* register on the bus... Not expected to be matched with anything there... */ - phy_driver_register(&fixed_mdio_driver); - - /* So let the fun begin... - We will create several mdio devices here, and will bound the upper - driver to them. - - Then the external software can lookup the phy bus by searching - fixed@speed:duplex, e.g. fixed@100:1, to be connected to the - virtual 100M Fdx phy. - - In case several virtual PHYs required, the bus_id will be in form - fixed_@:, which make it able even to define - driver-specific link control callback, if for instance PHY is completely - SW-driven. - - */ - -#ifdef CONFIG_FIXED_MII_DUPLEX - duplex = 1; -#endif - -#ifdef CONFIG_FIXED_MII_100_FDX - fixed_mdio_register_device(0, 100, 1); -#endif - -#ifdef CONFIX_FIXED_MII_10_FDX - fixed_mdio_register_device(0, 10, 1); -#endif - return 0; -} - -static void __exit fixed_exit(void) -{ - phy_driver_unregister(&fixed_mdio_driver); - /* :WARNING:02/18/2006 04:32:40 AM:: Cleanup all the created stuff */ -} - -module_init(fixed_init); -module_exit(fixed_exit); diff --git a/trunk/drivers/net/phy/mdio_bus.c b/trunk/drivers/net/phy/mdio_bus.c index cf6660c93ffa..1dde390c164d 100644 --- a/trunk/drivers/net/phy/mdio_bus.c +++ b/trunk/drivers/net/phy/mdio_bus.c @@ -159,7 +159,6 @@ struct bus_type mdio_bus_type = { .suspend = mdio_bus_suspend, .resume = mdio_bus_resume, }; -EXPORT_SYMBOL(mdio_bus_type); int __init mdio_bus_init(void) { diff --git a/trunk/drivers/net/phy/phy.c b/trunk/drivers/net/phy/phy.c index f5aad77288f9..7d5c2233c252 100644 --- a/trunk/drivers/net/phy/phy.c +++ b/trunk/drivers/net/phy/phy.c @@ -419,8 +419,9 @@ void phy_start_machine(struct phy_device *phydev, /* phy_stop_machine * - * description: Stops the state machine timer, sets the state to UP - * (unless it wasn't up yet). This function must be called BEFORE + * description: Stops the state machine timer, sets the state to + * UP (unless it wasn't up yet), and then frees the interrupt, + * if it is in use. This function must be called BEFORE * phy_detach. */ void phy_stop_machine(struct phy_device *phydev) @@ -432,6 +433,9 @@ void phy_stop_machine(struct phy_device *phydev) phydev->state = PHY_UP; spin_unlock(&phydev->lock); + if (phydev->irq != PHY_POLL) + phy_stop_interrupts(phydev); + phydev->adjust_state = NULL; } diff --git a/trunk/drivers/net/phy/phy_device.c b/trunk/drivers/net/phy/phy_device.c index 2d1ecfdc80db..1bc1e032c5d6 100644 --- a/trunk/drivers/net/phy/phy_device.c +++ b/trunk/drivers/net/phy/phy_device.c @@ -45,35 +45,6 @@ static struct phy_driver genphy_driver; extern int mdio_bus_init(void); extern void mdio_bus_exit(void); -struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) -{ - struct phy_device *dev; - /* We allocate the device, and initialize the - * default values */ - dev = kcalloc(1, sizeof(*dev), GFP_KERNEL); - - if (NULL == dev) - return (struct phy_device*) PTR_ERR((void*)-ENOMEM); - - dev->speed = 0; - dev->duplex = -1; - dev->pause = dev->asym_pause = 0; - dev->link = 1; - - dev->autoneg = AUTONEG_ENABLE; - - dev->addr = addr; - dev->phy_id = phy_id; - dev->bus = bus; - - dev->state = PHY_DOWN; - - spin_lock_init(&dev->lock); - - return dev; -} -EXPORT_SYMBOL(phy_device_create); - /* get_phy_device * * description: Reads the ID registers of the PHY at addr on the @@ -107,7 +78,27 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr) if (0xffffffff == phy_id) return NULL; - dev = phy_device_create(bus, addr, phy_id); + /* Otherwise, we allocate the device, and initialize the + * default values */ + dev = kcalloc(1, sizeof(*dev), GFP_KERNEL); + + if (NULL == dev) + return ERR_PTR(-ENOMEM); + + dev->speed = 0; + dev->duplex = -1; + dev->pause = dev->asym_pause = 0; + dev->link = 1; + + dev->autoneg = AUTONEG_ENABLE; + + dev->addr = addr; + dev->phy_id = phy_id; + dev->bus = bus; + + dev->state = PHY_DOWN; + + spin_lock_init(&dev->lock); return dev; } diff --git a/trunk/drivers/net/ppp_generic.c b/trunk/drivers/net/ppp_generic.c index c872f7c6cce3..0ec6e9d57b94 100644 --- a/trunk/drivers/net/ppp_generic.c +++ b/trunk/drivers/net/ppp_generic.c @@ -192,7 +192,7 @@ struct cardmap { void *ptr[CARDMAP_WIDTH]; }; static void *cardmap_get(struct cardmap *map, unsigned int nr); -static int cardmap_set(struct cardmap **map, unsigned int nr, void *ptr); +static void cardmap_set(struct cardmap **map, unsigned int nr, void *ptr); static unsigned int cardmap_find_first_free(struct cardmap *map); static void cardmap_destroy(struct cardmap **map); @@ -1995,9 +1995,10 @@ ppp_register_channel(struct ppp_channel *chan) { struct channel *pch; - pch = kzalloc(sizeof(struct channel), GFP_KERNEL); + pch = kmalloc(sizeof(struct channel), GFP_KERNEL); if (pch == 0) return -ENOMEM; + memset(pch, 0, sizeof(struct channel)); pch->ppp = NULL; pch->chan = chan; chan->ppp = pch; @@ -2407,12 +2408,13 @@ ppp_create_interface(int unit, int *retp) int ret = -ENOMEM; int i; - ppp = kzalloc(sizeof(struct ppp), GFP_KERNEL); + ppp = kmalloc(sizeof(struct ppp), GFP_KERNEL); if (!ppp) goto out; dev = alloc_netdev(0, "", ppp_setup); if (!dev) goto out1; + memset(ppp, 0, sizeof(struct ppp)); ppp->mru = PPP_MRU; init_ppp_file(&ppp->file, INTERFACE); @@ -2452,16 +2454,11 @@ ppp_create_interface(int unit, int *retp) } atomic_inc(&ppp_unit_count); - ret = cardmap_set(&all_ppp_units, unit, ppp); - if (ret != 0) - goto out3; - + cardmap_set(&all_ppp_units, unit, ppp); mutex_unlock(&all_ppp_mutex); *retp = 0; return ppp; -out3: - atomic_dec(&ppp_unit_count); out2: mutex_unlock(&all_ppp_mutex); free_netdev(dev); @@ -2698,7 +2695,7 @@ static void *cardmap_get(struct cardmap *map, unsigned int nr) return NULL; } -static int cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) +static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) { struct cardmap *p; int i; @@ -2707,9 +2704,8 @@ static int cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) if (p == NULL || (nr >> p->shift) >= CARDMAP_WIDTH) { do { /* need a new top level */ - struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL); - if (!np) - goto enomem; + struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL); + memset(np, 0, sizeof(*np)); np->ptr[0] = p; if (p != NULL) { np->shift = p->shift + CARDMAP_ORDER; @@ -2723,9 +2719,8 @@ static int cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) while (p->shift > 0) { i = (nr >> p->shift) & CARDMAP_MASK; if (p->ptr[i] == NULL) { - struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL); - if (!np) - goto enomem; + struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL); + memset(np, 0, sizeof(*np)); np->shift = p->shift - CARDMAP_ORDER; np->parent = p; p->ptr[i] = np; @@ -2740,9 +2735,6 @@ static int cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr) set_bit(i, &p->inuse); else clear_bit(i, &p->inuse); - return 0; - enomem: - return -ENOMEM; } static unsigned int cardmap_find_first_free(struct cardmap *map) diff --git a/trunk/drivers/net/ppp_mppe.c b/trunk/drivers/net/ppp_mppe.c index f3655fd772f5..51ff9a9d1bb5 100644 --- a/trunk/drivers/net/ppp_mppe.c +++ b/trunk/drivers/net/ppp_mppe.c @@ -43,7 +43,6 @@ * deprecated in 2.6 */ -#include #include #include #include @@ -65,13 +64,12 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_ALIAS("ppp-compress-" __stringify(CI_MPPE)); MODULE_VERSION("1.0.2"); -static unsigned int +static void setup_sg(struct scatterlist *sg, const void *address, unsigned int length) { sg[0].page = virt_to_page(address); sg[0].offset = offset_in_page(address); sg[0].length = length; - return length; } #define SHA1_PAD_SIZE 40 @@ -97,8 +95,8 @@ static inline void sha_pad_init(struct sha_pad *shapad) * State for an MPPE (de)compressor. */ struct ppp_mppe_state { - struct crypto_blkcipher *arc4; - struct crypto_hash *sha1; + struct crypto_tfm *arc4; + struct crypto_tfm *sha1; unsigned char *sha1_digest; unsigned char master_key[MPPE_MAX_KEY_LEN]; unsigned char session_key[MPPE_MAX_KEY_LEN]; @@ -138,21 +136,14 @@ struct ppp_mppe_state { */ static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *InterimKey) { - struct hash_desc desc; struct scatterlist sg[4]; - unsigned int nbytes; - nbytes = setup_sg(&sg[0], state->master_key, state->keylen); - nbytes += setup_sg(&sg[1], sha_pad->sha_pad1, - sizeof(sha_pad->sha_pad1)); - nbytes += setup_sg(&sg[2], state->session_key, state->keylen); - nbytes += setup_sg(&sg[3], sha_pad->sha_pad2, - sizeof(sha_pad->sha_pad2)); + setup_sg(&sg[0], state->master_key, state->keylen); + setup_sg(&sg[1], sha_pad->sha_pad1, sizeof(sha_pad->sha_pad1)); + setup_sg(&sg[2], state->session_key, state->keylen); + setup_sg(&sg[3], sha_pad->sha_pad2, sizeof(sha_pad->sha_pad2)); - desc.tfm = state->sha1; - desc.flags = 0; - - crypto_hash_digest(&desc, sg, nbytes, state->sha1_digest); + crypto_digest_digest (state->sha1, sg, 4, state->sha1_digest); memcpy(InterimKey, state->sha1_digest, state->keylen); } @@ -165,15 +156,14 @@ static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) { unsigned char InterimKey[MPPE_MAX_KEY_LEN]; struct scatterlist sg_in[1], sg_out[1]; - struct blkcipher_desc desc = { .tfm = state->arc4 }; get_new_key_from_sha(state, InterimKey); if (!initial_key) { - crypto_blkcipher_setkey(state->arc4, InterimKey, state->keylen); + crypto_cipher_setkey(state->arc4, InterimKey, state->keylen); setup_sg(sg_in, InterimKey, state->keylen); setup_sg(sg_out, state->session_key, state->keylen); - if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, - state->keylen) != 0) { + if (crypto_cipher_encrypt(state->arc4, sg_out, sg_in, + state->keylen) != 0) { printk(KERN_WARNING "mppe_rekey: cipher_encrypt failed\n"); } } else { @@ -185,7 +175,7 @@ static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) state->session_key[1] = 0x26; state->session_key[2] = 0x9e; } - crypto_blkcipher_setkey(state->arc4, state->session_key, state->keylen); + crypto_cipher_setkey(state->arc4, state->session_key, state->keylen); } /* @@ -206,19 +196,15 @@ static void *mppe_alloc(unsigned char *options, int optlen) memset(state, 0, sizeof(*state)); - state->arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(state->arc4)) { - state->arc4 = NULL; + state->arc4 = crypto_alloc_tfm("arc4", 0); + if (!state->arc4) goto out_free; - } - state->sha1 = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(state->sha1)) { - state->sha1 = NULL; + state->sha1 = crypto_alloc_tfm("sha1", 0); + if (!state->sha1) goto out_free; - } - digestsize = crypto_hash_digestsize(state->sha1); + digestsize = crypto_tfm_alg_digestsize(state->sha1); if (digestsize < MPPE_MAX_KEY_LEN) goto out_free; @@ -243,9 +229,9 @@ static void *mppe_alloc(unsigned char *options, int optlen) if (state->sha1_digest) kfree(state->sha1_digest); if (state->sha1) - crypto_free_hash(state->sha1); + crypto_free_tfm(state->sha1); if (state->arc4) - crypto_free_blkcipher(state->arc4); + crypto_free_tfm(state->arc4); kfree(state); out: return NULL; @@ -261,9 +247,9 @@ static void mppe_free(void *arg) if (state->sha1_digest) kfree(state->sha1_digest); if (state->sha1) - crypto_free_hash(state->sha1); + crypto_free_tfm(state->sha1); if (state->arc4) - crypto_free_blkcipher(state->arc4); + crypto_free_tfm(state->arc4); kfree(state); } } @@ -370,7 +356,6 @@ mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, int isize, int osize) { struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; - struct blkcipher_desc desc = { .tfm = state->arc4 }; int proto; struct scatterlist sg_in[1], sg_out[1]; @@ -428,7 +413,7 @@ mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, /* Encrypt packet */ setup_sg(sg_in, ibuf, isize); setup_sg(sg_out, obuf, osize); - if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in, isize) != 0) { + if (crypto_cipher_encrypt(state->arc4, sg_out, sg_in, isize) != 0) { printk(KERN_DEBUG "crypto_cypher_encrypt failed\n"); return -1; } @@ -477,7 +462,6 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, int osize) { struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; - struct blkcipher_desc desc = { .tfm = state->arc4 }; unsigned ccount; int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED; int sanity = 0; @@ -615,7 +599,7 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, */ setup_sg(sg_in, ibuf, 1); setup_sg(sg_out, obuf, 1); - if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, 1) != 0) { + if (crypto_cipher_decrypt(state->arc4, sg_out, sg_in, 1) != 0) { printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); return DECOMP_ERROR; } @@ -635,7 +619,7 @@ mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, /* And finally, decrypt the rest of the packet. */ setup_sg(sg_in, ibuf + 1, isize - 1); setup_sg(sg_out, obuf + 1, osize - 1); - if (crypto_blkcipher_decrypt(&desc, sg_out, sg_in, isize - 1)) { + if (crypto_cipher_decrypt(state->arc4, sg_out, sg_in, isize - 1) != 0) { printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); return DECOMP_ERROR; } @@ -710,8 +694,8 @@ static struct compressor ppp_mppe = { static int __init ppp_mppe_init(void) { int answer; - if (!(crypto_has_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC) && - crypto_has_hash("sha1", 0, CRYPTO_ALG_ASYNC))) + if (!(crypto_alg_available("arc4", 0) && + crypto_alg_available("sha1", 0))) return -ENODEV; sha_pad = kmalloc(sizeof(struct sha_pad), GFP_KERNEL); diff --git a/trunk/drivers/net/r8169.c b/trunk/drivers/net/r8169.c index d9b960aa9b0d..4c2f575faad7 100644 --- a/trunk/drivers/net/r8169.c +++ b/trunk/drivers/net/r8169.c @@ -2169,7 +2169,7 @@ static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev) if (mss) return LargeSend | ((mss & MSSMask) << MSSShift); } - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { const struct iphdr *ip = skb->nh.iph; if (ip->protocol == IPPROTO_TCP) diff --git a/trunk/drivers/net/s2io.c b/trunk/drivers/net/s2io.c index 5b3713f622d7..e1fe3a0a7b0b 100644 --- a/trunk/drivers/net/s2io.c +++ b/trunk/drivers/net/s2io.c @@ -71,13 +71,12 @@ #include #include #include -#include /* local include */ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.15.2" +#define DRV_VERSION "2.0.14.2" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; @@ -371,50 +370,38 @@ static const u64 fix_mac[] = { END_SIGN }; -MODULE_AUTHOR("Raghavendra Koushik "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - - /* Module Loadable parameters. */ -S2IO_PARM_INT(tx_fifo_num, 1); -S2IO_PARM_INT(rx_ring_num, 1); - - -S2IO_PARM_INT(rx_ring_mode, 1); -S2IO_PARM_INT(use_continuous_tx_intrs, 1); -S2IO_PARM_INT(rmac_pause_time, 0x100); -S2IO_PARM_INT(mc_pause_threshold_q0q3, 187); -S2IO_PARM_INT(mc_pause_threshold_q4q7, 187); -S2IO_PARM_INT(shared_splits, 0); -S2IO_PARM_INT(tmac_util_period, 5); -S2IO_PARM_INT(rmac_util_period, 5); -S2IO_PARM_INT(bimodal, 0); -S2IO_PARM_INT(l3l4hdr_size, 128); -/* Frequency of Rx desc syncs expressed as power of 2 */ -S2IO_PARM_INT(rxsync_frequency, 3); -/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */ -S2IO_PARM_INT(intr_type, 0); -/* Large receive offload feature */ -S2IO_PARM_INT(lro, 0); -/* Max pkts to be aggregated by LRO at one time. If not specified, - * aggregation happens until we hit max IP pkt size(64K) - */ -S2IO_PARM_INT(lro_max_pkts, 0xFFFF); -#ifndef CONFIG_S2IO_NAPI -S2IO_PARM_INT(indicate_max_pkts, 0); -#endif - +static unsigned int tx_fifo_num = 1; static unsigned int tx_fifo_len[MAX_TX_FIFOS] = {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN}; +static unsigned int rx_ring_num = 1; static unsigned int rx_ring_sz[MAX_RX_RINGS] = {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT}; static unsigned int rts_frm_len[MAX_RX_RINGS] = {[0 ...(MAX_RX_RINGS - 1)] = 0 }; - -module_param_array(tx_fifo_len, uint, NULL, 0); -module_param_array(rx_ring_sz, uint, NULL, 0); -module_param_array(rts_frm_len, uint, NULL, 0); +static unsigned int rx_ring_mode = 1; +static unsigned int use_continuous_tx_intrs = 1; +static unsigned int rmac_pause_time = 0x100; +static unsigned int mc_pause_threshold_q0q3 = 187; +static unsigned int mc_pause_threshold_q4q7 = 187; +static unsigned int shared_splits; +static unsigned int tmac_util_period = 5; +static unsigned int rmac_util_period = 5; +static unsigned int bimodal = 0; +static unsigned int l3l4hdr_size = 128; +#ifndef CONFIG_S2IO_NAPI +static unsigned int indicate_max_pkts; +#endif +/* Frequency of Rx desc syncs expressed as power of 2 */ +static unsigned int rxsync_frequency = 3; +/* Interrupt type. Values can be 0(INTA), 1(MSI), 2(MSI_X) */ +static unsigned int intr_type = 0; +/* Large receive offload feature */ +static unsigned int lro = 0; +/* Max pkts to be aggregated by LRO at one time. If not specified, + * aggregation happens until we hit max IP pkt size(64K) + */ +static unsigned int lro_max_pkts = 0xFFFF; /* * S2IO device table. @@ -477,9 +464,10 @@ static int init_shared_mem(struct s2io_nic *nic) size += config->tx_cfg[i].fifo_len; } if (size > MAX_AVAILABLE_TXDS) { - DBG_PRINT(ERR_DBG, "s2io: Requested TxDs too high, "); + DBG_PRINT(ERR_DBG, "%s: Requested TxDs too high, ", + __FUNCTION__); DBG_PRINT(ERR_DBG, "Requested: %d, max supported: 8192\n", size); - return -EINVAL; + return FAILURE; } lst_size = (sizeof(TxD_t) * config->max_txds); @@ -559,7 +547,6 @@ static int init_shared_mem(struct s2io_nic *nic) nic->ufo_in_band_v = kmalloc((sizeof(u64) * size), GFP_KERNEL); if (!nic->ufo_in_band_v) return -ENOMEM; - memset(nic->ufo_in_band_v, 0, size); /* Allocation and initialization of RXDs in Rings */ size = 0; @@ -1226,7 +1213,7 @@ static int init_nic(struct s2io_nic *nic) break; } - /* Enable all configured Tx FIFO partitions */ + /* Enable Tx FIFO partition 0. */ val64 = readq(&bar0->tx_fifo_partition_0); val64 |= (TX_FIFO_PARTITION_EN); writeq(val64, &bar0->tx_fifo_partition_0); @@ -1663,7 +1650,7 @@ static void en_dis_able_nic_intrs(struct s2io_nic *nic, u16 mask, int flag) writeq(temp64, &bar0->general_int_mask); /* * If Hercules adapter enable GPIO otherwise - * disable all PCIX, Flash, MDIO, IIC and GPIO + * disabled all PCIX, Flash, MDIO, IIC and GPIO * interrupts for now. * TODO */ @@ -2132,7 +2119,7 @@ static struct sk_buff *s2io_txdl_getskb(fifo_info_t *fifo_data, TxD_t *txdlp, in frag->size, PCI_DMA_TODEVICE); } } - memset(txdlp,0, (sizeof(TxD_t) * fifo_data->max_txds)); + txdlp->Host_Control = 0; return(skb); } @@ -2384,14 +2371,9 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) skb->data = (void *) (unsigned long)tmp; skb->tail = (void *) (unsigned long)tmp; - if (!(((RxD3_t*)rxdp)->Buffer0_ptr)) - ((RxD3_t*)rxdp)->Buffer0_ptr = - pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN, + ((RxD3_t*)rxdp)->Buffer0_ptr = + pci_map_single(nic->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); - else - pci_dma_sync_single_for_device(nic->pdev, - (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, - BUF0_LEN, PCI_DMA_FROMDEVICE); rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); if (nic->rxd_mode == RXD_MODE_3B) { /* Two buffer mode */ @@ -2404,13 +2386,10 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) (nic->pdev, skb->data, dev->mtu + 4, PCI_DMA_FROMDEVICE); - /* Buffer-1 will be dummy buffer. Not used */ - if (!(((RxD3_t*)rxdp)->Buffer1_ptr)) { - ((RxD3_t*)rxdp)->Buffer1_ptr = - pci_map_single(nic->pdev, - ba->ba_1, BUF1_LEN, - PCI_DMA_FROMDEVICE); - } + /* Buffer-1 will be dummy buffer not used */ + ((RxD3_t*)rxdp)->Buffer1_ptr = + pci_map_single(nic->pdev, ba->ba_1, BUF1_LEN, + PCI_DMA_FROMDEVICE); rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1); rxdp->Control_2 |= SET_BUFFER2_SIZE_3 (dev->mtu + 4); @@ -2635,23 +2614,23 @@ static int s2io_poll(struct net_device *dev, int *budget) } #endif -#ifdef CONFIG_NET_POLL_CONTROLLER /** - * s2io_netpoll - netpoll event handler entry point + * s2io_netpoll - Rx interrupt service handler for netpoll support * @dev : pointer to the device structure. * Description: - * This function will be called by upper layer to check for events on the - * interface in situations where interrupts are disabled. It is used for - * specific in-kernel networking tasks, such as remote consoles and kernel - * debugging over the network (example netdump in RedHat). + * Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. */ + +#ifdef CONFIG_NET_POLL_CONTROLLER static void s2io_netpoll(struct net_device *dev) { nic_t *nic = dev->priv; mac_info_t *mac_control; struct config_param *config; XENA_dev_config_t __iomem *bar0 = nic->bar0; - u64 val64 = 0xFFFFFFFFFFFFFFFFULL; + u64 val64; int i; disable_irq(dev->irq); @@ -2660,17 +2639,9 @@ static void s2io_netpoll(struct net_device *dev) mac_control = &nic->mac_control; config = &nic->config; + val64 = readq(&bar0->rx_traffic_int); writeq(val64, &bar0->rx_traffic_int); - writeq(val64, &bar0->tx_traffic_int); - /* we need to free up the transmitted skbufs or else netpoll will - * run out of skbs and will fail and eventually netpoll application such - * as netdump will fail. - */ - for (i = 0; i < config->tx_fifo_num; i++) - tx_intr_handler(&mac_control->fifos[i]); - - /* check for received packet and indicate up to network */ for (i = 0; i < config->rx_ring_num; i++) rx_intr_handler(&mac_control->rings[i]); @@ -2737,7 +2708,7 @@ static void rx_intr_handler(ring_info_t *ring_data) /* If your are next to put index then it's FIFO full condition */ if ((get_block == put_block) && (get_info.offset + 1) == put_info.offset) { - DBG_PRINT(INTR_DBG, "%s: Ring Full\n",dev->name); + DBG_PRINT(ERR_DBG, "%s: Ring Full\n",dev->name); break; } skb = (struct sk_buff *) ((unsigned long)rxdp->Host_Control); @@ -2757,15 +2728,18 @@ static void rx_intr_handler(ring_info_t *ring_data) HEADER_SNAP_SIZE, PCI_DMA_FROMDEVICE); } else if (nic->rxd_mode == RXD_MODE_3B) { - pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) + pci_unmap_single(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); + pci_unmap_single(nic->pdev, (dma_addr_t) + ((RxD3_t*)rxdp)->Buffer1_ptr, + BUF1_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer2_ptr, dev->mtu + 4, PCI_DMA_FROMDEVICE); } else { - pci_dma_sync_single_for_cpu(nic->pdev, (dma_addr_t) + pci_unmap_single(nic->pdev, (dma_addr_t) ((RxD3_t*)rxdp)->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); pci_unmap_single(nic->pdev, (dma_addr_t) @@ -3353,7 +3327,7 @@ static void s2io_reset(nic_t * sp) /* Clear certain PCI/PCI-X fields after reset */ if (sp->device_type == XFRAME_II_DEVICE) { - /* Clear "detected parity error" bit */ + /* Clear parity err detect bit */ pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000); /* Clearing PCIX Ecc status register */ @@ -3554,7 +3528,7 @@ static void restore_xmsi_data(nic_t *nic) u64 val64; int i; - for (i=0; i < MAX_REQUESTED_MSI_X; i++) { + for (i=0; i< nic->avail_msix_vectors; i++) { writeq(nic->msix_info[i].addr, &bar0->xmsi_address); writeq(nic->msix_info[i].data, &bar0->xmsi_data); val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6)); @@ -3573,7 +3547,7 @@ static void store_xmsi_data(nic_t *nic) int i; /* Store and display */ - for (i=0; i < MAX_REQUESTED_MSI_X; i++) { + for (i=0; i< nic->avail_msix_vectors; i++) { val64 = (BIT(15) | vBIT(i, 26, 6)); writeq(val64, &bar0->xmsi_access); if (wait_for_msix_trans(nic, i)) { @@ -3834,11 +3808,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) TxD_t *txdp; TxFIFO_element_t __iomem *tx_fifo; unsigned long flags; +#ifdef NETIF_F_TSO + int mss; +#endif u16 vlan_tag = 0; int vlan_priority = 0; mac_info_t *mac_control; struct config_param *config; - int offload_type; mac_control = &sp->mac_control; config = &sp->config; @@ -3886,14 +3862,16 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } - offload_type = s2io_offload_type(skb); + txdp->Control_1 = 0; + txdp->Control_2 = 0; #ifdef NETIF_F_TSO - if (offload_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { + mss = skb_shinfo(skb)->gso_size; + if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) { txdp->Control_1 |= TXD_TCP_LSO_EN; - txdp->Control_1 |= TXD_TCP_LSO_MSS(s2io_tcp_mss(skb)); + txdp->Control_1 |= TXD_TCP_LSO_MSS(mss); } #endif - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { txdp->Control_2 |= (TXD_TX_CKO_IPV4_EN | TXD_TX_CKO_TCP_EN | TXD_TX_CKO_UDP_EN); @@ -3908,10 +3886,10 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) } frg_len = skb->len - skb->data_len; - if (offload_type == SKB_GSO_UDP) { + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) { int ufo_size; - ufo_size = s2io_udp_mss(skb); + ufo_size = skb_shinfo(skb)->gso_size; ufo_size &= ~7; txdp->Control_1 |= TXD_UFO_EN; txdp->Control_1 |= TXD_UFO_MSS(ufo_size); @@ -3928,13 +3906,16 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) sp->ufo_in_band_v, sizeof(u64), PCI_DMA_TODEVICE); txdp++; + txdp->Control_1 = 0; + txdp->Control_2 = 0; } txdp->Buffer_Pointer = pci_map_single (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); txdp->Host_Control = (unsigned long) skb; txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len); - if (offload_type == SKB_GSO_UDP) + + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) txdp->Control_1 |= TXD_UFO_EN; frg_cnt = skb_shinfo(skb)->nr_frags; @@ -3949,12 +3930,12 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) (sp->pdev, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size); - if (offload_type == SKB_GSO_UDP) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) txdp->Control_1 |= TXD_UFO_EN; } txdp->Control_1 |= TXD_GATHER_CODE_LAST; - if (offload_type == SKB_GSO_UDP) + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) frg_cnt++; /* as Txd0 was used for inband header */ tx_fifo = mac_control->tx_FIFO_start[queue]; @@ -3963,9 +3944,13 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST | TX_FIFO_LAST_LIST); - if (offload_type) - val64 |= TX_FIFO_SPECIAL_FUNC; +#ifdef NETIF_F_TSO + if (mss) + val64 |= TX_FIFO_SPECIAL_FUNC; +#endif + if (skb_shinfo(skb)->gso_type == SKB_GSO_UDP) + val64 |= TX_FIFO_SPECIAL_FUNC; writeq(val64, &tx_fifo->List_Control); mmiowb(); @@ -3999,41 +3984,13 @@ s2io_alarm_handle(unsigned long data) mod_timer(&sp->alarm_timer, jiffies + HZ / 2); } -static int s2io_chk_rx_buffers(nic_t *sp, int rng_n) -{ - int rxb_size, level; - - if (!sp->lro) { - rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]); - level = rx_buffer_level(sp, rxb_size, rng_n); - - if ((level == PANIC) && (!TASKLET_IN_USE)) { - int ret; - DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__); - DBG_PRINT(INTR_DBG, "PANIC levels\n"); - if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "Out of memory in %s", - __FUNCTION__); - clear_bit(0, (&sp->tasklet_status)); - return -1; - } - clear_bit(0, (&sp->tasklet_status)); - } else if (level == LOW) - tasklet_schedule(&sp->task); - - } else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) { - DBG_PRINT(ERR_DBG, "%s:Out of memory", sp->dev->name); - DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); - } - return 0; -} - static irqreturn_t s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; nic_t *sp = dev->priv; int i; + int ret; mac_info_t *mac_control; struct config_param *config; @@ -4055,8 +4012,35 @@ s2io_msi_handle(int irq, void *dev_id, struct pt_regs *regs) * reallocate the buffers from the interrupt handler itself, * else schedule a tasklet to reallocate the buffers. */ - for (i = 0; i < config->rx_ring_num; i++) - s2io_chk_rx_buffers(sp, i); + for (i = 0; i < config->rx_ring_num; i++) { + if (!sp->lro) { + int rxb_size = atomic_read(&sp->rx_bufs_left[i]); + int level = rx_buffer_level(sp, rxb_size, i); + + if ((level == PANIC) && (!TASKLET_IN_USE)) { + DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", + dev->name); + DBG_PRINT(INTR_DBG, "PANIC levels\n"); + if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", + dev->name); + DBG_PRINT(ERR_DBG, " in ISR!!\n"); + clear_bit(0, (&sp->tasklet_status)); + atomic_dec(&sp->isr_cnt); + return IRQ_HANDLED; + } + clear_bit(0, (&sp->tasklet_status)); + } else if (level == LOW) { + tasklet_schedule(&sp->task); + } + } + else if (fill_rx_buffers(sp, i) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", + dev->name); + DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); + break; + } + } atomic_dec(&sp->isr_cnt); return IRQ_HANDLED; @@ -4067,13 +4051,39 @@ s2io_msix_ring_handle(int irq, void *dev_id, struct pt_regs *regs) { ring_info_t *ring = (ring_info_t *)dev_id; nic_t *sp = ring->nic; + struct net_device *dev = (struct net_device *) dev_id; + int rxb_size, level, rng_n; atomic_inc(&sp->isr_cnt); - rx_intr_handler(ring); - s2io_chk_rx_buffers(sp, ring->ring_no); + + rng_n = ring->ring_no; + if (!sp->lro) { + rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]); + level = rx_buffer_level(sp, rxb_size, rng_n); + + if ((level == PANIC) && (!TASKLET_IN_USE)) { + int ret; + DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__); + DBG_PRINT(INTR_DBG, "PANIC levels\n"); + if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "Out of memory in %s", + __FUNCTION__); + clear_bit(0, (&sp->tasklet_status)); + return IRQ_HANDLED; + } + clear_bit(0, (&sp->tasklet_status)); + } else if (level == LOW) { + tasklet_schedule(&sp->task); + } + } + else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name); + DBG_PRINT(ERR_DBG, " in Rx Intr!!\n"); + } atomic_dec(&sp->isr_cnt); + return IRQ_HANDLED; } @@ -4238,8 +4248,37 @@ static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs) * else schedule a tasklet to reallocate the buffers. */ #ifndef CONFIG_S2IO_NAPI - for (i = 0; i < config->rx_ring_num; i++) - s2io_chk_rx_buffers(sp, i); + for (i = 0; i < config->rx_ring_num; i++) { + if (!sp->lro) { + int ret; + int rxb_size = atomic_read(&sp->rx_bufs_left[i]); + int level = rx_buffer_level(sp, rxb_size, i); + + if ((level == PANIC) && (!TASKLET_IN_USE)) { + DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", + dev->name); + DBG_PRINT(INTR_DBG, "PANIC levels\n"); + if ((ret = fill_rx_buffers(sp, i)) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", + dev->name); + DBG_PRINT(ERR_DBG, " in ISR!!\n"); + clear_bit(0, (&sp->tasklet_status)); + atomic_dec(&sp->isr_cnt); + writeq(org_mask, &bar0->general_int_mask); + return IRQ_HANDLED; + } + clear_bit(0, (&sp->tasklet_status)); + } else if (level == LOW) { + tasklet_schedule(&sp->task); + } + } + else if (fill_rx_buffers(sp, i) == -ENOMEM) { + DBG_PRINT(ERR_DBG, "%s:Out of memory", + dev->name); + DBG_PRINT(ERR_DBG, " in Rx intr!!\n"); + break; + } + } #endif writeq(org_mask, &bar0->general_int_mask); atomic_dec(&sp->isr_cnt); @@ -4269,8 +4308,6 @@ static void s2io_updt_stats(nic_t *sp) if (cnt == 5) break; /* Updt failed */ } while(1); - } else { - memset(sp->mac_control.stats_info, 0, sizeof(StatInfo_t)); } } @@ -4905,8 +4942,7 @@ static int write_eeprom(nic_t * sp, int off, u64 data, int cnt) } static void s2io_vpd_read(nic_t *nic) { - u8 *vpd_data; - u8 data; + u8 vpd_data[256],data; int i=0, cnt, fail = 0; int vpd_addr = 0x80; @@ -4919,10 +4955,6 @@ static void s2io_vpd_read(nic_t *nic) vpd_addr = 0x50; } - vpd_data = kmalloc(256, GFP_KERNEL); - if (!vpd_data) - return; - for (i = 0; i < 256; i +=4 ) { pci_write_config_byte(nic->pdev, (vpd_addr + 2), i); pci_read_config_byte(nic->pdev, (vpd_addr + 2), &data); @@ -4945,7 +4977,6 @@ static void s2io_vpd_read(nic_t *nic) memset(nic->product_name, 0, vpd_data[1]); memcpy(nic->product_name, &vpd_data[3], vpd_data[1]); } - kfree(vpd_data); } /** @@ -5264,7 +5295,7 @@ static int s2io_link_test(nic_t * sp, uint64_t * data) else *data = 0; - return *data; + return 0; } /** @@ -5722,19 +5753,6 @@ static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data) return 0; } -static u32 s2io_ethtool_op_get_tso(struct net_device *dev) -{ - return (dev->features & NETIF_F_TSO) != 0; -} -static int s2io_ethtool_op_set_tso(struct net_device *dev, u32 data) -{ - if (data) - dev->features |= (NETIF_F_TSO | NETIF_F_TSO6); - else - dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6); - - return 0; -} static struct ethtool_ops netdev_ethtool_ops = { .get_settings = s2io_ethtool_gset, @@ -5755,8 +5773,8 @@ static struct ethtool_ops netdev_ethtool_ops = { .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, #ifdef NETIF_F_TSO - .get_tso = s2io_ethtool_op_get_tso, - .set_tso = s2io_ethtool_op_set_tso, + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, #endif .get_ufo = ethtool_op_get_ufo, .set_ufo = ethtool_op_set_ufo, @@ -6319,7 +6337,7 @@ static int s2io_card_up(nic_t * sp) s2io_set_multicast(dev); if (sp->lro) { - /* Initialize max aggregatable pkts per session based on MTU */ + /* Initialize max aggregatable pkts based on MTU */ sp->lro_max_aggr_per_sess = ((1<<16) - 1) / dev->mtu; /* Check if we can use(if specified) user provided value */ if (lro_max_pkts < sp->lro_max_aggr_per_sess) @@ -6420,7 +6438,7 @@ static void s2io_tx_watchdog(struct net_device *dev) * @cksum : FCS checksum of the frame. * @ring_no : the ring from which this RxD was extracted. * Description: - * This function is called by the Rx interrupt serivce routine to perform + * This function is called by the Tx interrupt serivce routine to perform * some OS related operations on the SKB before passing it to the upper * layers. It mainly checks if the checksum is OK, if so adds it to the * SKBs cksum variable, increments the Rx packet count and passes the SKB @@ -6680,6 +6698,33 @@ static void s2io_init_pci(nic_t * sp) pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); } +MODULE_AUTHOR("Raghavendra Koushik "); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_param(tx_fifo_num, int, 0); +module_param(rx_ring_num, int, 0); +module_param(rx_ring_mode, int, 0); +module_param_array(tx_fifo_len, uint, NULL, 0); +module_param_array(rx_ring_sz, uint, NULL, 0); +module_param_array(rts_frm_len, uint, NULL, 0); +module_param(use_continuous_tx_intrs, int, 1); +module_param(rmac_pause_time, int, 0); +module_param(mc_pause_threshold_q0q3, int, 0); +module_param(mc_pause_threshold_q4q7, int, 0); +module_param(shared_splits, int, 0); +module_param(tmac_util_period, int, 0); +module_param(rmac_util_period, int, 0); +module_param(bimodal, bool, 0); +module_param(l3l4hdr_size, int , 0); +#ifndef CONFIG_S2IO_NAPI +module_param(indicate_max_pkts, int, 0); +#endif +module_param(rxsync_frequency, int, 0); +module_param(intr_type, int, 0); +module_param(lro, int, 0); +module_param(lro_max_pkts, int, 0); + static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type) { if ( tx_fifo_num > 8) { @@ -6787,8 +6832,8 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) } if (dev_intr_type != MSI_X) { if (pci_request_regions(pdev, s2io_driver_name)) { - DBG_PRINT(ERR_DBG, "Request Regions failed\n"); - pci_disable_device(pdev); + DBG_PRINT(ERR_DBG, "Request Regions failed\n"), + pci_disable_device(pdev); return -ENODEV; } } @@ -6912,7 +6957,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) /* initialize the shared memory used by the NIC and the host */ if (init_shared_mem(sp)) { DBG_PRINT(ERR_DBG, "%s: Memory allocation failed\n", - dev->name); + __FUNCTION__); ret = -ENOMEM; goto mem_alloc_failed; } @@ -7049,9 +7094,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) dev->addr_len = ETH_ALEN; memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN); - /* reset Nic and bring it to known state */ - s2io_reset(sp); - /* * Initialize the tasklet status and link state flags * and the card state parameter @@ -7089,11 +7131,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) goto register_failed; } s2io_vpd_read(sp); + DBG_PRINT(ERR_DBG, "%s: Neterion %s",dev->name, sp->product_name); + DBG_PRINT(ERR_DBG, "(rev %d), Driver version %s\n", + get_xena_rev_id(sp->pdev), + s2io_driver_version); DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2005 Neterion Inc.\n"); - DBG_PRINT(ERR_DBG, "%s: Neterion %s (rev %d)\n",dev->name, - sp->product_name, get_xena_rev_id(sp->pdev)); - DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name, - s2io_driver_version); DBG_PRINT(ERR_DBG, "%s: MAC ADDR: " "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, sp->def_mac_addr[0].mac_addr[0], @@ -7394,13 +7436,8 @@ static int verify_l3_l4_lro_capable(lro_t *l_lro, struct iphdr *ip, if (ip->ihl != 5) /* IP has options */ return -1; - /* If we see CE codepoint in IP header, packet is not mergeable */ - if (INET_ECN_is_ce(ipv4_get_dsfield(ip))) - return -1; - - /* If we see ECE or CWR flags in TCP header, packet is not mergeable */ if (tcp->urg || tcp->psh || tcp->rst || tcp->syn || tcp->fin || - tcp->ece || tcp->cwr || !tcp->ack) { + !tcp->ack) { /* * Currently recognize only the ack control word and * any other control field being set would result in @@ -7554,16 +7591,18 @@ static void queue_rx_frame(struct sk_buff *skb) static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len) { - struct sk_buff *first = lro->parent; + struct sk_buff *tmp, *first = lro->parent; first->len += tcp_len; first->data_len = lro->frags_len; skb_pull(skb, (skb->len - tcp_len)); - if (skb_shinfo(first)->frag_list) - lro->last_frag->next = skb; + if ((tmp = skb_shinfo(first)->frag_list)) { + while (tmp->next) + tmp = tmp->next; + tmp->next = skb; + } else skb_shinfo(first)->frag_list = skb; - lro->last_frag = skb; sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++; return; } diff --git a/trunk/drivers/net/s2io.h b/trunk/drivers/net/s2io.h index 5ed49c3be1e9..217097bc22f1 100644 --- a/trunk/drivers/net/s2io.h +++ b/trunk/drivers/net/s2io.h @@ -719,7 +719,6 @@ struct msix_info_st { /* Data structure to represent a LRO session */ typedef struct lro { struct sk_buff *parent; - struct sk_buff *last_frag; u8 *l2h; struct iphdr *iph; struct tcphdr *tcph; @@ -1012,13 +1011,4 @@ static void clear_lro_session(lro_t *lro); static void queue_rx_frame(struct sk_buff *skb); static void update_L3L4_header(nic_t *sp, lro_t *lro); static void lro_append_pkt(nic_t *sp, lro_t *lro, struct sk_buff *skb, u32 tcp_len); - -#define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size -#define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size -#define s2io_offload_type(skb) skb_shinfo(skb)->gso_type - -#define S2IO_PARM_INT(X, def_val) \ - static unsigned int X = def_val;\ - module_param(X , uint, 0); - #endif /* _S2IO_H */ diff --git a/trunk/drivers/net/seeq8005.c b/trunk/drivers/net/seeq8005.c index 01392bca0223..efd0f235020f 100644 --- a/trunk/drivers/net/seeq8005.c +++ b/trunk/drivers/net/seeq8005.c @@ -742,7 +742,7 @@ module_param(irq, int, 0); MODULE_PARM_DESC(io, "SEEQ 8005 I/O base address"); MODULE_PARM_DESC(irq, "SEEQ 8005 IRQ number"); -int __init init_module(void) +int init_module(void) { dev_seeq = seeq8005_probe(-1); if (IS_ERR(dev_seeq)) diff --git a/trunk/drivers/net/sk98lin/skge.c b/trunk/drivers/net/sk98lin/skge.c index eb3b35180c2f..ee62845d3ac9 100644 --- a/trunk/drivers/net/sk98lin/skge.c +++ b/trunk/drivers/net/sk98lin/skge.c @@ -1559,7 +1559,7 @@ struct sk_buff *pMessage) /* pointer to send-message */ pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); pTxd->pMBuf = pMessage; - if (pMessage->ip_summed == CHECKSUM_PARTIAL) { + if (pMessage->ip_summed == CHECKSUM_HW) { u16 hdrlen = pMessage->h.raw - pMessage->data; u16 offset = hdrlen + pMessage->csum; @@ -1678,7 +1678,7 @@ struct sk_buff *pMessage) /* pointer to send-message */ /* ** Does the HW need to evaluate checksum for TCP or UDP packets? */ - if (pMessage->ip_summed == CHECKSUM_PARTIAL) { + if (pMessage->ip_summed == CHECKSUM_HW) { u16 hdrlen = pMessage->h.raw - pMessage->data; u16 offset = hdrlen + pMessage->csum; @@ -2158,7 +2158,7 @@ SK_U64 PhysAddr; #ifdef USE_SK_RX_CHECKSUM pMsg->csum = pRxd->TcpSums & 0xffff; - pMsg->ip_summed = CHECKSUM_COMPLETE; + pMsg->ip_summed = CHECKSUM_HW; #else pMsg->ip_summed = CHECKSUM_NONE; #endif diff --git a/trunk/drivers/net/skge.c b/trunk/drivers/net/skge.c index b3d6fa3d6df4..82200bfaa8ed 100644 --- a/trunk/drivers/net/skge.c +++ b/trunk/drivers/net/skge.c @@ -516,7 +516,10 @@ static int skge_set_pauseparam(struct net_device *dev, /* Chip internal frequency for clock calculations */ static inline u32 hwkhz(const struct skge_hw *hw) { - return (hw->chip_id == CHIP_ID_GENESIS) ? 53125 : 78125; + if (hw->chip_id == CHIP_ID_GENESIS) + return 53215; /* or: 53.125 MHz */ + else + return 78215; /* or: 78.125 MHz */ } /* Chip HZ to microseconds */ @@ -2211,7 +2214,6 @@ static int skge_up(struct net_device *dev) skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); skge_led(skge, LED_MODE_ON); - netif_poll_enable(dev); return 0; free_rx_ring: @@ -2280,7 +2282,6 @@ static int skge_down(struct net_device *dev) skge_led(skge, LED_MODE_OFF); - netif_poll_disable(dev); skge_tx_clean(skge); skge_rx_clean(skge); @@ -2338,7 +2339,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) td->dma_lo = map; td->dma_hi = map >> 32; - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { int offset = skb->h.raw - skb->data; /* This seems backwards, but it is what the sk98lin @@ -2642,7 +2643,7 @@ static inline struct sk_buff *skge_rx_get(struct skge_port *skge, skb->dev = skge->netdev; if (skge->rx_csum) { skb->csum = csum; - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_HW; } skb->protocol = eth_type_trans(skb, skge->netdev); diff --git a/trunk/drivers/net/sky2.c b/trunk/drivers/net/sky2.c index 8e92566b587e..de91609ca112 100644 --- a/trunk/drivers/net/sky2.c +++ b/trunk/drivers/net/sky2.c @@ -233,8 +233,6 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) if (hw->ports > 1) reg1 |= PCI_Y2_PHY2_COMA; } - sky2_pci_write32(hw, PCI_DEV_REG1, reg1); - udelay(100); if (hw->chip_id == CHIP_ID_YUKON_EC_U) { sky2_pci_write32(hw, PCI_DEV_REG3, 0); @@ -244,6 +242,9 @@ static void sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) sky2_pci_write32(hw, PCI_DEV_REG5, 0); } + sky2_pci_write32(hw, PCI_DEV_REG1, reg1); + udelay(100); + break; case PCI_D3hot: @@ -1163,7 +1164,7 @@ static unsigned tx_le_req(const struct sk_buff *skb) if (skb_is_gso(skb)) ++count; - if (skb->ip_summed == CHECKSUM_PARTIAL) + if (skb->ip_summed == CHECKSUM_HW) ++count; return count; @@ -1272,7 +1273,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) #endif /* Handle TCP checksum offload */ - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { u16 hdr = skb->h.raw - skb->data; u16 offset = hdr + skb->csum; @@ -2000,7 +2001,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) #endif case OP_RXCHKS: skb = sky2->rx_ring[sky2->rx_next].skb; - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_HW; skb->csum = le16_to_cpu(status); break; diff --git a/trunk/drivers/net/smc911x.c b/trunk/drivers/net/smc911x.c index 0b15290df278..d37bd860b336 100644 --- a/trunk/drivers/net/smc911x.c +++ b/trunk/drivers/net/smc911x.c @@ -1092,7 +1092,6 @@ static irqreturn_t smc911x_interrupt(int irq, void *dev_id, struct pt_regs *regs /* Spurious interrupt check */ if ((SMC_GET_IRQ_CFG() & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) != (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) { - spin_unlock_irqrestore(&lp->lock, flags); return IRQ_NONE; } diff --git a/trunk/drivers/net/smc91x.c b/trunk/drivers/net/smc91x.c index cf62373b808b..3d8dcb6c8758 100644 --- a/trunk/drivers/net/smc91x.c +++ b/trunk/drivers/net/smc91x.c @@ -321,12 +321,12 @@ static void smc_reset(struct net_device *dev) DBG(2, "%s: %s\n", dev->name, __FUNCTION__); /* Disable all interrupts, block TX tasklet */ - spin_lock_irq(&lp->lock); + spin_lock(&lp->lock); SMC_SELECT_BANK(2); SMC_SET_INT_MASK(0); pending_skb = lp->pending_tx_skb; lp->pending_tx_skb = NULL; - spin_unlock_irq(&lp->lock); + spin_unlock(&lp->lock); /* free any pending tx skb */ if (pending_skb) { @@ -448,12 +448,12 @@ static void smc_shutdown(struct net_device *dev) DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__); /* no more interrupts for me */ - spin_lock_irq(&lp->lock); + spin_lock(&lp->lock); SMC_SELECT_BANK(2); SMC_SET_INT_MASK(0); pending_skb = lp->pending_tx_skb; lp->pending_tx_skb = NULL; - spin_unlock_irq(&lp->lock); + spin_unlock(&lp->lock); if (pending_skb) dev_kfree_skb(pending_skb); diff --git a/trunk/drivers/net/smc91x.h b/trunk/drivers/net/smc91x.h index 7aa7fbac8224..4ec4b4d23ae5 100644 --- a/trunk/drivers/net/smc91x.h +++ b/trunk/drivers/net/smc91x.h @@ -136,9 +136,14 @@ #define SMC_CAN_USE_32BIT 0 #define SMC_IO_SHIFT 0 #define SMC_NOWAIT 1 +#define SMC_USE_PXA_DMA 1 +#define SMC_inb(a, r) readb((a) + (r)) #define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) #define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) #define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) @@ -184,10 +189,16 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_IO_SHIFT 0 #define SMC_NOWAIT 1 +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) #define SMC_inw(a, r) readw((a) + (r)) #define SMC_outw(v, a, r) writew(v, (a) + (r)) #define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) #include #include @@ -361,24 +372,6 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r, #define SMC_IRQ_FLAGS (0) -#elif defined(CONFIG_ARCH_VERSATILE) - -#define SMC_CAN_USE_8BIT 1 -#define SMC_CAN_USE_16BIT 1 -#define SMC_CAN_USE_32BIT 1 -#define SMC_NOWAIT 1 - -#define SMC_inb(a, r) readb((a) + (r)) -#define SMC_inw(a, r) readw((a) + (r)) -#define SMC_inl(a, r) readl((a) + (r)) -#define SMC_outb(v, a, r) writeb(v, (a) + (r)) -#define SMC_outw(v, a, r) writew(v, (a) + (r)) -#define SMC_outl(v, a, r) writel(v, (a) + (r)) -#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) -#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) - -#define SMC_IRQ_FLAGS (0) - #else #define SMC_CAN_USE_8BIT 1 diff --git a/trunk/drivers/net/spider_net.c b/trunk/drivers/net/spider_net.c index d64e718afbd2..647f62e9707d 100644 --- a/trunk/drivers/net/spider_net.c +++ b/trunk/drivers/net/spider_net.c @@ -1611,12 +1611,13 @@ spider_net_open(struct net_device *netdev) int result; result = -ENOMEM; - if (spider_net_init_chain(card, &card->tx_chain, card->descr, - PCI_DMA_TODEVICE, card->tx_desc)) + if (spider_net_init_chain(card, &card->tx_chain, + card->descr, + PCI_DMA_TODEVICE, tx_descriptors)) goto alloc_tx_failed; if (spider_net_init_chain(card, &card->rx_chain, - card->descr + card->rx_desc, - PCI_DMA_FROMDEVICE, card->rx_desc)) + card->descr + tx_descriptors, + PCI_DMA_FROMDEVICE, rx_descriptors)) goto alloc_rx_failed; /* allocate rx skbs */ @@ -1697,10 +1698,10 @@ spider_net_setup_phy(struct spider_net_card *card) */ static int spider_net_download_firmware(struct spider_net_card *card, - const void *firmware_ptr) + u8 *firmware_ptr) { int sequencer, i; - const u32 *fw_ptr = firmware_ptr; + u32 *fw_ptr = (u32 *)firmware_ptr; /* stop sequencers */ spider_net_write_reg(card, SPIDER_NET_GSINIT, @@ -1757,7 +1758,7 @@ spider_net_init_firmware(struct spider_net_card *card) { struct firmware *firmware = NULL; struct device_node *dn; - const u8 *fw_prop = NULL; + u8 *fw_prop = NULL; int err = -ENOENT; int fw_size; @@ -1783,7 +1784,7 @@ spider_net_init_firmware(struct spider_net_card *card) if (!dn) goto out_err; - fw_prop = get_property(dn, "firmware", &fw_size); + fw_prop = (u8 *)get_property(dn, "firmware", &fw_size); if (!fw_prop) goto out_err; @@ -1986,7 +1987,7 @@ spider_net_setup_netdev(struct spider_net_card *card) struct net_device *netdev = card->netdev; struct device_node *dn; struct sockaddr addr; - const u8 *mac; + u8 *mac; SET_MODULE_OWNER(netdev); SET_NETDEV_DEV(netdev, &card->pdev->dev); @@ -2004,9 +2005,6 @@ spider_net_setup_netdev(struct spider_net_card *card) card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT; - card->tx_desc = tx_descriptors; - card->rx_desc = rx_descriptors; - spider_net_setup_netdev_ops(netdev); netdev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX; @@ -2019,7 +2017,7 @@ spider_net_setup_netdev(struct spider_net_card *card) if (!dn) return -EIO; - mac = get_property(dn, "local-mac-address", NULL); + mac = (u8 *)get_property(dn, "local-mac-address", NULL); if (!mac) return -EIO; memcpy(addr.sa_data, mac, ETH_ALEN); diff --git a/trunk/drivers/net/spider_net.h b/trunk/drivers/net/spider_net.h index 30407cdf0892..f6dcf180ae3d 100644 --- a/trunk/drivers/net/spider_net.h +++ b/trunk/drivers/net/spider_net.h @@ -440,9 +440,6 @@ struct spider_net_card { /* for ethtool */ int msg_enable; - int rx_desc; - int tx_desc; - struct spider_net_descr descr[0]; }; diff --git a/trunk/drivers/net/spider_net_ethtool.c b/trunk/drivers/net/spider_net_ethtool.c index 02209222b8c9..a5bb0b7633af 100644 --- a/trunk/drivers/net/spider_net_ethtool.c +++ b/trunk/drivers/net/spider_net_ethtool.c @@ -130,18 +130,6 @@ spider_net_ethtool_set_tx_csum(struct net_device *netdev, uint32_t data) return 0; } -static void -spider_net_ethtool_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ering) -{ - struct spider_net_card *card = netdev->priv; - - ering->tx_max_pending = SPIDER_NET_TX_DESCRIPTORS_MAX; - ering->tx_pending = card->tx_desc; - ering->rx_max_pending = SPIDER_NET_RX_DESCRIPTORS_MAX; - ering->rx_pending = card->rx_desc; -} - struct ethtool_ops spider_net_ethtool_ops = { .get_settings = spider_net_ethtool_get_settings, .get_drvinfo = spider_net_ethtool_get_drvinfo, @@ -153,6 +141,5 @@ struct ethtool_ops spider_net_ethtool_ops = { .set_rx_csum = spider_net_ethtool_set_rx_csum, .get_tx_csum = spider_net_ethtool_get_tx_csum, .set_tx_csum = spider_net_ethtool_set_tx_csum, - .get_ringparam = spider_net_ethtool_get_ringparam, }; diff --git a/trunk/drivers/net/starfire.c b/trunk/drivers/net/starfire.c index 2607aa51d8e0..c0a62b00ffc8 100644 --- a/trunk/drivers/net/starfire.c +++ b/trunk/drivers/net/starfire.c @@ -1230,7 +1230,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) } #if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE) - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { if (skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK)) return NETDEV_TX_OK; } @@ -1252,7 +1252,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev) status |= TxDescIntr; np->reap_tx = 0; } - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { status |= TxCalTCP; np->stats.tx_compressed++; } @@ -1499,7 +1499,7 @@ static int __netdev_rx(struct net_device *dev, int *quota) * Until then, the printk stays. :-) -Ion */ else if (le16_to_cpu(desc->status2) & 0x0040) { - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_HW; skb->csum = le16_to_cpu(desc->csum); printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2)); } diff --git a/trunk/drivers/net/sundance.c b/trunk/drivers/net/sundance.c index 698568e751da..ac17377b3e9f 100644 --- a/trunk/drivers/net/sundance.c +++ b/trunk/drivers/net/sundance.c @@ -107,7 +107,7 @@ static char *media[MAX_UNITS]; #endif /* These identify the driver base version and may not be removed. */ -static char version[] = +static char version[] __devinitdata = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n" KERN_INFO " http://www.scyld.com/network/sundance.html\n"; diff --git a/trunk/drivers/net/sungem.c b/trunk/drivers/net/sungem.c index b388651b7836..b70bbd748978 100644 --- a/trunk/drivers/net/sungem.c +++ b/trunk/drivers/net/sungem.c @@ -855,7 +855,7 @@ static int gem_rx(struct gem *gp, int work_to_do) } skb->csum = ntohs((status & RXDCTRL_TCPCSUM) ^ 0xffff); - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_HW; skb->protocol = eth_type_trans(skb, gp->dev); netif_receive_skb(skb); @@ -1026,7 +1026,7 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned long flags; ctrl = 0; - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { u64 csum_start_off, csum_stuff_off; csum_start_off = (u64) (skb->h.raw - skb->data); @@ -2896,7 +2896,7 @@ static int __devinit gem_get_device_address(struct gem *gp) if (use_idprom) memcpy(dev->dev_addr, idprom->id_ethaddr, 6); #elif defined(CONFIG_PPC_PMAC) - const unsigned char *addr; + unsigned char *addr; addr = get_property(gp->of_node, "local-mac-address", NULL); if (addr == NULL) { diff --git a/trunk/drivers/net/sunhme.c b/trunk/drivers/net/sunhme.c index 17981da22730..c6f5bc3c042f 100644 --- a/trunk/drivers/net/sunhme.c +++ b/trunk/drivers/net/sunhme.c @@ -1207,7 +1207,7 @@ static void happy_meal_transceiver_check(struct happy_meal *hp, void __iomem *tr * flags, thus: * * skb->csum = rxd->rx_flags & 0xffff; - * skb->ip_summed = CHECKSUM_COMPLETE; + * skb->ip_summed = CHECKSUM_HW; * * before sending off the skb to the protocols, and we are good as gold. */ @@ -2074,7 +2074,7 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev) /* This card is _fucking_ hot... */ skb->csum = ntohs(csum ^ 0xffff); - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_HW; RXD(("len=%d csum=%4x]", len, csum)); skb->protocol = eth_type_trans(skb, dev); @@ -2268,7 +2268,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) u32 tx_flags; tx_flags = TXFLAG_OWN; - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { u32 csum_start_off, csum_stuff_off; csum_start_off = (u32) (skb->h.raw - skb->data); diff --git a/trunk/drivers/net/sunlance.c b/trunk/drivers/net/sunlance.c index ec0413609f36..1ef9fd39a79a 100644 --- a/trunk/drivers/net/sunlance.c +++ b/trunk/drivers/net/sunlance.c @@ -1537,7 +1537,7 @@ static int __init sparc_lance_init(void) { if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) || (idprom->id_machtype == (SM_SUN4|SM_4_470))) { - memset(&sun4_sdev, 0, sizeof(struct sbus_dev)); + memset(&sun4_sdev, 0, sizeof(sdev)); sun4_sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; sun4_sdev.irqs[0] = 6; return sparc_lance_probe_one(&sun4_sdev, NULL, NULL); @@ -1547,16 +1547,16 @@ static int __init sparc_lance_init(void) static int __exit sunlance_sun4_remove(void) { - struct lance_private *lp = dev_get_drvdata(&sun4_sdev.ofdev.dev); + struct lance_private *lp = dev_get_drvdata(&sun4_sdev->dev); struct net_device *net_dev = lp->dev; unregister_netdevice(net_dev); - lance_free_hwresources(lp); + lance_free_hwresources(root_lance_dev); free_netdev(net_dev); - dev_set_drvdata(&sun4_sdev.ofdev.dev, NULL); + dev_set_drvdata(&sun4_sdev->dev, NULL); return 0; } @@ -1566,21 +1566,20 @@ static int __exit sunlance_sun4_remove(void) static int __devinit sunlance_sbus_probe(struct of_device *dev, const struct of_device_id *match) { struct sbus_dev *sdev = to_sbus_device(&dev->dev); + struct device_node *dp = dev->node; int err; - if (sdev->parent) { - struct of_device *parent = &sdev->parent->ofdev; + if (!strcmp(dp->name, "le")) { + err = sparc_lance_probe_one(sdev, NULL, NULL); + } else if (!strcmp(dp->name, "ledma")) { + struct sbus_dma *ledma = find_ledma(sdev); - if (!strcmp(parent->node->name, "ledma")) { - struct sbus_dma *ledma = find_ledma(to_sbus_device(&parent->dev)); + err = sparc_lance_probe_one(sdev->child, ledma, NULL); + } else { + BUG_ON(strcmp(dp->name, "lebuffer")); - err = sparc_lance_probe_one(sdev, ledma, NULL); - } else if (!strcmp(parent->node->name, "lebuffer")) { - err = sparc_lance_probe_one(sdev, NULL, to_sbus_device(&parent->dev)); - } else - err = sparc_lance_probe_one(sdev, NULL, NULL); - } else - err = sparc_lance_probe_one(sdev, NULL, NULL); + err = sparc_lance_probe_one(sdev->child, NULL, sdev); + } return err; } @@ -1605,6 +1604,12 @@ static struct of_device_id sunlance_sbus_match[] = { { .name = "le", }, + { + .name = "ledma", + }, + { + .name = "lebuffer", + }, {}, }; diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index fb7026153861..1b8138f641e3 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.65" -#define DRV_MODULE_RELDATE "August 07, 2006" +#define DRV_MODULE_VERSION "3.63" +#define DRV_MODULE_RELDATE "July 25, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -123,6 +123,9 @@ TG3_RX_RCB_RING_SIZE(tp)) #define TG3_TX_RING_BYTES (sizeof(struct tg3_tx_buffer_desc) * \ TG3_TX_RING_SIZE) +#define TX_BUFFS_AVAIL(TP) \ + ((TP)->tx_pending - \ + (((TP)->tx_prod - (TP)->tx_cons) & (TG3_TX_RING_SIZE - 1))) #define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1)) #define RX_PKT_BUF_SZ (1536 + tp->rx_offset + 64) @@ -149,67 +152,122 @@ module_param(tg3_debug, int, 0); MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value"); static struct pci_device_id tg3_pci_tbl[] = { - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S)}, - {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781)}, - {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)}, - {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)}, - {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)}, - {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001)}, - {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003)}, - {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100)}, - {PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3)}, - {} + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5720, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5750M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { 0, } }; MODULE_DEVICE_TABLE(pci, tg3_pci_tbl); -static const struct { +static struct { const char string[ETH_GSTRING_LEN]; } ethtool_stats_keys[TG3_NUM_STATS] = { { "rx_octets" }, @@ -290,7 +348,7 @@ static const struct { { "nic_tx_threshold_hit" } }; -static const struct { +static struct { const char string[ETH_GSTRING_LEN]; } ethtool_test_keys[TG3_NUM_TEST] = { { "nvram test (online) " }, @@ -2929,13 +2987,6 @@ static void tg3_tx_recover(struct tg3 *tp) spin_unlock(&tp->lock); } -static inline u32 tg3_tx_avail(struct tg3 *tp) -{ - smp_mb(); - return (tp->tx_pending - - ((tp->tx_prod - tp->tx_cons) & (TG3_TX_RING_SIZE - 1))); -} - /* Tigon3 never reports partial packet sends. So we do not * need special logic to handle SKBs that have not had all * of their frags sent yet, like SunGEM does. @@ -2987,20 +3038,12 @@ static void tg3_tx(struct tg3 *tp) tp->tx_cons = sw_idx; - /* Need to make the tx_cons update visible to tg3_start_xmit() - * before checking for netif_queue_stopped(). Without the - * memory barrier, there is a small possibility that tg3_start_xmit() - * will miss it and cause the queue to be stopped forever. - */ - smp_mb(); - - if (unlikely(netif_queue_stopped(tp->dev) && - (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))) { - netif_tx_lock(tp->dev); + if (unlikely(netif_queue_stopped(tp->dev))) { + spin_lock(&tp->tx_lock); if (netif_queue_stopped(tp->dev) && - (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)) + (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)) netif_wake_queue(tp->dev); - netif_tx_unlock(tp->dev); + spin_unlock(&tp->tx_lock); } } @@ -3054,10 +3097,11 @@ static int tg3_alloc_rx_skb(struct tg3 *tp, u32 opaque_key, * Callers depend upon this behavior and assume that * we leave everything unchanged if we fail. */ - skb = netdev_alloc_skb(tp->dev, skb_size); + skb = dev_alloc_skb(skb_size); if (skb == NULL) return -ENOMEM; + skb->dev = tp->dev; skb_reserve(skb, tp->rx_offset); mapping = pci_map_single(tp->pdev, skb->data, @@ -3226,10 +3270,11 @@ static int tg3_rx(struct tg3 *tp, int budget) tg3_recycle_rx(tp, opaque_key, desc_idx, *post_ptr); - copy_skb = netdev_alloc_skb(tp->dev, len + 2); + copy_skb = dev_alloc_skb(len + 2); if (copy_skb == NULL) goto drop_it_no_recycle; + copy_skb->dev = tp->dev; skb_reserve(copy_skb, 2); skb_put(copy_skb, len); pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE); @@ -3752,7 +3797,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ - if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { + if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); @@ -3796,11 +3841,11 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) skb->h.th->check = 0; } - else if (skb->ip_summed == CHECKSUM_PARTIAL) + else if (skb->ip_summed == CHECKSUM_HW) base_flags |= TXD_FLAG_TCPUDP_CSUM; #else mss = 0; - if (skb->ip_summed == CHECKSUM_PARTIAL) + if (skb->ip_summed == CHECKSUM_HW) base_flags |= TXD_FLAG_TCPUDP_CSUM; #endif #if TG3_VLAN_TAG_USED @@ -3848,10 +3893,12 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); tp->tx_prod = entry; - if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { + if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) { + spin_lock(&tp->tx_lock); netif_stop_queue(dev); - if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH) + if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH) netif_wake_queue(tp->dev); + spin_unlock(&tp->tx_lock); } out_unlock: @@ -3873,7 +3920,7 @@ static int tg3_tso_bug(struct tg3 *tp, struct sk_buff *skb) struct sk_buff *segs, *nskb; /* Estimate the number of fragments in the worst case */ - if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->gso_segs * 3))) { + if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->gso_segs * 3))) { netif_stop_queue(tp->dev); return NETDEV_TX_BUSY; } @@ -3913,7 +3960,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) * interrupt. Furthermore, IRQ processing runs lockless so we have * no IRQ context deadlocks to worry about either. Rejoice! */ - if (unlikely(tg3_tx_avail(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { + if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) { if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); @@ -3926,7 +3973,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) entry = tp->tx_prod; base_flags = 0; - if (skb->ip_summed == CHECKSUM_PARTIAL) + if (skb->ip_summed == CHECKSUM_HW) base_flags |= TXD_FLAG_TCPUDP_CSUM; #if TG3_TSO_SUPPORT != 0 mss = 0; @@ -4063,10 +4110,12 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry); tp->tx_prod = entry; - if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { + if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) { + spin_lock(&tp->tx_lock); netif_stop_queue(dev); - if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH) + if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH) netif_wake_queue(tp->dev); + spin_unlock(&tp->tx_lock); } out_unlock: @@ -4914,7 +4963,7 @@ static int tg3_halt(struct tg3 *tp, int kind, int silent) #define TG3_FW_BSS_ADDR 0x08000a70 #define TG3_FW_BSS_LEN 0x10 -static const u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = { +static u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = { 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000018, 0x00000000, 0x0000000d, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100034, @@ -5008,7 +5057,7 @@ static const u32 tg3FwText[(TG3_FW_TEXT_LEN / sizeof(u32)) + 1] = { 0x27bd0008, 0x03e00008, 0x00000000, 0x00000000, 0x00000000 }; -static const u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = { +static u32 tg3FwRodata[(TG3_FW_RODATA_LEN / sizeof(u32)) + 1] = { 0x35373031, 0x726c7341, 0x00000000, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, 0x45766e74, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, @@ -5073,13 +5122,13 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) struct fw_info { unsigned int text_base; unsigned int text_len; - const u32 *text_data; + u32 *text_data; unsigned int rodata_base; unsigned int rodata_len; - const u32 *rodata_data; + u32 *rodata_data; unsigned int data_base; unsigned int data_len; - const u32 *data_data; + u32 *data_data; }; /* tp->lock is held. */ @@ -5211,7 +5260,7 @@ static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp) #define TG3_TSO_FW_BSS_ADDR 0x08001b80 #define TG3_TSO_FW_BSS_LEN 0x894 -static const u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = { +static u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = { 0x0e000003, 0x00000000, 0x08001b24, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0800, 0x37bd4000, 0x03a0f021, 0x3c100800, 0x26100000, 0x0e000010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe, @@ -5498,7 +5547,7 @@ static const u32 tg3TsoFwText[(TG3_TSO_FW_TEXT_LEN / 4) + 1] = { 0xac470014, 0xac4a0018, 0x03e00008, 0xac4b001c, 0x00000000, 0x00000000, }; -static const u32 tg3TsoFwRodata[] = { +static u32 tg3TsoFwRodata[] = { 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x496e0000, 0x73746b6f, 0x66662a2a, 0x00000000, 0x53774576, 0x656e7430, 0x00000000, 0x00000000, @@ -5506,7 +5555,7 @@ static const u32 tg3TsoFwRodata[] = { 0x00000000, }; -static const u32 tg3TsoFwData[] = { +static u32 tg3TsoFwData[] = { 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x362e3000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, @@ -5528,7 +5577,7 @@ static const u32 tg3TsoFwData[] = { #define TG3_TSO5_FW_BSS_ADDR 0x00010f50 #define TG3_TSO5_FW_BSS_LEN 0x88 -static const u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = { +static u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = { 0x0c004003, 0x00000000, 0x00010f04, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c1d0001, 0x37bde000, 0x03a0f021, 0x3c100001, 0x26100000, 0x0c004010, 0x00000000, 0x0000000d, 0x27bdffe0, 0x3c04fefe, @@ -5687,14 +5736,14 @@ static const u32 tg3Tso5FwText[(TG3_TSO5_FW_TEXT_LEN / 4) + 1] = { 0x00000000, 0x00000000, 0x00000000, }; -static const u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = { +static u32 tg3Tso5FwRodata[(TG3_TSO5_FW_RODATA_LEN / 4) + 1] = { 0x4d61696e, 0x43707542, 0x00000000, 0x4d61696e, 0x43707541, 0x00000000, 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x73746b6f, 0x66666c64, 0x00000000, 0x00000000, 0x66617461, 0x6c457272, 0x00000000, 0x00000000, 0x00000000, }; -static const u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = { +static u32 tg3Tso5FwData[(TG3_TSO5_FW_DATA_LEN / 4) + 1] = { 0x00000000, 0x73746b6f, 0x66666c64, 0x5f76312e, 0x322e3000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }; @@ -8569,7 +8618,7 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) err = -EIO; tx_len = 1514; - skb = netdev_alloc_skb(tp->dev, tx_len); + skb = dev_alloc_skb(tx_len); if (!skb) return -ENOMEM; @@ -11425,6 +11474,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->grc_mode |= GRC_MODE_BSWAP_NONFRM_DATA; #endif spin_lock_init(&tp->lock); + spin_lock_init(&tp->tx_lock); spin_lock_init(&tp->indirect_lock); INIT_WORK(&tp->reset_task, tg3_reset_task, tp); diff --git a/trunk/drivers/net/tg3.h b/trunk/drivers/net/tg3.h index 3ecf356cfb08..ba2c98711c88 100644 --- a/trunk/drivers/net/tg3.h +++ b/trunk/drivers/net/tg3.h @@ -2079,9 +2079,9 @@ struct tg3 { * lock: Held during reset, PHY access, timer, and when * updating tg3_flags and tg3_flags2. * - * netif_tx_lock: Held during tg3_start_xmit. tg3_tx holds - * netif_tx_lock when it needs to call - * netif_wake_queue. + * tx_lock: Held during tg3_start_xmit and tg3_tx only + * when calling netif_[start|stop]_queue. + * tg3_start_xmit is protected by netif_tx_lock. * * Both of these locks are to be held with BH safety. * @@ -2118,6 +2118,8 @@ struct tg3 { u32 tx_cons; u32 tx_pending; + spinlock_t tx_lock; + struct tg3_tx_buffer_desc *tx_ring; struct tx_ring_info *tx_buffers; dma_addr_t tx_desc_mapping; diff --git a/trunk/drivers/net/tokenring/ibmtr.c b/trunk/drivers/net/tokenring/ibmtr.c index 4470025ff7f8..9f491563944e 100644 --- a/trunk/drivers/net/tokenring/ibmtr.c +++ b/trunk/drivers/net/tokenring/ibmtr.c @@ -140,7 +140,7 @@ in the event that chatty debug messages are desired - jjs 12/30/98 */ /* version and credits */ #ifndef PCMCIA -static char version[] __devinitdata = +static char version[] __initdata = "\nibmtr.c: v1.3.57 8/ 7/94 Peter De Schrijver and Mark Swanson\n" " v2.1.125 10/20/98 Paul Norton \n" " v2.2.0 12/30/98 Joel Sloan \n" @@ -216,7 +216,7 @@ static int __devinitdata turbo_irq[IBMTR_MAX_ADAPTERS] = {0}; static int __devinitdata turbo_searched = 0; #ifndef PCMCIA -static __u32 ibmtr_mem_base __devinitdata = 0xd0000; +static __u32 ibmtr_mem_base __initdata = 0xd0000; #endif static void __devinit PrtChanID(char *pcid, short stride) diff --git a/trunk/drivers/net/tokenring/smctr.c b/trunk/drivers/net/tokenring/smctr.c index 85a7f797d343..cd2e0251e2bc 100644 --- a/trunk/drivers/net/tokenring/smctr.c +++ b/trunk/drivers/net/tokenring/smctr.c @@ -5666,7 +5666,7 @@ module_param_array(io, int, NULL, 0); module_param_array(irq, int, NULL, 0); module_param(ringspeed, int, 0); -static struct net_device * __init setup_card(int n) +static struct net_device *setup_card(int n) { struct net_device *dev = alloc_trdev(sizeof(struct net_local)); int err; @@ -5696,8 +5696,9 @@ static struct net_device * __init setup_card(int n) free_netdev(dev); return ERR_PTR(err); } + -int __init init_module(void) +int init_module(void) { int i, found = 0; struct net_device *dev; diff --git a/trunk/drivers/net/tulip/winbond-840.c b/trunk/drivers/net/tulip/winbond-840.c index eba9083da146..7f414815cc62 100644 --- a/trunk/drivers/net/tulip/winbond-840.c +++ b/trunk/drivers/net/tulip/winbond-840.c @@ -138,7 +138,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; #include /* These identify the driver base version and may not be removed. */ -static char version[] = +static char version[] __devinitdata = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " DRV_RELDATE " Donald Becker \n" KERN_INFO " http://www.scyld.com/network/drivers.html\n"; diff --git a/trunk/drivers/net/tulip/xircom_cb.c b/trunk/drivers/net/tulip/xircom_cb.c index cf43390d2c80..f874e4f6ccf6 100644 --- a/trunk/drivers/net/tulip/xircom_cb.c +++ b/trunk/drivers/net/tulip/xircom_cb.c @@ -1264,7 +1264,8 @@ static void investigate_write_descriptor(struct net_device *dev, struct xircom_p static int __init xircom_init(void) { - return pci_register_driver(&xircom_ops); + pci_register_driver(&xircom_ops); + return 0; } static void __exit xircom_exit(void) diff --git a/trunk/drivers/net/typhoon.c b/trunk/drivers/net/typhoon.c index c6e601dc6bbc..4103c37172f9 100644 --- a/trunk/drivers/net/typhoon.c +++ b/trunk/drivers/net/typhoon.c @@ -830,7 +830,7 @@ typhoon_start_tx(struct sk_buff *skb, struct net_device *dev) first_txd->addrHi = (u64)((unsigned long) skb) >> 32; first_txd->processFlags = 0; - if(skb->ip_summed == CHECKSUM_PARTIAL) { + if(skb->ip_summed == CHECKSUM_HW) { /* The 3XP will figure out if this is UDP/TCP */ first_txd->processFlags |= TYPHOON_TX_PF_TCP_CHKSUM; first_txd->processFlags |= TYPHOON_TX_PF_UDP_CHKSUM; diff --git a/trunk/drivers/net/ucc_geth.c b/trunk/drivers/net/ucc_geth.c deleted file mode 100644 index 47f49ef72bdc..000000000000 --- a/trunk/drivers/net/ucc_geth.c +++ /dev/null @@ -1,4278 +0,0 @@ -/* - * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. - * - * Author: Shlomi Gridish - * - * Description: - * QE UCC Gigabit Ethernet Driver - * - * Changelog: - * Jul 6, 2006 Li Yang - * - Rearrange code and style fixes - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "ucc_geth.h" -#include "ucc_geth_phy.h" - -#undef DEBUG - -#define DRV_DESC "QE UCC Gigabit Ethernet Controller version:June 20, 2006" -#define DRV_NAME "ucc_geth" - -#define ugeth_printk(level, format, arg...) \ - printk(level format "\n", ## arg) - -#define ugeth_dbg(format, arg...) \ - ugeth_printk(KERN_DEBUG , format , ## arg) -#define ugeth_err(format, arg...) \ - ugeth_printk(KERN_ERR , format , ## arg) -#define ugeth_info(format, arg...) \ - ugeth_printk(KERN_INFO , format , ## arg) -#define ugeth_warn(format, arg...) \ - ugeth_printk(KERN_WARNING , format , ## arg) - -#ifdef UGETH_VERBOSE_DEBUG -#define ugeth_vdbg ugeth_dbg -#else -#define ugeth_vdbg(fmt, args...) do { } while (0) -#endif /* UGETH_VERBOSE_DEBUG */ - -static DEFINE_SPINLOCK(ugeth_lock); - -static ucc_geth_info_t ugeth_primary_info = { - .uf_info = { - .bd_mem_part = MEM_PART_SYSTEM, - .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES, - .max_rx_buf_length = 1536, -/* FIXME: should be changed in run time for 1G and 100M */ -#ifdef CONFIG_UGETH_HAS_GIGA - .urfs = UCC_GETH_URFS_GIGA_INIT, - .urfet = UCC_GETH_URFET_GIGA_INIT, - .urfset = UCC_GETH_URFSET_GIGA_INIT, - .utfs = UCC_GETH_UTFS_GIGA_INIT, - .utfet = UCC_GETH_UTFET_GIGA_INIT, - .utftt = UCC_GETH_UTFTT_GIGA_INIT, -#else - .urfs = UCC_GETH_URFS_INIT, - .urfet = UCC_GETH_URFET_INIT, - .urfset = UCC_GETH_URFSET_INIT, - .utfs = UCC_GETH_UTFS_INIT, - .utfet = UCC_GETH_UTFET_INIT, - .utftt = UCC_GETH_UTFTT_INIT, -#endif - .ufpt = 256, - .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET, - .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL, - .tenc = UCC_FAST_TX_ENCODING_NRZ, - .renc = UCC_FAST_RX_ENCODING_NRZ, - .tcrc = UCC_FAST_16_BIT_CRC, - .synl = UCC_FAST_SYNC_LEN_NOT_USED, - }, - .numQueuesTx = 1, - .numQueuesRx = 1, - .extendedFilteringChainPointer = ((uint32_t) NULL), - .typeorlen = 3072 /*1536 */ , - .nonBackToBackIfgPart1 = 0x40, - .nonBackToBackIfgPart2 = 0x60, - .miminumInterFrameGapEnforcement = 0x50, - .backToBackInterFrameGap = 0x60, - .mblinterval = 128, - .nortsrbytetime = 5, - .fracsiz = 1, - .strictpriorityq = 0xff, - .altBebTruncation = 0xa, - .excessDefer = 1, - .maxRetransmission = 0xf, - .collisionWindow = 0x37, - .receiveFlowControl = 1, - .maxGroupAddrInHash = 4, - .maxIndAddrInHash = 4, - .prel = 7, - .maxFrameLength = 1518, - .minFrameLength = 64, - .maxD1Length = 1520, - .maxD2Length = 1520, - .vlantype = 0x8100, - .ecamptr = ((uint32_t) NULL), - .eventRegMask = UCCE_OTHER, - .pausePeriod = 0xf000, - .interruptcoalescingmaxvalue = {1, 1, 1, 1, 1, 1, 1, 1}, - .bdRingLenTx = { - TX_BD_RING_LEN, - TX_BD_RING_LEN, - TX_BD_RING_LEN, - TX_BD_RING_LEN, - TX_BD_RING_LEN, - TX_BD_RING_LEN, - TX_BD_RING_LEN, - TX_BD_RING_LEN}, - - .bdRingLenRx = { - RX_BD_RING_LEN, - RX_BD_RING_LEN, - RX_BD_RING_LEN, - RX_BD_RING_LEN, - RX_BD_RING_LEN, - RX_BD_RING_LEN, - RX_BD_RING_LEN, - RX_BD_RING_LEN}, - - .numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1, - .largestexternallookupkeysize = - QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE, - .statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_NONE, - .vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP, - .vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP, - .rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT, - .aufc = UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE, - .padAndCrc = MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC, - .numThreadsTx = UCC_GETH_NUM_OF_THREADS_4, - .numThreadsRx = UCC_GETH_NUM_OF_THREADS_4, - .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, - .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, -}; - -static ucc_geth_info_t ugeth_info[8]; - -#ifdef DEBUG -static void mem_disp(u8 *addr, int size) -{ - u8 *i; - int size16Aling = (size >> 4) << 4; - int size4Aling = (size >> 2) << 2; - int notAlign = 0; - if (size % 16) - notAlign = 1; - - for (i = addr; (u32) i < (u32) addr + size16Aling; i += 16) - printk("0x%08x: %08x %08x %08x %08x\r\n", - (u32) i, - *((u32 *) (i)), - *((u32 *) (i + 4)), - *((u32 *) (i + 8)), *((u32 *) (i + 12))); - if (notAlign == 1) - printk("0x%08x: ", (u32) i); - for (; (u32) i < (u32) addr + size4Aling; i += 4) - printk("%08x ", *((u32 *) (i))); - for (; (u32) i < (u32) addr + size; i++) - printk("%02x", *((u8 *) (i))); - if (notAlign == 1) - printk("\r\n"); -} -#endif /* DEBUG */ - -#ifdef CONFIG_UGETH_FILTERING -static void enqueue(struct list_head *node, struct list_head *lh) -{ - unsigned long flags; - - spin_lock_irqsave(ugeth_lock, flags); - list_add_tail(node, lh); - spin_unlock_irqrestore(ugeth_lock, flags); -} -#endif /* CONFIG_UGETH_FILTERING */ - -static struct list_head *dequeue(struct list_head *lh) -{ - unsigned long flags; - - spin_lock_irqsave(ugeth_lock, flags); - if (!list_empty(lh)) { - struct list_head *node = lh->next; - list_del(node); - spin_unlock_irqrestore(ugeth_lock, flags); - return node; - } else { - spin_unlock_irqrestore(ugeth_lock, flags); - return NULL; - } -} - -static int get_interface_details(enet_interface_e enet_interface, - enet_speed_e *speed, - int *r10m, - int *rmm, - int *rpm, - int *tbi, int *limited_to_full_duplex) -{ - /* Analyze enet_interface according to Interface Mode - Configuration table */ - switch (enet_interface) { - case ENET_10_MII: - *speed = ENET_SPEED_10BT; - break; - case ENET_10_RMII: - *speed = ENET_SPEED_10BT; - *r10m = 1; - *rmm = 1; - break; - case ENET_10_RGMII: - *speed = ENET_SPEED_10BT; - *rpm = 1; - *r10m = 1; - *limited_to_full_duplex = 1; - break; - case ENET_100_MII: - *speed = ENET_SPEED_100BT; - break; - case ENET_100_RMII: - *speed = ENET_SPEED_100BT; - *rmm = 1; - break; - case ENET_100_RGMII: - *speed = ENET_SPEED_100BT; - *rpm = 1; - *limited_to_full_duplex = 1; - break; - case ENET_1000_GMII: - *speed = ENET_SPEED_1000BT; - *limited_to_full_duplex = 1; - break; - case ENET_1000_RGMII: - *speed = ENET_SPEED_1000BT; - *rpm = 1; - *limited_to_full_duplex = 1; - break; - case ENET_1000_TBI: - *speed = ENET_SPEED_1000BT; - *tbi = 1; - *limited_to_full_duplex = 1; - break; - case ENET_1000_RTBI: - *speed = ENET_SPEED_1000BT; - *rpm = 1; - *tbi = 1; - *limited_to_full_duplex = 1; - break; - default: - return -EINVAL; - break; - } - - return 0; -} - -static struct sk_buff *get_new_skb(ucc_geth_private_t *ugeth, u8 *bd) -{ - struct sk_buff *skb = NULL; - - skb = dev_alloc_skb(ugeth->ug_info->uf_info.max_rx_buf_length + - UCC_GETH_RX_DATA_BUF_ALIGNMENT); - - if (skb == NULL) - return NULL; - - /* We need the data buffer to be aligned properly. We will reserve - * as many bytes as needed to align the data properly - */ - skb_reserve(skb, - UCC_GETH_RX_DATA_BUF_ALIGNMENT - - (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT - - 1))); - - skb->dev = ugeth->dev; - - BD_BUFFER_SET(bd, - dma_map_single(NULL, - skb->data, - ugeth->ug_info->uf_info.max_rx_buf_length + - UCC_GETH_RX_DATA_BUF_ALIGNMENT, - DMA_FROM_DEVICE)); - - BD_STATUS_AND_LENGTH_SET(bd, - (R_E | R_I | - (BD_STATUS_AND_LENGTH(bd) & R_W))); - - return skb; -} - -static int rx_bd_buffer_set(ucc_geth_private_t *ugeth, u8 rxQ) -{ - u8 *bd; - u32 bd_status; - struct sk_buff *skb; - int i; - - bd = ugeth->p_rx_bd_ring[rxQ]; - i = 0; - - do { - bd_status = BD_STATUS_AND_LENGTH(bd); - skb = get_new_skb(ugeth, bd); - - if (!skb) /* If can not allocate data buffer, - abort. Cleanup will be elsewhere */ - return -ENOMEM; - - ugeth->rx_skbuff[rxQ][i] = skb; - - /* advance the BD pointer */ - bd += UCC_GETH_SIZE_OF_BD; - i++; - } while (!(bd_status & R_W)); - - return 0; -} - -static int fill_init_enet_entries(ucc_geth_private_t *ugeth, - volatile u32 *p_start, - u8 num_entries, - u32 thread_size, - u32 thread_alignment, - qe_risc_allocation_e risc, - int skip_page_for_first_entry) -{ - u32 init_enet_offset; - u8 i; - int snum; - - for (i = 0; i < num_entries; i++) { - if ((snum = qe_get_snum()) < 0) { - ugeth_err("fill_init_enet_entries: Can not get SNUM."); - return snum; - } - if ((i == 0) && skip_page_for_first_entry) - /* First entry of Rx does not have page */ - init_enet_offset = 0; - else { - init_enet_offset = - qe_muram_alloc(thread_size, thread_alignment); - if (IS_MURAM_ERR(init_enet_offset)) { - ugeth_err - ("fill_init_enet_entries: Can not allocate DPRAM memory."); - qe_put_snum((u8) snum); - return -ENOMEM; - } - } - *(p_start++) = - ((u8) snum << ENET_INIT_PARAM_SNUM_SHIFT) | init_enet_offset - | risc; - } - - return 0; -} - -static int return_init_enet_entries(ucc_geth_private_t *ugeth, - volatile u32 *p_start, - u8 num_entries, - qe_risc_allocation_e risc, - int skip_page_for_first_entry) -{ - u32 init_enet_offset; - u8 i; - int snum; - - for (i = 0; i < num_entries; i++) { - /* Check that this entry was actually valid -- - needed in case failed in allocations */ - if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) { - snum = - (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >> - ENET_INIT_PARAM_SNUM_SHIFT; - qe_put_snum((u8) snum); - if (!((i == 0) && skip_page_for_first_entry)) { - /* First entry of Rx does not have page */ - init_enet_offset = - (in_be32(p_start) & - ENET_INIT_PARAM_PTR_MASK); - qe_muram_free(init_enet_offset); - } - *(p_start++) = 0; /* Just for cosmetics */ - } - } - - return 0; -} - -#ifdef DEBUG -static int dump_init_enet_entries(ucc_geth_private_t *ugeth, - volatile u32 *p_start, - u8 num_entries, - u32 thread_size, - qe_risc_allocation_e risc, - int skip_page_for_first_entry) -{ - u32 init_enet_offset; - u8 i; - int snum; - - for (i = 0; i < num_entries; i++) { - /* Check that this entry was actually valid -- - needed in case failed in allocations */ - if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) { - snum = - (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >> - ENET_INIT_PARAM_SNUM_SHIFT; - qe_put_snum((u8) snum); - if (!((i == 0) && skip_page_for_first_entry)) { - /* First entry of Rx does not have page */ - init_enet_offset = - (in_be32(p_start) & - ENET_INIT_PARAM_PTR_MASK); - ugeth_info("Init enet entry %d:", i); - ugeth_info("Base address: 0x%08x", - (u32) - qe_muram_addr(init_enet_offset)); - mem_disp(qe_muram_addr(init_enet_offset), - thread_size); - } - p_start++; - } - } - - return 0; -} -#endif - -#ifdef CONFIG_UGETH_FILTERING -static enet_addr_container_t *get_enet_addr_container(void) -{ - enet_addr_container_t *enet_addr_cont; - - /* allocate memory */ - enet_addr_cont = kmalloc(sizeof(enet_addr_container_t), GFP_KERNEL); - if (!enet_addr_cont) { - ugeth_err("%s: No memory for enet_addr_container_t object.", - __FUNCTION__); - return NULL; - } - - return enet_addr_cont; -} -#endif /* CONFIG_UGETH_FILTERING */ - -static void put_enet_addr_container(enet_addr_container_t *enet_addr_cont) -{ - kfree(enet_addr_cont); -} - -#ifdef CONFIG_UGETH_FILTERING -static int hw_add_addr_in_paddr(ucc_geth_private_t *ugeth, - enet_addr_t *p_enet_addr, u8 paddr_num) -{ - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; - - if (!(paddr_num < NUM_OF_PADDRS)) { - ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__); - return -EINVAL; - } - - p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> - addressfiltering; - - /* Ethernet frames are defined in Little Endian mode, */ - /* therefore to insert the address we reverse the bytes. */ - out_be16(&p_82xx_addr_filt->paddr[paddr_num].h, - (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) | - (u16) (*p_enet_addr)[4])); - out_be16(&p_82xx_addr_filt->paddr[paddr_num].m, - (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) | - (u16) (*p_enet_addr)[2])); - out_be16(&p_82xx_addr_filt->paddr[paddr_num].l, - (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) | - (u16) (*p_enet_addr)[0])); - - return 0; -} -#endif /* CONFIG_UGETH_FILTERING */ - -static int hw_clear_addr_in_paddr(ucc_geth_private_t *ugeth, u8 paddr_num) -{ - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; - - if (!(paddr_num < NUM_OF_PADDRS)) { - ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__); - return -EINVAL; - } - - p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> - addressfiltering; - - /* Writing address ff.ff.ff.ff.ff.ff disables address - recognition for this register */ - out_be16(&p_82xx_addr_filt->paddr[paddr_num].h, 0xffff); - out_be16(&p_82xx_addr_filt->paddr[paddr_num].m, 0xffff); - out_be16(&p_82xx_addr_filt->paddr[paddr_num].l, 0xffff); - - return 0; -} - -static void hw_add_addr_in_hash(ucc_geth_private_t *ugeth, - enet_addr_t *p_enet_addr) -{ - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; - u32 cecr_subblock; - - p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> - addressfiltering; - - cecr_subblock = - ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); - - /* Ethernet frames are defined in Little Endian mode, - therefor to insert */ - /* the address to the hash (Big Endian mode), we reverse the bytes.*/ - out_be16(&p_82xx_addr_filt->taddr.h, - (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) | - (u16) (*p_enet_addr)[4])); - out_be16(&p_82xx_addr_filt->taddr.m, - (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) | - (u16) (*p_enet_addr)[2])); - out_be16(&p_82xx_addr_filt->taddr.l, - (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) | - (u16) (*p_enet_addr)[0])); - - qe_issue_cmd(QE_SET_GROUP_ADDRESS, cecr_subblock, - (u8) QE_CR_PROTOCOL_ETHERNET, 0); -} - -#ifdef CONFIG_UGETH_MAGIC_PACKET -static void magic_packet_detection_enable(ucc_geth_private_t *ugeth) -{ - ucc_fast_private_t *uccf; - ucc_geth_t *ug_regs; - u32 maccfg2, uccm; - - uccf = ugeth->uccf; - ug_regs = ugeth->ug_regs; - - /* Enable interrupts for magic packet detection */ - uccm = in_be32(uccf->p_uccm); - uccm |= UCCE_MPD; - out_be32(uccf->p_uccm, uccm); - - /* Enable magic packet detection */ - maccfg2 = in_be32(&ug_regs->maccfg2); - maccfg2 |= MACCFG2_MPE; - out_be32(&ug_regs->maccfg2, maccfg2); -} - -static void magic_packet_detection_disable(ucc_geth_private_t *ugeth) -{ - ucc_fast_private_t *uccf; - ucc_geth_t *ug_regs; - u32 maccfg2, uccm; - - uccf = ugeth->uccf; - ug_regs = ugeth->ug_regs; - - /* Disable interrupts for magic packet detection */ - uccm = in_be32(uccf->p_uccm); - uccm &= ~UCCE_MPD; - out_be32(uccf->p_uccm, uccm); - - /* Disable magic packet detection */ - maccfg2 = in_be32(&ug_regs->maccfg2); - maccfg2 &= ~MACCFG2_MPE; - out_be32(&ug_regs->maccfg2, maccfg2); -} -#endif /* MAGIC_PACKET */ - -static inline int compare_addr(enet_addr_t *addr1, enet_addr_t *addr2) -{ - return memcmp(addr1, addr2, ENET_NUM_OCTETS_PER_ADDRESS); -} - -#ifdef DEBUG -static void get_statistics(ucc_geth_private_t *ugeth, - ucc_geth_tx_firmware_statistics_t * - tx_firmware_statistics, - ucc_geth_rx_firmware_statistics_t * - rx_firmware_statistics, - ucc_geth_hardware_statistics_t *hardware_statistics) -{ - ucc_fast_t *uf_regs; - ucc_geth_t *ug_regs; - ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram; - ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram; - - ug_regs = ugeth->ug_regs; - uf_regs = (ucc_fast_t *) ug_regs; - p_tx_fw_statistics_pram = ugeth->p_tx_fw_statistics_pram; - p_rx_fw_statistics_pram = ugeth->p_rx_fw_statistics_pram; - - /* Tx firmware only if user handed pointer and driver actually - gathers Tx firmware statistics */ - if (tx_firmware_statistics && p_tx_fw_statistics_pram) { - tx_firmware_statistics->sicoltx = - in_be32(&p_tx_fw_statistics_pram->sicoltx); - tx_firmware_statistics->mulcoltx = - in_be32(&p_tx_fw_statistics_pram->mulcoltx); - tx_firmware_statistics->latecoltxfr = - in_be32(&p_tx_fw_statistics_pram->latecoltxfr); - tx_firmware_statistics->frabortduecol = - in_be32(&p_tx_fw_statistics_pram->frabortduecol); - tx_firmware_statistics->frlostinmactxer = - in_be32(&p_tx_fw_statistics_pram->frlostinmactxer); - tx_firmware_statistics->carriersenseertx = - in_be32(&p_tx_fw_statistics_pram->carriersenseertx); - tx_firmware_statistics->frtxok = - in_be32(&p_tx_fw_statistics_pram->frtxok); - tx_firmware_statistics->txfrexcessivedefer = - in_be32(&p_tx_fw_statistics_pram->txfrexcessivedefer); - tx_firmware_statistics->txpkts256 = - in_be32(&p_tx_fw_statistics_pram->txpkts256); - tx_firmware_statistics->txpkts512 = - in_be32(&p_tx_fw_statistics_pram->txpkts512); - tx_firmware_statistics->txpkts1024 = - in_be32(&p_tx_fw_statistics_pram->txpkts1024); - tx_firmware_statistics->txpktsjumbo = - in_be32(&p_tx_fw_statistics_pram->txpktsjumbo); - } - - /* Rx firmware only if user handed pointer and driver actually - * gathers Rx firmware statistics */ - if (rx_firmware_statistics && p_rx_fw_statistics_pram) { - int i; - rx_firmware_statistics->frrxfcser = - in_be32(&p_rx_fw_statistics_pram->frrxfcser); - rx_firmware_statistics->fraligner = - in_be32(&p_rx_fw_statistics_pram->fraligner); - rx_firmware_statistics->inrangelenrxer = - in_be32(&p_rx_fw_statistics_pram->inrangelenrxer); - rx_firmware_statistics->outrangelenrxer = - in_be32(&p_rx_fw_statistics_pram->outrangelenrxer); - rx_firmware_statistics->frtoolong = - in_be32(&p_rx_fw_statistics_pram->frtoolong); - rx_firmware_statistics->runt = - in_be32(&p_rx_fw_statistics_pram->runt); - rx_firmware_statistics->verylongevent = - in_be32(&p_rx_fw_statistics_pram->verylongevent); - rx_firmware_statistics->symbolerror = - in_be32(&p_rx_fw_statistics_pram->symbolerror); - rx_firmware_statistics->dropbsy = - in_be32(&p_rx_fw_statistics_pram->dropbsy); - for (i = 0; i < 0x8; i++) - rx_firmware_statistics->res0[i] = - p_rx_fw_statistics_pram->res0[i]; - rx_firmware_statistics->mismatchdrop = - in_be32(&p_rx_fw_statistics_pram->mismatchdrop); - rx_firmware_statistics->underpkts = - in_be32(&p_rx_fw_statistics_pram->underpkts); - rx_firmware_statistics->pkts256 = - in_be32(&p_rx_fw_statistics_pram->pkts256); - rx_firmware_statistics->pkts512 = - in_be32(&p_rx_fw_statistics_pram->pkts512); - rx_firmware_statistics->pkts1024 = - in_be32(&p_rx_fw_statistics_pram->pkts1024); - rx_firmware_statistics->pktsjumbo = - in_be32(&p_rx_fw_statistics_pram->pktsjumbo); - rx_firmware_statistics->frlossinmacer = - in_be32(&p_rx_fw_statistics_pram->frlossinmacer); - rx_firmware_statistics->pausefr = - in_be32(&p_rx_fw_statistics_pram->pausefr); - for (i = 0; i < 0x4; i++) - rx_firmware_statistics->res1[i] = - p_rx_fw_statistics_pram->res1[i]; - rx_firmware_statistics->removevlan = - in_be32(&p_rx_fw_statistics_pram->removevlan); - rx_firmware_statistics->replacevlan = - in_be32(&p_rx_fw_statistics_pram->replacevlan); - rx_firmware_statistics->insertvlan = - in_be32(&p_rx_fw_statistics_pram->insertvlan); - } - - /* Hardware only if user handed pointer and driver actually - gathers hardware statistics */ - if (hardware_statistics && (in_be32(&uf_regs->upsmr) & UPSMR_HSE)) { - hardware_statistics->tx64 = in_be32(&ug_regs->tx64); - hardware_statistics->tx127 = in_be32(&ug_regs->tx127); - hardware_statistics->tx255 = in_be32(&ug_regs->tx255); - hardware_statistics->rx64 = in_be32(&ug_regs->rx64); - hardware_statistics->rx127 = in_be32(&ug_regs->rx127); - hardware_statistics->rx255 = in_be32(&ug_regs->rx255); - hardware_statistics->txok = in_be32(&ug_regs->txok); - hardware_statistics->txcf = in_be16(&ug_regs->txcf); - hardware_statistics->tmca = in_be32(&ug_regs->tmca); - hardware_statistics->tbca = in_be32(&ug_regs->tbca); - hardware_statistics->rxfok = in_be32(&ug_regs->rxfok); - hardware_statistics->rxbok = in_be32(&ug_regs->rxbok); - hardware_statistics->rbyt = in_be32(&ug_regs->rbyt); - hardware_statistics->rmca = in_be32(&ug_regs->rmca); - hardware_statistics->rbca = in_be32(&ug_regs->rbca); - } -} - -static void dump_bds(ucc_geth_private_t *ugeth) -{ - int i; - int length; - - for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { - if (ugeth->p_tx_bd_ring[i]) { - length = - (ugeth->ug_info->bdRingLenTx[i] * - UCC_GETH_SIZE_OF_BD); - ugeth_info("TX BDs[%d]", i); - mem_disp(ugeth->p_tx_bd_ring[i], length); - } - } - for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { - if (ugeth->p_rx_bd_ring[i]) { - length = - (ugeth->ug_info->bdRingLenRx[i] * - UCC_GETH_SIZE_OF_BD); - ugeth_info("RX BDs[%d]", i); - mem_disp(ugeth->p_rx_bd_ring[i], length); - } - } -} - -static void dump_regs(ucc_geth_private_t *ugeth) -{ - int i; - - ugeth_info("UCC%d Geth registers:", ugeth->ug_info->uf_info.ucc_num); - ugeth_info("Base address: 0x%08x", (u32) ugeth->ug_regs); - - ugeth_info("maccfg1 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->maccfg1, - in_be32(&ugeth->ug_regs->maccfg1)); - ugeth_info("maccfg2 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->maccfg2, - in_be32(&ugeth->ug_regs->maccfg2)); - ugeth_info("ipgifg : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->ipgifg, - in_be32(&ugeth->ug_regs->ipgifg)); - ugeth_info("hafdup : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->hafdup, - in_be32(&ugeth->ug_regs->hafdup)); - ugeth_info("miimcfg : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->miimng.miimcfg, - in_be32(&ugeth->ug_regs->miimng.miimcfg)); - ugeth_info("miimcom : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->miimng.miimcom, - in_be32(&ugeth->ug_regs->miimng.miimcom)); - ugeth_info("miimadd : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->miimng.miimadd, - in_be32(&ugeth->ug_regs->miimng.miimadd)); - ugeth_info("miimcon : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->miimng.miimcon, - in_be32(&ugeth->ug_regs->miimng.miimcon)); - ugeth_info("miimstat : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->miimng.miimstat, - in_be32(&ugeth->ug_regs->miimng.miimstat)); - ugeth_info("miimmind : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->miimng.miimind, - in_be32(&ugeth->ug_regs->miimng.miimind)); - ugeth_info("ifctl : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->ifctl, - in_be32(&ugeth->ug_regs->ifctl)); - ugeth_info("ifstat : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->ifstat, - in_be32(&ugeth->ug_regs->ifstat)); - ugeth_info("macstnaddr1: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->macstnaddr1, - in_be32(&ugeth->ug_regs->macstnaddr1)); - ugeth_info("macstnaddr2: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->macstnaddr2, - in_be32(&ugeth->ug_regs->macstnaddr2)); - ugeth_info("uempr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->uempr, - in_be32(&ugeth->ug_regs->uempr)); - ugeth_info("utbipar : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->utbipar, - in_be32(&ugeth->ug_regs->utbipar)); - ugeth_info("uescr : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->ug_regs->uescr, - in_be16(&ugeth->ug_regs->uescr)); - ugeth_info("tx64 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->tx64, - in_be32(&ugeth->ug_regs->tx64)); - ugeth_info("tx127 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->tx127, - in_be32(&ugeth->ug_regs->tx127)); - ugeth_info("tx255 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->tx255, - in_be32(&ugeth->ug_regs->tx255)); - ugeth_info("rx64 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rx64, - in_be32(&ugeth->ug_regs->rx64)); - ugeth_info("rx127 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rx127, - in_be32(&ugeth->ug_regs->rx127)); - ugeth_info("rx255 : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rx255, - in_be32(&ugeth->ug_regs->rx255)); - ugeth_info("txok : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->txok, - in_be32(&ugeth->ug_regs->txok)); - ugeth_info("txcf : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->ug_regs->txcf, - in_be16(&ugeth->ug_regs->txcf)); - ugeth_info("tmca : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->tmca, - in_be32(&ugeth->ug_regs->tmca)); - ugeth_info("tbca : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->tbca, - in_be32(&ugeth->ug_regs->tbca)); - ugeth_info("rxfok : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rxfok, - in_be32(&ugeth->ug_regs->rxfok)); - ugeth_info("rxbok : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rxbok, - in_be32(&ugeth->ug_regs->rxbok)); - ugeth_info("rbyt : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rbyt, - in_be32(&ugeth->ug_regs->rbyt)); - ugeth_info("rmca : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rmca, - in_be32(&ugeth->ug_regs->rmca)); - ugeth_info("rbca : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->rbca, - in_be32(&ugeth->ug_regs->rbca)); - ugeth_info("scar : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->scar, - in_be32(&ugeth->ug_regs->scar)); - ugeth_info("scam : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->ug_regs->scam, - in_be32(&ugeth->ug_regs->scam)); - - if (ugeth->p_thread_data_tx) { - int numThreadsTxNumerical; - switch (ugeth->ug_info->numThreadsTx) { - case UCC_GETH_NUM_OF_THREADS_1: - numThreadsTxNumerical = 1; - break; - case UCC_GETH_NUM_OF_THREADS_2: - numThreadsTxNumerical = 2; - break; - case UCC_GETH_NUM_OF_THREADS_4: - numThreadsTxNumerical = 4; - break; - case UCC_GETH_NUM_OF_THREADS_6: - numThreadsTxNumerical = 6; - break; - case UCC_GETH_NUM_OF_THREADS_8: - numThreadsTxNumerical = 8; - break; - default: - numThreadsTxNumerical = 0; - break; - } - - ugeth_info("Thread data TXs:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_thread_data_tx); - for (i = 0; i < numThreadsTxNumerical; i++) { - ugeth_info("Thread data TX[%d]:", i); - ugeth_info("Base address: 0x%08x", - (u32) & ugeth->p_thread_data_tx[i]); - mem_disp((u8 *) & ugeth->p_thread_data_tx[i], - sizeof(ucc_geth_thread_data_tx_t)); - } - } - if (ugeth->p_thread_data_rx) { - int numThreadsRxNumerical; - switch (ugeth->ug_info->numThreadsRx) { - case UCC_GETH_NUM_OF_THREADS_1: - numThreadsRxNumerical = 1; - break; - case UCC_GETH_NUM_OF_THREADS_2: - numThreadsRxNumerical = 2; - break; - case UCC_GETH_NUM_OF_THREADS_4: - numThreadsRxNumerical = 4; - break; - case UCC_GETH_NUM_OF_THREADS_6: - numThreadsRxNumerical = 6; - break; - case UCC_GETH_NUM_OF_THREADS_8: - numThreadsRxNumerical = 8; - break; - default: - numThreadsRxNumerical = 0; - break; - } - - ugeth_info("Thread data RX:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_thread_data_rx); - for (i = 0; i < numThreadsRxNumerical; i++) { - ugeth_info("Thread data RX[%d]:", i); - ugeth_info("Base address: 0x%08x", - (u32) & ugeth->p_thread_data_rx[i]); - mem_disp((u8 *) & ugeth->p_thread_data_rx[i], - sizeof(ucc_geth_thread_data_rx_t)); - } - } - if (ugeth->p_exf_glbl_param) { - ugeth_info("EXF global param:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_exf_glbl_param); - mem_disp((u8 *) ugeth->p_exf_glbl_param, - sizeof(*ugeth->p_exf_glbl_param)); - } - if (ugeth->p_tx_glbl_pram) { - ugeth_info("TX global param:"); - ugeth_info("Base address: 0x%08x", (u32) ugeth->p_tx_glbl_pram); - ugeth_info("temoder : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_tx_glbl_pram->temoder, - in_be16(&ugeth->p_tx_glbl_pram->temoder)); - ugeth_info("sqptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->sqptr, - in_be32(&ugeth->p_tx_glbl_pram->sqptr)); - ugeth_info("schedulerbasepointer: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->schedulerbasepointer, - in_be32(&ugeth->p_tx_glbl_pram-> - schedulerbasepointer)); - ugeth_info("txrmonbaseptr: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->txrmonbaseptr, - in_be32(&ugeth->p_tx_glbl_pram->txrmonbaseptr)); - ugeth_info("tstate : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->tstate, - in_be32(&ugeth->p_tx_glbl_pram->tstate)); - ugeth_info("iphoffset[0] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[0], - ugeth->p_tx_glbl_pram->iphoffset[0]); - ugeth_info("iphoffset[1] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[1], - ugeth->p_tx_glbl_pram->iphoffset[1]); - ugeth_info("iphoffset[2] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[2], - ugeth->p_tx_glbl_pram->iphoffset[2]); - ugeth_info("iphoffset[3] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[3], - ugeth->p_tx_glbl_pram->iphoffset[3]); - ugeth_info("iphoffset[4] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[4], - ugeth->p_tx_glbl_pram->iphoffset[4]); - ugeth_info("iphoffset[5] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[5], - ugeth->p_tx_glbl_pram->iphoffset[5]); - ugeth_info("iphoffset[6] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[6], - ugeth->p_tx_glbl_pram->iphoffset[6]); - ugeth_info("iphoffset[7] : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_tx_glbl_pram->iphoffset[7], - ugeth->p_tx_glbl_pram->iphoffset[7]); - ugeth_info("vtagtable[0] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[0], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[0])); - ugeth_info("vtagtable[1] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[1], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[1])); - ugeth_info("vtagtable[2] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[2], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[2])); - ugeth_info("vtagtable[3] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[3], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[3])); - ugeth_info("vtagtable[4] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[4], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[4])); - ugeth_info("vtagtable[5] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[5], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[5])); - ugeth_info("vtagtable[6] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[6], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[6])); - ugeth_info("vtagtable[7] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->vtagtable[7], - in_be32(&ugeth->p_tx_glbl_pram->vtagtable[7])); - ugeth_info("tqptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_tx_glbl_pram->tqptr, - in_be32(&ugeth->p_tx_glbl_pram->tqptr)); - } - if (ugeth->p_rx_glbl_pram) { - ugeth_info("RX global param:"); - ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_glbl_pram); - ugeth_info("remoder : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->remoder, - in_be32(&ugeth->p_rx_glbl_pram->remoder)); - ugeth_info("rqptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->rqptr, - in_be32(&ugeth->p_rx_glbl_pram->rqptr)); - ugeth_info("typeorlen : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->typeorlen, - in_be16(&ugeth->p_rx_glbl_pram->typeorlen)); - ugeth_info("rxgstpack : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_rx_glbl_pram->rxgstpack, - ugeth->p_rx_glbl_pram->rxgstpack); - ugeth_info("rxrmonbaseptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->rxrmonbaseptr, - in_be32(&ugeth->p_rx_glbl_pram->rxrmonbaseptr)); - ugeth_info("intcoalescingptr: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->intcoalescingptr, - in_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr)); - ugeth_info("rstate : addr - 0x%08x, val - 0x%02x", - (u32) & ugeth->p_rx_glbl_pram->rstate, - ugeth->p_rx_glbl_pram->rstate); - ugeth_info("mrblr : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->mrblr, - in_be16(&ugeth->p_rx_glbl_pram->mrblr)); - ugeth_info("rbdqptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->rbdqptr, - in_be32(&ugeth->p_rx_glbl_pram->rbdqptr)); - ugeth_info("mflr : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->mflr, - in_be16(&ugeth->p_rx_glbl_pram->mflr)); - ugeth_info("minflr : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->minflr, - in_be16(&ugeth->p_rx_glbl_pram->minflr)); - ugeth_info("maxd1 : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->maxd1, - in_be16(&ugeth->p_rx_glbl_pram->maxd1)); - ugeth_info("maxd2 : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->maxd2, - in_be16(&ugeth->p_rx_glbl_pram->maxd2)); - ugeth_info("ecamptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->ecamptr, - in_be32(&ugeth->p_rx_glbl_pram->ecamptr)); - ugeth_info("l2qt : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l2qt, - in_be32(&ugeth->p_rx_glbl_pram->l2qt)); - ugeth_info("l3qt[0] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[0], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[0])); - ugeth_info("l3qt[1] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[1], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[1])); - ugeth_info("l3qt[2] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[2], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[2])); - ugeth_info("l3qt[3] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[3], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[3])); - ugeth_info("l3qt[4] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[4], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[4])); - ugeth_info("l3qt[5] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[5], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[5])); - ugeth_info("l3qt[6] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[6], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[6])); - ugeth_info("l3qt[7] : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->l3qt[7], - in_be32(&ugeth->p_rx_glbl_pram->l3qt[7])); - ugeth_info("vlantype : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->vlantype, - in_be16(&ugeth->p_rx_glbl_pram->vlantype)); - ugeth_info("vlantci : addr - 0x%08x, val - 0x%04x", - (u32) & ugeth->p_rx_glbl_pram->vlantci, - in_be16(&ugeth->p_rx_glbl_pram->vlantci)); - for (i = 0; i < 64; i++) - ugeth_info - ("addressfiltering[%d]: addr - 0x%08x, val - 0x%02x", - i, - (u32) & ugeth->p_rx_glbl_pram->addressfiltering[i], - ugeth->p_rx_glbl_pram->addressfiltering[i]); - ugeth_info("exfGlobalParam : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_glbl_pram->exfGlobalParam, - in_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam)); - } - if (ugeth->p_send_q_mem_reg) { - ugeth_info("Send Q memory registers:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_send_q_mem_reg); - for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { - ugeth_info("SQQD[%d]:", i); - ugeth_info("Base address: 0x%08x", - (u32) & ugeth->p_send_q_mem_reg->sqqd[i]); - mem_disp((u8 *) & ugeth->p_send_q_mem_reg->sqqd[i], - sizeof(ucc_geth_send_queue_qd_t)); - } - } - if (ugeth->p_scheduler) { - ugeth_info("Scheduler:"); - ugeth_info("Base address: 0x%08x", (u32) ugeth->p_scheduler); - mem_disp((u8 *) ugeth->p_scheduler, - sizeof(*ugeth->p_scheduler)); - } - if (ugeth->p_tx_fw_statistics_pram) { - ugeth_info("TX FW statistics pram:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_tx_fw_statistics_pram); - mem_disp((u8 *) ugeth->p_tx_fw_statistics_pram, - sizeof(*ugeth->p_tx_fw_statistics_pram)); - } - if (ugeth->p_rx_fw_statistics_pram) { - ugeth_info("RX FW statistics pram:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_rx_fw_statistics_pram); - mem_disp((u8 *) ugeth->p_rx_fw_statistics_pram, - sizeof(*ugeth->p_rx_fw_statistics_pram)); - } - if (ugeth->p_rx_irq_coalescing_tbl) { - ugeth_info("RX IRQ coalescing tables:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_rx_irq_coalescing_tbl); - for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { - ugeth_info("RX IRQ coalescing table entry[%d]:", i); - ugeth_info("Base address: 0x%08x", - (u32) & ugeth->p_rx_irq_coalescing_tbl-> - coalescingentry[i]); - ugeth_info - ("interruptcoalescingmaxvalue: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_irq_coalescing_tbl-> - coalescingentry[i].interruptcoalescingmaxvalue, - in_be32(&ugeth->p_rx_irq_coalescing_tbl-> - coalescingentry[i]. - interruptcoalescingmaxvalue)); - ugeth_info - ("interruptcoalescingcounter : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_irq_coalescing_tbl-> - coalescingentry[i].interruptcoalescingcounter, - in_be32(&ugeth->p_rx_irq_coalescing_tbl-> - coalescingentry[i]. - interruptcoalescingcounter)); - } - } - if (ugeth->p_rx_bd_qs_tbl) { - ugeth_info("RX BD QS tables:"); - ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_bd_qs_tbl); - for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { - ugeth_info("RX BD QS table[%d]:", i); - ugeth_info("Base address: 0x%08x", - (u32) & ugeth->p_rx_bd_qs_tbl[i]); - ugeth_info - ("bdbaseptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_bd_qs_tbl[i].bdbaseptr, - in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdbaseptr)); - ugeth_info - ("bdptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_bd_qs_tbl[i].bdptr, - in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdptr)); - ugeth_info - ("externalbdbaseptr: addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr, - in_be32(&ugeth->p_rx_bd_qs_tbl[i]. - externalbdbaseptr)); - ugeth_info - ("externalbdptr : addr - 0x%08x, val - 0x%08x", - (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdptr, - in_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdptr)); - ugeth_info("ucode RX Prefetched BDs:"); - ugeth_info("Base address: 0x%08x", - (u32) - qe_muram_addr(in_be32 - (&ugeth->p_rx_bd_qs_tbl[i]. - bdbaseptr))); - mem_disp((u8 *) - qe_muram_addr(in_be32 - (&ugeth->p_rx_bd_qs_tbl[i]. - bdbaseptr)), - sizeof(ucc_geth_rx_prefetched_bds_t)); - } - } - if (ugeth->p_init_enet_param_shadow) { - int size; - ugeth_info("Init enet param shadow:"); - ugeth_info("Base address: 0x%08x", - (u32) ugeth->p_init_enet_param_shadow); - mem_disp((u8 *) ugeth->p_init_enet_param_shadow, - sizeof(*ugeth->p_init_enet_param_shadow)); - - size = sizeof(ucc_geth_thread_rx_pram_t); - if (ugeth->ug_info->rxExtendedFiltering) { - size += - THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING; - if (ugeth->ug_info->largestexternallookupkeysize == - QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES) - size += - THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8; - if (ugeth->ug_info->largestexternallookupkeysize == - QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES) - size += - THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16; - } - - dump_init_enet_entries(ugeth, - &(ugeth->p_init_enet_param_shadow-> - txthread[0]), - ENET_INIT_PARAM_MAX_ENTRIES_TX, - sizeof(ucc_geth_thread_tx_pram_t), - ugeth->ug_info->riscTx, 0); - dump_init_enet_entries(ugeth, - &(ugeth->p_init_enet_param_shadow-> - rxthread[0]), - ENET_INIT_PARAM_MAX_ENTRIES_RX, size, - ugeth->ug_info->riscRx, 1); - } -} -#endif /* DEBUG */ - -static void init_default_reg_vals(volatile u32 *upsmr_register, - volatile u32 *maccfg1_register, - volatile u32 *maccfg2_register) -{ - out_be32(upsmr_register, UCC_GETH_UPSMR_INIT); - out_be32(maccfg1_register, UCC_GETH_MACCFG1_INIT); - out_be32(maccfg2_register, UCC_GETH_MACCFG2_INIT); -} - -static int init_half_duplex_params(int alt_beb, - int back_pressure_no_backoff, - int no_backoff, - int excess_defer, - u8 alt_beb_truncation, - u8 max_retransmissions, - u8 collision_window, - volatile u32 *hafdup_register) -{ - u32 value = 0; - - if ((alt_beb_truncation > HALFDUP_ALT_BEB_TRUNCATION_MAX) || - (max_retransmissions > HALFDUP_MAX_RETRANSMISSION_MAX) || - (collision_window > HALFDUP_COLLISION_WINDOW_MAX)) - return -EINVAL; - - value = (u32) (alt_beb_truncation << HALFDUP_ALT_BEB_TRUNCATION_SHIFT); - - if (alt_beb) - value |= HALFDUP_ALT_BEB; - if (back_pressure_no_backoff) - value |= HALFDUP_BACK_PRESSURE_NO_BACKOFF; - if (no_backoff) - value |= HALFDUP_NO_BACKOFF; - if (excess_defer) - value |= HALFDUP_EXCESSIVE_DEFER; - - value |= (max_retransmissions << HALFDUP_MAX_RETRANSMISSION_SHIFT); - - value |= collision_window; - - out_be32(hafdup_register, value); - return 0; -} - -static int init_inter_frame_gap_params(u8 non_btb_cs_ipg, - u8 non_btb_ipg, - u8 min_ifg, - u8 btb_ipg, - volatile u32 *ipgifg_register) -{ - u32 value = 0; - - /* Non-Back-to-back IPG part 1 should be <= Non-Back-to-back - IPG part 2 */ - if (non_btb_cs_ipg > non_btb_ipg) - return -EINVAL; - - if ((non_btb_cs_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX) || - (non_btb_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX) || - /*(min_ifg > IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX) || */ - (btb_ipg > IPGIFG_BACK_TO_BACK_IFG_MAX)) - return -EINVAL; - - value |= - ((non_btb_cs_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT) & - IPGIFG_NBTB_CS_IPG_MASK); - value |= - ((non_btb_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT) & - IPGIFG_NBTB_IPG_MASK); - value |= - ((min_ifg << IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT) & - IPGIFG_MIN_IFG_MASK); - value |= (btb_ipg & IPGIFG_BTB_IPG_MASK); - - out_be32(ipgifg_register, value); - return 0; -} - -static int init_flow_control_params(u32 automatic_flow_control_mode, - int rx_flow_control_enable, - int tx_flow_control_enable, - u16 pause_period, - u16 extension_field, - volatile u32 *upsmr_register, - volatile u32 *uempr_register, - volatile u32 *maccfg1_register) -{ - u32 value = 0; - - /* Set UEMPR register */ - value = (u32) pause_period << UEMPR_PAUSE_TIME_VALUE_SHIFT; - value |= (u32) extension_field << UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT; - out_be32(uempr_register, value); - - /* Set UPSMR register */ - value = in_be32(upsmr_register); - value |= automatic_flow_control_mode; - out_be32(upsmr_register, value); - - value = in_be32(maccfg1_register); - if (rx_flow_control_enable) - value |= MACCFG1_FLOW_RX; - if (tx_flow_control_enable) - value |= MACCFG1_FLOW_TX; - out_be32(maccfg1_register, value); - - return 0; -} - -static int init_hw_statistics_gathering_mode(int enable_hardware_statistics, - int auto_zero_hardware_statistics, - volatile u32 *upsmr_register, - volatile u16 *uescr_register) -{ - u32 upsmr_value = 0; - u16 uescr_value = 0; - /* Enable hardware statistics gathering if requested */ - if (enable_hardware_statistics) { - upsmr_value = in_be32(upsmr_register); - upsmr_value |= UPSMR_HSE; - out_be32(upsmr_register, upsmr_value); - } - - /* Clear hardware statistics counters */ - uescr_value = in_be16(uescr_register); - uescr_value |= UESCR_CLRCNT; - /* Automatically zero hardware statistics counters on read, - if requested */ - if (auto_zero_hardware_statistics) - uescr_value |= UESCR_AUTOZ; - out_be16(uescr_register, uescr_value); - - return 0; -} - -static int init_firmware_statistics_gathering_mode(int - enable_tx_firmware_statistics, - int enable_rx_firmware_statistics, - volatile u32 *tx_rmon_base_ptr, - u32 tx_firmware_statistics_structure_address, - volatile u32 *rx_rmon_base_ptr, - u32 rx_firmware_statistics_structure_address, - volatile u16 *temoder_register, - volatile u32 *remoder_register) -{ - /* Note: this function does not check if */ - /* the parameters it receives are NULL */ - u16 temoder_value; - u32 remoder_value; - - if (enable_tx_firmware_statistics) { - out_be32(tx_rmon_base_ptr, - tx_firmware_statistics_structure_address); - temoder_value = in_be16(temoder_register); - temoder_value |= TEMODER_TX_RMON_STATISTICS_ENABLE; - out_be16(temoder_register, temoder_value); - } - - if (enable_rx_firmware_statistics) { - out_be32(rx_rmon_base_ptr, - rx_firmware_statistics_structure_address); - remoder_value = in_be32(remoder_register); - remoder_value |= REMODER_RX_RMON_STATISTICS_ENABLE; - out_be32(remoder_register, remoder_value); - } - - return 0; -} - -static int init_mac_station_addr_regs(u8 address_byte_0, - u8 address_byte_1, - u8 address_byte_2, - u8 address_byte_3, - u8 address_byte_4, - u8 address_byte_5, - volatile u32 *macstnaddr1_register, - volatile u32 *macstnaddr2_register) -{ - u32 value = 0; - - /* Example: for a station address of 0x12345678ABCD, */ - /* 0x12 is byte 0, 0x34 is byte 1 and so on and 0xCD is byte 5 */ - - /* MACSTNADDR1 Register: */ - - /* 0 7 8 15 */ - /* station address byte 5 station address byte 4 */ - /* 16 23 24 31 */ - /* station address byte 3 station address byte 2 */ - value |= (u32) ((address_byte_2 << 0) & 0x000000FF); - value |= (u32) ((address_byte_3 << 8) & 0x0000FF00); - value |= (u32) ((address_byte_4 << 16) & 0x00FF0000); - value |= (u32) ((address_byte_5 << 24) & 0xFF000000); - - out_be32(macstnaddr1_register, value); - - /* MACSTNADDR2 Register: */ - - /* 0 7 8 15 */ - /* station address byte 1 station address byte 0 */ - /* 16 23 24 31 */ - /* reserved reserved */ - value = 0; - value |= (u32) ((address_byte_0 << 16) & 0x00FF0000); - value |= (u32) ((address_byte_1 << 24) & 0xFF000000); - - out_be32(macstnaddr2_register, value); - - return 0; -} - -static int init_mac_duplex_mode(int full_duplex, - int limited_to_full_duplex, - volatile u32 *maccfg2_register) -{ - u32 value = 0; - - /* some interfaces must work in full duplex mode */ - if ((full_duplex == 0) && (limited_to_full_duplex == 1)) - return -EINVAL; - - value = in_be32(maccfg2_register); - - if (full_duplex) - value |= MACCFG2_FDX; - else - value &= ~MACCFG2_FDX; - - out_be32(maccfg2_register, value); - return 0; -} - -static int init_check_frame_length_mode(int length_check, - volatile u32 *maccfg2_register) -{ - u32 value = 0; - - value = in_be32(maccfg2_register); - - if (length_check) - value |= MACCFG2_LC; - else - value &= ~MACCFG2_LC; - - out_be32(maccfg2_register, value); - return 0; -} - -static int init_preamble_length(u8 preamble_length, - volatile u32 *maccfg2_register) -{ - u32 value = 0; - - if ((preamble_length < 3) || (preamble_length > 7)) - return -EINVAL; - - value = in_be32(maccfg2_register); - value &= ~MACCFG2_PREL_MASK; - value |= (preamble_length << MACCFG2_PREL_SHIFT); - out_be32(maccfg2_register, value); - return 0; -} - -static int init_mii_management_configuration(int reset_mgmt, - int preamble_supress, - volatile u32 *miimcfg_register, - volatile u32 *miimind_register) -{ - unsigned int timeout = PHY_INIT_TIMEOUT; - u32 value = 0; - - value = in_be32(miimcfg_register); - if (reset_mgmt) { - value |= MIIMCFG_RESET_MANAGEMENT; - out_be32(miimcfg_register, value); - } - - value = 0; - - if (preamble_supress) - value |= MIIMCFG_NO_PREAMBLE; - - value |= UCC_GETH_MIIMCFG_MNGMNT_CLC_DIV_INIT; - out_be32(miimcfg_register, value); - - /* Wait until the bus is free */ - while ((in_be32(miimind_register) & MIIMIND_BUSY) && timeout--) - cpu_relax(); - - if (timeout <= 0) { - ugeth_err("%s: The MII Bus is stuck!", __FUNCTION__); - return -ETIMEDOUT; - } - - return 0; -} - -static int init_rx_parameters(int reject_broadcast, - int receive_short_frames, - int promiscuous, volatile u32 *upsmr_register) -{ - u32 value = 0; - - value = in_be32(upsmr_register); - - if (reject_broadcast) - value |= UPSMR_BRO; - else - value &= ~UPSMR_BRO; - - if (receive_short_frames) - value |= UPSMR_RSH; - else - value &= ~UPSMR_RSH; - - if (promiscuous) - value |= UPSMR_PRO; - else - value &= ~UPSMR_PRO; - - out_be32(upsmr_register, value); - - return 0; -} - -static int init_max_rx_buff_len(u16 max_rx_buf_len, - volatile u16 *mrblr_register) -{ - /* max_rx_buf_len value must be a multiple of 128 */ - if ((max_rx_buf_len == 0) - || (max_rx_buf_len % UCC_GETH_MRBLR_ALIGNMENT)) - return -EINVAL; - - out_be16(mrblr_register, max_rx_buf_len); - return 0; -} - -static int init_min_frame_len(u16 min_frame_length, - volatile u16 *minflr_register, - volatile u16 *mrblr_register) -{ - u16 mrblr_value = 0; - - mrblr_value = in_be16(mrblr_register); - if (min_frame_length >= (mrblr_value - 4)) - return -EINVAL; - - out_be16(minflr_register, min_frame_length); - return 0; -} - -static int adjust_enet_interface(ucc_geth_private_t *ugeth) -{ - ucc_geth_info_t *ug_info; - ucc_geth_t *ug_regs; - ucc_fast_t *uf_regs; - enet_speed_e speed; - int ret_val, rpm = 0, tbi = 0, r10m = 0, rmm = - 0, limited_to_full_duplex = 0; - u32 upsmr, maccfg2, utbipar, tbiBaseAddress; - u16 value; - - ugeth_vdbg("%s: IN", __FUNCTION__); - - ug_info = ugeth->ug_info; - ug_regs = ugeth->ug_regs; - uf_regs = ugeth->uccf->uf_regs; - - /* Analyze enet_interface according to Interface Mode Configuration - table */ - ret_val = - get_interface_details(ug_info->enet_interface, &speed, &r10m, &rmm, - &rpm, &tbi, &limited_to_full_duplex); - if (ret_val != 0) { - ugeth_err - ("%s: half duplex not supported in requested configuration.", - __FUNCTION__); - return ret_val; - } - - /* Set MACCFG2 */ - maccfg2 = in_be32(&ug_regs->maccfg2); - maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK; - if ((speed == ENET_SPEED_10BT) || (speed == ENET_SPEED_100BT)) - maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; - else if (speed == ENET_SPEED_1000BT) - maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; - maccfg2 |= ug_info->padAndCrc; - out_be32(&ug_regs->maccfg2, maccfg2); - - /* Set UPSMR */ - upsmr = in_be32(&uf_regs->upsmr); - upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM); - if (rpm) - upsmr |= UPSMR_RPM; - if (r10m) - upsmr |= UPSMR_R10M; - if (tbi) - upsmr |= UPSMR_TBIM; - if (rmm) - upsmr |= UPSMR_RMM; - out_be32(&uf_regs->upsmr, upsmr); - - /* Set UTBIPAR */ - utbipar = in_be32(&ug_regs->utbipar); - utbipar &= ~UTBIPAR_PHY_ADDRESS_MASK; - if (tbi) - utbipar |= - (ug_info->phy_address + - ugeth->ug_info->uf_info. - ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT; - else - utbipar |= - (0x10 + - ugeth->ug_info->uf_info. - ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT; - out_be32(&ug_regs->utbipar, utbipar); - - /* Disable autonegotiation in tbi mode, because by default it - comes up in autonegotiation mode. */ - /* Note that this depends on proper setting in utbipar register. */ - if (tbi) { - tbiBaseAddress = in_be32(&ug_regs->utbipar); - tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK; - tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT; - value = - ugeth->mii_info->mdio_read(ugeth->dev, (u8) tbiBaseAddress, - ENET_TBI_MII_CR); - value &= ~0x1000; /* Turn off autonegotiation */ - ugeth->mii_info->mdio_write(ugeth->dev, (u8) tbiBaseAddress, - ENET_TBI_MII_CR, value); - } - - ret_val = init_mac_duplex_mode(1, - limited_to_full_duplex, - &ug_regs->maccfg2); - if (ret_val != 0) { - ugeth_err - ("%s: half duplex not supported in requested configuration.", - __FUNCTION__); - return ret_val; - } - - init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2); - - ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2); - if (ret_val != 0) { - ugeth_err - ("%s: Preamble length must be between 3 and 7 inclusive.", - __FUNCTION__); - return ret_val; - } - - return 0; -} - -/* Called every time the controller might need to be made - * aware of new link state. The PHY code conveys this - * information through variables in the ugeth structure, and this - * function converts those variables into the appropriate - * register values, and can bring down the device if needed. - */ -static void adjust_link(struct net_device *dev) -{ - ucc_geth_private_t *ugeth = netdev_priv(dev); - ucc_geth_t *ug_regs; - u32 tempval; - struct ugeth_mii_info *mii_info = ugeth->mii_info; - - ug_regs = ugeth->ug_regs; - - if (mii_info->link) { - /* Now we make sure that we can be in full duplex mode. - * If not, we operate in half-duplex mode. */ - if (mii_info->duplex != ugeth->oldduplex) { - if (!(mii_info->duplex)) { - tempval = in_be32(&ug_regs->maccfg2); - tempval &= ~(MACCFG2_FDX); - out_be32(&ug_regs->maccfg2, tempval); - - ugeth_info("%s: Half Duplex", dev->name); - } else { - tempval = in_be32(&ug_regs->maccfg2); - tempval |= MACCFG2_FDX; - out_be32(&ug_regs->maccfg2, tempval); - - ugeth_info("%s: Full Duplex", dev->name); - } - - ugeth->oldduplex = mii_info->duplex; - } - - if (mii_info->speed != ugeth->oldspeed) { - switch (mii_info->speed) { - case 1000: -#ifdef CONFIG_MPC836x -/* FIXME: This code is for 100Mbs BUG fixing, -remove this when it is fixed!!! */ - if (ugeth->ug_info->enet_interface == - ENET_1000_GMII) - /* Run the commands which initialize the PHY */ - { - tempval = - (u32) mii_info->mdio_read(ugeth-> - dev, mii_info->mii_id, 0x1b); - tempval |= 0x000f; - mii_info->mdio_write(ugeth->dev, - mii_info->mii_id, 0x1b, - (u16) tempval); - tempval = - (u32) mii_info->mdio_read(ugeth-> - dev, mii_info->mii_id, - MII_BMCR); - mii_info->mdio_write(ugeth->dev, - mii_info->mii_id, MII_BMCR, - (u16) (tempval | BMCR_RESET)); - } else if (ugeth->ug_info->enet_interface == - ENET_1000_RGMII) - /* Run the commands which initialize the PHY */ - { - tempval = - (u32) mii_info->mdio_read(ugeth-> - dev, mii_info->mii_id, 0x1b); - tempval = (tempval & ~0x000f) | 0x000b; - mii_info->mdio_write(ugeth->dev, - mii_info->mii_id, 0x1b, - (u16) tempval); - tempval = - (u32) mii_info->mdio_read(ugeth-> - dev, mii_info->mii_id, - MII_BMCR); - mii_info->mdio_write(ugeth->dev, - mii_info->mii_id, MII_BMCR, - (u16) (tempval | BMCR_RESET)); - } - msleep(4000); -#endif /* CONFIG_MPC8360 */ - adjust_enet_interface(ugeth); - break; - case 100: - case 10: -#ifdef CONFIG_MPC836x -/* FIXME: This code is for 100Mbs BUG fixing, -remove this lines when it will be fixed!!! */ - ugeth->ug_info->enet_interface = ENET_100_RGMII; - tempval = - (u32) mii_info->mdio_read(ugeth->dev, - mii_info->mii_id, - 0x1b); - tempval = (tempval & ~0x000f) | 0x000b; - mii_info->mdio_write(ugeth->dev, - mii_info->mii_id, 0x1b, - (u16) tempval); - tempval = - (u32) mii_info->mdio_read(ugeth->dev, - mii_info->mii_id, - MII_BMCR); - mii_info->mdio_write(ugeth->dev, - mii_info->mii_id, MII_BMCR, - (u16) (tempval | - BMCR_RESET)); - msleep(4000); -#endif /* CONFIG_MPC8360 */ - adjust_enet_interface(ugeth); - break; - default: - ugeth_warn - ("%s: Ack! Speed (%d) is not 10/100/1000!", - dev->name, mii_info->speed); - break; - } - - ugeth_info("%s: Speed %dBT", dev->name, - mii_info->speed); - - ugeth->oldspeed = mii_info->speed; - } - - if (!ugeth->oldlink) { - ugeth_info("%s: Link is up", dev->name); - ugeth->oldlink = 1; - netif_carrier_on(dev); - netif_schedule(dev); - } - } else { - if (ugeth->oldlink) { - ugeth_info("%s: Link is down", dev->name); - ugeth->oldlink = 0; - ugeth->oldspeed = 0; - ugeth->oldduplex = -1; - netif_carrier_off(dev); - } - } -} - -/* Configure the PHY for dev. - * returns 0 if success. -1 if failure - */ -static int init_phy(struct net_device *dev) -{ - ucc_geth_private_t *ugeth = netdev_priv(dev); - struct phy_info *curphy; - ucc_mii_mng_t *mii_regs; - struct ugeth_mii_info *mii_info; - int err; - - mii_regs = &ugeth->ug_regs->miimng; - - ugeth->oldlink = 0; - ugeth->oldspeed = 0; - ugeth->oldduplex = -1; - - mii_info = kmalloc(sizeof(struct ugeth_mii_info), GFP_KERNEL); - - if (NULL == mii_info) { - ugeth_err("%s: Could not allocate mii_info", dev->name); - return -ENOMEM; - } - - mii_info->mii_regs = mii_regs; - mii_info->speed = SPEED_1000; - mii_info->duplex = DUPLEX_FULL; - mii_info->pause = 0; - mii_info->link = 0; - - mii_info->advertising = (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Full); - mii_info->autoneg = 1; - - mii_info->mii_id = ugeth->ug_info->phy_address; - - mii_info->dev = dev; - - mii_info->mdio_read = &read_phy_reg; - mii_info->mdio_write = &write_phy_reg; - - ugeth->mii_info = mii_info; - - spin_lock_irq(&ugeth->lock); - - /* Set this UCC to be the master of the MII managment */ - ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num); - - if (init_mii_management_configuration(1, - ugeth->ug_info-> - miiPreambleSupress, - &mii_regs->miimcfg, - &mii_regs->miimind)) { - ugeth_err("%s: The MII Bus is stuck!", dev->name); - err = -1; - goto bus_fail; - } - - spin_unlock_irq(&ugeth->lock); - - /* get info for this PHY */ - curphy = get_phy_info(ugeth->mii_info); - - if (curphy == NULL) { - ugeth_err("%s: No PHY found", dev->name); - err = -1; - goto no_phy; - } - - mii_info->phyinfo = curphy; - - /* Run the commands which initialize the PHY */ - if (curphy->init) { - err = curphy->init(ugeth->mii_info); - if (err) - goto phy_init_fail; - } - - return 0; - - phy_init_fail: - no_phy: - bus_fail: - kfree(mii_info); - - return err; -} - -#ifdef CONFIG_UGETH_TX_ON_DEMOND -static int ugeth_transmit_on_demand(ucc_geth_private_t *ugeth) -{ - ucc_fast_transmit_on_demand(ugeth->uccf); - - return 0; -} -#endif - -static int ugeth_graceful_stop_tx(ucc_geth_private_t *ugeth) -{ - ucc_fast_private_t *uccf; - u32 cecr_subblock; - u32 temp; - - uccf = ugeth->uccf; - - /* Mask GRACEFUL STOP TX interrupt bit and clear it */ - temp = in_be32(uccf->p_uccm); - temp &= ~UCCE_GRA; - out_be32(uccf->p_uccm, temp); - out_be32(uccf->p_ucce, UCCE_GRA); /* clear by writing 1 */ - - /* Issue host command */ - cecr_subblock = - ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); - qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock, - (u8) QE_CR_PROTOCOL_ETHERNET, 0); - - /* Wait for command to complete */ - do { - temp = in_be32(uccf->p_ucce); - } while (!(temp & UCCE_GRA)); - - uccf->stopped_tx = 1; - - return 0; -} - -static int ugeth_graceful_stop_rx(ucc_geth_private_t * ugeth) -{ - ucc_fast_private_t *uccf; - u32 cecr_subblock; - u8 temp; - - uccf = ugeth->uccf; - - /* Clear acknowledge bit */ - temp = ugeth->p_rx_glbl_pram->rxgstpack; - temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX; - ugeth->p_rx_glbl_pram->rxgstpack = temp; - - /* Keep issuing command and checking acknowledge bit until - it is asserted, according to spec */ - do { - /* Issue host command */ - cecr_subblock = - ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info. - ucc_num); - qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock, - (u8) QE_CR_PROTOCOL_ETHERNET, 0); - - temp = ugeth->p_rx_glbl_pram->rxgstpack; - } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX)); - - uccf->stopped_rx = 1; - - return 0; -} - -static int ugeth_restart_tx(ucc_geth_private_t *ugeth) -{ - ucc_fast_private_t *uccf; - u32 cecr_subblock; - - uccf = ugeth->uccf; - - cecr_subblock = - ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); - qe_issue_cmd(QE_RESTART_TX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET, - 0); - uccf->stopped_tx = 0; - - return 0; -} - -static int ugeth_restart_rx(ucc_geth_private_t *ugeth) -{ - ucc_fast_private_t *uccf; - u32 cecr_subblock; - - uccf = ugeth->uccf; - - cecr_subblock = - ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); - qe_issue_cmd(QE_RESTART_RX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET, - 0); - uccf->stopped_rx = 0; - - return 0; -} - -static int ugeth_enable(ucc_geth_private_t *ugeth, comm_dir_e mode) -{ - ucc_fast_private_t *uccf; - int enabled_tx, enabled_rx; - - uccf = ugeth->uccf; - - /* check if the UCC number is in range. */ - if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { - ugeth_err("%s: ucc_num out of range.", __FUNCTION__); - return -EINVAL; - } - - enabled_tx = uccf->enabled_tx; - enabled_rx = uccf->enabled_rx; - - /* Get Tx and Rx going again, in case this channel was actively - disabled. */ - if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx) - ugeth_restart_tx(ugeth); - if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx) - ugeth_restart_rx(ugeth); - - ucc_fast_enable(uccf, mode); /* OK to do even if not disabled */ - - return 0; - -} - -static int ugeth_disable(ucc_geth_private_t * ugeth, comm_dir_e mode) -{ - ucc_fast_private_t *uccf; - - uccf = ugeth->uccf; - - /* check if the UCC number is in range. */ - if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { - ugeth_err("%s: ucc_num out of range.", __FUNCTION__); - return -EINVAL; - } - - /* Stop any transmissions */ - if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx) - ugeth_graceful_stop_tx(ugeth); - - /* Stop any receptions */ - if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx) - ugeth_graceful_stop_rx(ugeth); - - ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */ - - return 0; -} - -static void ugeth_dump_regs(ucc_geth_private_t *ugeth) -{ -#ifdef DEBUG - ucc_fast_dump_regs(ugeth->uccf); - dump_regs(ugeth); - dump_bds(ugeth); -#endif -} - -#ifdef CONFIG_UGETH_FILTERING -static int ugeth_ext_filtering_serialize_tad(ucc_geth_tad_params_t * - p_UccGethTadParams, - qe_fltr_tad_t *qe_fltr_tad) -{ - u16 temp; - - /* Zero serialized TAD */ - memset(qe_fltr_tad, 0, QE_FLTR_TAD_SIZE); - - qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_V; /* Must have this */ - if (p_UccGethTadParams->rx_non_dynamic_extended_features_mode || - (p_UccGethTadParams->vtag_op != UCC_GETH_VLAN_OPERATION_TAGGED_NOP) - || (p_UccGethTadParams->vnontag_op != - UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP) - ) - qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_EF; - if (p_UccGethTadParams->reject_frame) - qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_REJ; - temp = - (u16) (((u16) p_UccGethTadParams-> - vtag_op) << UCC_GETH_TAD_VTAG_OP_SHIFT); - qe_fltr_tad->serialized[0] |= (u8) (temp >> 8); /* upper bits */ - - qe_fltr_tad->serialized[1] |= (u8) (temp & 0x00ff); /* lower bits */ - if (p_UccGethTadParams->vnontag_op == - UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT) - qe_fltr_tad->serialized[1] |= UCC_GETH_TAD_V_NON_VTAG_OP; - qe_fltr_tad->serialized[1] |= - p_UccGethTadParams->rqos << UCC_GETH_TAD_RQOS_SHIFT; - - qe_fltr_tad->serialized[2] |= - p_UccGethTadParams->vpri << UCC_GETH_TAD_V_PRIORITY_SHIFT; - /* upper bits */ - qe_fltr_tad->serialized[2] |= (u8) (p_UccGethTadParams->vid >> 8); - /* lower bits */ - qe_fltr_tad->serialized[3] |= (u8) (p_UccGethTadParams->vid & 0x00ff); - - return 0; -} - -static enet_addr_container_t - *ugeth_82xx_filtering_get_match_addr_in_hash(ucc_geth_private_t *ugeth, - enet_addr_t *p_enet_addr) -{ - enet_addr_container_t *enet_addr_cont; - struct list_head *p_lh; - u16 i, num; - int32_t j; - u8 *p_counter; - - if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) { - p_lh = &ugeth->group_hash_q; - p_counter = &(ugeth->numGroupAddrInHash); - } else { - p_lh = &ugeth->ind_hash_q; - p_counter = &(ugeth->numIndAddrInHash); - } - - if (!p_lh) - return NULL; - - num = *p_counter; - - for (i = 0; i < num; i++) { - enet_addr_cont = - (enet_addr_container_t *) - ENET_ADDR_CONT_ENTRY(dequeue(p_lh)); - for (j = ENET_NUM_OCTETS_PER_ADDRESS - 1; j >= 0; j--) { - if ((*p_enet_addr)[j] != (enet_addr_cont->address)[j]) - break; - if (j == 0) - return enet_addr_cont; /* Found */ - } - enqueue(p_lh, &enet_addr_cont->node); /* Put it back */ - } - return NULL; -} - -static int ugeth_82xx_filtering_add_addr_in_hash(ucc_geth_private_t *ugeth, - enet_addr_t *p_enet_addr) -{ - ucc_geth_enet_address_recognition_location_e location; - enet_addr_container_t *enet_addr_cont; - struct list_head *p_lh; - u8 i; - u32 limit; - u8 *p_counter; - - if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) { - p_lh = &ugeth->group_hash_q; - limit = ugeth->ug_info->maxGroupAddrInHash; - location = - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH; - p_counter = &(ugeth->numGroupAddrInHash); - } else { - p_lh = &ugeth->ind_hash_q; - limit = ugeth->ug_info->maxIndAddrInHash; - location = - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH; - p_counter = &(ugeth->numIndAddrInHash); - } - - if ((enet_addr_cont = - ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr))) { - list_add(p_lh, &enet_addr_cont->node); /* Put it back */ - return 0; - } - if ((!p_lh) || (!(*p_counter < limit))) - return -EBUSY; - if (!(enet_addr_cont = get_enet_addr_container())) - return -ENOMEM; - for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) - (enet_addr_cont->address)[i] = (*p_enet_addr)[i]; - enet_addr_cont->location = location; - enqueue(p_lh, &enet_addr_cont->node); /* Put it back */ - ++(*p_counter); - - hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address)); - - return 0; -} - -static int ugeth_82xx_filtering_clear_addr_in_hash(ucc_geth_private_t *ugeth, - enet_addr_t *p_enet_addr) -{ - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; - enet_addr_container_t *enet_addr_cont; - ucc_fast_private_t *uccf; - comm_dir_e comm_dir; - u16 i, num; - struct list_head *p_lh; - u32 *addr_h, *addr_l; - u8 *p_counter; - - uccf = ugeth->uccf; - - p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> - addressfiltering; - - if (! - (enet_addr_cont = - ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr))) - return -ENOENT; - - /* It's been found and removed from the CQ. */ - /* Now destroy its container */ - put_enet_addr_container(enet_addr_cont); - - if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) { - addr_h = &(p_82xx_addr_filt->gaddr_h); - addr_l = &(p_82xx_addr_filt->gaddr_l); - p_lh = &ugeth->group_hash_q; - p_counter = &(ugeth->numGroupAddrInHash); - } else { - addr_h = &(p_82xx_addr_filt->iaddr_h); - addr_l = &(p_82xx_addr_filt->iaddr_l); - p_lh = &ugeth->ind_hash_q; - p_counter = &(ugeth->numIndAddrInHash); - } - - comm_dir = 0; - if (uccf->enabled_tx) - comm_dir |= COMM_DIR_TX; - if (uccf->enabled_rx) - comm_dir |= COMM_DIR_RX; - if (comm_dir) - ugeth_disable(ugeth, comm_dir); - - /* Clear the hash table. */ - out_be32(addr_h, 0x00000000); - out_be32(addr_l, 0x00000000); - - /* Add all remaining CQ elements back into hash */ - num = --(*p_counter); - for (i = 0; i < num; i++) { - enet_addr_cont = - (enet_addr_container_t *) - ENET_ADDR_CONT_ENTRY(dequeue(p_lh)); - hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address)); - enqueue(p_lh, &enet_addr_cont->node); /* Put it back */ - } - - if (comm_dir) - ugeth_enable(ugeth, comm_dir); - - return 0; -} -#endif /* CONFIG_UGETH_FILTERING */ - -static int ugeth_82xx_filtering_clear_all_addr_in_hash(ucc_geth_private_t * - ugeth, - enet_addr_type_e - enet_addr_type) -{ - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; - ucc_fast_private_t *uccf; - comm_dir_e comm_dir; - struct list_head *p_lh; - u16 i, num; - u32 *addr_h, *addr_l; - u8 *p_counter; - - uccf = ugeth->uccf; - - p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> - addressfiltering; - - if (enet_addr_type == ENET_ADDR_TYPE_GROUP) { - addr_h = &(p_82xx_addr_filt->gaddr_h); - addr_l = &(p_82xx_addr_filt->gaddr_l); - p_lh = &ugeth->group_hash_q; - p_counter = &(ugeth->numGroupAddrInHash); - } else if (enet_addr_type == ENET_ADDR_TYPE_INDIVIDUAL) { - addr_h = &(p_82xx_addr_filt->iaddr_h); - addr_l = &(p_82xx_addr_filt->iaddr_l); - p_lh = &ugeth->ind_hash_q; - p_counter = &(ugeth->numIndAddrInHash); - } else - return -EINVAL; - - comm_dir = 0; - if (uccf->enabled_tx) - comm_dir |= COMM_DIR_TX; - if (uccf->enabled_rx) - comm_dir |= COMM_DIR_RX; - if (comm_dir) - ugeth_disable(ugeth, comm_dir); - - /* Clear the hash table. */ - out_be32(addr_h, 0x00000000); - out_be32(addr_l, 0x00000000); - - if (!p_lh) - return 0; - - num = *p_counter; - - /* Delete all remaining CQ elements */ - for (i = 0; i < num; i++) - put_enet_addr_container(ENET_ADDR_CONT_ENTRY(dequeue(p_lh))); - - *p_counter = 0; - - if (comm_dir) - ugeth_enable(ugeth, comm_dir); - - return 0; -} - -#ifdef CONFIG_UGETH_FILTERING -static int ugeth_82xx_filtering_add_addr_in_paddr(ucc_geth_private_t *ugeth, - enet_addr_t *p_enet_addr, - u8 paddr_num) -{ - int i; - - if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) - ugeth_warn - ("%s: multicast address added to paddr will have no " - "effect - is this what you wanted?", - __FUNCTION__); - - ugeth->indAddrRegUsed[paddr_num] = 1; /* mark this paddr as used */ - /* store address in our database */ - for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) - ugeth->paddr[paddr_num][i] = (*p_enet_addr)[i]; - /* put in hardware */ - return hw_add_addr_in_paddr(ugeth, p_enet_addr, paddr_num); -} -#endif /* CONFIG_UGETH_FILTERING */ - -static int ugeth_82xx_filtering_clear_addr_in_paddr(ucc_geth_private_t *ugeth, - u8 paddr_num) -{ - ugeth->indAddrRegUsed[paddr_num] = 0; /* mark this paddr as not used */ - return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */ -} - -static void ucc_geth_memclean(ucc_geth_private_t *ugeth) -{ - u16 i, j; - u8 *bd; - - if (!ugeth) - return; - - if (ugeth->uccf) - ucc_fast_free(ugeth->uccf); - - if (ugeth->p_thread_data_tx) { - qe_muram_free(ugeth->thread_dat_tx_offset); - ugeth->p_thread_data_tx = NULL; - } - if (ugeth->p_thread_data_rx) { - qe_muram_free(ugeth->thread_dat_rx_offset); - ugeth->p_thread_data_rx = NULL; - } - if (ugeth->p_exf_glbl_param) { - qe_muram_free(ugeth->exf_glbl_param_offset); - ugeth->p_exf_glbl_param = NULL; - } - if (ugeth->p_rx_glbl_pram) { - qe_muram_free(ugeth->rx_glbl_pram_offset); - ugeth->p_rx_glbl_pram = NULL; - } - if (ugeth->p_tx_glbl_pram) { - qe_muram_free(ugeth->tx_glbl_pram_offset); - ugeth->p_tx_glbl_pram = NULL; - } - if (ugeth->p_send_q_mem_reg) { - qe_muram_free(ugeth->send_q_mem_reg_offset); - ugeth->p_send_q_mem_reg = NULL; - } - if (ugeth->p_scheduler) { - qe_muram_free(ugeth->scheduler_offset); - ugeth->p_scheduler = NULL; - } - if (ugeth->p_tx_fw_statistics_pram) { - qe_muram_free(ugeth->tx_fw_statistics_pram_offset); - ugeth->p_tx_fw_statistics_pram = NULL; - } - if (ugeth->p_rx_fw_statistics_pram) { - qe_muram_free(ugeth->rx_fw_statistics_pram_offset); - ugeth->p_rx_fw_statistics_pram = NULL; - } - if (ugeth->p_rx_irq_coalescing_tbl) { - qe_muram_free(ugeth->rx_irq_coalescing_tbl_offset); - ugeth->p_rx_irq_coalescing_tbl = NULL; - } - if (ugeth->p_rx_bd_qs_tbl) { - qe_muram_free(ugeth->rx_bd_qs_tbl_offset); - ugeth->p_rx_bd_qs_tbl = NULL; - } - if (ugeth->p_init_enet_param_shadow) { - return_init_enet_entries(ugeth, - &(ugeth->p_init_enet_param_shadow-> - rxthread[0]), - ENET_INIT_PARAM_MAX_ENTRIES_RX, - ugeth->ug_info->riscRx, 1); - return_init_enet_entries(ugeth, - &(ugeth->p_init_enet_param_shadow-> - txthread[0]), - ENET_INIT_PARAM_MAX_ENTRIES_TX, - ugeth->ug_info->riscTx, 0); - kfree(ugeth->p_init_enet_param_shadow); - ugeth->p_init_enet_param_shadow = NULL; - } - for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { - bd = ugeth->p_tx_bd_ring[i]; - for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) { - if (ugeth->tx_skbuff[i][j]) { - dma_unmap_single(NULL, - BD_BUFFER_ARG(bd), - (BD_STATUS_AND_LENGTH(bd) & - BD_LENGTH_MASK), - DMA_TO_DEVICE); - dev_kfree_skb_any(ugeth->tx_skbuff[i][j]); - ugeth->tx_skbuff[i][j] = NULL; - } - } - - kfree(ugeth->tx_skbuff[i]); - - if (ugeth->p_tx_bd_ring[i]) { - if (ugeth->ug_info->uf_info.bd_mem_part == - MEM_PART_SYSTEM) - kfree((void *)ugeth->tx_bd_ring_offset[i]); - else if (ugeth->ug_info->uf_info.bd_mem_part == - MEM_PART_MURAM) - qe_muram_free(ugeth->tx_bd_ring_offset[i]); - ugeth->p_tx_bd_ring[i] = NULL; - } - } - for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { - if (ugeth->p_rx_bd_ring[i]) { - /* Return existing data buffers in ring */ - bd = ugeth->p_rx_bd_ring[i]; - for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) { - if (ugeth->rx_skbuff[i][j]) { - dma_unmap_single(NULL, BD_BUFFER(bd), - ugeth->ug_info-> - uf_info. - max_rx_buf_length + - UCC_GETH_RX_DATA_BUF_ALIGNMENT, - DMA_FROM_DEVICE); - - dev_kfree_skb_any(ugeth-> - rx_skbuff[i][j]); - ugeth->rx_skbuff[i][j] = NULL; - } - bd += UCC_GETH_SIZE_OF_BD; - } - - kfree(ugeth->rx_skbuff[i]); - - if (ugeth->ug_info->uf_info.bd_mem_part == - MEM_PART_SYSTEM) - kfree((void *)ugeth->rx_bd_ring_offset[i]); - else if (ugeth->ug_info->uf_info.bd_mem_part == - MEM_PART_MURAM) - qe_muram_free(ugeth->rx_bd_ring_offset[i]); - ugeth->p_rx_bd_ring[i] = NULL; - } - } - while (!list_empty(&ugeth->group_hash_q)) - put_enet_addr_container(ENET_ADDR_CONT_ENTRY - (dequeue(&ugeth->group_hash_q))); - while (!list_empty(&ugeth->ind_hash_q)) - put_enet_addr_container(ENET_ADDR_CONT_ENTRY - (dequeue(&ugeth->ind_hash_q))); - -} - -static void ucc_geth_set_multi(struct net_device *dev) -{ - ucc_geth_private_t *ugeth; - struct dev_mc_list *dmi; - ucc_fast_t *uf_regs; - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; - enet_addr_t tempaddr; - u8 *mcptr, *tdptr; - int i, j; - - ugeth = netdev_priv(dev); - - uf_regs = ugeth->uccf->uf_regs; - - if (dev->flags & IFF_PROMISC) { - - /* Log any net taps. */ - printk("%s: Promiscuous mode enabled.\n", dev->name); - uf_regs->upsmr |= UPSMR_PRO; - - } else { - - uf_regs->upsmr &= ~UPSMR_PRO; - - p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth-> - p_rx_glbl_pram->addressfiltering; - - if (dev->flags & IFF_ALLMULTI) { - /* Catch all multicast addresses, so set the - * filter to all 1's. - */ - out_be32(&p_82xx_addr_filt->gaddr_h, 0xffffffff); - out_be32(&p_82xx_addr_filt->gaddr_l, 0xffffffff); - } else { - /* Clear filter and add the addresses in the list. - */ - out_be32(&p_82xx_addr_filt->gaddr_h, 0x0); - out_be32(&p_82xx_addr_filt->gaddr_l, 0x0); - - dmi = dev->mc_list; - - for (i = 0; i < dev->mc_count; i++, dmi = dmi->next) { - - /* Only support group multicast for now. - */ - if (!(dmi->dmi_addr[0] & 1)) - continue; - - /* The address in dmi_addr is LSB first, - * and taddr is MSB first. We have to - * copy bytes MSB first from dmi_addr. - */ - mcptr = (u8 *) dmi->dmi_addr + 5; - tdptr = (u8 *) & tempaddr; - for (j = 0; j < 6; j++) - *tdptr++ = *mcptr--; - - /* Ask CPM to run CRC and set bit in - * filter mask. - */ - hw_add_addr_in_hash(ugeth, &tempaddr); - - } - } - } -} - -static void ucc_geth_stop(ucc_geth_private_t *ugeth) -{ - ucc_geth_t *ug_regs = ugeth->ug_regs; - u32 tempval; - - ugeth_vdbg("%s: IN", __FUNCTION__); - - /* Disable the controller */ - ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); - - /* Tell the kernel the link is down */ - ugeth->mii_info->link = 0; - adjust_link(ugeth->dev); - - /* Mask all interrupts */ - out_be32(ugeth->uccf->p_ucce, 0x00000000); - - /* Clear all interrupts */ - out_be32(ugeth->uccf->p_ucce, 0xffffffff); - - /* Disable Rx and Tx */ - tempval = in_be32(&ug_regs->maccfg1); - tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); - out_be32(&ug_regs->maccfg1, tempval); - - if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) { - /* Clear any pending interrupts */ - mii_clear_phy_interrupt(ugeth->mii_info); - - /* Disable PHY Interrupts */ - mii_configure_phy_interrupt(ugeth->mii_info, - MII_INTERRUPT_DISABLED); - } - - free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev); - - if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) { - free_irq(ugeth->ug_info->phy_interrupt, ugeth->dev); - } else { - del_timer_sync(&ugeth->phy_info_timer); - } - - ucc_geth_memclean(ugeth); -} - -static int ucc_geth_startup(ucc_geth_private_t *ugeth) -{ - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; - ucc_geth_init_pram_t *p_init_enet_pram; - ucc_fast_private_t *uccf; - ucc_geth_info_t *ug_info; - ucc_fast_info_t *uf_info; - ucc_fast_t *uf_regs; - ucc_geth_t *ug_regs; - int ret_val = -EINVAL; - u32 remoder = UCC_GETH_REMODER_INIT; - u32 init_enet_pram_offset, cecr_subblock, command, maccfg1; - u32 ifstat, i, j, size, l2qt, l3qt, length; - u16 temoder = UCC_GETH_TEMODER_INIT; - u16 test; - u8 function_code = 0; - u8 *bd, *endOfRing; - u8 numThreadsRxNumerical, numThreadsTxNumerical; - - ugeth_vdbg("%s: IN", __FUNCTION__); - - ug_info = ugeth->ug_info; - uf_info = &ug_info->uf_info; - - if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) || - (uf_info->bd_mem_part == MEM_PART_MURAM))) { - ugeth_err("%s: Bad memory partition value.", __FUNCTION__); - return -EINVAL; - } - - /* Rx BD lengths */ - for (i = 0; i < ug_info->numQueuesRx; i++) { - if ((ug_info->bdRingLenRx[i] < UCC_GETH_RX_BD_RING_SIZE_MIN) || - (ug_info->bdRingLenRx[i] % - UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT)) { - ugeth_err - ("%s: Rx BD ring length must be multiple of 4," - " no smaller than 8.", __FUNCTION__); - return -EINVAL; - } - } - - /* Tx BD lengths */ - for (i = 0; i < ug_info->numQueuesTx; i++) { - if (ug_info->bdRingLenTx[i] < UCC_GETH_TX_BD_RING_SIZE_MIN) { - ugeth_err - ("%s: Tx BD ring length must be no smaller than 2.", - __FUNCTION__); - return -EINVAL; - } - } - - /* mrblr */ - if ((uf_info->max_rx_buf_length == 0) || - (uf_info->max_rx_buf_length % UCC_GETH_MRBLR_ALIGNMENT)) { - ugeth_err - ("%s: max_rx_buf_length must be non-zero multiple of 128.", - __FUNCTION__); - return -EINVAL; - } - - /* num Tx queues */ - if (ug_info->numQueuesTx > NUM_TX_QUEUES) { - ugeth_err("%s: number of tx queues too large.", __FUNCTION__); - return -EINVAL; - } - - /* num Rx queues */ - if (ug_info->numQueuesRx > NUM_RX_QUEUES) { - ugeth_err("%s: number of rx queues too large.", __FUNCTION__); - return -EINVAL; - } - - /* l2qt */ - for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) { - if (ug_info->l2qt[i] >= ug_info->numQueuesRx) { - ugeth_err - ("%s: VLAN priority table entry must not be" - " larger than number of Rx queues.", - __FUNCTION__); - return -EINVAL; - } - } - - /* l3qt */ - for (i = 0; i < UCC_GETH_IP_PRIORITY_MAX; i++) { - if (ug_info->l3qt[i] >= ug_info->numQueuesRx) { - ugeth_err - ("%s: IP priority table entry must not be" - " larger than number of Rx queues.", - __FUNCTION__); - return -EINVAL; - } - } - - if (ug_info->cam && !ug_info->ecamptr) { - ugeth_err("%s: If cam mode is chosen, must supply cam ptr.", - __FUNCTION__); - return -EINVAL; - } - - if ((ug_info->numStationAddresses != - UCC_GETH_NUM_OF_STATION_ADDRESSES_1) - && ug_info->rxExtendedFiltering) { - ugeth_err("%s: Number of station addresses greater than 1 " - "not allowed in extended parsing mode.", - __FUNCTION__); - return -EINVAL; - } - - /* Generate uccm_mask for receive */ - uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */ - for (i = 0; i < ug_info->numQueuesRx; i++) - uf_info->uccm_mask |= (UCCE_RXBF_SINGLE_MASK << i); - - for (i = 0; i < ug_info->numQueuesTx; i++) - uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i); - /* Initialize the general fast UCC block. */ - if (ucc_fast_init(uf_info, &uccf)) { - ugeth_err("%s: Failed to init uccf.", __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - ugeth->uccf = uccf; - - switch (ug_info->numThreadsRx) { - case UCC_GETH_NUM_OF_THREADS_1: - numThreadsRxNumerical = 1; - break; - case UCC_GETH_NUM_OF_THREADS_2: - numThreadsRxNumerical = 2; - break; - case UCC_GETH_NUM_OF_THREADS_4: - numThreadsRxNumerical = 4; - break; - case UCC_GETH_NUM_OF_THREADS_6: - numThreadsRxNumerical = 6; - break; - case UCC_GETH_NUM_OF_THREADS_8: - numThreadsRxNumerical = 8; - break; - default: - ugeth_err("%s: Bad number of Rx threads value.", __FUNCTION__); - ucc_geth_memclean(ugeth); - return -EINVAL; - break; - } - - switch (ug_info->numThreadsTx) { - case UCC_GETH_NUM_OF_THREADS_1: - numThreadsTxNumerical = 1; - break; - case UCC_GETH_NUM_OF_THREADS_2: - numThreadsTxNumerical = 2; - break; - case UCC_GETH_NUM_OF_THREADS_4: - numThreadsTxNumerical = 4; - break; - case UCC_GETH_NUM_OF_THREADS_6: - numThreadsTxNumerical = 6; - break; - case UCC_GETH_NUM_OF_THREADS_8: - numThreadsTxNumerical = 8; - break; - default: - ugeth_err("%s: Bad number of Tx threads value.", __FUNCTION__); - ucc_geth_memclean(ugeth); - return -EINVAL; - break; - } - - /* Calculate rx_extended_features */ - ugeth->rx_non_dynamic_extended_features = ug_info->ipCheckSumCheck || - ug_info->ipAddressAlignment || - (ug_info->numStationAddresses != - UCC_GETH_NUM_OF_STATION_ADDRESSES_1); - - ugeth->rx_extended_features = ugeth->rx_non_dynamic_extended_features || - (ug_info->vlanOperationTagged != UCC_GETH_VLAN_OPERATION_TAGGED_NOP) - || (ug_info->vlanOperationNonTagged != - UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP); - - uf_regs = uccf->uf_regs; - ug_regs = (ucc_geth_t *) (uccf->uf_regs); - ugeth->ug_regs = ug_regs; - - init_default_reg_vals(&uf_regs->upsmr, - &ug_regs->maccfg1, &ug_regs->maccfg2); - - /* Set UPSMR */ - /* For more details see the hardware spec. */ - init_rx_parameters(ug_info->bro, - ug_info->rsh, ug_info->pro, &uf_regs->upsmr); - - /* We're going to ignore other registers for now, */ - /* except as needed to get up and running */ - - /* Set MACCFG1 */ - /* For more details see the hardware spec. */ - init_flow_control_params(ug_info->aufc, - ug_info->receiveFlowControl, - 1, - ug_info->pausePeriod, - ug_info->extensionField, - &uf_regs->upsmr, - &ug_regs->uempr, &ug_regs->maccfg1); - - maccfg1 = in_be32(&ug_regs->maccfg1); - maccfg1 |= MACCFG1_ENABLE_RX; - maccfg1 |= MACCFG1_ENABLE_TX; - out_be32(&ug_regs->maccfg1, maccfg1); - - /* Set IPGIFG */ - /* For more details see the hardware spec. */ - ret_val = init_inter_frame_gap_params(ug_info->nonBackToBackIfgPart1, - ug_info->nonBackToBackIfgPart2, - ug_info-> - miminumInterFrameGapEnforcement, - ug_info->backToBackInterFrameGap, - &ug_regs->ipgifg); - if (ret_val != 0) { - ugeth_err("%s: IPGIFG initialization parameter too large.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return ret_val; - } - - /* Set HAFDUP */ - /* For more details see the hardware spec. */ - ret_val = init_half_duplex_params(ug_info->altBeb, - ug_info->backPressureNoBackoff, - ug_info->noBackoff, - ug_info->excessDefer, - ug_info->altBebTruncation, - ug_info->maxRetransmission, - ug_info->collisionWindow, - &ug_regs->hafdup); - if (ret_val != 0) { - ugeth_err("%s: Half Duplex initialization parameter too large.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return ret_val; - } - - /* Set IFSTAT */ - /* For more details see the hardware spec. */ - /* Read only - resets upon read */ - ifstat = in_be32(&ug_regs->ifstat); - - /* Clear UEMPR */ - /* For more details see the hardware spec. */ - out_be32(&ug_regs->uempr, 0); - - /* Set UESCR */ - /* For more details see the hardware spec. */ - init_hw_statistics_gathering_mode((ug_info->statisticsMode & - UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE), - 0, &uf_regs->upsmr, &ug_regs->uescr); - - /* Allocate Tx bds */ - for (j = 0; j < ug_info->numQueuesTx; j++) { - /* Allocate in multiple of - UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT, - according to spec */ - length = ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD) - / UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT) - * UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT; - if ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD) % - UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT) - length += UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT; - if (uf_info->bd_mem_part == MEM_PART_SYSTEM) { - u32 align = 4; - if (UCC_GETH_TX_BD_RING_ALIGNMENT > 4) - align = UCC_GETH_TX_BD_RING_ALIGNMENT; - ugeth->tx_bd_ring_offset[j] = - (u32) (kmalloc((u32) (length + align), - GFP_KERNEL)); - if (ugeth->tx_bd_ring_offset[j] != 0) - ugeth->p_tx_bd_ring[j] = - (void*)((ugeth->tx_bd_ring_offset[j] + - align) & ~(align - 1)); - } else if (uf_info->bd_mem_part == MEM_PART_MURAM) { - ugeth->tx_bd_ring_offset[j] = - qe_muram_alloc(length, - UCC_GETH_TX_BD_RING_ALIGNMENT); - if (!IS_MURAM_ERR(ugeth->tx_bd_ring_offset[j])) - ugeth->p_tx_bd_ring[j] = - (u8 *) qe_muram_addr(ugeth-> - tx_bd_ring_offset[j]); - } - if (!ugeth->p_tx_bd_ring[j]) { - ugeth_err - ("%s: Can not allocate memory for Tx bd rings.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - /* Zero unused end of bd ring, according to spec */ - memset(ugeth->p_tx_bd_ring[j] + - ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD, 0, - length - ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD); - } - - /* Allocate Rx bds */ - for (j = 0; j < ug_info->numQueuesRx; j++) { - length = ug_info->bdRingLenRx[j] * UCC_GETH_SIZE_OF_BD; - if (uf_info->bd_mem_part == MEM_PART_SYSTEM) { - u32 align = 4; - if (UCC_GETH_RX_BD_RING_ALIGNMENT > 4) - align = UCC_GETH_RX_BD_RING_ALIGNMENT; - ugeth->rx_bd_ring_offset[j] = - (u32) (kmalloc((u32) (length + align), GFP_KERNEL)); - if (ugeth->rx_bd_ring_offset[j] != 0) - ugeth->p_rx_bd_ring[j] = - (void*)((ugeth->rx_bd_ring_offset[j] + - align) & ~(align - 1)); - } else if (uf_info->bd_mem_part == MEM_PART_MURAM) { - ugeth->rx_bd_ring_offset[j] = - qe_muram_alloc(length, - UCC_GETH_RX_BD_RING_ALIGNMENT); - if (!IS_MURAM_ERR(ugeth->rx_bd_ring_offset[j])) - ugeth->p_rx_bd_ring[j] = - (u8 *) qe_muram_addr(ugeth-> - rx_bd_ring_offset[j]); - } - if (!ugeth->p_rx_bd_ring[j]) { - ugeth_err - ("%s: Can not allocate memory for Rx bd rings.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - } - - /* Init Tx bds */ - for (j = 0; j < ug_info->numQueuesTx; j++) { - /* Setup the skbuff rings */ - ugeth->tx_skbuff[j] = - (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) * - ugeth->ug_info->bdRingLenTx[j], - GFP_KERNEL); - - if (ugeth->tx_skbuff[j] == NULL) { - ugeth_err("%s: Could not allocate tx_skbuff", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - - for (i = 0; i < ugeth->ug_info->bdRingLenTx[j]; i++) - ugeth->tx_skbuff[j][i] = NULL; - - ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0; - bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j]; - for (i = 0; i < ug_info->bdRingLenTx[j]; i++) { - BD_BUFFER_CLEAR(bd); - BD_STATUS_AND_LENGTH_SET(bd, 0); - bd += UCC_GETH_SIZE_OF_BD; - } - bd -= UCC_GETH_SIZE_OF_BD; - BD_STATUS_AND_LENGTH_SET(bd, T_W);/* for last BD set Wrap bit */ - } - - /* Init Rx bds */ - for (j = 0; j < ug_info->numQueuesRx; j++) { - /* Setup the skbuff rings */ - ugeth->rx_skbuff[j] = - (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) * - ugeth->ug_info->bdRingLenRx[j], - GFP_KERNEL); - - if (ugeth->rx_skbuff[j] == NULL) { - ugeth_err("%s: Could not allocate rx_skbuff", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - - for (i = 0; i < ugeth->ug_info->bdRingLenRx[j]; i++) - ugeth->rx_skbuff[j][i] = NULL; - - ugeth->skb_currx[j] = 0; - bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j]; - for (i = 0; i < ug_info->bdRingLenRx[j]; i++) { - BD_STATUS_AND_LENGTH_SET(bd, R_I); - BD_BUFFER_CLEAR(bd); - bd += UCC_GETH_SIZE_OF_BD; - } - bd -= UCC_GETH_SIZE_OF_BD; - BD_STATUS_AND_LENGTH_SET(bd, R_W);/* for last BD set Wrap bit */ - } - - /* - * Global PRAM - */ - /* Tx global PRAM */ - /* Allocate global tx parameter RAM page */ - ugeth->tx_glbl_pram_offset = - qe_muram_alloc(sizeof(ucc_geth_tx_global_pram_t), - UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT); - if (IS_MURAM_ERR(ugeth->tx_glbl_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - ugeth->p_tx_glbl_pram = - (ucc_geth_tx_global_pram_t *) qe_muram_addr(ugeth-> - tx_glbl_pram_offset); - /* Zero out p_tx_glbl_pram */ - memset(ugeth->p_tx_glbl_pram, 0, sizeof(ucc_geth_tx_global_pram_t)); - - /* Fill global PRAM */ - - /* TQPTR */ - /* Size varies with number of Tx threads */ - ugeth->thread_dat_tx_offset = - qe_muram_alloc(numThreadsTxNumerical * - sizeof(ucc_geth_thread_data_tx_t) + - 32 * (numThreadsTxNumerical == 1), - UCC_GETH_THREAD_DATA_ALIGNMENT); - if (IS_MURAM_ERR(ugeth->thread_dat_tx_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_thread_data_tx.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - - ugeth->p_thread_data_tx = - (ucc_geth_thread_data_tx_t *) qe_muram_addr(ugeth-> - thread_dat_tx_offset); - out_be32(&ugeth->p_tx_glbl_pram->tqptr, ugeth->thread_dat_tx_offset); - - /* vtagtable */ - for (i = 0; i < UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX; i++) - out_be32(&ugeth->p_tx_glbl_pram->vtagtable[i], - ug_info->vtagtable[i]); - - /* iphoffset */ - for (i = 0; i < TX_IP_OFFSET_ENTRY_MAX; i++) - ugeth->p_tx_glbl_pram->iphoffset[i] = ug_info->iphoffset[i]; - - /* SQPTR */ - /* Size varies with number of Tx queues */ - ugeth->send_q_mem_reg_offset = - qe_muram_alloc(ug_info->numQueuesTx * - sizeof(ucc_geth_send_queue_qd_t), - UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT); - if (IS_MURAM_ERR(ugeth->send_q_mem_reg_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - - ugeth->p_send_q_mem_reg = - (ucc_geth_send_queue_mem_region_t *) qe_muram_addr(ugeth-> - send_q_mem_reg_offset); - out_be32(&ugeth->p_tx_glbl_pram->sqptr, ugeth->send_q_mem_reg_offset); - - /* Setup the table */ - /* Assume BD rings are already established */ - for (i = 0; i < ug_info->numQueuesTx; i++) { - endOfRing = - ugeth->p_tx_bd_ring[i] + (ug_info->bdRingLenTx[i] - - 1) * UCC_GETH_SIZE_OF_BD; - if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) { - out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base, - (u32) virt_to_phys(ugeth->p_tx_bd_ring[i])); - out_be32(&ugeth->p_send_q_mem_reg->sqqd[i]. - last_bd_completed_address, - (u32) virt_to_phys(endOfRing)); - } else if (ugeth->ug_info->uf_info.bd_mem_part == - MEM_PART_MURAM) { - out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base, - (u32) immrbar_virt_to_phys(ugeth-> - p_tx_bd_ring[i])); - out_be32(&ugeth->p_send_q_mem_reg->sqqd[i]. - last_bd_completed_address, - (u32) immrbar_virt_to_phys(endOfRing)); - } - } - - /* schedulerbasepointer */ - - if (ug_info->numQueuesTx > 1) { - /* scheduler exists only if more than 1 tx queue */ - ugeth->scheduler_offset = - qe_muram_alloc(sizeof(ucc_geth_scheduler_t), - UCC_GETH_SCHEDULER_ALIGNMENT); - if (IS_MURAM_ERR(ugeth->scheduler_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_scheduler.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - - ugeth->p_scheduler = - (ucc_geth_scheduler_t *) qe_muram_addr(ugeth-> - scheduler_offset); - out_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer, - ugeth->scheduler_offset); - /* Zero out p_scheduler */ - memset(ugeth->p_scheduler, 0, sizeof(ucc_geth_scheduler_t)); - - /* Set values in scheduler */ - out_be32(&ugeth->p_scheduler->mblinterval, - ug_info->mblinterval); - out_be16(&ugeth->p_scheduler->nortsrbytetime, - ug_info->nortsrbytetime); - ugeth->p_scheduler->fracsiz = ug_info->fracsiz; - ugeth->p_scheduler->strictpriorityq = ug_info->strictpriorityq; - ugeth->p_scheduler->txasap = ug_info->txasap; - ugeth->p_scheduler->extrabw = ug_info->extrabw; - for (i = 0; i < NUM_TX_QUEUES; i++) - ugeth->p_scheduler->weightfactor[i] = - ug_info->weightfactor[i]; - - /* Set pointers to cpucount registers in scheduler */ - ugeth->p_cpucount[0] = &(ugeth->p_scheduler->cpucount0); - ugeth->p_cpucount[1] = &(ugeth->p_scheduler->cpucount1); - ugeth->p_cpucount[2] = &(ugeth->p_scheduler->cpucount2); - ugeth->p_cpucount[3] = &(ugeth->p_scheduler->cpucount3); - ugeth->p_cpucount[4] = &(ugeth->p_scheduler->cpucount4); - ugeth->p_cpucount[5] = &(ugeth->p_scheduler->cpucount5); - ugeth->p_cpucount[6] = &(ugeth->p_scheduler->cpucount6); - ugeth->p_cpucount[7] = &(ugeth->p_scheduler->cpucount7); - } - - /* schedulerbasepointer */ - /* TxRMON_PTR (statistics) */ - if (ug_info-> - statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { - ugeth->tx_fw_statistics_pram_offset = - qe_muram_alloc(sizeof - (ucc_geth_tx_firmware_statistics_pram_t), - UCC_GETH_TX_STATISTICS_ALIGNMENT); - if (IS_MURAM_ERR(ugeth->tx_fw_statistics_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_tx_fw_statistics_pram.", __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - ugeth->p_tx_fw_statistics_pram = - (ucc_geth_tx_firmware_statistics_pram_t *) - qe_muram_addr(ugeth->tx_fw_statistics_pram_offset); - /* Zero out p_tx_fw_statistics_pram */ - memset(ugeth->p_tx_fw_statistics_pram, - 0, sizeof(ucc_geth_tx_firmware_statistics_pram_t)); - } - - /* temoder */ - /* Already has speed set */ - - if (ug_info->numQueuesTx > 1) - temoder |= TEMODER_SCHEDULER_ENABLE; - if (ug_info->ipCheckSumGenerate) - temoder |= TEMODER_IP_CHECKSUM_GENERATE; - temoder |= ((ug_info->numQueuesTx - 1) << TEMODER_NUM_OF_QUEUES_SHIFT); - out_be16(&ugeth->p_tx_glbl_pram->temoder, temoder); - - test = in_be16(&ugeth->p_tx_glbl_pram->temoder); - - /* Function code register value to be used later */ - function_code = QE_BMR_BYTE_ORDER_BO_MOT | UCC_FAST_FUNCTION_CODE_GBL; - /* Required for QE */ - - /* function code register */ - out_be32(&ugeth->p_tx_glbl_pram->tstate, ((u32) function_code) << 24); - - /* Rx global PRAM */ - /* Allocate global rx parameter RAM page */ - ugeth->rx_glbl_pram_offset = - qe_muram_alloc(sizeof(ucc_geth_rx_global_pram_t), - UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT); - if (IS_MURAM_ERR(ugeth->rx_glbl_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - ugeth->p_rx_glbl_pram = - (ucc_geth_rx_global_pram_t *) qe_muram_addr(ugeth-> - rx_glbl_pram_offset); - /* Zero out p_rx_glbl_pram */ - memset(ugeth->p_rx_glbl_pram, 0, sizeof(ucc_geth_rx_global_pram_t)); - - /* Fill global PRAM */ - - /* RQPTR */ - /* Size varies with number of Rx threads */ - ugeth->thread_dat_rx_offset = - qe_muram_alloc(numThreadsRxNumerical * - sizeof(ucc_geth_thread_data_rx_t), - UCC_GETH_THREAD_DATA_ALIGNMENT); - if (IS_MURAM_ERR(ugeth->thread_dat_rx_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_thread_data_rx.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - - ugeth->p_thread_data_rx = - (ucc_geth_thread_data_rx_t *) qe_muram_addr(ugeth-> - thread_dat_rx_offset); - out_be32(&ugeth->p_rx_glbl_pram->rqptr, ugeth->thread_dat_rx_offset); - - /* typeorlen */ - out_be16(&ugeth->p_rx_glbl_pram->typeorlen, ug_info->typeorlen); - - /* rxrmonbaseptr (statistics) */ - if (ug_info-> - statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) { - ugeth->rx_fw_statistics_pram_offset = - qe_muram_alloc(sizeof - (ucc_geth_rx_firmware_statistics_pram_t), - UCC_GETH_RX_STATISTICS_ALIGNMENT); - if (IS_MURAM_ERR(ugeth->rx_fw_statistics_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_rx_fw_statistics_pram.", __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - ugeth->p_rx_fw_statistics_pram = - (ucc_geth_rx_firmware_statistics_pram_t *) - qe_muram_addr(ugeth->rx_fw_statistics_pram_offset); - /* Zero out p_rx_fw_statistics_pram */ - memset(ugeth->p_rx_fw_statistics_pram, 0, - sizeof(ucc_geth_rx_firmware_statistics_pram_t)); - } - - /* intCoalescingPtr */ - - /* Size varies with number of Rx queues */ - ugeth->rx_irq_coalescing_tbl_offset = - qe_muram_alloc(ug_info->numQueuesRx * - sizeof(ucc_geth_rx_interrupt_coalescing_entry_t), - UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT); - if (IS_MURAM_ERR(ugeth->rx_irq_coalescing_tbl_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_rx_irq_coalescing_tbl.", __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - - ugeth->p_rx_irq_coalescing_tbl = - (ucc_geth_rx_interrupt_coalescing_table_t *) - qe_muram_addr(ugeth->rx_irq_coalescing_tbl_offset); - out_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr, - ugeth->rx_irq_coalescing_tbl_offset); - - /* Fill interrupt coalescing table */ - for (i = 0; i < ug_info->numQueuesRx; i++) { - out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i]. - interruptcoalescingmaxvalue, - ug_info->interruptcoalescingmaxvalue[i]); - out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i]. - interruptcoalescingcounter, - ug_info->interruptcoalescingmaxvalue[i]); - } - - /* MRBLR */ - init_max_rx_buff_len(uf_info->max_rx_buf_length, - &ugeth->p_rx_glbl_pram->mrblr); - /* MFLR */ - out_be16(&ugeth->p_rx_glbl_pram->mflr, ug_info->maxFrameLength); - /* MINFLR */ - init_min_frame_len(ug_info->minFrameLength, - &ugeth->p_rx_glbl_pram->minflr, - &ugeth->p_rx_glbl_pram->mrblr); - /* MAXD1 */ - out_be16(&ugeth->p_rx_glbl_pram->maxd1, ug_info->maxD1Length); - /* MAXD2 */ - out_be16(&ugeth->p_rx_glbl_pram->maxd2, ug_info->maxD2Length); - - /* l2qt */ - l2qt = 0; - for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) - l2qt |= (ug_info->l2qt[i] << (28 - 4 * i)); - out_be32(&ugeth->p_rx_glbl_pram->l2qt, l2qt); - - /* l3qt */ - for (j = 0; j < UCC_GETH_IP_PRIORITY_MAX; j += 8) { - l3qt = 0; - for (i = 0; i < 8; i++) - l3qt |= (ug_info->l3qt[j + i] << (28 - 4 * i)); - out_be32(&ugeth->p_rx_glbl_pram->l3qt[j], l3qt); - } - - /* vlantype */ - out_be16(&ugeth->p_rx_glbl_pram->vlantype, ug_info->vlantype); - - /* vlantci */ - out_be16(&ugeth->p_rx_glbl_pram->vlantci, ug_info->vlantci); - - /* ecamptr */ - out_be32(&ugeth->p_rx_glbl_pram->ecamptr, ug_info->ecamptr); - - /* RBDQPTR */ - /* Size varies with number of Rx queues */ - ugeth->rx_bd_qs_tbl_offset = - qe_muram_alloc(ug_info->numQueuesRx * - (sizeof(ucc_geth_rx_bd_queues_entry_t) + - sizeof(ucc_geth_rx_prefetched_bds_t)), - UCC_GETH_RX_BD_QUEUES_ALIGNMENT); - if (IS_MURAM_ERR(ugeth->rx_bd_qs_tbl_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - - ugeth->p_rx_bd_qs_tbl = - (ucc_geth_rx_bd_queues_entry_t *) qe_muram_addr(ugeth-> - rx_bd_qs_tbl_offset); - out_be32(&ugeth->p_rx_glbl_pram->rbdqptr, ugeth->rx_bd_qs_tbl_offset); - /* Zero out p_rx_bd_qs_tbl */ - memset(ugeth->p_rx_bd_qs_tbl, - 0, - ug_info->numQueuesRx * (sizeof(ucc_geth_rx_bd_queues_entry_t) + - sizeof(ucc_geth_rx_prefetched_bds_t))); - - /* Setup the table */ - /* Assume BD rings are already established */ - for (i = 0; i < ug_info->numQueuesRx; i++) { - if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) { - out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr, - (u32) virt_to_phys(ugeth->p_rx_bd_ring[i])); - } else if (ugeth->ug_info->uf_info.bd_mem_part == - MEM_PART_MURAM) { - out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr, - (u32) immrbar_virt_to_phys(ugeth-> - p_rx_bd_ring[i])); - } - /* rest of fields handled by QE */ - } - - /* remoder */ - /* Already has speed set */ - - if (ugeth->rx_extended_features) - remoder |= REMODER_RX_EXTENDED_FEATURES; - if (ug_info->rxExtendedFiltering) - remoder |= REMODER_RX_EXTENDED_FILTERING; - if (ug_info->dynamicMaxFrameLength) - remoder |= REMODER_DYNAMIC_MAX_FRAME_LENGTH; - if (ug_info->dynamicMinFrameLength) - remoder |= REMODER_DYNAMIC_MIN_FRAME_LENGTH; - remoder |= - ug_info->vlanOperationTagged << REMODER_VLAN_OPERATION_TAGGED_SHIFT; - remoder |= - ug_info-> - vlanOperationNonTagged << REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT; - remoder |= ug_info->rxQoSMode << REMODER_RX_QOS_MODE_SHIFT; - remoder |= ((ug_info->numQueuesRx - 1) << REMODER_NUM_OF_QUEUES_SHIFT); - if (ug_info->ipCheckSumCheck) - remoder |= REMODER_IP_CHECKSUM_CHECK; - if (ug_info->ipAddressAlignment) - remoder |= REMODER_IP_ADDRESS_ALIGNMENT; - out_be32(&ugeth->p_rx_glbl_pram->remoder, remoder); - - /* Note that this function must be called */ - /* ONLY AFTER p_tx_fw_statistics_pram */ - /* andp_UccGethRxFirmwareStatisticsPram are allocated ! */ - init_firmware_statistics_gathering_mode((ug_info-> - statisticsMode & - UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX), - (ug_info->statisticsMode & - UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX), - &ugeth->p_tx_glbl_pram->txrmonbaseptr, - ugeth->tx_fw_statistics_pram_offset, - &ugeth->p_rx_glbl_pram->rxrmonbaseptr, - ugeth->rx_fw_statistics_pram_offset, - &ugeth->p_tx_glbl_pram->temoder, - &ugeth->p_rx_glbl_pram->remoder); - - /* function code register */ - ugeth->p_rx_glbl_pram->rstate = function_code; - - /* initialize extended filtering */ - if (ug_info->rxExtendedFiltering) { - if (!ug_info->extendedFilteringChainPointer) { - ugeth_err("%s: Null Extended Filtering Chain Pointer.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -EINVAL; - } - - /* Allocate memory for extended filtering Mode Global - Parameters */ - ugeth->exf_glbl_param_offset = - qe_muram_alloc(sizeof(ucc_geth_exf_global_pram_t), - UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT); - if (IS_MURAM_ERR(ugeth->exf_glbl_param_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for" - " p_exf_glbl_param.", __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - - ugeth->p_exf_glbl_param = - (ucc_geth_exf_global_pram_t *) qe_muram_addr(ugeth-> - exf_glbl_param_offset); - out_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam, - ugeth->exf_glbl_param_offset); - out_be32(&ugeth->p_exf_glbl_param->l2pcdptr, - (u32) ug_info->extendedFilteringChainPointer); - - } else { /* initialize 82xx style address filtering */ - - /* Init individual address recognition registers to disabled */ - - for (j = 0; j < NUM_OF_PADDRS; j++) - ugeth_82xx_filtering_clear_addr_in_paddr(ugeth, (u8) j); - - /* Create CQs for hash tables */ - if (ug_info->maxGroupAddrInHash > 0) { - INIT_LIST_HEAD(&ugeth->group_hash_q); - } - if (ug_info->maxIndAddrInHash > 0) { - INIT_LIST_HEAD(&ugeth->ind_hash_q); - } - p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth-> - p_rx_glbl_pram->addressfiltering; - - ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth, - ENET_ADDR_TYPE_GROUP); - ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth, - ENET_ADDR_TYPE_INDIVIDUAL); - } - - /* - * Initialize UCC at QE level - */ - - command = QE_INIT_TX_RX; - - /* Allocate shadow InitEnet command parameter structure. - * This is needed because after the InitEnet command is executed, - * the structure in DPRAM is released, because DPRAM is a premium - * resource. - * This shadow structure keeps a copy of what was done so that the - * allocated resources can be released when the channel is freed. - */ - if (!(ugeth->p_init_enet_param_shadow = - (ucc_geth_init_pram_t *) kmalloc(sizeof(ucc_geth_init_pram_t), - GFP_KERNEL))) { - ugeth_err - ("%s: Can not allocate memory for" - " p_UccInitEnetParamShadows.", __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - /* Zero out *p_init_enet_param_shadow */ - memset((char *)ugeth->p_init_enet_param_shadow, - 0, sizeof(ucc_geth_init_pram_t)); - - /* Fill shadow InitEnet command parameter structure */ - - ugeth->p_init_enet_param_shadow->resinit1 = - ENET_INIT_PARAM_MAGIC_RES_INIT1; - ugeth->p_init_enet_param_shadow->resinit2 = - ENET_INIT_PARAM_MAGIC_RES_INIT2; - ugeth->p_init_enet_param_shadow->resinit3 = - ENET_INIT_PARAM_MAGIC_RES_INIT3; - ugeth->p_init_enet_param_shadow->resinit4 = - ENET_INIT_PARAM_MAGIC_RES_INIT4; - ugeth->p_init_enet_param_shadow->resinit5 = - ENET_INIT_PARAM_MAGIC_RES_INIT5; - ugeth->p_init_enet_param_shadow->rgftgfrxglobal |= - ((u32) ug_info->numThreadsRx) << ENET_INIT_PARAM_RGF_SHIFT; - ugeth->p_init_enet_param_shadow->rgftgfrxglobal |= - ((u32) ug_info->numThreadsTx) << ENET_INIT_PARAM_TGF_SHIFT; - - ugeth->p_init_enet_param_shadow->rgftgfrxglobal |= - ugeth->rx_glbl_pram_offset | ug_info->riscRx; - if ((ug_info->largestexternallookupkeysize != - QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE) - && (ug_info->largestexternallookupkeysize != - QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES) - && (ug_info->largestexternallookupkeysize != - QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) { - ugeth_err("%s: Invalid largest External Lookup Key Size.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -EINVAL; - } - ugeth->p_init_enet_param_shadow->largestexternallookupkeysize = - ug_info->largestexternallookupkeysize; - size = sizeof(ucc_geth_thread_rx_pram_t); - if (ug_info->rxExtendedFiltering) { - size += THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING; - if (ug_info->largestexternallookupkeysize == - QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES) - size += - THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8; - if (ug_info->largestexternallookupkeysize == - QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES) - size += - THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16; - } - - if ((ret_val = fill_init_enet_entries(ugeth, &(ugeth-> - p_init_enet_param_shadow->rxthread[0]), - (u8) (numThreadsRxNumerical + 1) - /* Rx needs one extra for terminator */ - , size, UCC_GETH_THREAD_RX_PRAM_ALIGNMENT, - ug_info->riscRx, 1)) != 0) { - ugeth_err("%s: Can not fill p_init_enet_param_shadow.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return ret_val; - } - - ugeth->p_init_enet_param_shadow->txglobal = - ugeth->tx_glbl_pram_offset | ug_info->riscTx; - if ((ret_val = - fill_init_enet_entries(ugeth, - &(ugeth->p_init_enet_param_shadow-> - txthread[0]), numThreadsTxNumerical, - sizeof(ucc_geth_thread_tx_pram_t), - UCC_GETH_THREAD_TX_PRAM_ALIGNMENT, - ug_info->riscTx, 0)) != 0) { - ugeth_err("%s: Can not fill p_init_enet_param_shadow.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return ret_val; - } - - /* Load Rx bds with buffers */ - for (i = 0; i < ug_info->numQueuesRx; i++) { - if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) { - ugeth_err("%s: Can not fill Rx bds with buffers.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return ret_val; - } - } - - /* Allocate InitEnet command parameter structure */ - init_enet_pram_offset = qe_muram_alloc(sizeof(ucc_geth_init_pram_t), 4); - if (IS_MURAM_ERR(init_enet_pram_offset)) { - ugeth_err - ("%s: Can not allocate DPRAM memory for p_init_enet_pram.", - __FUNCTION__); - ucc_geth_memclean(ugeth); - return -ENOMEM; - } - p_init_enet_pram = - (ucc_geth_init_pram_t *) qe_muram_addr(init_enet_pram_offset); - - /* Copy shadow InitEnet command parameter structure into PRAM */ - p_init_enet_pram->resinit1 = ugeth->p_init_enet_param_shadow->resinit1; - p_init_enet_pram->resinit2 = ugeth->p_init_enet_param_shadow->resinit2; - p_init_enet_pram->resinit3 = ugeth->p_init_enet_param_shadow->resinit3; - p_init_enet_pram->resinit4 = ugeth->p_init_enet_param_shadow->resinit4; - out_be16(&p_init_enet_pram->resinit5, - ugeth->p_init_enet_param_shadow->resinit5); - p_init_enet_pram->largestexternallookupkeysize = - ugeth->p_init_enet_param_shadow->largestexternallookupkeysize; - out_be32(&p_init_enet_pram->rgftgfrxglobal, - ugeth->p_init_enet_param_shadow->rgftgfrxglobal); - for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_RX; i++) - out_be32(&p_init_enet_pram->rxthread[i], - ugeth->p_init_enet_param_shadow->rxthread[i]); - out_be32(&p_init_enet_pram->txglobal, - ugeth->p_init_enet_param_shadow->txglobal); - for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_TX; i++) - out_be32(&p_init_enet_pram->txthread[i], - ugeth->p_init_enet_param_shadow->txthread[i]); - - /* Issue QE command */ - cecr_subblock = - ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); - qe_issue_cmd(command, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET, - init_enet_pram_offset); - - /* Free InitEnet command parameter */ - qe_muram_free(init_enet_pram_offset); - - return 0; -} - -/* returns a net_device_stats structure pointer */ -static struct net_device_stats *ucc_geth_get_stats(struct net_device *dev) -{ - ucc_geth_private_t *ugeth = netdev_priv(dev); - - return &(ugeth->stats); -} - -/* ucc_geth_timeout gets called when a packet has not been - * transmitted after a set amount of time. - * For now, assume that clearing out all the structures, and - * starting over will fix the problem. */ -static void ucc_geth_timeout(struct net_device *dev) -{ - ucc_geth_private_t *ugeth = netdev_priv(dev); - - ugeth_vdbg("%s: IN", __FUNCTION__); - - ugeth->stats.tx_errors++; - - ugeth_dump_regs(ugeth); - - if (dev->flags & IFF_UP) { - ucc_geth_stop(ugeth); - ucc_geth_startup(ugeth); - } - - netif_schedule(dev); -} - -/* This is called by the kernel when a frame is ready for transmission. */ -/* It is pointed to by the dev->hard_start_xmit function pointer */ -static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - ucc_geth_private_t *ugeth = netdev_priv(dev); - u8 *bd; /* BD pointer */ - u32 bd_status; - u8 txQ = 0; - - ugeth_vdbg("%s: IN", __FUNCTION__); - - spin_lock_irq(&ugeth->lock); - - ugeth->stats.tx_bytes += skb->len; - - /* Start from the next BD that should be filled */ - bd = ugeth->txBd[txQ]; - bd_status = BD_STATUS_AND_LENGTH(bd); - /* Save the skb pointer so we can free it later */ - ugeth->tx_skbuff[txQ][ugeth->skb_curtx[txQ]] = skb; - - /* Update the current skb pointer (wrapping if this was the last) */ - ugeth->skb_curtx[txQ] = - (ugeth->skb_curtx[txQ] + - 1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]); - - /* set up the buffer descriptor */ - BD_BUFFER_SET(bd, - dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE)); - - //printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data); - - bd_status = (bd_status & T_W) | T_R | T_I | T_L | skb->len; - - BD_STATUS_AND_LENGTH_SET(bd, bd_status); - - dev->trans_start = jiffies; - - /* Move to next BD in the ring */ - if (!(bd_status & T_W)) - ugeth->txBd[txQ] = bd + UCC_GETH_SIZE_OF_BD; - else - ugeth->txBd[txQ] = ugeth->p_tx_bd_ring[txQ]; - - /* If the next BD still needs to be cleaned up, then the bds - are full. We need to tell the kernel to stop sending us stuff. */ - if (bd == ugeth->confBd[txQ]) { - if (!netif_queue_stopped(dev)) - netif_stop_queue(dev); - } - - if (ugeth->p_scheduler) { - ugeth->cpucount[txQ]++; - /* Indicate to QE that there are more Tx bds ready for - transmission */ - /* This is done by writing a running counter of the bd - count to the scheduler PRAM. */ - out_be16(ugeth->p_cpucount[txQ], ugeth->cpucount[txQ]); - } - - spin_unlock_irq(&ugeth->lock); - - return 0; -} - -static int ucc_geth_rx(ucc_geth_private_t *ugeth, u8 rxQ, int rx_work_limit) -{ - struct sk_buff *skb; - u8 *bd; - u16 length, howmany = 0; - u32 bd_status; - u8 *bdBuffer; - - ugeth_vdbg("%s: IN", __FUNCTION__); - - spin_lock(&ugeth->lock); - /* collect received buffers */ - bd = ugeth->rxBd[rxQ]; - - bd_status = BD_STATUS_AND_LENGTH(bd); - - /* while there are received buffers and BD is full (~R_E) */ - while (!((bd_status & (R_E)) || (--rx_work_limit < 0))) { - bdBuffer = (u8 *) BD_BUFFER(bd); - length = (u16) ((bd_status & BD_LENGTH_MASK) - 4); - skb = ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]]; - - /* determine whether buffer is first, last, first and last - (single buffer frame) or middle (not first and not last) */ - if (!skb || - (!(bd_status & (R_F | R_L))) || - (bd_status & R_ERRORS_FATAL)) { - ugeth_vdbg("%s, %d: ERROR!!! skb - 0x%08x", - __FUNCTION__, __LINE__, (u32) skb); - if (skb) - dev_kfree_skb_any(skb); - - ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = NULL; - ugeth->stats.rx_dropped++; - } else { - ugeth->stats.rx_packets++; - howmany++; - - /* Prep the skb for the packet */ - skb_put(skb, length); - - /* Tell the skb what kind of packet this is */ - skb->protocol = eth_type_trans(skb, ugeth->dev); - - ugeth->stats.rx_bytes += length; - /* Send the packet up the stack */ -#ifdef CONFIG_UGETH_NAPI - netif_receive_skb(skb); -#else - netif_rx(skb); -#endif /* CONFIG_UGETH_NAPI */ - } - - ugeth->dev->last_rx = jiffies; - - skb = get_new_skb(ugeth, bd); - if (!skb) { - ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__); - spin_unlock(&ugeth->lock); - ugeth->stats.rx_dropped++; - break; - } - - ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = skb; - - /* update to point at the next skb */ - ugeth->skb_currx[rxQ] = - (ugeth->skb_currx[rxQ] + - 1) & RX_RING_MOD_MASK(ugeth->ug_info->bdRingLenRx[rxQ]); - - if (bd_status & R_W) - bd = ugeth->p_rx_bd_ring[rxQ]; - else - bd += UCC_GETH_SIZE_OF_BD; - - bd_status = BD_STATUS_AND_LENGTH(bd); - } - - ugeth->rxBd[rxQ] = bd; - spin_unlock(&ugeth->lock); - return howmany; -} - -static int ucc_geth_tx(struct net_device *dev, u8 txQ) -{ - /* Start from the next BD that should be filled */ - ucc_geth_private_t *ugeth = netdev_priv(dev); - u8 *bd; /* BD pointer */ - u32 bd_status; - - bd = ugeth->confBd[txQ]; - bd_status = BD_STATUS_AND_LENGTH(bd); - - /* Normal processing. */ - while ((bd_status & T_R) == 0) { - /* BD contains already transmitted buffer. */ - /* Handle the transmitted buffer and release */ - /* the BD to be used with the current frame */ - - if ((bd = ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0)) - break; - - ugeth->stats.tx_packets++; - - /* Free the sk buffer associated with this TxBD */ - dev_kfree_skb_irq(ugeth-> - tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]); - ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL; - ugeth->skb_dirtytx[txQ] = - (ugeth->skb_dirtytx[txQ] + - 1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]); - - /* We freed a buffer, so now we can restart transmission */ - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); - - /* Advance the confirmation BD pointer */ - if (!(bd_status & T_W)) - ugeth->confBd[txQ] += UCC_GETH_SIZE_OF_BD; - else - ugeth->confBd[txQ] = ugeth->p_tx_bd_ring[txQ]; - } - return 0; -} - -#ifdef CONFIG_UGETH_NAPI -static int ucc_geth_poll(struct net_device *dev, int *budget) -{ - ucc_geth_private_t *ugeth = netdev_priv(dev); - int howmany; - int rx_work_limit = *budget; - u8 rxQ = 0; - - if (rx_work_limit > dev->quota) - rx_work_limit = dev->quota; - - howmany = ucc_geth_rx(ugeth, rxQ, rx_work_limit); - - dev->quota -= howmany; - rx_work_limit -= howmany; - *budget -= howmany; - - if (rx_work_limit >= 0) - netif_rx_complete(dev); - - return (rx_work_limit < 0) ? 1 : 0; -} -#endif /* CONFIG_UGETH_NAPI */ - -static irqreturn_t ucc_geth_irq_handler(int irq, void *info, - struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)info; - ucc_geth_private_t *ugeth = netdev_priv(dev); - ucc_fast_private_t *uccf; - ucc_geth_info_t *ug_info; - register u32 ucce = 0; - register u32 bit_mask = UCCE_RXBF_SINGLE_MASK; - register u32 tx_mask = UCCE_TXBF_SINGLE_MASK; - register u8 i; - - ugeth_vdbg("%s: IN", __FUNCTION__); - - if (!ugeth) - return IRQ_NONE; - - uccf = ugeth->uccf; - ug_info = ugeth->ug_info; - - do { - ucce |= (u32) (in_be32(uccf->p_ucce) & in_be32(uccf->p_uccm)); - - /* clear event bits for next time */ - /* Side effect here is to mask ucce variable - for future processing below. */ - out_be32(uccf->p_ucce, ucce); /* Clear with ones, - but only bits in UCCM */ - - /* We ignore Tx interrupts because Tx confirmation is - done inside Tx routine */ - - for (i = 0; i < ug_info->numQueuesRx; i++) { - if (ucce & bit_mask) - ucc_geth_rx(ugeth, i, - (int)ugeth->ug_info-> - bdRingLenRx[i]); - ucce &= ~bit_mask; - bit_mask <<= 1; - } - - for (i = 0; i < ug_info->numQueuesTx; i++) { - if (ucce & tx_mask) - ucc_geth_tx(dev, i); - ucce &= ~tx_mask; - tx_mask <<= 1; - } - - /* Exceptions */ - if (ucce & UCCE_BSY) { - ugeth_vdbg("Got BUSY irq!!!!"); - ugeth->stats.rx_errors++; - ucce &= ~UCCE_BSY; - } - if (ucce & UCCE_OTHER) { - ugeth_vdbg("Got frame with error (ucce - 0x%08x)!!!!", - ucce); - ugeth->stats.rx_errors++; - ucce &= ~ucce; - } - } - while (ucce); - - return IRQ_HANDLED; -} - -static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)dev_id; - ucc_geth_private_t *ugeth = netdev_priv(dev); - - ugeth_vdbg("%s: IN", __FUNCTION__); - - /* Clear the interrupt */ - mii_clear_phy_interrupt(ugeth->mii_info); - - /* Disable PHY interrupts */ - mii_configure_phy_interrupt(ugeth->mii_info, MII_INTERRUPT_DISABLED); - - /* Schedule the phy change */ - schedule_work(&ugeth->tq); - - return IRQ_HANDLED; -} - -/* Scheduled by the phy_interrupt/timer to handle PHY changes */ -static void ugeth_phy_change(void *data) -{ - struct net_device *dev = (struct net_device *)data; - ucc_geth_private_t *ugeth = netdev_priv(dev); - ucc_geth_t *ug_regs; - int result = 0; - - ugeth_vdbg("%s: IN", __FUNCTION__); - - ug_regs = ugeth->ug_regs; - - /* Delay to give the PHY a chance to change the - * register state */ - msleep(1); - - /* Update the link, speed, duplex */ - result = ugeth->mii_info->phyinfo->read_status(ugeth->mii_info); - - /* Adjust the known status as long as the link - * isn't still coming up */ - if ((0 == result) || (ugeth->mii_info->link == 0)) - adjust_link(dev); - - /* Reenable interrupts, if needed */ - if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) - mii_configure_phy_interrupt(ugeth->mii_info, - MII_INTERRUPT_ENABLED); -} - -/* Called every so often on systems that don't interrupt - * the core for PHY changes */ -static void ugeth_phy_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - ucc_geth_private_t *ugeth = netdev_priv(dev); - - schedule_work(&ugeth->tq); - - mod_timer(&ugeth->phy_info_timer, jiffies + PHY_CHANGE_TIME * HZ); -} - -/* Keep trying aneg for some time - * If, after GFAR_AN_TIMEOUT seconds, it has not - * finished, we switch to forced. - * Either way, once the process has completed, we either - * request the interrupt, or switch the timer over to - * using ugeth_phy_timer to check status */ -static void ugeth_phy_startup_timer(unsigned long data) -{ - struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data; - ucc_geth_private_t *ugeth = netdev_priv(mii_info->dev); - static int secondary = UGETH_AN_TIMEOUT; - int result; - - /* Configure the Auto-negotiation */ - result = mii_info->phyinfo->config_aneg(mii_info); - - /* If autonegotiation failed to start, and - * we haven't timed out, reset the timer, and return */ - if (result && secondary--) { - mod_timer(&ugeth->phy_info_timer, jiffies + HZ); - return; - } else if (result) { - /* Couldn't start autonegotiation. - * Try switching to forced */ - mii_info->autoneg = 0; - result = mii_info->phyinfo->config_aneg(mii_info); - - /* Forcing failed! Give up */ - if (result) { - ugeth_err("%s: Forcing failed!", mii_info->dev->name); - return; - } - } - - /* Kill the timer so it can be restarted */ - del_timer_sync(&ugeth->phy_info_timer); - - /* Grab the PHY interrupt, if necessary/possible */ - if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) { - if (request_irq(ugeth->ug_info->phy_interrupt, - phy_interrupt, - SA_SHIRQ, "phy_interrupt", mii_info->dev) < 0) { - ugeth_err("%s: Can't get IRQ %d (PHY)", - mii_info->dev->name, - ugeth->ug_info->phy_interrupt); - } else { - mii_configure_phy_interrupt(ugeth->mii_info, - MII_INTERRUPT_ENABLED); - return; - } - } - - /* Start the timer again, this time in order to - * handle a change in status */ - init_timer(&ugeth->phy_info_timer); - ugeth->phy_info_timer.function = &ugeth_phy_timer; - ugeth->phy_info_timer.data = (unsigned long)mii_info->dev; - mod_timer(&ugeth->phy_info_timer, jiffies + PHY_CHANGE_TIME * HZ); -} - -/* Called when something needs to use the ethernet device */ -/* Returns 0 for success. */ -static int ucc_geth_open(struct net_device *dev) -{ - ucc_geth_private_t *ugeth = netdev_priv(dev); - int err; - - ugeth_vdbg("%s: IN", __FUNCTION__); - - /* Test station address */ - if (dev->dev_addr[0] & ENET_GROUP_ADDR) { - ugeth_err("%s: Multicast address used for station address" - " - is this what you wanted?", __FUNCTION__); - return -EINVAL; - } - - err = ucc_geth_startup(ugeth); - if (err) { - ugeth_err("%s: Cannot configure net device, aborting.", - dev->name); - return err; - } - - err = adjust_enet_interface(ugeth); - if (err) { - ugeth_err("%s: Cannot configure net device, aborting.", - dev->name); - return err; - } - - /* Set MACSTNADDR1, MACSTNADDR2 */ - /* For more details see the hardware spec. */ - init_mac_station_addr_regs(dev->dev_addr[0], - dev->dev_addr[1], - dev->dev_addr[2], - dev->dev_addr[3], - dev->dev_addr[4], - dev->dev_addr[5], - &ugeth->ug_regs->macstnaddr1, - &ugeth->ug_regs->macstnaddr2); - - err = init_phy(dev); - if (err) { - ugeth_err("%s: Cannot initialzie PHY, aborting.", dev->name); - return err; - } -#ifndef CONFIG_UGETH_NAPI - err = - request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0, - "UCC Geth", dev); - if (err) { - ugeth_err("%s: Cannot get IRQ for net device, aborting.", - dev->name); - ucc_geth_stop(ugeth); - return err; - } -#endif /* CONFIG_UGETH_NAPI */ - - /* Set up the PHY change work queue */ - INIT_WORK(&ugeth->tq, ugeth_phy_change, dev); - - init_timer(&ugeth->phy_info_timer); - ugeth->phy_info_timer.function = &ugeth_phy_startup_timer; - ugeth->phy_info_timer.data = (unsigned long)ugeth->mii_info; - mod_timer(&ugeth->phy_info_timer, jiffies + HZ); - - err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); - if (err) { - ugeth_err("%s: Cannot enable net device, aborting.", dev->name); - ucc_geth_stop(ugeth); - return err; - } - - netif_start_queue(dev); - - return err; -} - -/* Stops the kernel queue, and halts the controller */ -static int ucc_geth_close(struct net_device *dev) -{ - ucc_geth_private_t *ugeth = netdev_priv(dev); - - ugeth_vdbg("%s: IN", __FUNCTION__); - - ucc_geth_stop(ugeth); - - /* Shutdown the PHY */ - if (ugeth->mii_info->phyinfo->close) - ugeth->mii_info->phyinfo->close(ugeth->mii_info); - - kfree(ugeth->mii_info); - - netif_stop_queue(dev); - - return 0; -} - -struct ethtool_ops ucc_geth_ethtool_ops = { - .get_settings = NULL, - .get_drvinfo = NULL, - .get_regs_len = NULL, - .get_regs = NULL, - .get_link = NULL, - .get_coalesce = NULL, - .set_coalesce = NULL, - .get_ringparam = NULL, - .set_ringparam = NULL, - .get_strings = NULL, - .get_stats_count = NULL, - .get_ethtool_stats = NULL, -}; - -static int ucc_geth_probe(struct device *device) -{ - struct platform_device *pdev = to_platform_device(device); - struct ucc_geth_platform_data *ugeth_pdata; - struct net_device *dev = NULL; - struct ucc_geth_private *ugeth = NULL; - struct ucc_geth_info *ug_info; - int err; - static int mii_mng_configured = 0; - - ugeth_vdbg("%s: IN", __FUNCTION__); - - ugeth_pdata = (struct ucc_geth_platform_data *)pdev->dev.platform_data; - - ug_info = &ugeth_info[pdev->id]; - ug_info->uf_info.ucc_num = pdev->id; - ug_info->uf_info.rx_clock = ugeth_pdata->rx_clock; - ug_info->uf_info.tx_clock = ugeth_pdata->tx_clock; - ug_info->uf_info.regs = ugeth_pdata->phy_reg_addr; - ug_info->uf_info.irq = platform_get_irq(pdev, 0); - ug_info->phy_address = ugeth_pdata->phy_id; - ug_info->enet_interface = ugeth_pdata->phy_interface; - ug_info->board_flags = ugeth_pdata->board_flags; - ug_info->phy_interrupt = ugeth_pdata->phy_interrupt; - - printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n", - ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs, - ug_info->uf_info.irq); - - if (ug_info == NULL) { - ugeth_err("%s: [%d] Missing additional data!", __FUNCTION__, - pdev->id); - return -ENODEV; - } - - if (!mii_mng_configured) { - ucc_set_qe_mux_mii_mng(ug_info->uf_info.ucc_num); - mii_mng_configured = 1; - } - - /* Create an ethernet device instance */ - dev = alloc_etherdev(sizeof(*ugeth)); - - if (dev == NULL) - return -ENOMEM; - - ugeth = netdev_priv(dev); - spin_lock_init(&ugeth->lock); - - dev_set_drvdata(device, dev); - - /* Set the dev->base_addr to the gfar reg region */ - dev->base_addr = (unsigned long)(ug_info->uf_info.regs); - - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, device); - - /* Fill in the dev structure */ - dev->open = ucc_geth_open; - dev->hard_start_xmit = ucc_geth_start_xmit; - dev->tx_timeout = ucc_geth_timeout; - dev->watchdog_timeo = TX_TIMEOUT; -#ifdef CONFIG_UGETH_NAPI - dev->poll = ucc_geth_poll; - dev->weight = UCC_GETH_DEV_WEIGHT; -#endif /* CONFIG_UGETH_NAPI */ - dev->stop = ucc_geth_close; - dev->get_stats = ucc_geth_get_stats; -// dev->change_mtu = ucc_geth_change_mtu; - dev->mtu = 1500; - dev->set_multicast_list = ucc_geth_set_multi; - dev->ethtool_ops = &ucc_geth_ethtool_ops; - - err = register_netdev(dev); - if (err) { - ugeth_err("%s: Cannot register net device, aborting.", - dev->name); - free_netdev(dev); - return err; - } - - ugeth->ug_info = ug_info; - ugeth->dev = dev; - memcpy(dev->dev_addr, ugeth_pdata->mac_addr, 6); - - return 0; -} - -static int ucc_geth_remove(struct device *device) -{ - struct net_device *dev = dev_get_drvdata(device); - struct ucc_geth_private *ugeth = netdev_priv(dev); - - dev_set_drvdata(device, NULL); - ucc_geth_memclean(ugeth); - free_netdev(dev); - - return 0; -} - -/* Structure for a device driver */ -static struct device_driver ucc_geth_driver = { - .name = DRV_NAME, - .bus = &platform_bus_type, - .probe = ucc_geth_probe, - .remove = ucc_geth_remove, -}; - -static int __init ucc_geth_init(void) -{ - int i; - printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); - for (i = 0; i < 8; i++) - memcpy(&(ugeth_info[i]), &ugeth_primary_info, - sizeof(ugeth_primary_info)); - - return driver_register(&ucc_geth_driver); -} - -static void __exit ucc_geth_exit(void) -{ - driver_unregister(&ucc_geth_driver); -} - -module_init(ucc_geth_init); -module_exit(ucc_geth_exit); - -MODULE_AUTHOR("Freescale Semiconductor, Inc"); -MODULE_DESCRIPTION(DRV_DESC); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/net/ucc_geth.h b/trunk/drivers/net/ucc_geth.h deleted file mode 100644 index 005965f5dd9b..000000000000 --- a/trunk/drivers/net/ucc_geth.h +++ /dev/null @@ -1,1339 +0,0 @@ -/* - * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. - * - * Author: Shlomi Gridish - * - * Description: - * Internal header file for UCC Gigabit Ethernet unit routines. - * - * Changelog: - * Jun 28, 2006 Li Yang - * - Rearrange code and style fixes - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#ifndef __UCC_GETH_H__ -#define __UCC_GETH_H__ - -#include -#include -#include - -#include -#include - -#include -#include - -#define NUM_TX_QUEUES 8 -#define NUM_RX_QUEUES 8 -#define NUM_BDS_IN_PREFETCHED_BDS 4 -#define TX_IP_OFFSET_ENTRY_MAX 8 -#define NUM_OF_PADDRS 4 -#define ENET_INIT_PARAM_MAX_ENTRIES_RX 9 -#define ENET_INIT_PARAM_MAX_ENTRIES_TX 8 - -typedef struct ucc_mii_mng { - u32 miimcfg; /* MII management configuration reg */ - u32 miimcom; /* MII management command reg */ - u32 miimadd; /* MII management address reg */ - u32 miimcon; /* MII management control reg */ - u32 miimstat; /* MII management status reg */ - u32 miimind; /* MII management indication reg */ -} __attribute__ ((packed)) ucc_mii_mng_t; - -typedef struct ucc_geth { - ucc_fast_t uccf; - - u32 maccfg1; /* mac configuration reg. 1 */ - u32 maccfg2; /* mac configuration reg. 2 */ - u32 ipgifg; /* interframe gap reg. */ - u32 hafdup; /* half-duplex reg. */ - u8 res1[0x10]; - ucc_mii_mng_t miimng; /* MII management structure */ - u32 ifctl; /* interface control reg */ - u32 ifstat; /* interface statux reg */ - u32 macstnaddr1; /* mac station address part 1 reg */ - u32 macstnaddr2; /* mac station address part 2 reg */ - u8 res2[0x8]; - u32 uempr; /* UCC Ethernet Mac parameter reg */ - u32 utbipar; /* UCC tbi address reg */ - u16 uescr; /* UCC Ethernet statistics control reg */ - u8 res3[0x180 - 0x15A]; - u32 tx64; /* Total number of frames (including bad - frames) transmitted that were exactly of the - minimal length (64 for un tagged, 68 for - tagged, or with length exactly equal to the - parameter MINLength */ - u32 tx127; /* Total number of frames (including bad - frames) transmitted that were between - MINLength (Including FCS length==4) and 127 - octets */ - u32 tx255; /* Total number of frames (including bad - frames) transmitted that were between 128 - (Including FCS length==4) and 255 octets */ - u32 rx64; /* Total number of frames received including - bad frames that were exactly of the mninimal - length (64 bytes) */ - u32 rx127; /* Total number of frames (including bad - frames) received that were between MINLength - (Including FCS length==4) and 127 octets */ - u32 rx255; /* Total number of frames (including bad - frames) received that were between 128 - (Including FCS length==4) and 255 octets */ - u32 txok; /* Total number of octets residing in frames - that where involved in succesfull - transmission */ - u16 txcf; /* Total number of PAUSE control frames - transmitted by this MAC */ - u8 res4[0x2]; - u32 tmca; /* Total number of frames that were transmitted - succesfully with the group address bit set - that are not broadcast frames */ - u32 tbca; /* Total number of frames transmitted - succesfully that had destination address - field equal to the broadcast address */ - u32 rxfok; /* Total number of frames received OK */ - u32 rxbok; /* Total number of octets received OK */ - u32 rbyt; /* Total number of octets received including - octets in bad frames. Must be implemented in - HW because it includes octets in frames that - never even reach the UCC */ - u32 rmca; /* Total number of frames that were received - succesfully with the group address bit set - that are not broadcast frames */ - u32 rbca; /* Total number of frames received succesfully - that had destination address equal to the - broadcast address */ - u32 scar; /* Statistics carry register */ - u32 scam; /* Statistics caryy mask register */ - u8 res5[0x200 - 0x1c4]; -} __attribute__ ((packed)) ucc_geth_t; - -/* UCC GETH TEMODR Register */ -#define TEMODER_TX_RMON_STATISTICS_ENABLE 0x0100 /* enable Tx statistics - */ -#define TEMODER_SCHEDULER_ENABLE 0x2000 /* enable scheduler */ -#define TEMODER_IP_CHECKSUM_GENERATE 0x0400 /* generate IPv4 - checksums */ -#define TEMODER_PERFORMANCE_OPTIMIZATION_MODE1 0x0200 /* enable performance - optimization - enhancement (mode1) */ -#define TEMODER_RMON_STATISTICS 0x0100 /* enable tx statistics - */ -#define TEMODER_NUM_OF_QUEUES_SHIFT (15-15) /* Number of queues << - shift */ - -/* UCC GETH TEMODR Register */ -#define REMODER_RX_RMON_STATISTICS_ENABLE 0x00001000 /* enable Rx - statistics */ -#define REMODER_RX_EXTENDED_FEATURES 0x80000000 /* enable - extended - features */ -#define REMODER_VLAN_OPERATION_TAGGED_SHIFT (31-9 ) /* vlan operation - tagged << shift */ -#define REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT (31-10) /* vlan operation non - tagged << shift */ -#define REMODER_RX_QOS_MODE_SHIFT (31-15) /* rx QoS mode << shift - */ -#define REMODER_RMON_STATISTICS 0x00001000 /* enable rx - statistics */ -#define REMODER_RX_EXTENDED_FILTERING 0x00000800 /* extended - filtering - vs. - mpc82xx-like - filtering */ -#define REMODER_NUM_OF_QUEUES_SHIFT (31-23) /* Number of queues << - shift */ -#define REMODER_DYNAMIC_MAX_FRAME_LENGTH 0x00000008 /* enable - dynamic max - frame length - */ -#define REMODER_DYNAMIC_MIN_FRAME_LENGTH 0x00000004 /* enable - dynamic min - frame length - */ -#define REMODER_IP_CHECKSUM_CHECK 0x00000002 /* check IPv4 - checksums */ -#define REMODER_IP_ADDRESS_ALIGNMENT 0x00000001 /* align ip - address to - 4-byte - boundary */ - -/* UCC GETH Event Register */ -#define UCCE_MPD 0x80000000 /* Magic packet - detection */ -#define UCCE_SCAR 0x40000000 -#define UCCE_GRA 0x20000000 /* Tx graceful - stop - complete */ -#define UCCE_CBPR 0x10000000 -#define UCCE_BSY 0x08000000 -#define UCCE_RXC 0x04000000 -#define UCCE_TXC 0x02000000 -#define UCCE_TXE 0x01000000 -#define UCCE_TXB7 0x00800000 -#define UCCE_TXB6 0x00400000 -#define UCCE_TXB5 0x00200000 -#define UCCE_TXB4 0x00100000 -#define UCCE_TXB3 0x00080000 -#define UCCE_TXB2 0x00040000 -#define UCCE_TXB1 0x00020000 -#define UCCE_TXB0 0x00010000 -#define UCCE_RXB7 0x00008000 -#define UCCE_RXB6 0x00004000 -#define UCCE_RXB5 0x00002000 -#define UCCE_RXB4 0x00001000 -#define UCCE_RXB3 0x00000800 -#define UCCE_RXB2 0x00000400 -#define UCCE_RXB1 0x00000200 -#define UCCE_RXB0 0x00000100 -#define UCCE_RXF7 0x00000080 -#define UCCE_RXF6 0x00000040 -#define UCCE_RXF5 0x00000020 -#define UCCE_RXF4 0x00000010 -#define UCCE_RXF3 0x00000008 -#define UCCE_RXF2 0x00000004 -#define UCCE_RXF1 0x00000002 -#define UCCE_RXF0 0x00000001 - -#define UCCE_RXBF_SINGLE_MASK (UCCE_RXF0) -#define UCCE_TXBF_SINGLE_MASK (UCCE_TXB0) - -#define UCCE_TXB (UCCE_TXB7 | UCCE_TXB6 | UCCE_TXB5 | UCCE_TXB4 |\ - UCCE_TXB3 | UCCE_TXB2 | UCCE_TXB1 | UCCE_TXB0) -#define UCCE_RXB (UCCE_RXB7 | UCCE_RXB6 | UCCE_RXB5 | UCCE_RXB4 |\ - UCCE_RXB3 | UCCE_RXB2 | UCCE_RXB1 | UCCE_RXB0) -#define UCCE_RXF (UCCE_RXF7 | UCCE_RXF6 | UCCE_RXF5 | UCCE_RXF4 |\ - UCCE_RXF3 | UCCE_RXF2 | UCCE_RXF1 | UCCE_RXF0) -#define UCCE_OTHER (UCCE_SCAR | UCCE_GRA | UCCE_CBPR | UCCE_BSY |\ - UCCE_RXC | UCCE_TXC | UCCE_TXE) - -/* UCC GETH UPSMR (Protocol Specific Mode Register) */ -#define UPSMR_ECM 0x04000000 /* Enable CAM - Miss or - Enable - Filtering - Miss */ -#define UPSMR_HSE 0x02000000 /* Hardware - Statistics - Enable */ -#define UPSMR_PRO 0x00400000 /* Promiscuous*/ -#define UPSMR_CAP 0x00200000 /* CAM polarity - */ -#define UPSMR_RSH 0x00100000 /* Receive - Short Frames - */ -#define UPSMR_RPM 0x00080000 /* Reduced Pin - Mode - interfaces */ -#define UPSMR_R10M 0x00040000 /* RGMII/RMII - 10 Mode */ -#define UPSMR_RLPB 0x00020000 /* RMII - Loopback - Mode */ -#define UPSMR_TBIM 0x00010000 /* Ten-bit - Interface - Mode */ -#define UPSMR_RMM 0x00001000 /* RMII/RGMII - Mode */ -#define UPSMR_CAM 0x00000400 /* CAM Address - Matching */ -#define UPSMR_BRO 0x00000200 /* Broadcast - Address */ -#define UPSMR_RES1 0x00002000 /* Reserved - feild - must - be 1 */ - -/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */ -#define MACCFG1_FLOW_RX 0x00000020 /* Flow Control - Rx */ -#define MACCFG1_FLOW_TX 0x00000010 /* Flow Control - Tx */ -#define MACCFG1_ENABLE_SYNCHED_RX 0x00000008 /* Rx Enable - synchronized - to Rx stream - */ -#define MACCFG1_ENABLE_RX 0x00000004 /* Enable Rx */ -#define MACCFG1_ENABLE_SYNCHED_TX 0x00000002 /* Tx Enable - synchronized - to Tx stream - */ -#define MACCFG1_ENABLE_TX 0x00000001 /* Enable Tx */ - -/* UCC GETH MACCFG2 (MAC Configuration 2 Register) */ -#define MACCFG2_PREL_SHIFT (31 - 19) /* Preamble - Length << - shift */ -#define MACCFG2_PREL_MASK 0x0000f000 /* Preamble - Length mask */ -#define MACCFG2_SRP 0x00000080 /* Soft Receive - Preamble */ -#define MACCFG2_STP 0x00000040 /* Soft - Transmit - Preamble */ -#define MACCFG2_RESERVED_1 0x00000020 /* Reserved - - must be set - to 1 */ -#define MACCFG2_LC 0x00000010 /* Length Check - */ -#define MACCFG2_MPE 0x00000008 /* Magic packet - detect */ -#define MACCFG2_FDX 0x00000001 /* Full Duplex */ -#define MACCFG2_FDX_MASK 0x00000001 /* Full Duplex - mask */ -#define MACCFG2_PAD_CRC 0x00000004 -#define MACCFG2_CRC_EN 0x00000002 -#define MACCFG2_PAD_AND_CRC_MODE_NONE 0x00000000 /* Neither - Padding - short frames - nor CRC */ -#define MACCFG2_PAD_AND_CRC_MODE_CRC_ONLY 0x00000002 /* Append CRC - only */ -#define MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC 0x00000004 -#define MACCFG2_INTERFACE_MODE_NIBBLE 0x00000100 /* nibble mode - (MII/RMII/RGMII - 10/100bps) */ -#define MACCFG2_INTERFACE_MODE_BYTE 0x00000200 /* byte mode - (GMII/TBI/RTB/RGMII - 1000bps ) */ -#define MACCFG2_INTERFACE_MODE_MASK 0x00000300 /* mask - covering all - relevant - bits */ - -/* UCC GETH IPGIFG (Inter-frame Gap / Inter-Frame Gap Register) */ -#define IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT (31 - 7) /* Non - back-to-back - inter frame - gap part 1. - << shift */ -#define IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT (31 - 15) /* Non - back-to-back - inter frame - gap part 2. - << shift */ -#define IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT (31 - 23) /* Mimimum IFG - Enforcement - << shift */ -#define IPGIFG_BACK_TO_BACK_IFG_SHIFT (31 - 31) /* back-to-back - inter frame - gap << shift - */ -#define IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX 127 /* Non back-to-back - inter frame gap part - 1. max val */ -#define IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX 127 /* Non back-to-back - inter frame gap part - 2. max val */ -#define IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX 255 /* Mimimum IFG - Enforcement max val */ -#define IPGIFG_BACK_TO_BACK_IFG_MAX 127 /* back-to-back inter - frame gap max val */ -#define IPGIFG_NBTB_CS_IPG_MASK 0x7F000000 -#define IPGIFG_NBTB_IPG_MASK 0x007F0000 -#define IPGIFG_MIN_IFG_MASK 0x0000FF00 -#define IPGIFG_BTB_IPG_MASK 0x0000007F - -/* UCC GETH HAFDUP (Half Duplex Register) */ -#define HALFDUP_ALT_BEB_TRUNCATION_SHIFT (31 - 11) /* Alternate - Binary - Exponential - Backoff - Truncation - << shift */ -#define HALFDUP_ALT_BEB_TRUNCATION_MAX 0xf /* Alternate Binary - Exponential Backoff - Truncation max val */ -#define HALFDUP_ALT_BEB 0x00080000 /* Alternate - Binary - Exponential - Backoff */ -#define HALFDUP_BACK_PRESSURE_NO_BACKOFF 0x00040000 /* Back - pressure no - backoff */ -#define HALFDUP_NO_BACKOFF 0x00020000 /* No Backoff */ -#define HALFDUP_EXCESSIVE_DEFER 0x00010000 /* Excessive - Defer */ -#define HALFDUP_MAX_RETRANSMISSION_SHIFT (31 - 19) /* Maximum - Retransmission - << shift */ -#define HALFDUP_MAX_RETRANSMISSION_MAX 0xf /* Maximum - Retransmission max - val */ -#define HALFDUP_COLLISION_WINDOW_SHIFT (31 - 31) /* Collision - Window << - shift */ -#define HALFDUP_COLLISION_WINDOW_MAX 0x3f /* Collision Window max - val */ -#define HALFDUP_ALT_BEB_TR_MASK 0x00F00000 -#define HALFDUP_RETRANS_MASK 0x0000F000 -#define HALFDUP_COL_WINDOW_MASK 0x0000003F - -/* UCC GETH UCCS (Ethernet Status Register) */ -#define UCCS_BPR 0x02 /* Back pressure (in - half duplex mode) */ -#define UCCS_PAU 0x02 /* Pause state (in full - duplex mode) */ -#define UCCS_MPD 0x01 /* Magic Packet - Detected */ - -/* UCC GETH MIIMCFG (MII Management Configuration Register) */ -#define MIIMCFG_RESET_MANAGEMENT 0x80000000 /* Reset - management */ -#define MIIMCFG_NO_PREAMBLE 0x00000010 /* Preamble - suppress */ -#define MIIMCFG_CLOCK_DIVIDE_SHIFT (31 - 31) /* clock divide - << shift */ -#define MIIMCFG_CLOCK_DIVIDE_MAX 0xf /* clock divide max val - */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_2 0x00000000 /* divide by 2 */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_4 0x00000001 /* divide by 4 */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_6 0x00000002 /* divide by 6 */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_8 0x00000003 /* divide by 8 */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_10 0x00000004 /* divide by 10 - */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_14 0x00000005 /* divide by 14 - */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_16 0x00000008 /* divide by 16 - */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_20 0x00000006 /* divide by 20 - */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_28 0x00000007 /* divide by 28 - */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_32 0x00000009 /* divide by 32 - */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_48 0x0000000a /* divide by 48 - */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_64 0x0000000b /* divide by 64 - */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_80 0x0000000c /* divide by 80 - */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112 0x0000000d /* divide by - 112 */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_160 0x0000000e /* divide by - 160 */ -#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_224 0x0000000f /* divide by - 224 */ - -/* UCC GETH MIIMCOM (MII Management Command Register) */ -#define MIIMCOM_SCAN_CYCLE 0x00000002 /* Scan cycle */ -#define MIIMCOM_READ_CYCLE 0x00000001 /* Read cycle */ - -/* UCC GETH MIIMADD (MII Management Address Register) */ -#define MIIMADD_PHY_ADDRESS_SHIFT (31 - 23) /* PHY Address - << shift */ -#define MIIMADD_PHY_REGISTER_SHIFT (31 - 31) /* PHY Register - << shift */ - -/* UCC GETH MIIMCON (MII Management Control Register) */ -#define MIIMCON_PHY_CONTROL_SHIFT (31 - 31) /* PHY Control - << shift */ -#define MIIMCON_PHY_STATUS_SHIFT (31 - 31) /* PHY Status - << shift */ - -/* UCC GETH MIIMIND (MII Management Indicator Register) */ -#define MIIMIND_NOT_VALID 0x00000004 /* Not valid */ -#define MIIMIND_SCAN 0x00000002 /* Scan in - progress */ -#define MIIMIND_BUSY 0x00000001 - -/* UCC GETH IFSTAT (Interface Status Register) */ -#define IFSTAT_EXCESS_DEFER 0x00000200 /* Excessive - transmission - defer */ - -/* UCC GETH MACSTNADDR1 (Station Address Part 1 Register) */ -#define MACSTNADDR1_OCTET_6_SHIFT (31 - 7) /* Station - address 6th - octet << - shift */ -#define MACSTNADDR1_OCTET_5_SHIFT (31 - 15) /* Station - address 5th - octet << - shift */ -#define MACSTNADDR1_OCTET_4_SHIFT (31 - 23) /* Station - address 4th - octet << - shift */ -#define MACSTNADDR1_OCTET_3_SHIFT (31 - 31) /* Station - address 3rd - octet << - shift */ - -/* UCC GETH MACSTNADDR2 (Station Address Part 2 Register) */ -#define MACSTNADDR2_OCTET_2_SHIFT (31 - 7) /* Station - address 2nd - octet << - shift */ -#define MACSTNADDR2_OCTET_1_SHIFT (31 - 15) /* Station - address 1st - octet << - shift */ - -/* UCC GETH UEMPR (Ethernet Mac Parameter Register) */ -#define UEMPR_PAUSE_TIME_VALUE_SHIFT (31 - 15) /* Pause time - value << - shift */ -#define UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT (31 - 31) /* Extended - pause time - value << - shift */ - -/* UCC GETH UTBIPAR (Ten Bit Interface Physical Address Register) */ -#define UTBIPAR_PHY_ADDRESS_SHIFT (31 - 31) /* Phy address - << shift */ -#define UTBIPAR_PHY_ADDRESS_MASK 0x0000001f /* Phy address - mask */ - -/* UCC GETH UESCR (Ethernet Statistics Control Register) */ -#define UESCR_AUTOZ 0x8000 /* Automatically zero - addressed - statistical counter - values */ -#define UESCR_CLRCNT 0x4000 /* Clear all statistics - counters */ -#define UESCR_MAXCOV_SHIFT (15 - 7) /* Max - Coalescing - Value << - shift */ -#define UESCR_SCOV_SHIFT (15 - 15) /* Status - Coalescing - Value << - shift */ - -/* UCC GETH UDSR (Data Synchronization Register) */ -#define UDSR_MAGIC 0x067E - -typedef struct ucc_geth_thread_data_tx { - u8 res0[104]; -} __attribute__ ((packed)) ucc_geth_thread_data_tx_t; - -typedef struct ucc_geth_thread_data_rx { - u8 res0[40]; -} __attribute__ ((packed)) ucc_geth_thread_data_rx_t; - -/* Send Queue Queue-Descriptor */ -typedef struct ucc_geth_send_queue_qd { - u32 bd_ring_base; /* pointer to BD ring base address */ - u8 res0[0x8]; - u32 last_bd_completed_address;/* initialize to last entry in BD ring */ - u8 res1[0x30]; -} __attribute__ ((packed)) ucc_geth_send_queue_qd_t; - -typedef struct ucc_geth_send_queue_mem_region { - ucc_geth_send_queue_qd_t sqqd[NUM_TX_QUEUES]; -} __attribute__ ((packed)) ucc_geth_send_queue_mem_region_t; - -typedef struct ucc_geth_thread_tx_pram { - u8 res0[64]; -} __attribute__ ((packed)) ucc_geth_thread_tx_pram_t; - -typedef struct ucc_geth_thread_rx_pram { - u8 res0[128]; -} __attribute__ ((packed)) ucc_geth_thread_rx_pram_t; - -#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING 64 -#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8 64 -#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16 96 - -typedef struct ucc_geth_scheduler { - u16 cpucount0; /* CPU packet counter */ - u16 cpucount1; /* CPU packet counter */ - u16 cecount0; /* QE packet counter */ - u16 cecount1; /* QE packet counter */ - u16 cpucount2; /* CPU packet counter */ - u16 cpucount3; /* CPU packet counter */ - u16 cecount2; /* QE packet counter */ - u16 cecount3; /* QE packet counter */ - u16 cpucount4; /* CPU packet counter */ - u16 cpucount5; /* CPU packet counter */ - u16 cecount4; /* QE packet counter */ - u16 cecount5; /* QE packet counter */ - u16 cpucount6; /* CPU packet counter */ - u16 cpucount7; /* CPU packet counter */ - u16 cecount6; /* QE packet counter */ - u16 cecount7; /* QE packet counter */ - u32 weightstatus[NUM_TX_QUEUES]; /* accumulated weight factor */ - u32 rtsrshadow; /* temporary variable handled by QE */ - u32 time; /* temporary variable handled by QE */ - u32 ttl; /* temporary variable handled by QE */ - u32 mblinterval; /* max burst length interval */ - u16 nortsrbytetime; /* normalized value of byte time in tsr units */ - u8 fracsiz; /* radix 2 log value of denom. of - NorTSRByteTime */ - u8 res0[1]; - u8 strictpriorityq; /* Strict Priority Mask register */ - u8 txasap; /* Transmit ASAP register */ - u8 extrabw; /* Extra BandWidth register */ - u8 oldwfqmask; /* temporary variable handled by QE */ - u8 weightfactor[NUM_TX_QUEUES]; - /**< weight factor for queues */ - u32 minw; /* temporary variable handled by QE */ - u8 res1[0x70 - 0x64]; -} __attribute__ ((packed)) ucc_geth_scheduler_t; - -typedef struct ucc_geth_tx_firmware_statistics_pram { - u32 sicoltx; /* single collision */ - u32 mulcoltx; /* multiple collision */ - u32 latecoltxfr; /* late collision */ - u32 frabortduecol; /* frames aborted due to transmit collision */ - u32 frlostinmactxer; /* frames lost due to internal MAC error - transmission that are not counted on any - other counter */ - u32 carriersenseertx; /* carrier sense error */ - u32 frtxok; /* frames transmitted OK */ - u32 txfrexcessivedefer; /* frames with defferal time greater than - specified threshold */ - u32 txpkts256; /* total packets (including bad) between 256 - and 511 octets */ - u32 txpkts512; /* total packets (including bad) between 512 - and 1023 octets */ - u32 txpkts1024; /* total packets (including bad) between 1024 - and 1518 octets */ - u32 txpktsjumbo; /* total packets (including bad) between 1024 - and MAXLength octets */ -} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_pram_t; - -typedef struct ucc_geth_rx_firmware_statistics_pram { - u32 frrxfcser; /* frames with crc error */ - u32 fraligner; /* frames with alignment error */ - u32 inrangelenrxer; /* in range length error */ - u32 outrangelenrxer; /* out of range length error */ - u32 frtoolong; /* frame too long */ - u32 runt; /* runt */ - u32 verylongevent; /* very long event */ - u32 symbolerror; /* symbol error */ - u32 dropbsy; /* drop because of BD not ready */ - u8 res0[0x8]; - u32 mismatchdrop; /* drop because of MAC filtering (e.g. address - or type mismatch) */ - u32 underpkts; /* total frames less than 64 octets */ - u32 pkts256; /* total frames (including bad) between 256 and - 511 octets */ - u32 pkts512; /* total frames (including bad) between 512 and - 1023 octets */ - u32 pkts1024; /* total frames (including bad) between 1024 - and 1518 octets */ - u32 pktsjumbo; /* total frames (including bad) between 1024 - and MAXLength octets */ - u32 frlossinmacer; /* frames lost because of internal MAC error - that is not counted in any other counter */ - u32 pausefr; /* pause frames */ - u8 res1[0x4]; - u32 removevlan; /* total frames that had their VLAN tag removed - */ - u32 replacevlan; /* total frames that had their VLAN tag - replaced */ - u32 insertvlan; /* total frames that had their VLAN tag - inserted */ -} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_pram_t; - -typedef struct ucc_geth_rx_interrupt_coalescing_entry { - u32 interruptcoalescingmaxvalue; /* interrupt coalescing max - value */ - u32 interruptcoalescingcounter; /* interrupt coalescing counter, - initialize to - interruptcoalescingmaxvalue */ -} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_entry_t; - -typedef struct ucc_geth_rx_interrupt_coalescing_table { - ucc_geth_rx_interrupt_coalescing_entry_t coalescingentry[NUM_RX_QUEUES]; - /**< interrupt coalescing entry */ -} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_table_t; - -typedef struct ucc_geth_rx_prefetched_bds { - qe_bd_t bd[NUM_BDS_IN_PREFETCHED_BDS]; /* prefetched bd */ -} __attribute__ ((packed)) ucc_geth_rx_prefetched_bds_t; - -typedef struct ucc_geth_rx_bd_queues_entry { - u32 bdbaseptr; /* BD base pointer */ - u32 bdptr; /* BD pointer */ - u32 externalbdbaseptr; /* external BD base pointer */ - u32 externalbdptr; /* external BD pointer */ -} __attribute__ ((packed)) ucc_geth_rx_bd_queues_entry_t; - -typedef struct ucc_geth_tx_global_pram { - u16 temoder; - u8 res0[0x38 - 0x02]; - u32 sqptr; /* a base pointer to send queue memory region */ - u32 schedulerbasepointer; /* a base pointer to scheduler memory - region */ - u32 txrmonbaseptr; /* base pointer to Tx RMON statistics counter */ - u32 tstate; /* tx internal state. High byte contains - function code */ - u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX]; - u32 vtagtable[0x8]; /* 8 4-byte VLAN tags */ - u32 tqptr; /* a base pointer to the Tx Queues Memory - Region */ - u8 res2[0x80 - 0x74]; -} __attribute__ ((packed)) ucc_geth_tx_global_pram_t; - -/* structure representing Extended Filtering Global Parameters in PRAM */ -typedef struct ucc_geth_exf_global_pram { - u32 l2pcdptr; /* individual address filter, high */ - u8 res0[0x10 - 0x04]; -} __attribute__ ((packed)) ucc_geth_exf_global_pram_t; - -typedef struct ucc_geth_rx_global_pram { - u32 remoder; /* ethernet mode reg. */ - u32 rqptr; /* base pointer to the Rx Queues Memory Region*/ - u32 res0[0x1]; - u8 res1[0x20 - 0xC]; - u16 typeorlen; /* cutoff point less than which, type/len field - is considered length */ - u8 res2[0x1]; - u8 rxgstpack; /* acknowledgement on GRACEFUL STOP RX command*/ - u32 rxrmonbaseptr; /* base pointer to Rx RMON statistics counter */ - u8 res3[0x30 - 0x28]; - u32 intcoalescingptr; /* Interrupt coalescing table pointer */ - u8 res4[0x36 - 0x34]; - u8 rstate; /* rx internal state. High byte contains - function code */ - u8 res5[0x46 - 0x37]; - u16 mrblr; /* max receive buffer length reg. */ - u32 rbdqptr; /* base pointer to RxBD parameter table - description */ - u16 mflr; /* max frame length reg. */ - u16 minflr; /* min frame length reg. */ - u16 maxd1; /* max dma1 length reg. */ - u16 maxd2; /* max dma2 length reg. */ - u32 ecamptr; /* external CAM address */ - u32 l2qt; /* VLAN priority mapping table. */ - u32 l3qt[0x8]; /* IP priority mapping table. */ - u16 vlantype; /* vlan type */ - u16 vlantci; /* default vlan tci */ - u8 addressfiltering[64]; /* address filtering data structure */ - u32 exfGlobalParam; /* base address for extended filtering global - parameters */ - u8 res6[0x100 - 0xC4]; /* Initialize to zero */ -} __attribute__ ((packed)) ucc_geth_rx_global_pram_t; - -#define GRACEFUL_STOP_ACKNOWLEDGE_RX 0x01 - -/* structure representing InitEnet command */ -typedef struct ucc_geth_init_pram { - u8 resinit1; - u8 resinit2; - u8 resinit3; - u8 resinit4; - u16 resinit5; - u8 res1[0x1]; - u8 largestexternallookupkeysize; - u32 rgftgfrxglobal; - u32 rxthread[ENET_INIT_PARAM_MAX_ENTRIES_RX]; /* rx threads */ - u8 res2[0x38 - 0x30]; - u32 txglobal; /* tx global */ - u32 txthread[ENET_INIT_PARAM_MAX_ENTRIES_TX]; /* tx threads */ - u8 res3[0x1]; -} __attribute__ ((packed)) ucc_geth_init_pram_t; - -#define ENET_INIT_PARAM_RGF_SHIFT (32 - 4) -#define ENET_INIT_PARAM_TGF_SHIFT (32 - 8) - -#define ENET_INIT_PARAM_RISC_MASK 0x0000003f -#define ENET_INIT_PARAM_PTR_MASK 0x00ffffc0 -#define ENET_INIT_PARAM_SNUM_MASK 0xff000000 -#define ENET_INIT_PARAM_SNUM_SHIFT 24 - -#define ENET_INIT_PARAM_MAGIC_RES_INIT1 0x06 -#define ENET_INIT_PARAM_MAGIC_RES_INIT2 0x30 -#define ENET_INIT_PARAM_MAGIC_RES_INIT3 0xff -#define ENET_INIT_PARAM_MAGIC_RES_INIT4 0x00 -#define ENET_INIT_PARAM_MAGIC_RES_INIT5 0x0400 - -/* structure representing 82xx Address Filtering Enet Address in PRAM */ -typedef struct ucc_geth_82xx_enet_address { - u8 res1[0x2]; - u16 h; /* address (MSB) */ - u16 m; /* address */ - u16 l; /* address (LSB) */ -} __attribute__ ((packed)) ucc_geth_82xx_enet_address_t; - -/* structure representing 82xx Address Filtering PRAM */ -typedef struct ucc_geth_82xx_address_filtering_pram { - u32 iaddr_h; /* individual address filter, high */ - u32 iaddr_l; /* individual address filter, low */ - u32 gaddr_h; /* group address filter, high */ - u32 gaddr_l; /* group address filter, low */ - ucc_geth_82xx_enet_address_t taddr; - ucc_geth_82xx_enet_address_t paddr[NUM_OF_PADDRS]; - u8 res0[0x40 - 0x38]; -} __attribute__ ((packed)) ucc_geth_82xx_address_filtering_pram_t; - -/* GETH Tx firmware statistics structure, used when calling - UCC_GETH_GetStatistics. */ -typedef struct ucc_geth_tx_firmware_statistics { - u32 sicoltx; /* single collision */ - u32 mulcoltx; /* multiple collision */ - u32 latecoltxfr; /* late collision */ - u32 frabortduecol; /* frames aborted due to transmit collision */ - u32 frlostinmactxer; /* frames lost due to internal MAC error - transmission that are not counted on any - other counter */ - u32 carriersenseertx; /* carrier sense error */ - u32 frtxok; /* frames transmitted OK */ - u32 txfrexcessivedefer; /* frames with defferal time greater than - specified threshold */ - u32 txpkts256; /* total packets (including bad) between 256 - and 511 octets */ - u32 txpkts512; /* total packets (including bad) between 512 - and 1023 octets */ - u32 txpkts1024; /* total packets (including bad) between 1024 - and 1518 octets */ - u32 txpktsjumbo; /* total packets (including bad) between 1024 - and MAXLength octets */ -} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_t; - -/* GETH Rx firmware statistics structure, used when calling - UCC_GETH_GetStatistics. */ -typedef struct ucc_geth_rx_firmware_statistics { - u32 frrxfcser; /* frames with crc error */ - u32 fraligner; /* frames with alignment error */ - u32 inrangelenrxer; /* in range length error */ - u32 outrangelenrxer; /* out of range length error */ - u32 frtoolong; /* frame too long */ - u32 runt; /* runt */ - u32 verylongevent; /* very long event */ - u32 symbolerror; /* symbol error */ - u32 dropbsy; /* drop because of BD not ready */ - u8 res0[0x8]; - u32 mismatchdrop; /* drop because of MAC filtering (e.g. address - or type mismatch) */ - u32 underpkts; /* total frames less than 64 octets */ - u32 pkts256; /* total frames (including bad) between 256 and - 511 octets */ - u32 pkts512; /* total frames (including bad) between 512 and - 1023 octets */ - u32 pkts1024; /* total frames (including bad) between 1024 - and 1518 octets */ - u32 pktsjumbo; /* total frames (including bad) between 1024 - and MAXLength octets */ - u32 frlossinmacer; /* frames lost because of internal MAC error - that is not counted in any other counter */ - u32 pausefr; /* pause frames */ - u8 res1[0x4]; - u32 removevlan; /* total frames that had their VLAN tag removed - */ - u32 replacevlan; /* total frames that had their VLAN tag - replaced */ - u32 insertvlan; /* total frames that had their VLAN tag - inserted */ -} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_t; - -/* GETH hardware statistics structure, used when calling - UCC_GETH_GetStatistics. */ -typedef struct ucc_geth_hardware_statistics { - u32 tx64; /* Total number of frames (including bad - frames) transmitted that were exactly of the - minimal length (64 for un tagged, 68 for - tagged, or with length exactly equal to the - parameter MINLength */ - u32 tx127; /* Total number of frames (including bad - frames) transmitted that were between - MINLength (Including FCS length==4) and 127 - octets */ - u32 tx255; /* Total number of frames (including bad - frames) transmitted that were between 128 - (Including FCS length==4) and 255 octets */ - u32 rx64; /* Total number of frames received including - bad frames that were exactly of the mninimal - length (64 bytes) */ - u32 rx127; /* Total number of frames (including bad - frames) received that were between MINLength - (Including FCS length==4) and 127 octets */ - u32 rx255; /* Total number of frames (including bad - frames) received that were between 128 - (Including FCS length==4) and 255 octets */ - u32 txok; /* Total number of octets residing in frames - that where involved in succesfull - transmission */ - u16 txcf; /* Total number of PAUSE control frames - transmitted by this MAC */ - u32 tmca; /* Total number of frames that were transmitted - succesfully with the group address bit set - that are not broadcast frames */ - u32 tbca; /* Total number of frames transmitted - succesfully that had destination address - field equal to the broadcast address */ - u32 rxfok; /* Total number of frames received OK */ - u32 rxbok; /* Total number of octets received OK */ - u32 rbyt; /* Total number of octets received including - octets in bad frames. Must be implemented in - HW because it includes octets in frames that - never even reach the UCC */ - u32 rmca; /* Total number of frames that were received - succesfully with the group address bit set - that are not broadcast frames */ - u32 rbca; /* Total number of frames received succesfully - that had destination address equal to the - broadcast address */ -} __attribute__ ((packed)) ucc_geth_hardware_statistics_t; - -/* UCC GETH Tx errors returned via TxConf callback */ -#define TX_ERRORS_DEF 0x0200 -#define TX_ERRORS_EXDEF 0x0100 -#define TX_ERRORS_LC 0x0080 -#define TX_ERRORS_RL 0x0040 -#define TX_ERRORS_RC_MASK 0x003C -#define TX_ERRORS_RC_SHIFT 2 -#define TX_ERRORS_UN 0x0002 -#define TX_ERRORS_CSL 0x0001 - -/* UCC GETH Rx errors returned via RxStore callback */ -#define RX_ERRORS_CMR 0x0200 -#define RX_ERRORS_M 0x0100 -#define RX_ERRORS_BC 0x0080 -#define RX_ERRORS_MC 0x0040 - -/* Transmit BD. These are in addition to values defined in uccf. */ -#define T_VID 0x003c0000 /* insert VLAN id index mask. */ -#define T_DEF (((u32) TX_ERRORS_DEF ) << 16) -#define T_EXDEF (((u32) TX_ERRORS_EXDEF ) << 16) -#define T_LC (((u32) TX_ERRORS_LC ) << 16) -#define T_RL (((u32) TX_ERRORS_RL ) << 16) -#define T_RC_MASK (((u32) TX_ERRORS_RC_MASK ) << 16) -#define T_UN (((u32) TX_ERRORS_UN ) << 16) -#define T_CSL (((u32) TX_ERRORS_CSL ) << 16) -#define T_ERRORS_REPORT (T_DEF | T_EXDEF | T_LC | T_RL | T_RC_MASK \ - | T_UN | T_CSL) /* transmit errors to report */ - -/* Receive BD. These are in addition to values defined in uccf. */ -#define R_LG 0x00200000 /* Frame length violation. */ -#define R_NO 0x00100000 /* Non-octet aligned frame. */ -#define R_SH 0x00080000 /* Short frame. */ -#define R_CR 0x00040000 /* CRC error. */ -#define R_OV 0x00020000 /* Overrun. */ -#define R_IPCH 0x00010000 /* IP checksum check failed. */ -#define R_CMR (((u32) RX_ERRORS_CMR ) << 16) -#define R_M (((u32) RX_ERRORS_M ) << 16) -#define R_BC (((u32) RX_ERRORS_BC ) << 16) -#define R_MC (((u32) RX_ERRORS_MC ) << 16) -#define R_ERRORS_REPORT (R_CMR | R_M | R_BC | R_MC) /* receive errors to - report */ -#define R_ERRORS_FATAL (R_LG | R_NO | R_SH | R_CR | \ - R_OV | R_IPCH) /* receive errors to discard */ - -/* Alignments */ -#define UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT 256 -#define UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT 128 -#define UCC_GETH_THREAD_RX_PRAM_ALIGNMENT 128 -#define UCC_GETH_THREAD_TX_PRAM_ALIGNMENT 64 -#define UCC_GETH_THREAD_DATA_ALIGNMENT 256 /* spec gives values - based on num of - threads, but always - using the maximum is - easier */ -#define UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT 32 -#define UCC_GETH_SCHEDULER_ALIGNMENT 4 /* This is a guess */ -#define UCC_GETH_TX_STATISTICS_ALIGNMENT 4 /* This is a guess */ -#define UCC_GETH_RX_STATISTICS_ALIGNMENT 4 /* This is a guess */ -#define UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT 4 /* This is a - guess */ -#define UCC_GETH_RX_BD_QUEUES_ALIGNMENT 8 /* This is a guess */ -#define UCC_GETH_RX_PREFETCHED_BDS_ALIGNMENT 128 /* This is a guess */ -#define UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT 4 /* This - is a - guess - */ -#define UCC_GETH_RX_BD_RING_ALIGNMENT 32 -#define UCC_GETH_TX_BD_RING_ALIGNMENT 32 -#define UCC_GETH_MRBLR_ALIGNMENT 128 -#define UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT 4 -#define UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT 32 -#define UCC_GETH_RX_DATA_BUF_ALIGNMENT 64 - -#define UCC_GETH_TAD_EF 0x80 -#define UCC_GETH_TAD_V 0x40 -#define UCC_GETH_TAD_REJ 0x20 -#define UCC_GETH_TAD_VTAG_OP_RIGHT_SHIFT 2 -#define UCC_GETH_TAD_VTAG_OP_SHIFT 6 -#define UCC_GETH_TAD_V_NON_VTAG_OP 0x20 -#define UCC_GETH_TAD_RQOS_SHIFT 0 -#define UCC_GETH_TAD_V_PRIORITY_SHIFT 5 -#define UCC_GETH_TAD_CFI 0x10 - -#define UCC_GETH_VLAN_PRIORITY_MAX 8 -#define UCC_GETH_IP_PRIORITY_MAX 64 -#define UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX 8 -#define UCC_GETH_RX_BD_RING_SIZE_MIN 8 -#define UCC_GETH_TX_BD_RING_SIZE_MIN 2 - -#define UCC_GETH_SIZE_OF_BD QE_SIZEOF_BD - -/* Driver definitions */ -#define TX_BD_RING_LEN 0x10 -#define RX_BD_RING_LEN 0x10 -#define UCC_GETH_DEV_WEIGHT TX_BD_RING_LEN - -#define TX_RING_MOD_MASK(size) (size-1) -#define RX_RING_MOD_MASK(size) (size-1) - -#define ENET_NUM_OCTETS_PER_ADDRESS 6 -#define ENET_GROUP_ADDR 0x01 /* Group address mask - for ethernet - addresses */ - -#define TX_TIMEOUT (1*HZ) -#define SKB_ALLOC_TIMEOUT 100000 -#define PHY_INIT_TIMEOUT 100000 -#define PHY_CHANGE_TIME 2 - -/* Fast Ethernet (10/100 Mbps) */ -#define UCC_GETH_URFS_INIT 512 /* Rx virtual FIFO size - */ -#define UCC_GETH_URFET_INIT 256 /* 1/2 urfs */ -#define UCC_GETH_URFSET_INIT 384 /* 3/4 urfs */ -#define UCC_GETH_UTFS_INIT 512 /* Tx virtual FIFO size - */ -#define UCC_GETH_UTFET_INIT 256 /* 1/2 utfs */ -#define UCC_GETH_UTFTT_INIT 128 -/* Gigabit Ethernet (1000 Mbps) */ -#define UCC_GETH_URFS_GIGA_INIT 4096/*2048*/ /* Rx virtual - FIFO size */ -#define UCC_GETH_URFET_GIGA_INIT 2048/*1024*/ /* 1/2 urfs */ -#define UCC_GETH_URFSET_GIGA_INIT 3072/*1536*/ /* 3/4 urfs */ -#define UCC_GETH_UTFS_GIGA_INIT 8192/*2048*/ /* Tx virtual - FIFO size */ -#define UCC_GETH_UTFET_GIGA_INIT 4096/*1024*/ /* 1/2 utfs */ -#define UCC_GETH_UTFTT_GIGA_INIT 0x400/*0x40*/ /* */ - -#define UCC_GETH_REMODER_INIT 0 /* bits that must be - set */ -#define UCC_GETH_TEMODER_INIT 0xC000 /* bits that must */ -#define UCC_GETH_UPSMR_INIT (UPSMR_RES1) /* Start value - for this - register */ -#define UCC_GETH_MACCFG1_INIT 0 -#define UCC_GETH_MACCFG2_INIT (MACCFG2_RESERVED_1) -#define UCC_GETH_MIIMCFG_MNGMNT_CLC_DIV_INIT \ - (MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112) - -/* Ethernet speed */ -typedef enum enet_speed { - ENET_SPEED_10BT, /* 10 Base T */ - ENET_SPEED_100BT, /* 100 Base T */ - ENET_SPEED_1000BT /* 1000 Base T */ -} enet_speed_e; - -/* Ethernet Address Type. */ -typedef enum enet_addr_type { - ENET_ADDR_TYPE_INDIVIDUAL, - ENET_ADDR_TYPE_GROUP, - ENET_ADDR_TYPE_BROADCAST -} enet_addr_type_e; - -/* TBI / MII Set Register */ -typedef enum enet_tbi_mii_reg { - ENET_TBI_MII_CR = 0x00, /* Control (CR ) */ - ENET_TBI_MII_SR = 0x01, /* Status (SR ) */ - ENET_TBI_MII_ANA = 0x04, /* AN advertisement (ANA ) */ - ENET_TBI_MII_ANLPBPA = 0x05, /* AN link partner base page ability - (ANLPBPA) */ - ENET_TBI_MII_ANEX = 0x06, /* AN expansion (ANEX ) */ - ENET_TBI_MII_ANNPT = 0x07, /* AN next page transmit (ANNPT ) */ - ENET_TBI_MII_ANLPANP = 0x08, /* AN link partner ability next page - (ANLPANP) */ - ENET_TBI_MII_EXST = 0x0F, /* Extended status (EXST ) */ - ENET_TBI_MII_JD = 0x10, /* Jitter diagnostics (JD ) */ - ENET_TBI_MII_TBICON = 0x11 /* TBI control (TBICON ) */ -} enet_tbi_mii_reg_e; - -/* UCC GETH 82xx Ethernet Address Recognition Location */ -typedef enum ucc_geth_enet_address_recognition_location { - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_STATION_ADDRESS,/* station - address */ - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_FIRST, /* additional - station - address - paddr1 */ - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR2, /* additional - station - address - paddr2 */ - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR3, /* additional - station - address - paddr3 */ - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_LAST, /* additional - station - address - paddr4 */ - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH, /* group hash */ - UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH /* individual - hash */ -} ucc_geth_enet_address_recognition_location_e; - -/* UCC GETH vlan operation tagged */ -typedef enum ucc_geth_vlan_operation_tagged { - UCC_GETH_VLAN_OPERATION_TAGGED_NOP = 0x0, /* Tagged - nop */ - UCC_GETH_VLAN_OPERATION_TAGGED_REPLACE_VID_PORTION_OF_Q_TAG - = 0x1, /* Tagged - replace vid portion of q tag */ - UCC_GETH_VLAN_OPERATION_TAGGED_IF_VID0_REPLACE_VID_WITH_DEFAULT_VALUE - = 0x2, /* Tagged - if vid0 replace vid with default value */ - UCC_GETH_VLAN_OPERATION_TAGGED_EXTRACT_Q_TAG_FROM_FRAME - = 0x3 /* Tagged - extract q tag from frame */ -} ucc_geth_vlan_operation_tagged_e; - -/* UCC GETH vlan operation non-tagged */ -typedef enum ucc_geth_vlan_operation_non_tagged { - UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP = 0x0, /* Non tagged - nop */ - UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT = 0x1 /* Non tagged - - q tag insert - */ -} ucc_geth_vlan_operation_non_tagged_e; - -/* UCC GETH Rx Quality of Service Mode */ -typedef enum ucc_geth_qos_mode { - UCC_GETH_QOS_MODE_DEFAULT = 0x0, /* default queue */ - UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L2_CRITERIA = 0x1, /* queue - determined - by L2 - criteria */ - UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L3_CRITERIA = 0x2 /* queue - determined - by L3 - criteria */ -} ucc_geth_qos_mode_e; - -/* UCC GETH Statistics Gathering Mode - These are bit flags, 'or' them together - for combined functionality */ -typedef enum ucc_geth_statistics_gathering_mode { - UCC_GETH_STATISTICS_GATHERING_MODE_NONE = 0x00000000, /* No - statistics - gathering */ - UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE = 0x00000001,/* Enable - hardware - statistics - gathering - */ - UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX = 0x00000004,/*Enable - firmware - tx - statistics - gathering - */ - UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX = 0x00000008/* Enable - firmware - rx - statistics - gathering - */ -} ucc_geth_statistics_gathering_mode_e; - -/* UCC GETH Pad and CRC Mode - Note, Padding without CRC is not possible */ -typedef enum ucc_geth_maccfg2_pad_and_crc_mode { - UCC_GETH_PAD_AND_CRC_MODE_NONE - = MACCFG2_PAD_AND_CRC_MODE_NONE, /* Neither Padding - short frames - nor CRC */ - UCC_GETH_PAD_AND_CRC_MODE_CRC_ONLY - = MACCFG2_PAD_AND_CRC_MODE_CRC_ONLY, /* Append - CRC only */ - UCC_GETH_PAD_AND_CRC_MODE_PAD_AND_CRC = - MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC -} ucc_geth_maccfg2_pad_and_crc_mode_e; - -/* UCC GETH upsmr Flow Control Mode */ -typedef enum ucc_geth_flow_control_mode { - UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE = 0x00000000, /* No automatic - flow control - */ - UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_PAUSE_WHEN_EMERGENCY - = 0x00004000 /* Send pause frame when RxFIFO reaches its - emergency threshold */ -} ucc_geth_flow_control_mode_e; - -/* UCC GETH number of threads */ -typedef enum ucc_geth_num_of_threads { - UCC_GETH_NUM_OF_THREADS_1 = 0x1, /* 1 */ - UCC_GETH_NUM_OF_THREADS_2 = 0x2, /* 2 */ - UCC_GETH_NUM_OF_THREADS_4 = 0x0, /* 4 */ - UCC_GETH_NUM_OF_THREADS_6 = 0x3, /* 6 */ - UCC_GETH_NUM_OF_THREADS_8 = 0x4 /* 8 */ -} ucc_geth_num_of_threads_e; - -/* UCC GETH number of station addresses */ -typedef enum ucc_geth_num_of_station_addresses { - UCC_GETH_NUM_OF_STATION_ADDRESSES_1, /* 1 */ - UCC_GETH_NUM_OF_STATION_ADDRESSES_5 /* 5 */ -} ucc_geth_num_of_station_addresses_e; - -typedef u8 enet_addr_t[ENET_NUM_OCTETS_PER_ADDRESS]; - -/* UCC GETH 82xx Ethernet Address Container */ -typedef struct enet_addr_container { - enet_addr_t address; /* ethernet address */ - ucc_geth_enet_address_recognition_location_e location; /* location in - 82xx address - recognition - hardware */ - struct list_head node; -} enet_addr_container_t; - -#define ENET_ADDR_CONT_ENTRY(ptr) list_entry(ptr, enet_addr_container_t, node) - -/* UCC GETH Termination Action Descriptor (TAD) structure. */ -typedef struct ucc_geth_tad_params { - int rx_non_dynamic_extended_features_mode; - int reject_frame; - ucc_geth_vlan_operation_tagged_e vtag_op; - ucc_geth_vlan_operation_non_tagged_e vnontag_op; - ucc_geth_qos_mode_e rqos; - u8 vpri; - u16 vid; -} ucc_geth_tad_params_t; - -/* GETH protocol initialization structure */ -typedef struct ucc_geth_info { - ucc_fast_info_t uf_info; - u8 numQueuesTx; - u8 numQueuesRx; - int ipCheckSumCheck; - int ipCheckSumGenerate; - int rxExtendedFiltering; - u32 extendedFilteringChainPointer; - u16 typeorlen; - int dynamicMaxFrameLength; - int dynamicMinFrameLength; - u8 nonBackToBackIfgPart1; - u8 nonBackToBackIfgPart2; - u8 miminumInterFrameGapEnforcement; - u8 backToBackInterFrameGap; - int ipAddressAlignment; - int lengthCheckRx; - u32 mblinterval; - u16 nortsrbytetime; - u8 fracsiz; - u8 strictpriorityq; - u8 txasap; - u8 extrabw; - int miiPreambleSupress; - u8 altBebTruncation; - int altBeb; - int backPressureNoBackoff; - int noBackoff; - int excessDefer; - u8 maxRetransmission; - u8 collisionWindow; - int pro; - int cap; - int rsh; - int rlpb; - int cam; - int bro; - int ecm; - int receiveFlowControl; - u8 maxGroupAddrInHash; - u8 maxIndAddrInHash; - u8 prel; - u16 maxFrameLength; - u16 minFrameLength; - u16 maxD1Length; - u16 maxD2Length; - u16 vlantype; - u16 vlantci; - u32 ecamptr; - u32 eventRegMask; - u16 pausePeriod; - u16 extensionField; - u8 phy_address; - u32 board_flags; - u32 phy_interrupt; - u8 weightfactor[NUM_TX_QUEUES]; - u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES]; - u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX]; - u8 l3qt[UCC_GETH_IP_PRIORITY_MAX]; - u32 vtagtable[UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX]; - u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX]; - u16 bdRingLenTx[NUM_TX_QUEUES]; - u16 bdRingLenRx[NUM_RX_QUEUES]; - enet_interface_e enet_interface; - ucc_geth_num_of_station_addresses_e numStationAddresses; - qe_fltr_largest_external_tbl_lookup_key_size_e - largestexternallookupkeysize; - ucc_geth_statistics_gathering_mode_e statisticsMode; - ucc_geth_vlan_operation_tagged_e vlanOperationTagged; - ucc_geth_vlan_operation_non_tagged_e vlanOperationNonTagged; - ucc_geth_qos_mode_e rxQoSMode; - ucc_geth_flow_control_mode_e aufc; - ucc_geth_maccfg2_pad_and_crc_mode_e padAndCrc; - ucc_geth_num_of_threads_e numThreadsTx; - ucc_geth_num_of_threads_e numThreadsRx; - qe_risc_allocation_e riscTx; - qe_risc_allocation_e riscRx; -} ucc_geth_info_t; - -/* structure representing UCC GETH */ -typedef struct ucc_geth_private { - ucc_geth_info_t *ug_info; - ucc_fast_private_t *uccf; - struct net_device *dev; - struct net_device_stats stats; /* linux network statistics */ - ucc_geth_t *ug_regs; - ucc_geth_init_pram_t *p_init_enet_param_shadow; - ucc_geth_exf_global_pram_t *p_exf_glbl_param; - u32 exf_glbl_param_offset; - ucc_geth_rx_global_pram_t *p_rx_glbl_pram; - u32 rx_glbl_pram_offset; - ucc_geth_tx_global_pram_t *p_tx_glbl_pram; - u32 tx_glbl_pram_offset; - ucc_geth_send_queue_mem_region_t *p_send_q_mem_reg; - u32 send_q_mem_reg_offset; - ucc_geth_thread_data_tx_t *p_thread_data_tx; - u32 thread_dat_tx_offset; - ucc_geth_thread_data_rx_t *p_thread_data_rx; - u32 thread_dat_rx_offset; - ucc_geth_scheduler_t *p_scheduler; - u32 scheduler_offset; - ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram; - u32 tx_fw_statistics_pram_offset; - ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram; - u32 rx_fw_statistics_pram_offset; - ucc_geth_rx_interrupt_coalescing_table_t *p_rx_irq_coalescing_tbl; - u32 rx_irq_coalescing_tbl_offset; - ucc_geth_rx_bd_queues_entry_t *p_rx_bd_qs_tbl; - u32 rx_bd_qs_tbl_offset; - u8 *p_tx_bd_ring[NUM_TX_QUEUES]; - u32 tx_bd_ring_offset[NUM_TX_QUEUES]; - u8 *p_rx_bd_ring[NUM_RX_QUEUES]; - u32 rx_bd_ring_offset[NUM_RX_QUEUES]; - u8 *confBd[NUM_TX_QUEUES]; - u8 *txBd[NUM_TX_QUEUES]; - u8 *rxBd[NUM_RX_QUEUES]; - int badFrame[NUM_RX_QUEUES]; - u16 cpucount[NUM_TX_QUEUES]; - volatile u16 *p_cpucount[NUM_TX_QUEUES]; - int indAddrRegUsed[NUM_OF_PADDRS]; - enet_addr_t paddr[NUM_OF_PADDRS]; - u8 numGroupAddrInHash; - u8 numIndAddrInHash; - u8 numIndAddrInReg; - int rx_extended_features; - int rx_non_dynamic_extended_features; - struct list_head conf_skbs; - struct list_head group_hash_q; - struct list_head ind_hash_q; - u32 saved_uccm; - spinlock_t lock; - /* pointers to arrays of skbuffs for tx and rx */ - struct sk_buff **tx_skbuff[NUM_TX_QUEUES]; - struct sk_buff **rx_skbuff[NUM_RX_QUEUES]; - /* indices pointing to the next free sbk in skb arrays */ - u16 skb_curtx[NUM_TX_QUEUES]; - u16 skb_currx[NUM_RX_QUEUES]; - /* index of the first skb which hasn't been transmitted yet. */ - u16 skb_dirtytx[NUM_TX_QUEUES]; - - struct work_struct tq; - struct timer_list phy_info_timer; - struct ugeth_mii_info *mii_info; - int oldspeed; - int oldduplex; - int oldlink; -} ucc_geth_private_t; - -#endif /* __UCC_GETH_H__ */ diff --git a/trunk/drivers/net/ucc_geth_phy.c b/trunk/drivers/net/ucc_geth_phy.c deleted file mode 100644 index f91028c5386d..000000000000 --- a/trunk/drivers/net/ucc_geth_phy.c +++ /dev/null @@ -1,801 +0,0 @@ -/* - * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. - * - * Author: Shlomi Gridish - * - * Description: - * UCC GETH Driver -- PHY handling - * - * Changelog: - * Jun 28, 2006 Li Yang - * - Rearrange code and style fixes - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ucc_geth.h" -#include "ucc_geth_phy.h" -#include - -#define ugphy_printk(level, format, arg...) \ - printk(level format "\n", ## arg) - -#define ugphy_dbg(format, arg...) \ - ugphy_printk(KERN_DEBUG, format , ## arg) -#define ugphy_err(format, arg...) \ - ugphy_printk(KERN_ERR, format , ## arg) -#define ugphy_info(format, arg...) \ - ugphy_printk(KERN_INFO, format , ## arg) -#define ugphy_warn(format, arg...) \ - ugphy_printk(KERN_WARNING, format , ## arg) - -#ifdef UGETH_VERBOSE_DEBUG -#define ugphy_vdbg ugphy_dbg -#else -#define ugphy_vdbg(fmt, args...) do { } while (0) -#endif /* UGETH_VERBOSE_DEBUG */ - -static void config_genmii_advert(struct ugeth_mii_info *mii_info); -static void genmii_setup_forced(struct ugeth_mii_info *mii_info); -static void genmii_restart_aneg(struct ugeth_mii_info *mii_info); -static int gbit_config_aneg(struct ugeth_mii_info *mii_info); -static int genmii_config_aneg(struct ugeth_mii_info *mii_info); -static int genmii_update_link(struct ugeth_mii_info *mii_info); -static int genmii_read_status(struct ugeth_mii_info *mii_info); -u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum); -void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val); - -static u8 *bcsr_regs = NULL; - -/* Write value to the PHY for this device to the register at regnum, */ -/* waiting until the write is done before it returns. All PHY */ -/* configuration has to be done through the TSEC1 MIIM regs */ -void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value) -{ - ucc_geth_private_t *ugeth = netdev_priv(dev); - ucc_mii_mng_t *mii_regs; - enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum; - u32 tmp_reg; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - spin_lock_irq(&ugeth->lock); - - mii_regs = ugeth->mii_info->mii_regs; - - /* Set this UCC to be the master of the MII managment */ - ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num); - - /* Stop the MII management read cycle */ - out_be32(&mii_regs->miimcom, 0); - /* Setting up the MII Mangement Address Register */ - tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg; - out_be32(&mii_regs->miimadd, tmp_reg); - - /* Setting up the MII Mangement Control Register with the value */ - out_be32(&mii_regs->miimcon, (u32) value); - - /* Wait till MII management write is complete */ - while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY) - cpu_relax(); - - spin_unlock_irq(&ugeth->lock); - - udelay(10000); -} - -/* Reads from register regnum in the PHY for device dev, */ -/* returning the value. Clears miimcom first. All PHY */ -/* configuration has to be done through the TSEC1 MIIM regs */ -int read_phy_reg(struct net_device *dev, int mii_id, int regnum) -{ - ucc_geth_private_t *ugeth = netdev_priv(dev); - ucc_mii_mng_t *mii_regs; - enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum; - u32 tmp_reg; - u16 value; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - spin_lock_irq(&ugeth->lock); - - mii_regs = ugeth->mii_info->mii_regs; - - /* Setting up the MII Mangement Address Register */ - tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg; - out_be32(&mii_regs->miimadd, tmp_reg); - - /* Perform an MII management read cycle */ - out_be32(&mii_regs->miimcom, MIIMCOM_READ_CYCLE); - - /* Wait till MII management write is complete */ - while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY) - cpu_relax(); - - udelay(10000); - - /* Read MII management status */ - value = (u16) in_be32(&mii_regs->miimstat); - out_be32(&mii_regs->miimcom, 0); - if (value == 0xffff) - ugphy_warn("read wrong value : mii_id %d,mii_reg %d, base %08x", - mii_id, mii_reg, (u32) & (mii_regs->miimcfg)); - - spin_unlock_irq(&ugeth->lock); - - return (value); -} - -void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info) -{ - ugphy_vdbg("%s: IN", __FUNCTION__); - - if (mii_info->phyinfo->ack_interrupt) - mii_info->phyinfo->ack_interrupt(mii_info); -} - -void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info, - u32 interrupts) -{ - ugphy_vdbg("%s: IN", __FUNCTION__); - - mii_info->interrupts = interrupts; - if (mii_info->phyinfo->config_intr) - mii_info->phyinfo->config_intr(mii_info); -} - -/* Writes MII_ADVERTISE with the appropriate values, after - * sanitizing advertise to make sure only supported features - * are advertised - */ -static void config_genmii_advert(struct ugeth_mii_info *mii_info) -{ - u32 advertise; - u16 adv; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - /* Only allow advertising what this PHY supports */ - mii_info->advertising &= mii_info->phyinfo->features; - advertise = mii_info->advertising; - - /* Setup standard advertisement */ - adv = phy_read(mii_info, MII_ADVERTISE); - adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); - if (advertise & ADVERTISED_10baseT_Half) - adv |= ADVERTISE_10HALF; - if (advertise & ADVERTISED_10baseT_Full) - adv |= ADVERTISE_10FULL; - if (advertise & ADVERTISED_100baseT_Half) - adv |= ADVERTISE_100HALF; - if (advertise & ADVERTISED_100baseT_Full) - adv |= ADVERTISE_100FULL; - phy_write(mii_info, MII_ADVERTISE, adv); -} - -static void genmii_setup_forced(struct ugeth_mii_info *mii_info) -{ - u16 ctrl; - u32 features = mii_info->phyinfo->features; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - ctrl = phy_read(mii_info, MII_BMCR); - - ctrl &= - ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE); - ctrl |= BMCR_RESET; - - switch (mii_info->speed) { - case SPEED_1000: - if (features & (SUPPORTED_1000baseT_Half - | SUPPORTED_1000baseT_Full)) { - ctrl |= BMCR_SPEED1000; - break; - } - mii_info->speed = SPEED_100; - case SPEED_100: - if (features & (SUPPORTED_100baseT_Half - | SUPPORTED_100baseT_Full)) { - ctrl |= BMCR_SPEED100; - break; - } - mii_info->speed = SPEED_10; - case SPEED_10: - if (features & (SUPPORTED_10baseT_Half - | SUPPORTED_10baseT_Full)) - break; - default: /* Unsupported speed! */ - ugphy_err("%s: Bad speed!", mii_info->dev->name); - break; - } - - phy_write(mii_info, MII_BMCR, ctrl); -} - -/* Enable and Restart Autonegotiation */ -static void genmii_restart_aneg(struct ugeth_mii_info *mii_info) -{ - u16 ctl; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - ctl = phy_read(mii_info, MII_BMCR); - ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); - phy_write(mii_info, MII_BMCR, ctl); -} - -static int gbit_config_aneg(struct ugeth_mii_info *mii_info) -{ - u16 adv; - u32 advertise; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - if (mii_info->autoneg) { - /* Configure the ADVERTISE register */ - config_genmii_advert(mii_info); - advertise = mii_info->advertising; - - adv = phy_read(mii_info, MII_1000BASETCONTROL); - adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP | - MII_1000BASETCONTROL_HALFDUPLEXCAP); - if (advertise & SUPPORTED_1000baseT_Half) - adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP; - if (advertise & SUPPORTED_1000baseT_Full) - adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP; - phy_write(mii_info, MII_1000BASETCONTROL, adv); - - /* Start/Restart aneg */ - genmii_restart_aneg(mii_info); - } else - genmii_setup_forced(mii_info); - - return 0; -} - -static int genmii_config_aneg(struct ugeth_mii_info *mii_info) -{ - ugphy_vdbg("%s: IN", __FUNCTION__); - - if (mii_info->autoneg) { - config_genmii_advert(mii_info); - genmii_restart_aneg(mii_info); - } else - genmii_setup_forced(mii_info); - - return 0; -} - -static int genmii_update_link(struct ugeth_mii_info *mii_info) -{ - u16 status; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - /* Do a fake read */ - phy_read(mii_info, MII_BMSR); - - /* Read link and autonegotiation status */ - status = phy_read(mii_info, MII_BMSR); - if ((status & BMSR_LSTATUS) == 0) - mii_info->link = 0; - else - mii_info->link = 1; - - /* If we are autonegotiating, and not done, - * return an error */ - if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE)) - return -EAGAIN; - - return 0; -} - -static int genmii_read_status(struct ugeth_mii_info *mii_info) -{ - u16 status; - int err; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - /* Update the link, but return if there - * was an error */ - err = genmii_update_link(mii_info); - if (err) - return err; - - if (mii_info->autoneg) { - status = phy_read(mii_info, MII_LPA); - - if (status & (LPA_10FULL | LPA_100FULL)) - mii_info->duplex = DUPLEX_FULL; - else - mii_info->duplex = DUPLEX_HALF; - if (status & (LPA_100FULL | LPA_100HALF)) - mii_info->speed = SPEED_100; - else - mii_info->speed = SPEED_10; - mii_info->pause = 0; - } - /* On non-aneg, we assume what we put in BMCR is the speed, - * though magic-aneg shouldn't prevent this case from occurring - */ - - return 0; -} - -static int marvell_init(struct ugeth_mii_info *mii_info) -{ - ugphy_vdbg("%s: IN", __FUNCTION__); - - phy_write(mii_info, 0x14, 0x0cd2); - phy_write(mii_info, MII_BMCR, - phy_read(mii_info, MII_BMCR) | BMCR_RESET); - msleep(4000); - - return 0; -} - -static int marvell_config_aneg(struct ugeth_mii_info *mii_info) -{ - ugphy_vdbg("%s: IN", __FUNCTION__); - - /* The Marvell PHY has an errata which requires - * that certain registers get written in order - * to restart autonegotiation */ - phy_write(mii_info, MII_BMCR, BMCR_RESET); - - phy_write(mii_info, 0x1d, 0x1f); - phy_write(mii_info, 0x1e, 0x200c); - phy_write(mii_info, 0x1d, 0x5); - phy_write(mii_info, 0x1e, 0); - phy_write(mii_info, 0x1e, 0x100); - - gbit_config_aneg(mii_info); - - return 0; -} - -static int marvell_read_status(struct ugeth_mii_info *mii_info) -{ - u16 status; - int err; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - /* Update the link, but return if there - * was an error */ - err = genmii_update_link(mii_info); - if (err) - return err; - - /* If the link is up, read the speed and duplex */ - /* If we aren't autonegotiating, assume speeds - * are as set */ - if (mii_info->autoneg && mii_info->link) { - int speed; - status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS); - - /* Get the duplexity */ - if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX) - mii_info->duplex = DUPLEX_FULL; - else - mii_info->duplex = DUPLEX_HALF; - - /* Get the speed */ - speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK; - switch (speed) { - case MII_M1011_PHY_SPEC_STATUS_1000: - mii_info->speed = SPEED_1000; - break; - case MII_M1011_PHY_SPEC_STATUS_100: - mii_info->speed = SPEED_100; - break; - default: - mii_info->speed = SPEED_10; - break; - } - mii_info->pause = 0; - } - - return 0; -} - -static int marvell_ack_interrupt(struct ugeth_mii_info *mii_info) -{ - ugphy_vdbg("%s: IN", __FUNCTION__); - - /* Clear the interrupts by reading the reg */ - phy_read(mii_info, MII_M1011_IEVENT); - - return 0; -} - -static int marvell_config_intr(struct ugeth_mii_info *mii_info) -{ - ugphy_vdbg("%s: IN", __FUNCTION__); - - if (mii_info->interrupts == MII_INTERRUPT_ENABLED) - phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT); - else - phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); - - return 0; -} - -static int cis820x_init(struct ugeth_mii_info *mii_info) -{ - ugphy_vdbg("%s: IN", __FUNCTION__); - - phy_write(mii_info, MII_CIS8201_AUX_CONSTAT, - MII_CIS8201_AUXCONSTAT_INIT); - phy_write(mii_info, MII_CIS8201_EXT_CON1, MII_CIS8201_EXTCON1_INIT); - - return 0; -} - -static int cis820x_read_status(struct ugeth_mii_info *mii_info) -{ - u16 status; - int err; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - /* Update the link, but return if there - * was an error */ - err = genmii_update_link(mii_info); - if (err) - return err; - - /* If the link is up, read the speed and duplex */ - /* If we aren't autonegotiating, assume speeds - * are as set */ - if (mii_info->autoneg && mii_info->link) { - int speed; - - status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT); - if (status & MII_CIS8201_AUXCONSTAT_DUPLEX) - mii_info->duplex = DUPLEX_FULL; - else - mii_info->duplex = DUPLEX_HALF; - - speed = status & MII_CIS8201_AUXCONSTAT_SPEED; - - switch (speed) { - case MII_CIS8201_AUXCONSTAT_GBIT: - mii_info->speed = SPEED_1000; - break; - case MII_CIS8201_AUXCONSTAT_100: - mii_info->speed = SPEED_100; - break; - default: - mii_info->speed = SPEED_10; - break; - } - } - - return 0; -} - -static int cis820x_ack_interrupt(struct ugeth_mii_info *mii_info) -{ - ugphy_vdbg("%s: IN", __FUNCTION__); - - phy_read(mii_info, MII_CIS8201_ISTAT); - - return 0; -} - -static int cis820x_config_intr(struct ugeth_mii_info *mii_info) -{ - ugphy_vdbg("%s: IN", __FUNCTION__); - - if (mii_info->interrupts == MII_INTERRUPT_ENABLED) - phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK); - else - phy_write(mii_info, MII_CIS8201_IMASK, 0); - - return 0; -} - -#define DM9161_DELAY 10 - -static int dm9161_read_status(struct ugeth_mii_info *mii_info) -{ - u16 status; - int err; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - /* Update the link, but return if there - * was an error */ - err = genmii_update_link(mii_info); - if (err) - return err; - - /* If the link is up, read the speed and duplex */ - /* If we aren't autonegotiating, assume speeds - * are as set */ - if (mii_info->autoneg && mii_info->link) { - status = phy_read(mii_info, MII_DM9161_SCSR); - if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H)) - mii_info->speed = SPEED_100; - else - mii_info->speed = SPEED_10; - - if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F)) - mii_info->duplex = DUPLEX_FULL; - else - mii_info->duplex = DUPLEX_HALF; - } - - return 0; -} - -static int dm9161_config_aneg(struct ugeth_mii_info *mii_info) -{ - struct dm9161_private *priv = mii_info->priv; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - if (0 == priv->resetdone) - return -EAGAIN; - - return 0; -} - -static void dm9161_timer(unsigned long data) -{ - struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data; - struct dm9161_private *priv = mii_info->priv; - u16 status = phy_read(mii_info, MII_BMSR); - - ugphy_vdbg("%s: IN", __FUNCTION__); - - if (status & BMSR_ANEGCOMPLETE) { - priv->resetdone = 1; - } else - mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ); -} - -static int dm9161_init(struct ugeth_mii_info *mii_info) -{ - struct dm9161_private *priv; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - /* Allocate the private data structure */ - priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL); - - if (NULL == priv) - return -ENOMEM; - - mii_info->priv = priv; - - /* Reset is not done yet */ - priv->resetdone = 0; - - phy_write(mii_info, MII_BMCR, - phy_read(mii_info, MII_BMCR) | BMCR_RESET); - - phy_write(mii_info, MII_BMCR, - phy_read(mii_info, MII_BMCR) & ~BMCR_ISOLATE); - - config_genmii_advert(mii_info); - /* Start/Restart aneg */ - genmii_config_aneg(mii_info); - - /* Start a timer for DM9161_DELAY seconds to wait - * for the PHY to be ready */ - init_timer(&priv->timer); - priv->timer.function = &dm9161_timer; - priv->timer.data = (unsigned long)mii_info; - mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ); - - return 0; -} - -static void dm9161_close(struct ugeth_mii_info *mii_info) -{ - struct dm9161_private *priv = mii_info->priv; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - del_timer_sync(&priv->timer); - kfree(priv); -} - -static int dm9161_ack_interrupt(struct ugeth_mii_info *mii_info) -{ -/* FIXME: This lines are for BUG fixing in the mpc8325. -Remove this from here when it's fixed */ - if (bcsr_regs == NULL) - bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE); - bcsr_regs[14] |= 0x40; - ugphy_vdbg("%s: IN", __FUNCTION__); - - /* Clear the interrupts by reading the reg */ - phy_read(mii_info, MII_DM9161_INTR); - - - return 0; -} - -static int dm9161_config_intr(struct ugeth_mii_info *mii_info) -{ -/* FIXME: This lines are for BUG fixing in the mpc8325. -Remove this from here when it's fixed */ - if (bcsr_regs == NULL) { - bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE); - bcsr_regs[14] &= ~0x40; - } - ugphy_vdbg("%s: IN", __FUNCTION__); - - if (mii_info->interrupts == MII_INTERRUPT_ENABLED) - phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT); - else - phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP); - - return 0; -} - -/* Cicada 820x */ -static struct phy_info phy_info_cis820x = { - .phy_id = 0x000fc440, - .name = "Cicada Cis8204", - .phy_id_mask = 0x000fffc0, - .features = MII_GBIT_FEATURES, - .init = &cis820x_init, - .config_aneg = &gbit_config_aneg, - .read_status = &cis820x_read_status, - .ack_interrupt = &cis820x_ack_interrupt, - .config_intr = &cis820x_config_intr, -}; - -static struct phy_info phy_info_dm9161 = { - .phy_id = 0x0181b880, - .phy_id_mask = 0x0ffffff0, - .name = "Davicom DM9161E", - .init = dm9161_init, - .config_aneg = dm9161_config_aneg, - .read_status = dm9161_read_status, - .close = dm9161_close, -}; - -static struct phy_info phy_info_dm9161a = { - .phy_id = 0x0181b8a0, - .phy_id_mask = 0x0ffffff0, - .name = "Davicom DM9161A", - .features = MII_BASIC_FEATURES, - .init = dm9161_init, - .config_aneg = dm9161_config_aneg, - .read_status = dm9161_read_status, - .ack_interrupt = dm9161_ack_interrupt, - .config_intr = dm9161_config_intr, - .close = dm9161_close, -}; - -static struct phy_info phy_info_marvell = { - .phy_id = 0x01410c00, - .phy_id_mask = 0xffffff00, - .name = "Marvell 88E11x1", - .features = MII_GBIT_FEATURES, - .init = &marvell_init, - .config_aneg = &marvell_config_aneg, - .read_status = &marvell_read_status, - .ack_interrupt = &marvell_ack_interrupt, - .config_intr = &marvell_config_intr, -}; - -static struct phy_info phy_info_genmii = { - .phy_id = 0x00000000, - .phy_id_mask = 0x00000000, - .name = "Generic MII", - .features = MII_BASIC_FEATURES, - .config_aneg = genmii_config_aneg, - .read_status = genmii_read_status, -}; - -static struct phy_info *phy_info[] = { - &phy_info_cis820x, - &phy_info_marvell, - &phy_info_dm9161, - &phy_info_dm9161a, - &phy_info_genmii, - NULL -}; - -u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum) -{ - u16 retval; - unsigned long flags; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - spin_lock_irqsave(&mii_info->mdio_lock, flags); - retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum); - spin_unlock_irqrestore(&mii_info->mdio_lock, flags); - - return retval; -} - -void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val) -{ - unsigned long flags; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - spin_lock_irqsave(&mii_info->mdio_lock, flags); - mii_info->mdio_write(mii_info->dev, mii_info->mii_id, regnum, val); - spin_unlock_irqrestore(&mii_info->mdio_lock, flags); -} - -/* Use the PHY ID registers to determine what type of PHY is attached - * to device dev. return a struct phy_info structure describing that PHY - */ -struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info) -{ - u16 phy_reg; - u32 phy_ID; - int i; - struct phy_info *theInfo = NULL; - struct net_device *dev = mii_info->dev; - - ugphy_vdbg("%s: IN", __FUNCTION__); - - /* Grab the bits from PHYIR1, and put them in the upper half */ - phy_reg = phy_read(mii_info, MII_PHYSID1); - phy_ID = (phy_reg & 0xffff) << 16; - - /* Grab the bits from PHYIR2, and put them in the lower half */ - phy_reg = phy_read(mii_info, MII_PHYSID2); - phy_ID |= (phy_reg & 0xffff); - - /* loop through all the known PHY types, and find one that */ - /* matches the ID we read from the PHY. */ - for (i = 0; phy_info[i]; i++) - if (phy_info[i]->phy_id == (phy_ID & phy_info[i]->phy_id_mask)){ - theInfo = phy_info[i]; - break; - } - - /* This shouldn't happen, as we have generic PHY support */ - if (theInfo == NULL) { - ugphy_info("%s: PHY id %x is not supported!", dev->name, - phy_ID); - return NULL; - } else { - ugphy_info("%s: PHY is %s (%x)", dev->name, theInfo->name, - phy_ID); - } - - return theInfo; -} diff --git a/trunk/drivers/net/ucc_geth_phy.h b/trunk/drivers/net/ucc_geth_phy.h deleted file mode 100644 index 2f98b8f1bb0a..000000000000 --- a/trunk/drivers/net/ucc_geth_phy.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. - * - * Author: Shlomi Gridish - * - * Description: - * UCC GETH Driver -- PHY handling - * - * Changelog: - * Jun 28, 2006 Li Yang - * - Rearrange code and style fixes - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ -#ifndef __UCC_GETH_PHY_H__ -#define __UCC_GETH_PHY_H__ - -#define MII_end ((u32)-2) -#define MII_read ((u32)-1) - -#define MIIMIND_BUSY 0x00000001 -#define MIIMIND_NOTVALID 0x00000004 - -#define UGETH_AN_TIMEOUT 2000 - -/* 1000BT control (Marvell & BCM54xx at least) */ -#define MII_1000BASETCONTROL 0x09 -#define MII_1000BASETCONTROL_FULLDUPLEXCAP 0x0200 -#define MII_1000BASETCONTROL_HALFDUPLEXCAP 0x0100 - -/* Cicada Extended Control Register 1 */ -#define MII_CIS8201_EXT_CON1 0x17 -#define MII_CIS8201_EXTCON1_INIT 0x0000 - -/* Cicada Interrupt Mask Register */ -#define MII_CIS8201_IMASK 0x19 -#define MII_CIS8201_IMASK_IEN 0x8000 -#define MII_CIS8201_IMASK_SPEED 0x4000 -#define MII_CIS8201_IMASK_LINK 0x2000 -#define MII_CIS8201_IMASK_DUPLEX 0x1000 -#define MII_CIS8201_IMASK_MASK 0xf000 - -/* Cicada Interrupt Status Register */ -#define MII_CIS8201_ISTAT 0x1a -#define MII_CIS8201_ISTAT_STATUS 0x8000 -#define MII_CIS8201_ISTAT_SPEED 0x4000 -#define MII_CIS8201_ISTAT_LINK 0x2000 -#define MII_CIS8201_ISTAT_DUPLEX 0x1000 - -/* Cicada Auxiliary Control/Status Register */ -#define MII_CIS8201_AUX_CONSTAT 0x1c -#define MII_CIS8201_AUXCONSTAT_INIT 0x0004 -#define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020 -#define MII_CIS8201_AUXCONSTAT_SPEED 0x0018 -#define MII_CIS8201_AUXCONSTAT_GBIT 0x0010 -#define MII_CIS8201_AUXCONSTAT_100 0x0008 - -/* 88E1011 PHY Status Register */ -#define MII_M1011_PHY_SPEC_STATUS 0x11 -#define MII_M1011_PHY_SPEC_STATUS_1000 0x8000 -#define MII_M1011_PHY_SPEC_STATUS_100 0x4000 -#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK 0xc000 -#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX 0x2000 -#define MII_M1011_PHY_SPEC_STATUS_RESOLVED 0x0800 -#define MII_M1011_PHY_SPEC_STATUS_LINK 0x0400 - -#define MII_M1011_IEVENT 0x13 -#define MII_M1011_IEVENT_CLEAR 0x0000 - -#define MII_M1011_IMASK 0x12 -#define MII_M1011_IMASK_INIT 0x6400 -#define MII_M1011_IMASK_CLEAR 0x0000 - -#define MII_DM9161_SCR 0x10 -#define MII_DM9161_SCR_INIT 0x0610 - -/* DM9161 Specified Configuration and Status Register */ -#define MII_DM9161_SCSR 0x11 -#define MII_DM9161_SCSR_100F 0x8000 -#define MII_DM9161_SCSR_100H 0x4000 -#define MII_DM9161_SCSR_10F 0x2000 -#define MII_DM9161_SCSR_10H 0x1000 - -/* DM9161 Interrupt Register */ -#define MII_DM9161_INTR 0x15 -#define MII_DM9161_INTR_PEND 0x8000 -#define MII_DM9161_INTR_DPLX_MASK 0x0800 -#define MII_DM9161_INTR_SPD_MASK 0x0400 -#define MII_DM9161_INTR_LINK_MASK 0x0200 -#define MII_DM9161_INTR_MASK 0x0100 -#define MII_DM9161_INTR_DPLX_CHANGE 0x0010 -#define MII_DM9161_INTR_SPD_CHANGE 0x0008 -#define MII_DM9161_INTR_LINK_CHANGE 0x0004 -#define MII_DM9161_INTR_INIT 0x0000 -#define MII_DM9161_INTR_STOP \ -(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \ - | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK) - -/* DM9161 10BT Configuration/Status */ -#define MII_DM9161_10BTCSR 0x12 -#define MII_DM9161_10BTCSR_INIT 0x7800 - -#define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | \ - SUPPORTED_10baseT_Full | \ - SUPPORTED_100baseT_Half | \ - SUPPORTED_100baseT_Full | \ - SUPPORTED_Autoneg | \ - SUPPORTED_TP | \ - SUPPORTED_MII) - -#define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \ - SUPPORTED_1000baseT_Half | \ - SUPPORTED_1000baseT_Full) - -#define MII_READ_COMMAND 0x00000001 - -#define MII_INTERRUPT_DISABLED 0x0 -#define MII_INTERRUPT_ENABLED 0x1 -/* Taken from mii_if_info and sungem_phy.h */ -struct ugeth_mii_info { - /* Information about the PHY type */ - /* And management functions */ - struct phy_info *phyinfo; - - ucc_mii_mng_t *mii_regs; - - /* forced speed & duplex (no autoneg) - * partner speed & duplex & pause (autoneg) - */ - int speed; - int duplex; - int pause; - - /* The most recently read link state */ - int link; - - /* Enabled Interrupts */ - u32 interrupts; - - u32 advertising; - int autoneg; - int mii_id; - - /* private data pointer */ - /* For use by PHYs to maintain extra state */ - void *priv; - - /* Provided by host chip */ - struct net_device *dev; - - /* A lock to ensure that only one thing can read/write - * the MDIO bus at a time */ - spinlock_t mdio_lock; - - /* Provided by ethernet driver */ - int (*mdio_read) (struct net_device * dev, int mii_id, int reg); - void (*mdio_write) (struct net_device * dev, int mii_id, int reg, - int val); -}; - -/* struct phy_info: a structure which defines attributes for a PHY - * - * id will contain a number which represents the PHY. During - * startup, the driver will poll the PHY to find out what its - * UID--as defined by registers 2 and 3--is. The 32-bit result - * gotten from the PHY will be ANDed with phy_id_mask to - * discard any bits which may change based on revision numbers - * unimportant to functionality - * - * There are 6 commands which take a ugeth_mii_info structure. - * Each PHY must declare config_aneg, and read_status. - */ -struct phy_info { - u32 phy_id; - char *name; - unsigned int phy_id_mask; - u32 features; - - /* Called to initialize the PHY */ - int (*init) (struct ugeth_mii_info * mii_info); - - /* Called to suspend the PHY for power */ - int (*suspend) (struct ugeth_mii_info * mii_info); - - /* Reconfigures autonegotiation (or disables it) */ - int (*config_aneg) (struct ugeth_mii_info * mii_info); - - /* Determines the negotiated speed and duplex */ - int (*read_status) (struct ugeth_mii_info * mii_info); - - /* Clears any pending interrupts */ - int (*ack_interrupt) (struct ugeth_mii_info * mii_info); - - /* Enables or disables interrupts */ - int (*config_intr) (struct ugeth_mii_info * mii_info); - - /* Clears up any memory if needed */ - void (*close) (struct ugeth_mii_info * mii_info); -}; - -struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info); -void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value); -int read_phy_reg(struct net_device *dev, int mii_id, int regnum); -void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info); -void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info, - u32 interrupts); - -struct dm9161_private { - struct timer_list timer; - int resetdone; -}; - -#endif /* __UCC_GETH_PHY_H__ */ diff --git a/trunk/drivers/net/via-rhine.c b/trunk/drivers/net/via-rhine.c index 66547159bfd9..d3d0ec970318 100644 --- a/trunk/drivers/net/via-rhine.c +++ b/trunk/drivers/net/via-rhine.c @@ -30,8 +30,8 @@ */ #define DRV_NAME "via-rhine" -#define DRV_VERSION "1.4.1" -#define DRV_RELDATE "July-24-2006" +#define DRV_VERSION "1.4.0" +#define DRV_RELDATE "June-27-2006" /* A few user-configurable values. @@ -44,10 +44,6 @@ static int max_interrupt_work = 20; Setting to > 1518 effectively disables this feature. */ static int rx_copybreak; -/* Work-around for broken BIOSes: they are unable to get the chip back out of - power state D3 so PXE booting fails. bootparam(7): via-rhine.avoid_D3=1 */ -static int avoid_D3; - /* * In case you are looking for 'options[]' or 'full_duplex[]', they * are gone. Use ethtool(8) instead. @@ -67,11 +63,7 @@ static const int multicast_filter_limit = 32; There are no ill effects from too-large receive rings. */ #define TX_RING_SIZE 16 #define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ -#ifdef CONFIG_VIA_RHINE_NAPI -#define RX_RING_SIZE 64 -#else #define RX_RING_SIZE 16 -#endif /* Operational parameters that usually are not changed. */ @@ -124,11 +116,9 @@ MODULE_LICENSE("GPL"); module_param(max_interrupt_work, int, 0); module_param(debug, int, 0); module_param(rx_copybreak, int, 0); -module_param(avoid_D3, bool, 0); MODULE_PARM_DESC(max_interrupt_work, "VIA Rhine maximum events handled per interrupt"); MODULE_PARM_DESC(debug, "VIA Rhine debug level (0-7)"); MODULE_PARM_DESC(rx_copybreak, "VIA Rhine copy breakpoint for copy-only-tiny-frames"); -MODULE_PARM_DESC(avoid_D3, "Avoid power state D3 (work-around for broken BIOSes)"); /* Theory of Operation @@ -406,7 +396,7 @@ static void rhine_tx_timeout(struct net_device *dev); static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev); static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static void rhine_tx(struct net_device *dev); -static int rhine_rx(struct net_device *dev, int limit); +static void rhine_rx(struct net_device *dev); static void rhine_error(struct net_device *dev, int intr_status); static void rhine_set_rx_mode(struct net_device *dev); static struct net_device_stats *rhine_get_stats(struct net_device *dev); @@ -574,32 +564,6 @@ static void rhine_poll(struct net_device *dev) } #endif -#ifdef CONFIG_VIA_RHINE_NAPI -static int rhine_napipoll(struct net_device *dev, int *budget) -{ - struct rhine_private *rp = netdev_priv(dev); - void __iomem *ioaddr = rp->base; - int done, limit = min(dev->quota, *budget); - - done = rhine_rx(dev, limit); - *budget -= done; - dev->quota -= done; - - if (done < limit) { - netif_rx_complete(dev); - - iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow | - IntrRxDropped | IntrRxNoBuf | IntrTxAborted | - IntrTxDone | IntrTxError | IntrTxUnderrun | - IntrPCIErr | IntrStatsMax | IntrLinkChange, - ioaddr + IntrEnable); - return 0; - } - else - return 1; -} -#endif - static void rhine_hw_init(struct net_device *dev, long pioaddr) { struct rhine_private *rp = netdev_priv(dev); @@ -779,10 +743,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, dev->watchdog_timeo = TX_TIMEOUT; #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = rhine_poll; -#endif -#ifdef CONFIG_VIA_RHINE_NAPI - dev->poll = rhine_napipoll; - dev->weight = 64; #endif if (rp->quirks & rqRhineI) dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM; @@ -829,9 +789,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, } } rp->mii_if.phy_id = phy_id; - if (debug > 1 && avoid_D3) - printk(KERN_INFO "%s: No D3 power state at shutdown.\n", - dev->name); return 0; @@ -1057,8 +1014,6 @@ static void init_registers(struct net_device *dev) rhine_set_rx_mode(dev); - netif_poll_enable(dev); - /* Enable interrupts by setting the interrupt mask. */ iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow | IntrRxDropped | IntrRxNoBuf | IntrTxAborted | @@ -1230,7 +1185,7 @@ static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev) rp->tx_skbuff[entry] = skb; if ((rp->quirks & rqRhineI) && - (((unsigned long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_PARTIAL)) { + (((unsigned long)skb->data & 3) || skb_shinfo(skb)->nr_frags != 0 || skb->ip_summed == CHECKSUM_HW)) { /* Must use alignment buffer. */ if (skb->len > PKT_BUF_SZ) { /* packet too long, drop it */ @@ -1313,18 +1268,8 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs * dev->name, intr_status); if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped | - IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) { -#ifdef CONFIG_VIA_RHINE_NAPI - iowrite16(IntrTxAborted | - IntrTxDone | IntrTxError | IntrTxUnderrun | - IntrPCIErr | IntrStatsMax | IntrLinkChange, - ioaddr + IntrEnable); - - netif_rx_schedule(dev); -#else - rhine_rx(dev, RX_RING_SIZE); -#endif - } + IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) + rhine_rx(dev); if (intr_status & (IntrTxErrSummary | IntrTxDone)) { if (intr_status & IntrTxErrSummary) { @@ -1422,12 +1367,13 @@ static void rhine_tx(struct net_device *dev) spin_unlock(&rp->lock); } -/* Process up to limit frames from receive ring */ -static int rhine_rx(struct net_device *dev, int limit) +/* This routine is logically part of the interrupt handler, but isolated + for clarity and better register allocation. */ +static void rhine_rx(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); - int count; int entry = rp->cur_rx % RX_RING_SIZE; + int boguscnt = rp->dirty_rx + RX_RING_SIZE - rp->cur_rx; if (debug > 4) { printk(KERN_DEBUG "%s: rhine_rx(), entry %d status %8.8x.\n", @@ -1436,18 +1382,16 @@ static int rhine_rx(struct net_device *dev, int limit) } /* If EOP is set on the next entry, it's a new packet. Send it up. */ - for (count = 0; count < limit; ++count) { + while (!(rp->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) { struct rx_desc *desc = rp->rx_head_desc; u32 desc_status = le32_to_cpu(desc->rx_status); int data_size = desc_status >> 16; - if (desc_status & DescOwn) - break; - if (debug > 4) printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n", desc_status); - + if (--boguscnt < 0) + break; if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) { if ((desc_status & RxWholePkt) != RxWholePkt) { printk(KERN_WARNING "%s: Oversized Ethernet " @@ -1516,11 +1460,7 @@ static int rhine_rx(struct net_device *dev, int limit) PCI_DMA_FROMDEVICE); } skb->protocol = eth_type_trans(skb, dev); -#ifdef CONFIG_VIA_RHINE_NAPI - netif_receive_skb(skb); -#else netif_rx(skb); -#endif dev->last_rx = jiffies; rp->stats.rx_bytes += pkt_len; rp->stats.rx_packets++; @@ -1547,8 +1487,6 @@ static int rhine_rx(struct net_device *dev, int limit) } rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn); } - - return count; } /* @@ -1838,7 +1776,6 @@ static int rhine_close(struct net_device *dev) spin_lock_irq(&rp->lock); netif_stop_queue(dev); - netif_poll_disable(dev); if (debug > 1) printk(KERN_DEBUG "%s: Shutting down ethercard, " @@ -1920,8 +1857,7 @@ static void rhine_shutdown (struct pci_dev *pdev) } /* Hit power state D3 (sleep) */ - if (!avoid_D3) - iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW); + iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW); /* TODO: Check use of pci_enable_wake() */ diff --git a/trunk/drivers/net/via-velocity.c b/trunk/drivers/net/via-velocity.c index f1e0c746a388..f5b0078eb4ad 100644 --- a/trunk/drivers/net/via-velocity.c +++ b/trunk/drivers/net/via-velocity.c @@ -2002,7 +2002,7 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev) * Handle hardware checksum */ if ((vptr->flags & VELOCITY_FLAGS_TX_CSUM) - && (skb->ip_summed == CHECKSUM_PARTIAL)) { + && (skb->ip_summed == CHECKSUM_HW)) { struct iphdr *ip = skb->nh.iph; if (ip->protocol == IPPROTO_TCP) td_ptr->tdesc1.TCR |= TCR0_TCPCK; @@ -2742,7 +2742,7 @@ static u32 check_connection_type(struct mac_regs __iomem * regs) if (PHYSR0 & PHYSR0_SPDG) status |= VELOCITY_SPEED_1000; - else if (PHYSR0 & PHYSR0_SPD10) + if (PHYSR0 & PHYSR0_SPD10) status |= VELOCITY_SPEED_10; else status |= VELOCITY_SPEED_100; @@ -2851,17 +2851,8 @@ static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd u32 status; status = check_connection_type(vptr->mac_regs); - cmd->supported = SUPPORTED_TP | - SUPPORTED_Autoneg | - SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Half | - SUPPORTED_1000baseT_Full; - if (status & VELOCITY_SPEED_1000) - cmd->speed = SPEED_1000; - else if (status & VELOCITY_SPEED_100) + cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full; + if (status & VELOCITY_SPEED_100) cmd->speed = SPEED_100; else cmd->speed = SPEED_10; @@ -2905,7 +2896,7 @@ static u32 velocity_get_link(struct net_device *dev) { struct velocity_info *vptr = netdev_priv(dev); struct mac_regs __iomem * regs = vptr->mac_regs; - return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, ®s->PHYSR0) ? 1 : 0; + return BYTE_REG_BITS_IS_ON(PHYSR0_LINKGD, ®s->PHYSR0) ? 0 : 1; } static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) diff --git a/trunk/drivers/net/wan/c101.c b/trunk/drivers/net/wan/c101.c index 6b63b350cd52..435e91ec4620 100644 --- a/trunk/drivers/net/wan/c101.c +++ b/trunk/drivers/net/wan/c101.c @@ -118,7 +118,7 @@ static inline void openwin(card_t *card, u8 page) static inline void set_carrier(port_t *port) { - if (!(sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD)) + if (!sca_in(MSCI1_OFFSET + ST3, port) & ST3_DCD) netif_carrier_on(port_to_dev(port)); else netif_carrier_off(port_to_dev(port)); @@ -127,10 +127,10 @@ static inline void set_carrier(port_t *port) static void sca_msci_intr(port_t *port) { - u8 stat = sca_in(MSCI0_OFFSET + ST1, port); /* read MSCI ST1 status */ + u8 stat = sca_in(MSCI1_OFFSET + ST1, port); /* read MSCI ST1 status */ - /* Reset MSCI TX underrun and CDCD (ignored) status bit */ - sca_out(stat & (ST1_UDRN | ST1_CDCD), MSCI0_OFFSET + ST1, port); + /* Reset MSCI TX underrun status bit */ + sca_out(stat & ST1_UDRN, MSCI0_OFFSET + ST1, port); if (stat & ST1_UDRN) { struct net_device_stats *stats = hdlc_stats(port_to_dev(port)); @@ -138,7 +138,6 @@ static void sca_msci_intr(port_t *port) stats->tx_fifo_errors++; } - stat = sca_in(MSCI1_OFFSET + ST1, port); /* read MSCI1 ST1 status */ /* Reset MSCI CDCD status bit - uses ch#2 DCD input */ sca_out(stat & ST1_CDCD, MSCI1_OFFSET + ST1, port); diff --git a/trunk/drivers/net/wd.c b/trunk/drivers/net/wd.c index b1ba1872f315..7caa8dc88a58 100644 --- a/trunk/drivers/net/wd.c +++ b/trunk/drivers/net/wd.c @@ -500,8 +500,8 @@ MODULE_LICENSE("GPL"); /* This is set up so that only a single autoprobe takes place per call. ISA device autoprobes on a running machine are not recommended. */ - -int __init init_module(void) +int +init_module(void) { struct net_device *dev; int this_dev, found = 0; diff --git a/trunk/drivers/net/wireless/Kconfig b/trunk/drivers/net/wireless/Kconfig index 2e8ac995d56f..fa9d2c4edc93 100644 --- a/trunk/drivers/net/wireless/Kconfig +++ b/trunk/drivers/net/wireless/Kconfig @@ -447,7 +447,6 @@ config AIRO_CS tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards" depends on NET_RADIO && PCMCIA && (BROKEN || !M32R) select CRYPTO - select CRYPTO_AES ---help--- This is the standard Linux driver to support Cisco/Aironet PCMCIA 802.11 wireless cards. This driver is the same as the Aironet diff --git a/trunk/drivers/net/wireless/airo.c b/trunk/drivers/net/wireless/airo.c index 170c500169da..a4dd13942714 100644 --- a/trunk/drivers/net/wireless/airo.c +++ b/trunk/drivers/net/wireless/airo.c @@ -19,7 +19,6 @@ ======================================================================*/ -#include #include #include @@ -1204,7 +1203,7 @@ struct airo_info { struct iw_spy_data spy_data; struct iw_public_data wireless_data; /* MIC stuff */ - struct crypto_cipher *tfm; + struct crypto_tfm *tfm; mic_module mod[2]; mic_statistics micstats; HostRxDesc rxfids[MPI_MAX_FIDS]; // rx/tx/config MPI350 descriptors @@ -1272,8 +1271,7 @@ static int flashrestart(struct airo_info *ai,struct net_device *dev); static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq); static void MoveWindow(miccntx *context, u32 micSeq); -static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, - struct crypto_cipher *tfm); +static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *); static void emmh32_init(emmh32_context *context); static void emmh32_update(emmh32_context *context, u8 *pOctets, int len); static void emmh32_final(emmh32_context *context, u8 digest[4]); @@ -1341,11 +1339,10 @@ static int micsetup(struct airo_info *ai) { int i; if (ai->tfm == NULL) - ai->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); + ai->tfm = crypto_alloc_tfm("aes", CRYPTO_TFM_REQ_MAY_SLEEP); - if (IS_ERR(ai->tfm)) { + if (ai->tfm == NULL) { airo_print_err(ai->dev->name, "failed to load transform for AES"); - ai->tfm = NULL; return ERROR; } @@ -1611,8 +1608,7 @@ static void MoveWindow(miccntx *context, u32 micSeq) static unsigned char aes_counter[16]; /* expand the key to fill the MMH coefficient array */ -static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, - struct crypto_cipher *tfm) +static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *tfm) { /* take the keying material, expand if necessary, truncate at 16-bytes */ /* run through AES counter mode to generate context->coeff[] */ @@ -1620,6 +1616,7 @@ static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, int i,j; u32 counter; u8 *cipher, plain[16]; + struct scatterlist sg[1]; crypto_cipher_setkey(tfm, pkey, 16); counter = 0; @@ -1630,8 +1627,9 @@ static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, aes_counter[12] = (u8)(counter >> 24); counter++; memcpy (plain, aes_counter, 16); - crypto_cipher_encrypt_one(tfm, plain, plain); - cipher = plain; + sg_set_buf(sg, plain, 16); + crypto_cipher_encrypt(tfm, sg, sg, 16); + cipher = kmap(sg->page) + sg->offset; for (j=0; (j<16) && (i< (sizeof(context->coeff)/sizeof(context->coeff[0]))); ) { context->coeff[i++] = ntohl(*(u32 *)&cipher[j]); j += 4; @@ -2434,7 +2432,7 @@ void stop_airo_card( struct net_device *dev, int freeres ) ai->shared, ai->shared_dma); } } - crypto_free_cipher(ai->tfm); + crypto_free_tfm(ai->tfm); del_airo_dev( dev ); free_netdev( dev ); } diff --git a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c index df317c1e12a8..3889f79e7128 100644 --- a/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/trunk/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3701,7 +3701,7 @@ static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, } if (sec->flags & SEC_AUTH_MODE) { secinfo->auth_mode = sec->auth_mode; - dprintk(", .auth_mode = %d", sec->auth_mode); + dprintk(", .auth_mode = %d\n", sec->auth_mode); } dprintk("\n"); if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED && diff --git a/trunk/drivers/net/wireless/hostap/hostap_hw.c b/trunk/drivers/net/wireless/hostap/hostap_hw.c index d500012fdc7a..dafaa5ff5aa6 100644 --- a/trunk/drivers/net/wireless/hostap/hostap_hw.c +++ b/trunk/drivers/net/wireless/hostap/hostap_hw.c @@ -1042,9 +1042,6 @@ static int prism2_reset_port(struct net_device *dev) dev->name, local->fragm_threshold); } - /* Some firmwares lose antenna selection settings on reset */ - (void) hostap_set_antsel(local); - return res; } diff --git a/trunk/drivers/net/wireless/orinoco.c b/trunk/drivers/net/wireless/orinoco.c index 317ace7f9aae..d6ed5781b93a 100644 --- a/trunk/drivers/net/wireless/orinoco.c +++ b/trunk/drivers/net/wireless/orinoco.c @@ -2875,7 +2875,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - if (erq->length > 0) { + if (erq->pointer) { if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) index = priv->tx_key; @@ -2918,7 +2918,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, if (erq->flags & IW_ENCODE_RESTRICTED) restricted = 1; - if (erq->pointer && erq->length > 0) { + if (erq->pointer) { priv->keys[index].len = cpu_to_le16(xlen); memset(priv->keys[index].data, 0, sizeof(priv->keys[index].data)); diff --git a/trunk/drivers/net/wireless/spectrum_cs.c b/trunk/drivers/net/wireless/spectrum_cs.c index bcc7038130f6..7f78b7801fb3 100644 --- a/trunk/drivers/net/wireless/spectrum_cs.c +++ b/trunk/drivers/net/wireless/spectrum_cs.c @@ -242,7 +242,7 @@ spectrum_reset(struct pcmcia_device *link, int idle) u_int save_cor; /* Doing it if hardware is gone is guaranteed crash */ - if (!pcmcia_dev_present(link)) + if (pcmcia_dev_present(link)) return -ENODEV; /* Save original COR value */ diff --git a/trunk/drivers/net/wireless/strip.c b/trunk/drivers/net/wireless/strip.c index ccaf28e8db0a..fd31885c6844 100644 --- a/trunk/drivers/net/wireless/strip.c +++ b/trunk/drivers/net/wireless/strip.c @@ -467,7 +467,6 @@ static int arp_query(unsigned char *haddr, u32 paddr, struct net_device *dev) { struct neighbour *neighbor_entry; - int ret = 0; neighbor_entry = neigh_lookup(&arp_tbl, &paddr, dev); @@ -475,11 +474,10 @@ static int arp_query(unsigned char *haddr, u32 paddr, neighbor_entry->used = jiffies; if (neighbor_entry->nud_state & NUD_VALID) { memcpy(haddr, neighbor_entry->ha, dev->addr_len); - ret = 1; + return 1; } - neigh_release(neighbor_entry); } - return ret; + return 0; } static void DumpData(char *msg, struct strip *strip_info, __u8 * ptr, diff --git a/trunk/drivers/net/wireless/zd1201.c b/trunk/drivers/net/wireless/zd1201.c index c52e9bcf8d02..662ecc8a33ff 100644 --- a/trunk/drivers/net/wireless/zd1201.c +++ b/trunk/drivers/net/wireless/zd1201.c @@ -1820,8 +1820,6 @@ static int zd1201_probe(struct usb_interface *interface, zd->dev->name); usb_set_intfdata(interface, zd); - zd1201_enable(zd); /* zd1201 likes to startup enabled, */ - zd1201_disable(zd); /* interfering with all the wifis in range */ return 0; err_net: diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c index aa792821854e..efc9c4bd826f 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_chip.c @@ -797,7 +797,7 @@ static int zd1211_hw_init_hmac(struct zd_chip *chip) { CR_ADDA_MBIAS_WARMTIME, 0x30000808 }, { CR_ZD1211_RETRY_MAX, 0x2 }, { CR_SNIFFER_ON, 0 }, - { CR_RX_FILTER, STA_RX_FILTER }, + { CR_RX_FILTER, AP_RX_FILTER }, { CR_GROUP_HASH_P1, 0x00 }, { CR_GROUP_HASH_P2, 0x80000000 }, { CR_REG1, 0xa4 }, @@ -844,7 +844,7 @@ static int zd1211b_hw_init_hmac(struct zd_chip *chip) { CR_ZD1211B_AIFS_CTL2, 0x008C003C }, { CR_ZD1211B_TXOP, 0x01800824 }, { CR_SNIFFER_ON, 0 }, - { CR_RX_FILTER, STA_RX_FILTER }, + { CR_RX_FILTER, AP_RX_FILTER }, { CR_GROUP_HASH_P1, 0x00 }, { CR_GROUP_HASH_P2, 0x80000000 }, { CR_REG1, 0xa4 }, @@ -1430,43 +1430,9 @@ static int ofdm_qual_db(u8 status_quality, u8 rate, unsigned int size) break; } - switch (rate) { - case ZD_OFDM_RATE_6M: - case ZD_OFDM_RATE_9M: - i += 3; - break; - case ZD_OFDM_RATE_12M: - case ZD_OFDM_RATE_18M: - i += 5; - break; - case ZD_OFDM_RATE_24M: - case ZD_OFDM_RATE_36M: - i += 9; - break; - case ZD_OFDM_RATE_48M: - case ZD_OFDM_RATE_54M: - i += 15; - break; - default: - return -EINVAL; - } - return i; } -static int ofdm_qual_percent(u8 status_quality, u8 rate, unsigned int size) -{ - int r; - - r = ofdm_qual_db(status_quality, rate, size); - ZD_ASSERT(r >= 0); - if (r < 0) - r = 0; - - r = (r * 100)/29; - return r <= 100 ? r : 100; -} - static unsigned int log10times100(unsigned int x) { static const u8 log10[] = { @@ -1510,28 +1476,31 @@ static int cck_snr_db(u8 status_quality) return r; } -static int cck_qual_percent(u8 status_quality) +static int rx_qual_db(const void *rx_frame, unsigned int size, + const struct rx_status *status) { - int r; - - r = cck_snr_db(status_quality); - r = (100*r)/17; - return r <= 100 ? r : 100; + return (status->frame_status&ZD_RX_OFDM) ? + ofdm_qual_db(status->signal_quality_ofdm, + zd_ofdm_plcp_header_rate(rx_frame), + size) : + cck_snr_db(status->signal_quality_cck); } u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, const struct rx_status *status) { - return (status->frame_status&ZD_RX_OFDM) ? - ofdm_qual_percent(status->signal_quality_ofdm, - zd_ofdm_plcp_header_rate(rx_frame), - size) : - cck_qual_percent(status->signal_quality_cck); + int r = rx_qual_db(rx_frame, size, status); + if (r < 0) + r = 0; + r = (r * 100) / 14; + if (r > 100) + r = 100; + return r; } u8 zd_rx_strength_percent(u8 rssi) { - int r = (rssi*100) / 41; + int r = (rssi*100) / 30; if (r > 100) r = 100; return (u8) r; diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_chip.h b/trunk/drivers/net/wireless/zd1211rw/zd_chip.h index 069d2b467339..805121093ab5 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_chip.h @@ -461,15 +461,10 @@ #define CR_RX_FILTER CTL_REG(0x068c) #define RX_FILTER_ASSOC_RESPONSE 0x0002 -#define RX_FILTER_REASSOC_RESPONSE 0x0008 #define RX_FILTER_PROBE_RESPONSE 0x0020 #define RX_FILTER_BEACON 0x0100 -#define RX_FILTER_DISASSOC 0x0400 #define RX_FILTER_AUTH 0x0800 -#define AP_RX_FILTER 0x0400feff -#define STA_RX_FILTER 0x0000ffff - -/* Monitor mode sets filter to 0xfffff */ +/* Sniff modus sets filter to 0xfffff */ #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) #define CR_BCN_FIFO_SEMAPHORE CTL_REG(0x0694) @@ -551,6 +546,9 @@ #define CR_ZD1211B_TXOP CTL_REG(0x0b20) #define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28) +#define AP_RX_FILTER 0x0400feff +#define STA_RX_FILTER 0x0000ffff + #define CWIN_SIZE 0x007f043f diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c index a9bd80a08613..3bdc54d128d0 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_mac.c @@ -108,9 +108,7 @@ int zd_mac_init_hw(struct zd_mac *mac, u8 device_type) if (r) goto disable_int; - /* We must inform the device that we are doing encryption/decryption in - * software at the moment. */ - r = zd_set_encryption_type(chip, ENC_SNIFFER); + r = zd_set_encryption_type(chip, NO_WEP); if (r) goto disable_int; @@ -138,8 +136,10 @@ static int reset_mode(struct zd_mac *mac) { struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); struct zd_ioreq32 ioreqs[3] = { - { CR_RX_FILTER, STA_RX_FILTER }, + { CR_RX_FILTER, RX_FILTER_BEACON|RX_FILTER_PROBE_RESPONSE| + RX_FILTER_AUTH|RX_FILTER_ASSOC_RESPONSE }, { CR_SNIFFER_ON, 0U }, + { CR_ENCRYPTION_TYPE, NO_WEP }, }; if (ieee->iw_mode == IW_MODE_MONITOR) { @@ -713,10 +713,10 @@ static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri) struct zd_rt_hdr { struct ieee80211_radiotap_header rt_hdr; u8 rt_flags; - u8 rt_rate; u16 rt_channel; u16 rt_chbitmask; -} __attribute__((packed)); + u16 rt_rate; +}; static void fill_rt_header(void *buffer, struct zd_mac *mac, const struct ieee80211_rx_stats *stats, @@ -735,14 +735,14 @@ static void fill_rt_header(void *buffer, struct zd_mac *mac, if (status->decryption_type & (ZD_RX_WEP64|ZD_RX_WEP128|ZD_RX_WEP256)) hdr->rt_flags |= IEEE80211_RADIOTAP_F_WEP; - hdr->rt_rate = stats->rate / 5; - /* FIXME: 802.11a */ hdr->rt_channel = cpu_to_le16(ieee80211chan2mhz( _zd_chip_get_channel(&mac->chip))); hdr->rt_chbitmask = cpu_to_le16(IEEE80211_CHAN_2GHZ | ((status->frame_status & ZD_RX_FRAME_MODULATION_MASK) == ZD_RX_OFDM ? IEEE80211_CHAN_OFDM : IEEE80211_CHAN_CCK)); + + hdr->rt_rate = stats->rate / 5; } /* Returns 1 if the data packet is for us and 0 otherwise. */ @@ -816,25 +816,13 @@ static int filter_rx(struct ieee80211_device *ieee, return -EINVAL; } -static void update_qual_rssi(struct zd_mac *mac, - const u8 *buffer, unsigned int length, - u8 qual_percent, u8 rssi_percent) +static void update_qual_rssi(struct zd_mac *mac, u8 qual_percent, u8 rssi) { unsigned long flags; - struct ieee80211_hdr_3addr *hdr; - int i; - - hdr = (struct ieee80211_hdr_3addr *)buffer; - if (length < offsetof(struct ieee80211_hdr_3addr, addr3)) - return; - if (memcmp(hdr->addr2, zd_mac_to_ieee80211(mac)->bssid, ETH_ALEN) != 0) - return; spin_lock_irqsave(&mac->lock, flags); - i = mac->stats_count % ZD_MAC_STATS_BUFFER_SIZE; - mac->qual_buffer[i] = qual_percent; - mac->rssi_buffer[i] = rssi_percent; - mac->stats_count++; + mac->qual_average = (7 * mac->qual_average + qual_percent) / 8; + mac->rssi_average = (7 * mac->rssi_average + rssi) / 8; spin_unlock_irqrestore(&mac->lock, flags); } @@ -865,6 +853,7 @@ static int fill_rx_stats(struct ieee80211_rx_stats *stats, if (stats->rate) stats->mask |= IEEE80211_STATMASK_RATE; + update_qual_rssi(mac, stats->signal, stats->rssi); return 0; } @@ -888,8 +877,6 @@ int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length) sizeof(struct rx_status); buffer += ZD_PLCP_HEADER_SIZE; - update_qual_rssi(mac, buffer, length, stats.signal, stats.rssi); - r = filter_rx(ieee, buffer, length, &stats); if (r <= 0) return r; @@ -994,31 +981,17 @@ struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) { struct zd_mac *mac = zd_netdev_mac(ndev); struct iw_statistics *iw_stats = &mac->iw_stats; - unsigned int i, count, qual_total, rssi_total; memset(iw_stats, 0, sizeof(struct iw_statistics)); /* We are not setting the status, because ieee->state is not updated * at all and this driver doesn't track authentication state. */ spin_lock_irq(&mac->lock); - count = mac->stats_count < ZD_MAC_STATS_BUFFER_SIZE ? - mac->stats_count : ZD_MAC_STATS_BUFFER_SIZE; - qual_total = rssi_total = 0; - for (i = 0; i < count; i++) { - qual_total += mac->qual_buffer[i]; - rssi_total += mac->rssi_buffer[i]; - } + iw_stats->qual.qual = mac->qual_average; + iw_stats->qual.level = mac->rssi_average; + iw_stats->qual.updated = IW_QUAL_QUAL_UPDATED|IW_QUAL_LEVEL_UPDATED| + IW_QUAL_NOISE_INVALID; spin_unlock_irq(&mac->lock); - iw_stats->qual.updated = IW_QUAL_NOISE_INVALID; - if (count > 0) { - iw_stats->qual.qual = qual_total / count; - iw_stats->qual.level = rssi_total / count; - iw_stats->qual.updated |= - IW_QUAL_QUAL_UPDATED|IW_QUAL_LEVEL_UPDATED; - } else { - iw_stats->qual.updated |= - IW_QUAL_QUAL_INVALID|IW_QUAL_LEVEL_INVALID; - } /* TODO: update counter */ return iw_stats; } diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_mac.h b/trunk/drivers/net/wireless/zd1211rw/zd_mac.h index b3ba49b84634..71e382c589ee 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/trunk/drivers/net/wireless/zd1211rw/zd_mac.h @@ -1,4 +1,4 @@ -/* zd_mac.h +/* zd_mac.c * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -87,9 +87,9 @@ struct rx_length_info { #define RX_LENGTH_INFO_TAG 0x697e struct rx_status { - u8 signal_quality_cck; /* rssi */ u8 signal_strength; + u8 signal_quality_cck; u8 signal_quality_ofdm; u8 decryption_type; u8 frame_status; @@ -120,17 +120,14 @@ enum mac_flags { MAC_FIXED_CHANNEL = 0x01, }; -#define ZD_MAC_STATS_BUFFER_SIZE 16 - struct zd_mac { struct net_device *netdev; struct zd_chip chip; spinlock_t lock; /* Unlocked reading possible */ struct iw_statistics iw_stats; - unsigned int stats_count; - u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE]; - u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE]; + u8 qual_average; + u8 rssi_average; u8 regdomain; u8 default_regdomain; u8 requested_channel; diff --git a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c index 6320984126c7..72f90525bf68 100644 --- a/trunk/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/trunk/drivers/net/wireless/zd1211rw/zd_usb.c @@ -323,6 +323,7 @@ static void disable_read_regs_int(struct zd_usb *usb) { struct zd_usb_interrupt *intr = &usb->intr; + ZD_ASSERT(in_interrupt()); spin_lock(&intr->lock); intr->read_regs_enabled = 0; spin_unlock(&intr->lock); @@ -544,11 +545,11 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer, * be padded. Unaligned access might also happen if the length_info * structure is not present. */ - if (get_unaligned(&length_info->tag) == cpu_to_le16(RX_LENGTH_INFO_TAG)) - { + if (get_unaligned(&length_info->tag) == RX_LENGTH_INFO_TAG) { unsigned int l, k, n; for (i = 0, l = 0;; i++) { - k = le16_to_cpu(get_unaligned(&length_info->length[i])); + k = le16_to_cpu(get_unaligned( + &length_info->length[i])); n = l+k; if (n > length) return; diff --git a/trunk/drivers/pci/hotplug/Kconfig b/trunk/drivers/pci/hotplug/Kconfig index 8a60f391ffcf..3fae77ffb2fa 100644 --- a/trunk/drivers/pci/hotplug/Kconfig +++ b/trunk/drivers/pci/hotplug/Kconfig @@ -76,7 +76,7 @@ config HOTPLUG_PCI_IBM config HOTPLUG_PCI_ACPI tristate "ACPI PCI Hotplug driver" - depends on (!ACPI_DOCK && ACPI && HOTPLUG_PCI) || (ACPI_DOCK && HOTPLUG_PCI) + depends on ACPI_DOCK && HOTPLUG_PCI help Say Y here if you have a system that supports PCI Hotplug using ACPI. @@ -153,6 +153,13 @@ config HOTPLUG_PCI_SHPC_POLL_EVENT_MODE When in doubt, say N. +config HOTPLUG_PCI_SHPC_PHPRM_LEGACY + bool "For AMD SHPC only: Use $HRT for resource/configuration" + depends on HOTPLUG_PCI_SHPC && !ACPI + help + Say Y here for AMD SHPC. You have to select this option if you are + using this driver on platform with AMD SHPC. + config HOTPLUG_PCI_RPA tristate "RPA PCI Hotplug driver" depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE diff --git a/trunk/drivers/pci/hotplug/acpiphp_core.c b/trunk/drivers/pci/hotplug/acpiphp_core.c index e2fef60c2d06..34de5697983d 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_core.c +++ b/trunk/drivers/pci/hotplug/acpiphp_core.c @@ -27,7 +27,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to + * Send feedback to , + * * */ diff --git a/trunk/drivers/pci/hotplug/acpiphp_glue.c b/trunk/drivers/pci/hotplug/acpiphp_glue.c index ae67a8f55ba1..ef95d12fb32c 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_glue.c +++ b/trunk/drivers/pci/hotplug/acpiphp_glue.c @@ -26,7 +26,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to + * Send feedback to * */ diff --git a/trunk/drivers/pci/hotplug/cpci_hotplug_pci.c b/trunk/drivers/pci/hotplug/cpci_hotplug_pci.c index 4afcaffd031c..02be74caa89f 100644 --- a/trunk/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/trunk/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -254,8 +254,8 @@ int cpci_led_off(struct slot* slot) int cpci_configure_slot(struct slot* slot) { - struct pci_bus *parent; - int fn; + unsigned char busnr; + struct pci_bus *child; dbg("%s - enter", __FUNCTION__); @@ -276,53 +276,23 @@ int cpci_configure_slot(struct slot* slot) */ n = pci_scan_slot(slot->bus, slot->devfn); dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n); + if (n > 0) + pci_bus_add_devices(slot->bus); slot->dev = pci_get_slot(slot->bus, slot->devfn); if (slot->dev == NULL) { err("Could not find PCI device for slot %02x", slot->number); - return -ENODEV; + return 1; } } - parent = slot->dev->bus; - - for (fn = 0; fn < 8; fn++) { - struct pci_dev *dev; - - dev = pci_get_slot(parent, PCI_DEVFN(PCI_SLOT(slot->devfn), fn)); - if (!dev) - continue; - if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || - (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { - /* Find an unused bus number for the new bridge */ - struct pci_bus *child; - unsigned char busnr, start = parent->secondary; - unsigned char end = parent->subordinate; - - for (busnr = start; busnr <= end; busnr++) { - if (!pci_find_bus(pci_domain_nr(parent), - busnr)) - break; - } - if (busnr >= end) { - err("No free bus for hot-added bridge\n"); - pci_dev_put(dev); - continue; - } - child = pci_add_new_bus(parent, dev, busnr); - if (!child) { - err("Cannot add new bus for %s\n", - pci_name(dev)); - pci_dev_put(dev); - continue; - } - child->subordinate = pci_do_scan_bus(child); - pci_bus_size_bridges(child); - } - pci_dev_put(dev); + + if (slot->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + pci_read_config_byte(slot->dev, PCI_SECONDARY_BUS, &busnr); + child = pci_add_new_bus(slot->dev->bus, slot->dev, busnr); + pci_do_scan_bus(child); + pci_bus_size_bridges(child); } - pci_bus_assign_resources(parent); - pci_bus_add_devices(parent); - pci_enable_bridges(parent); + pci_bus_assign_resources(slot->dev->bus); dbg("%s - exit", __FUNCTION__); return 0; diff --git a/trunk/drivers/pci/hotplug/pciehp.h b/trunk/drivers/pci/hotplug/pciehp.h index eaea9d36a1bb..ce89f5815861 100644 --- a/trunk/drivers/pci/hotplug/pciehp.h +++ b/trunk/drivers/pci/hotplug/pciehp.h @@ -279,11 +279,6 @@ struct hpc_ops { #ifdef CONFIG_ACPI -#include -#include -#include -#include - #define pciehp_get_hp_hw_control_from_firmware(dev) \ pciehp_acpi_get_hp_hw_control_from_firmware(dev) static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, diff --git a/trunk/drivers/pci/hotplug/pciehp_hpc.c b/trunk/drivers/pci/hotplug/pciehp_hpc.c index 6ab3b6cd2b54..0d8fb6e607a1 100644 --- a/trunk/drivers/pci/hotplug/pciehp_hpc.c +++ b/trunk/drivers/pci/hotplug/pciehp_hpc.c @@ -38,6 +38,10 @@ #include "../pci.h" #include "pciehp.h" +#include +#include +#include +#include #ifdef DEBUG #define DBG_K_TRACE_ENTRY ((unsigned int)0x00000001) /* On function entry */ #define DBG_K_TRACE_EXIT ((unsigned int)0x00000002) /* On function exit */ diff --git a/trunk/drivers/pci/hotplug/rpaphp_core.c b/trunk/drivers/pci/hotplug/rpaphp_core.c index 7288a3eccfb3..076bd6dcafae 100644 --- a/trunk/drivers/pci/hotplug/rpaphp_core.c +++ b/trunk/drivers/pci/hotplug/rpaphp_core.c @@ -176,16 +176,16 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe return 0; } -static int get_children_props(struct device_node *dn, const int **drc_indexes, - const int **drc_names, const int **drc_types, - const int **drc_power_domains) +static int get_children_props(struct device_node *dn, int **drc_indexes, + int **drc_names, int **drc_types, int **drc_power_domains) { - const int *indexes, *names, *types, *domains; + int *indexes, *names; + int *types, *domains; - indexes = get_property(dn, "ibm,drc-indexes", NULL); - names = get_property(dn, "ibm,drc-names", NULL); - types = get_property(dn, "ibm,drc-types", NULL); - domains = get_property(dn, "ibm,drc-power-domains", NULL); + indexes = (int *) get_property(dn, "ibm,drc-indexes", NULL); + names = (int *) get_property(dn, "ibm,drc-names", NULL); + types = (int *) get_property(dn, "ibm,drc-types", NULL); + domains = (int *) get_property(dn, "ibm,drc-power-domains", NULL); if (!indexes || !names || !types || !domains) { /* Slot does not have dynamically-removable children */ @@ -212,13 +212,13 @@ static int get_children_props(struct device_node *dn, const int **drc_indexes, int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, char **drc_name, char **drc_type, int *drc_power_domain) { - const int *indexes, *names; - const int *types, *domains; - const unsigned int *my_index; + int *indexes, *names; + int *types, *domains; + unsigned int *my_index; char *name_tmp, *type_tmp; int i, rc; - my_index = get_property(dn, "ibm,my-drc-index", NULL); + my_index = (int *) get_property(dn, "ibm,my-drc-index", NULL); if (!my_index) { /* Node isn't DLPAR/hotplug capable */ return -EINVAL; @@ -265,10 +265,10 @@ static int is_php_type(char *drc_type) return 1; } -static int is_php_dn(struct device_node *dn, const int **indexes, - const int **names, const int **types, const int **power_domains) +static int is_php_dn(struct device_node *dn, int **indexes, int **names, + int **types, int **power_domains) { - const int *drc_types; + int *drc_types; int rc; rc = get_children_props(dn, indexes, names, &drc_types, power_domains); @@ -296,7 +296,7 @@ int rpaphp_add_slot(struct device_node *dn) struct slot *slot; int retval = 0; int i; - const int *indexes, *names, *types, *power_domains; + int *indexes, *names, *types, *power_domains; char *name, *type; dbg("Entry %s: dn->full_name=%s\n", __FUNCTION__, dn->full_name); diff --git a/trunk/drivers/pci/pci-driver.c b/trunk/drivers/pci/pci-driver.c index 474e9cd0e9e4..10e1a905c144 100644 --- a/trunk/drivers/pci/pci-driver.c +++ b/trunk/drivers/pci/pci-driver.c @@ -139,8 +139,9 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, /** * pci_match_device - Tell if a PCI device structure has a matching * PCI device id structure - * @drv: the PCI driver to match against + * @ids: array of PCI device id structures to search in * @dev: the PCI device structure to match against + * @drv: the PCI driver to match against * * Used by a driver to check whether a PCI device present in the * system is in its list of supported devices. Returns the matching diff --git a/trunk/drivers/pci/pcie/portdrv_pci.c b/trunk/drivers/pci/pcie/portdrv_pci.c index 478d0d28f7ad..50bfc1b2f3bf 100644 --- a/trunk/drivers/pci/pcie/portdrv_pci.c +++ b/trunk/drivers/pci/pcie/portdrv_pci.c @@ -30,6 +30,23 @@ MODULE_LICENSE("GPL"); /* global data */ static const char device_name[] = "pcieport-driver"; +static int pcie_portdrv_save_config(struct pci_dev *dev) +{ + return pci_save_state(dev); +} + +static int pcie_portdrv_restore_config(struct pci_dev *dev) +{ + int retval; + + pci_restore_state(dev); + retval = pci_enable_device(dev); + if (retval) + return retval; + pci_set_master(dev); + return 0; +} + /* * pcie_portdrv_probe - Probe PCI-Express port devices * @dev: PCI-Express port device being probed @@ -56,10 +73,8 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev, "%s->Dev[%04x:%04x] has invalid IRQ. Check vendor BIOS\n", __FUNCTION__, dev->device, dev->vendor); } - if (pcie_port_device_register(dev)) { - pci_disable_device(dev); + if (pcie_port_device_register(dev)) return -ENOMEM; - } return 0; } @@ -71,23 +86,6 @@ static void pcie_portdrv_remove (struct pci_dev *dev) } #ifdef CONFIG_PM -static int pcie_portdrv_save_config(struct pci_dev *dev) -{ - return pci_save_state(dev); -} - -static int pcie_portdrv_restore_config(struct pci_dev *dev) -{ - int retval; - - pci_restore_state(dev); - retval = pci_enable_device(dev); - if (retval) - return retval; - pci_set_master(dev); - return 0; -} - static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state) { int ret = pcie_port_device_suspend(dev, state); diff --git a/trunk/drivers/pci/quirks.c b/trunk/drivers/pci/quirks.c index 17e709e7d72a..e3c78c39b7e4 100644 --- a/trunk/drivers/pci/quirks.c +++ b/trunk/drivers/pci/quirks.c @@ -438,7 +438,6 @@ static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev) pci_read_config_dword(dev, 0x48, ®ion); quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO"); } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi ); /* @@ -667,7 +666,6 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_vi DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, quirk_via_irq); DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irq); DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_irq); -DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235_USB_2, quirk_via_irq); DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq); DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq); DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq); @@ -992,11 +990,6 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) case 0x8070: /* P4G8X Deluxe */ asus_hides_smbus = 1; } - if (dev->device == PCI_DEVICE_ID_INTEL_E7501_MCH) - switch (dev->subsystem_device) { - case 0x80c9: /* PU-DLS */ - asus_hides_smbus = 1; - } if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB) switch (dev->subsystem_device) { case 0x1751: /* M2N notebook */ @@ -1065,7 +1058,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_HB, asu DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82850_HB, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_7205_0, asus_hides_smbus_hostbridge ); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7501_MCH, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge ); @@ -1089,10 +1081,10 @@ static void __init asus_hides_smbus_lpc(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc ); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc ); static void __init asus_hides_smbus_lpc_ich6(struct pci_dev *dev) { @@ -1519,63 +1511,6 @@ static void __devinit quirk_netmos(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos); -static void __devinit quirk_e100_interrupt(struct pci_dev *dev) -{ - u16 command; - u32 bar; - u8 __iomem *csr; - u8 cmd_hi; - - switch (dev->device) { - /* PCI IDs taken from drivers/net/e100.c */ - case 0x1029: - case 0x1030 ... 0x1034: - case 0x1038 ... 0x103E: - case 0x1050 ... 0x1057: - case 0x1059: - case 0x1064 ... 0x106B: - case 0x1091 ... 0x1095: - case 0x1209: - case 0x1229: - case 0x2449: - case 0x2459: - case 0x245D: - case 0x27DC: - break; - default: - return; - } - - /* - * Some firmware hands off the e100 with interrupts enabled, - * which can cause a flood of interrupts if packets are - * received before the driver attaches to the device. So - * disable all e100 interrupts here. The driver will - * re-enable them when it's ready. - */ - pci_read_config_word(dev, PCI_COMMAND, &command); - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar); - - if (!(command & PCI_COMMAND_MEMORY) || !bar) - return; - - csr = ioremap(bar, 8); - if (!csr) { - printk(KERN_WARNING "PCI: Can't map %s e100 registers\n", - pci_name(dev)); - return; - } - - cmd_hi = readb(csr + 3); - if (cmd_hi == 0) { - printk(KERN_WARNING "PCI: Firmware left %s e100 interrupts " - "enabled, disabling\n", pci_name(dev)); - writeb(1, csr + 3); - } - - iounmap(csr); -} -DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_e100_interrupt); static void __devinit fixup_rev1_53c810(struct pci_dev* dev) { diff --git a/trunk/drivers/pci/search.c b/trunk/drivers/pci/search.c index d529462d1b53..622b3f8ba820 100644 --- a/trunk/drivers/pci/search.c +++ b/trunk/drivers/pci/search.c @@ -41,7 +41,7 @@ pci_do_find_bus(struct pci_bus* bus, unsigned char busnr) * in the global list of PCI buses. If the bus is found, a pointer to its * data structure is returned. If no bus is found, %NULL is returned. */ -struct pci_bus * pci_find_bus(int domain, int busnr) +struct pci_bus * __devinit pci_find_bus(int domain, int busnr) { struct pci_bus *bus = NULL; struct pci_bus *tmp_bus; @@ -61,7 +61,7 @@ struct pci_bus * pci_find_bus(int domain, int busnr) * @from: Previous PCI bus found, or %NULL for new search. * * Iterates through the list of known PCI busses. A new search is - * initiated by passing %NULL as the @from argument. Otherwise if + * initiated by passing %NULL to the @from argument. Otherwise if * @from is not %NULL, searches continue from next device on the * global list. */ @@ -148,14 +148,13 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) * @from: Previous PCI device found in search, or %NULL for new search. * * Iterates through the list of known PCI devices. If a PCI device is - * found with a matching @vendor, @device, @ss_vendor and @ss_device, a - * pointer to its device structure is returned. Otherwise, %NULL is returned. - * A new search is initiated by passing %NULL as the @from argument. - * Otherwise if @from is not %NULL, searches continue from next device - * on the global list. + * found with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its + * device structure is returned. Otherwise, %NULL is returned. + * A new search is initiated by passing %NULL to the @from argument. + * Otherwise if @from is not %NULL, searches continue from next device on the global list. * - * NOTE: Do not use this function any more; use pci_get_subsys() instead, as - * the PCI device returned by this function can disappear at any moment in + * NOTE: Do not use this function anymore, use pci_get_subsys() instead, as + * the pci device returned by this function can disappear at any moment in * time. */ static struct pci_dev * pci_find_subsys(unsigned int vendor, @@ -192,15 +191,14 @@ static struct pci_dev * pci_find_subsys(unsigned int vendor, * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids * @from: Previous PCI device found in search, or %NULL for new search. * - * Iterates through the list of known PCI devices. If a PCI device is found - * with a matching @vendor and @device, a pointer to its device structure is + * Iterates through the list of known PCI devices. If a PCI device is + * found with a matching @vendor and @device, a pointer to its device structure is * returned. Otherwise, %NULL is returned. - * A new search is initiated by passing %NULL as the @from argument. - * Otherwise if @from is not %NULL, searches continue from next device - * on the global list. + * A new search is initiated by passing %NULL to the @from argument. + * Otherwise if @from is not %NULL, searches continue from next device on the global list. * - * NOTE: Do not use this function any more; use pci_get_device() instead, as - * the PCI device returned by this function can disappear at any moment in + * NOTE: Do not use this function anymore, use pci_get_device() instead, as + * the pci device returned by this function can disappear at any moment in * time. */ struct pci_dev * @@ -217,11 +215,11 @@ pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev * * @ss_device: PCI subsystem device id to match, or %PCI_ANY_ID to match all device ids * @from: Previous PCI device found in search, or %NULL for new search. * - * Iterates through the list of known PCI devices. If a PCI device is found - * with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its + * Iterates through the list of known PCI devices. If a PCI device is + * found with a matching @vendor, @device, @ss_vendor and @ss_device, a pointer to its * device structure is returned, and the reference count to the device is * incremented. Otherwise, %NULL is returned. A new search is initiated by - * passing %NULL as the @from argument. Otherwise if @from is not %NULL, + * passing %NULL to the @from argument. Otherwise if @from is not %NULL, * searches continue from next device on the global list. * The reference count for @from is always decremented if it is not %NULL. */ @@ -264,7 +262,7 @@ pci_get_subsys(unsigned int vendor, unsigned int device, * found with a matching @vendor and @device, the reference count to the * device is incremented and a pointer to its device structure is returned. * Otherwise, %NULL is returned. A new search is initiated by passing %NULL - * as the @from argument. Otherwise if @from is not %NULL, searches continue + * to the @from argument. Otherwise if @from is not %NULL, searches continue * from next device on the global list. The reference count for @from is * always decremented if it is not %NULL. */ @@ -281,13 +279,11 @@ pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from) * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids * @from: Previous PCI device found in search, or %NULL for new search. * - * Iterates through the list of known PCI devices in the reverse order of - * pci_find_device(). + * Iterates through the list of known PCI devices in the reverse order of pci_find_device(). * If a PCI device is found with a matching @vendor and @device, a pointer to * its device structure is returned. Otherwise, %NULL is returned. - * A new search is initiated by passing %NULL as the @from argument. - * Otherwise if @from is not %NULL, searches continue from previous device - * on the global list. + * A new search is initiated by passing %NULL to the @from argument. + * Otherwise if @from is not %NULL, searches continue from previous device on the global list. */ struct pci_dev * pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct pci_dev *from) @@ -321,7 +317,7 @@ pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct p * found with a matching @class, the reference count to the device is * incremented and a pointer to its device structure is returned. * Otherwise, %NULL is returned. - * A new search is initiated by passing %NULL as the @from argument. + * A new search is initiated by passing %NULL to the @from argument. * Otherwise if @from is not %NULL, searches continue from next device * on the global list. The reference count for @from is always decremented * if it is not %NULL. diff --git a/trunk/drivers/pcmcia/pcmcia_ioctl.c b/trunk/drivers/pcmcia/pcmcia_ioctl.c index 9ad18e62658d..738b1ef595a3 100644 --- a/trunk/drivers/pcmcia/pcmcia_ioctl.c +++ b/trunk/drivers/pcmcia/pcmcia_ioctl.c @@ -601,8 +601,12 @@ static int ds_ioctl(struct inode * inode, struct file * file, ret = CS_BAD_ARGS; else { struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->config.Function); - ret = pccard_get_configuration_info(s, p_dev, &buf->config); - pcmcia_put_dev(p_dev); + if (p_dev == NULL) + ret = CS_BAD_ARGS; + else { + ret = pccard_get_configuration_info(s, p_dev, &buf->config); + pcmcia_put_dev(p_dev); + } } break; case DS_GET_FIRST_TUPLE: @@ -632,8 +636,12 @@ static int ds_ioctl(struct inode * inode, struct file * file, ret = CS_BAD_ARGS; else { struct pcmcia_device *p_dev = get_pcmcia_device(s, buf->status.Function); - ret = pccard_get_status(s, p_dev, &buf->status); - pcmcia_put_dev(p_dev); + if (p_dev == NULL) + ret = CS_BAD_ARGS; + else { + ret = pccard_get_status(s, p_dev, &buf->status); + pcmcia_put_dev(p_dev); + } } break; case DS_VALIDATE_CIS: diff --git a/trunk/drivers/pcmcia/pcmcia_resource.c b/trunk/drivers/pcmcia/pcmcia_resource.c index c8323399e9e4..7bf25b88ea31 100644 --- a/trunk/drivers/pcmcia/pcmcia_resource.c +++ b/trunk/drivers/pcmcia/pcmcia_resource.c @@ -245,17 +245,10 @@ int pccard_get_configuration_info(struct pcmcia_socket *s, return CS_SUCCESS; } - config->Attributes = c->Attributes | CONF_VALID_CLIENT; - config->Vcc = s->socket.Vcc; - config->Vpp1 = config->Vpp2 = s->socket.Vpp; - config->IntType = c->IntType; - config->ConfigBase = c->ConfigBase; - config->Status = c->Status; - config->Pin = c->Pin; - config->Copy = c->Copy; - config->Option = c->Option; - config->ExtStatus = c->ExtStatus; - config->Present = config->CardValues = c->CardValues; + /* !!! This is a hack !!! */ + memcpy(&config->Attributes, &c->Attributes, sizeof(config_t)); + config->Attributes |= CONF_VALID_CLIENT; + config->CardValues = c->CardValues; config->IRQAttributes = c->irq.Attributes; config->AssignedIRQ = s->irq.AssignedIRQ; config->BasePort1 = c->io.BasePort1; diff --git a/trunk/drivers/pnp/interface.c b/trunk/drivers/pnp/interface.c index 9d8b415eca79..3163e3d73da1 100644 --- a/trunk/drivers/pnp/interface.c +++ b/trunk/drivers/pnp/interface.c @@ -265,8 +265,8 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at pnp_printf(buffer," disabled\n"); else pnp_printf(buffer," 0x%llx-0x%llx\n", - (unsigned long long)pnp_port_start(dev, i), - (unsigned long long)pnp_port_end(dev, i)); + pnp_port_start(dev, i), + pnp_port_end(dev, i)); } } for (i = 0; i < PNP_MAX_MEM; i++) { @@ -276,8 +276,8 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at pnp_printf(buffer," disabled\n"); else pnp_printf(buffer," 0x%llx-0x%llx\n", - (unsigned long long)pnp_mem_start(dev, i), - (unsigned long long)pnp_mem_end(dev, i)); + pnp_mem_start(dev, i), + pnp_mem_end(dev, i)); } } for (i = 0; i < PNP_MAX_IRQ; i++) { @@ -287,7 +287,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at pnp_printf(buffer," disabled\n"); else pnp_printf(buffer," %lld\n", - (unsigned long long)pnp_irq(dev, i)); + pnp_irq(dev, i)); } } for (i = 0; i < PNP_MAX_DMA; i++) { @@ -297,7 +297,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_at pnp_printf(buffer," disabled\n"); else pnp_printf(buffer," %lld\n", - (unsigned long long)pnp_dma(dev, i)); + pnp_dma(dev, i)); } } ret = (buffer->curr - buf); diff --git a/trunk/drivers/pnp/pnpacpi/rsparser.c b/trunk/drivers/pnp/pnpacpi/rsparser.c index dc79b0a0059f..212268881857 100644 --- a/trunk/drivers/pnp/pnpacpi/rsparser.c +++ b/trunk/drivers/pnp/pnpacpi/rsparser.c @@ -173,9 +173,6 @@ pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table, return; } - if (p->producer_consumer == ACPI_PRODUCER) - return; - if (p->resource_type == ACPI_MEMORY_RANGE) pnpacpi_parse_allocated_memresource(res_table, p->minimum, p->address_length); @@ -255,14 +252,9 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, break; case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: - if (res->data.ext_address64.producer_consumer == ACPI_PRODUCER) - return AE_OK; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: - if (res->data.extended_irq.producer_consumer == ACPI_PRODUCER) - return AE_OK; - for (i = 0; i < res->data.extended_irq.interrupt_count; i++) { pnpacpi_parse_allocated_irqresource(res_table, res->data.extended_irq.interrupts[i], diff --git a/trunk/drivers/pnp/pnpbios/core.c b/trunk/drivers/pnp/pnpbios/core.c index 551f58e29810..b154b3f52cbe 100644 --- a/trunk/drivers/pnp/pnpbios/core.c +++ b/trunk/drivers/pnp/pnpbios/core.c @@ -346,7 +346,7 @@ static int insert_device(struct pnp_dev *dev, struct pnp_bios_node * node) dev->flags = node->flags; if (!(dev->flags & PNPBIOS_NO_CONFIG)) dev->capabilities |= PNP_CONFIGURABLE; - if (!(dev->flags & PNPBIOS_NO_DISABLE) && pnpbios_is_dynamic(dev)) + if (!(dev->flags & PNPBIOS_NO_DISABLE)) dev->capabilities |= PNP_DISABLE; dev->capabilities |= PNP_READ; if (pnpbios_is_dynamic(dev)) diff --git a/trunk/drivers/rtc/rtc-s3c.c b/trunk/drivers/rtc/rtc-s3c.c index 2c7de79c83b9..d6d1bff52b8e 100644 --- a/trunk/drivers/rtc/rtc-s3c.c +++ b/trunk/drivers/rtc/rtc-s3c.c @@ -69,12 +69,12 @@ static void s3c_rtc_setaie(int to) pr_debug("%s: aie=%d\n", __FUNCTION__, to); - tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; + tmp = readb(S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; if (to) tmp |= S3C2410_RTCALM_ALMEN; - writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); + writeb(tmp, S3C2410_RTCALM); } static void s3c_rtc_setpie(int to) @@ -84,12 +84,12 @@ static void s3c_rtc_setpie(int to) pr_debug("%s: pie=%d\n", __FUNCTION__, to); spin_lock_irq(&s3c_rtc_pie_lock); - tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; + tmp = readb(S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; if (to) tmp |= S3C2410_TICNT_ENABLE; - writeb(tmp, s3c_rtc_base + S3C2410_TICNT); + writeb(tmp, S3C2410_TICNT); spin_unlock_irq(&s3c_rtc_pie_lock); } @@ -98,13 +98,13 @@ static void s3c_rtc_setfreq(int freq) unsigned int tmp; spin_lock_irq(&s3c_rtc_pie_lock); - tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; + tmp = readb(S3C2410_TICNT) & S3C2410_TICNT_ENABLE; s3c_rtc_freq = freq; tmp |= (128 / freq)-1; - writeb(tmp, s3c_rtc_base + S3C2410_TICNT); + writeb(tmp, S3C2410_TICNT); spin_unlock_irq(&s3c_rtc_pie_lock); } @@ -113,15 +113,14 @@ static void s3c_rtc_setfreq(int freq) static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) { unsigned int have_retried = 0; - void __iomem *base = s3c_rtc_base; retry_get_time: - rtc_tm->tm_min = readb(base + S3C2410_RTCMIN); - rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR); - rtc_tm->tm_mday = readb(base + S3C2410_RTCDATE); - rtc_tm->tm_mon = readb(base + S3C2410_RTCMON); - rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR); - rtc_tm->tm_sec = readb(base + S3C2410_RTCSEC); + rtc_tm->tm_min = readb(S3C2410_RTCMIN); + rtc_tm->tm_hour = readb(S3C2410_RTCHOUR); + rtc_tm->tm_mday = readb(S3C2410_RTCDATE); + rtc_tm->tm_mon = readb(S3C2410_RTCMON); + rtc_tm->tm_year = readb(S3C2410_RTCYEAR); + rtc_tm->tm_sec = readb(S3C2410_RTCSEC); /* the only way to work out wether the system was mid-update * when we read it is to check the second counter, and if it @@ -152,26 +151,17 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) { - void __iomem *base = s3c_rtc_base; - int year = tm->tm_year - 100; + /* the rtc gets round the y2k problem by just not supporting it */ - pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n", - tm->tm_year, tm->tm_mon, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); - - /* we get around y2k by simply not supporting it */ - - if (year < 0 || year >= 100) { - dev_err(dev, "rtc only supports 100 years\n"); + if (tm->tm_year < 100) return -EINVAL; - } - writeb(BIN2BCD(tm->tm_sec), base + S3C2410_RTCSEC); - writeb(BIN2BCD(tm->tm_min), base + S3C2410_RTCMIN); - writeb(BIN2BCD(tm->tm_hour), base + S3C2410_RTCHOUR); - writeb(BIN2BCD(tm->tm_mday), base + S3C2410_RTCDATE); - writeb(BIN2BCD(tm->tm_mon + 1), base + S3C2410_RTCMON); - writeb(BIN2BCD(year), base + S3C2410_RTCYEAR); + writeb(BIN2BCD(tm->tm_sec), S3C2410_RTCSEC); + writeb(BIN2BCD(tm->tm_min), S3C2410_RTCMIN); + writeb(BIN2BCD(tm->tm_hour), S3C2410_RTCHOUR); + writeb(BIN2BCD(tm->tm_mday), S3C2410_RTCDATE); + writeb(BIN2BCD(tm->tm_mon + 1), S3C2410_RTCMON); + writeb(BIN2BCD(tm->tm_year - 100), S3C2410_RTCYEAR); return 0; } @@ -179,17 +169,16 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_time *alm_tm = &alrm->time; - void __iomem *base = s3c_rtc_base; unsigned int alm_en; - alm_tm->tm_sec = readb(base + S3C2410_ALMSEC); - alm_tm->tm_min = readb(base + S3C2410_ALMMIN); - alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR); - alm_tm->tm_mon = readb(base + S3C2410_ALMMON); - alm_tm->tm_mday = readb(base + S3C2410_ALMDATE); - alm_tm->tm_year = readb(base + S3C2410_ALMYEAR); + alm_tm->tm_sec = readb(S3C2410_ALMSEC); + alm_tm->tm_min = readb(S3C2410_ALMMIN); + alm_tm->tm_hour = readb(S3C2410_ALMHOUR); + alm_tm->tm_mon = readb(S3C2410_ALMMON); + alm_tm->tm_mday = readb(S3C2410_ALMDATE); + alm_tm->tm_year = readb(S3C2410_ALMYEAR); - alm_en = readb(base + S3C2410_RTCALM); + alm_en = readb(S3C2410_RTCALM); pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n", alm_en, @@ -237,7 +226,6 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) { struct rtc_time *tm = &alrm->time; - void __iomem *base = s3c_rtc_base; unsigned int alrm_en; pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n", @@ -246,32 +234,32 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec); - alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; - writeb(0x00, base + S3C2410_RTCALM); + alrm_en = readb(S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; + writeb(0x00, S3C2410_RTCALM); if (tm->tm_sec < 60 && tm->tm_sec >= 0) { alrm_en |= S3C2410_RTCALM_SECEN; - writeb(BIN2BCD(tm->tm_sec), base + S3C2410_ALMSEC); + writeb(BIN2BCD(tm->tm_sec), S3C2410_ALMSEC); } if (tm->tm_min < 60 && tm->tm_min >= 0) { alrm_en |= S3C2410_RTCALM_MINEN; - writeb(BIN2BCD(tm->tm_min), base + S3C2410_ALMMIN); + writeb(BIN2BCD(tm->tm_min), S3C2410_ALMMIN); } if (tm->tm_hour < 24 && tm->tm_hour >= 0) { alrm_en |= S3C2410_RTCALM_HOUREN; - writeb(BIN2BCD(tm->tm_hour), base + S3C2410_ALMHOUR); + writeb(BIN2BCD(tm->tm_hour), S3C2410_ALMHOUR); } pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en); - writeb(alrm_en, base + S3C2410_RTCALM); + writeb(alrm_en, S3C2410_RTCALM); if (0) { - alrm_en = readb(base + S3C2410_RTCALM); + alrm_en = readb(S3C2410_RTCALM); alrm_en &= ~S3C2410_RTCALM_ALMEN; - writeb(alrm_en, base + S3C2410_RTCALM); + writeb(alrm_en, S3C2410_RTCALM); disable_irq_wake(s3c_rtc_alarmno); } @@ -331,8 +319,8 @@ static int s3c_rtc_ioctl(struct device *dev, static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) { - unsigned int rtcalm = readb(s3c_rtc_base + S3C2410_RTCALM); - unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); + unsigned int rtcalm = readb(S3C2410_RTCALM); + unsigned int ticnt = readb (S3C2410_TICNT); seq_printf(seq, "alarm_IRQ\t: %s\n", (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" ); @@ -399,40 +387,39 @@ static struct rtc_class_ops s3c_rtcops = { static void s3c_rtc_enable(struct platform_device *pdev, int en) { - void __iomem *base = s3c_rtc_base; unsigned int tmp; if (s3c_rtc_base == NULL) return; if (!en) { - tmp = readb(base + S3C2410_RTCCON); - writeb(tmp & ~S3C2410_RTCCON_RTCEN, base + S3C2410_RTCCON); + tmp = readb(S3C2410_RTCCON); + writeb(tmp & ~S3C2410_RTCCON_RTCEN, S3C2410_RTCCON); - tmp = readb(base + S3C2410_TICNT); - writeb(tmp & ~S3C2410_TICNT_ENABLE, base + S3C2410_TICNT); + tmp = readb(S3C2410_TICNT); + writeb(tmp & ~S3C2410_TICNT_ENABLE, S3C2410_TICNT); } else { /* re-enable the device, and check it is ok */ - if ((readb(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){ + if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){ dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); - tmp = readb(base + S3C2410_RTCCON); - writeb(tmp|S3C2410_RTCCON_RTCEN, base+S3C2410_RTCCON); + tmp = readb(S3C2410_RTCCON); + writeb(tmp | S3C2410_RTCCON_RTCEN , S3C2410_RTCCON); } - if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){ + if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){ dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); - tmp = readb(base + S3C2410_RTCCON); - writeb(tmp& ~S3C2410_RTCCON_CNTSEL, base+S3C2410_RTCCON); + tmp = readb(S3C2410_RTCCON); + writeb(tmp& ~S3C2410_RTCCON_CNTSEL , S3C2410_RTCCON); } - if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){ + if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){ dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); - tmp = readb(base + S3C2410_RTCCON); - writeb(tmp & ~S3C2410_RTCCON_CLKRST, base+S3C2410_RTCCON); + tmp = readb(S3C2410_RTCCON); + writeb(tmp & ~S3C2410_RTCCON_CLKRST, S3C2410_RTCCON); } } } @@ -488,8 +475,8 @@ static int s3c_rtc_probe(struct platform_device *pdev) } s3c_rtc_mem = request_mem_region(res->start, - res->end-res->start+1, - pdev->name); + res->end-res->start+1, + pdev->name); if (s3c_rtc_mem == NULL) { dev_err(&pdev->dev, "failed to reserve memory region\n"); @@ -508,8 +495,7 @@ static int s3c_rtc_probe(struct platform_device *pdev) s3c_rtc_enable(pdev, 1); - pr_debug("s3c2410_rtc: RTCCON=%02x\n", - readb(s3c_rtc_base + S3C2410_RTCCON)); + pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON)); s3c_rtc_setfreq(s3c_rtc_freq); @@ -557,7 +543,7 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) /* save TICNT for anyone using periodic interrupts */ - ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); + ticnt_save = readb(S3C2410_TICNT); /* calculate time delta for suspend */ @@ -581,7 +567,7 @@ static int s3c_rtc_resume(struct platform_device *pdev) rtc_tm_to_time(&tm, &time.tv_sec); restore_time_delta(&s3c_rtc_delta, &time); - writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); + writeb(ticnt_save, S3C2410_TICNT); return 0; } #else diff --git a/trunk/drivers/s390/Kconfig b/trunk/drivers/s390/Kconfig index ae89b9b88743..4d36208ff8de 100644 --- a/trunk/drivers/s390/Kconfig +++ b/trunk/drivers/s390/Kconfig @@ -213,35 +213,17 @@ config MONREADER help Character device driver for reading z/VM monitor service records -config MONWRITER - tristate "API for writing z/VM monitor service records" - default "m" - help - Character device driver for writing z/VM monitor service records - endmenu menu "Cryptographic devices" -config ZCRYPT +config Z90CRYPT tristate "Support for PCI-attached cryptographic adapters" - select ZCRYPT_MONOLITHIC if ZCRYPT="y" - default "m" - help + default "m" + help Select this option if you want to use a PCI-attached cryptographic - adapter like: - + PCI Cryptographic Accelerator (PCICA) - + PCI Cryptographic Coprocessor (PCICC) - + PCI-X Cryptographic Coprocessor (PCIXCC) - + Crypto Express2 Coprocessor (CEX2C) - + Crypto Express2 Accelerator (CEX2A) - -config ZCRYPT_MONOLITHIC - bool "Monolithic zcrypt module" - depends on ZCRYPT="m" - help - Select this option if you want to have a single module z90crypt.ko - that contains all parts of the crypto device driver (ap bus, - request router and all the card drivers). + adapter like the PCI Cryptographic Accelerator (PCICA) or the PCI + Cryptographic Coprocessor (PCICC). This option is also available + as a module called z90crypt.ko. endmenu diff --git a/trunk/drivers/s390/block/dasd.c b/trunk/drivers/s390/block/dasd.c index d0647d116eaa..4bf03fb67f8d 100644 --- a/trunk/drivers/s390/block/dasd.c +++ b/trunk/drivers/s390/block/dasd.c @@ -52,7 +52,7 @@ static void dasd_setup_queue(struct dasd_device * device); static void dasd_free_queue(struct dasd_device * device); static void dasd_flush_request_queue(struct dasd_device *); static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *); -static int dasd_flush_ccw_queue(struct dasd_device *, int); +static void dasd_flush_ccw_queue(struct dasd_device *, int); static void dasd_tasklet(struct dasd_device *); static void do_kick_device(void *data); @@ -60,7 +60,6 @@ static void do_kick_device(void *data); * SECTION: Operations on the device structure. */ static wait_queue_head_t dasd_init_waitq; -static wait_queue_head_t dasd_flush_wq; /* * Allocate memory for a new device structure. @@ -122,7 +121,7 @@ dasd_free_device(struct dasd_device *device) /* * Make a new device known to the system. */ -static int +static inline int dasd_state_new_to_known(struct dasd_device *device) { int rc; @@ -146,7 +145,7 @@ dasd_state_new_to_known(struct dasd_device *device) /* * Let the system forget about a device. */ -static int +static inline void dasd_state_known_to_new(struct dasd_device * device) { /* Disable extended error reporting for this device. */ @@ -164,13 +163,12 @@ dasd_state_known_to_new(struct dasd_device * device) /* Give up reference we took in dasd_state_new_to_known. */ dasd_put_device(device); - return 0; } /* * Request the irq line for the device. */ -static int +static inline int dasd_state_known_to_basic(struct dasd_device * device) { int rc; @@ -184,7 +182,7 @@ dasd_state_known_to_basic(struct dasd_device * device) device->debug_area = debug_register(device->cdev->dev.bus_id, 1, 2, 8 * sizeof (long)); debug_register_view(device->debug_area, &debug_sprintf_view); - debug_set_level(device->debug_area, DBF_WARNING); + debug_set_level(device->debug_area, DBF_EMERG); DBF_DEV_EVENT(DBF_EMERG, device, "%s", "debug area created"); device->state = DASD_STATE_BASIC; @@ -194,23 +192,17 @@ dasd_state_known_to_basic(struct dasd_device * device) /* * Release the irq line for the device. Terminate any running i/o. */ -static int +static inline void dasd_state_basic_to_known(struct dasd_device * device) { - int rc; - dasd_gendisk_free(device); - rc = dasd_flush_ccw_queue(device, 1); - if (rc) - return rc; - + dasd_flush_ccw_queue(device, 1); DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device); if (device->debug_area != NULL) { debug_unregister(device->debug_area); device->debug_area = NULL; } device->state = DASD_STATE_KNOWN; - return 0; } /* @@ -227,7 +219,7 @@ dasd_state_basic_to_known(struct dasd_device * device) * In case the analysis returns an error, the device setup is stopped * (a fake disk was already added to allow formatting). */ -static int +static inline int dasd_state_basic_to_ready(struct dasd_device * device) { int rc; @@ -255,31 +247,25 @@ dasd_state_basic_to_ready(struct dasd_device * device) * Forget format information. Check if the target level is basic * and if it is create fake disk for formatting. */ -static int +static inline void dasd_state_ready_to_basic(struct dasd_device * device) { - int rc; - - rc = dasd_flush_ccw_queue(device, 0); - if (rc) - return rc; + dasd_flush_ccw_queue(device, 0); dasd_destroy_partitions(device); dasd_flush_request_queue(device); device->blocks = 0; device->bp_block = 0; device->s2b_shift = 0; device->state = DASD_STATE_BASIC; - return 0; } /* * Back to basic. */ -static int +static inline void dasd_state_unfmt_to_basic(struct dasd_device * device) { device->state = DASD_STATE_BASIC; - return 0; } /* @@ -287,7 +273,7 @@ dasd_state_unfmt_to_basic(struct dasd_device * device) * the requeueing of requests from the linux request queue to the * ccw queue. */ -static int +static inline int dasd_state_ready_to_online(struct dasd_device * device) { device->state = DASD_STATE_ONLINE; @@ -298,17 +284,16 @@ dasd_state_ready_to_online(struct dasd_device * device) /* * Stop the requeueing of requests again. */ -static int +static inline void dasd_state_online_to_ready(struct dasd_device * device) { device->state = DASD_STATE_READY; - return 0; } /* * Device startup state changes. */ -static int +static inline int dasd_increase_state(struct dasd_device *device) { int rc; @@ -344,37 +329,30 @@ dasd_increase_state(struct dasd_device *device) /* * Device shutdown state changes. */ -static int +static inline int dasd_decrease_state(struct dasd_device *device) { - int rc; - - rc = 0; if (device->state == DASD_STATE_ONLINE && device->target <= DASD_STATE_READY) - rc = dasd_state_online_to_ready(device); + dasd_state_online_to_ready(device); - if (!rc && - device->state == DASD_STATE_READY && + if (device->state == DASD_STATE_READY && device->target <= DASD_STATE_BASIC) - rc = dasd_state_ready_to_basic(device); + dasd_state_ready_to_basic(device); - if (!rc && - device->state == DASD_STATE_UNFMT && + if (device->state == DASD_STATE_UNFMT && device->target <= DASD_STATE_BASIC) - rc = dasd_state_unfmt_to_basic(device); + dasd_state_unfmt_to_basic(device); - if (!rc && - device->state == DASD_STATE_BASIC && + if (device->state == DASD_STATE_BASIC && device->target <= DASD_STATE_KNOWN) - rc = dasd_state_basic_to_known(device); + dasd_state_basic_to_known(device); - if (!rc && - device->state == DASD_STATE_KNOWN && + if (device->state == DASD_STATE_KNOWN && device->target <= DASD_STATE_NEW) - rc = dasd_state_known_to_new(device); + dasd_state_known_to_new(device); - return rc; + return 0; } /* @@ -723,7 +701,6 @@ dasd_term_IO(struct dasd_ccw_req * cqr) cqr->retries--; cqr->status = DASD_CQR_CLEAR; cqr->stopclk = get_clock(); - cqr->starttime = 0; DBF_DEV_EVENT(DBF_DEBUG, device, "terminate cqr %p successful", cqr); @@ -893,7 +870,7 @@ dasd_handle_killed_request(struct ccw_device *cdev, unsigned long intparm) device = (struct dasd_device *) cqr->device; if (device == NULL || - device != dasd_device_from_cdev_locked(cdev) || + device != dasd_device_from_cdev(cdev) || strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s", cdev->dev.bus_id); @@ -970,7 +947,7 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, /* first of all check for state change pending interrupt */ mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; if ((irb->scsw.dstat & mask) == mask) { - device = dasd_device_from_cdev_locked(cdev); + device = dasd_device_from_cdev(cdev); if (!IS_ERR(device)) { dasd_handle_state_change_pending(device); dasd_put_device(device); @@ -1001,7 +978,6 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, irb->scsw.fctl & SCSW_FCTL_CLEAR_FUNC) { cqr->status = DASD_CQR_QUEUED; dasd_clear_timer(device); - wake_up(&dasd_flush_wq); dasd_schedule_bh(device); return; } @@ -1265,10 +1241,6 @@ __dasd_check_expire(struct dasd_device * device) cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); if (cqr->status == DASD_CQR_IN_IO && cqr->expires != 0) { if (time_after_eq(jiffies, cqr->expires + cqr->starttime)) { - DEV_MESSAGE(KERN_ERR, device, - "internal error - timeout (%is) expired " - "for cqr %p (%i retries left)", - (cqr->expires/HZ), cqr, cqr->retries); if (device->discipline->term_IO(cqr) != 0) /* Hmpf, try again in 1/10 sec */ dasd_set_timer(device, 10); @@ -1313,100 +1285,46 @@ __dasd_start_head(struct dasd_device * device) dasd_set_timer(device, 50); } -static inline int -_wait_for_clear(struct dasd_ccw_req *cqr) -{ - return (cqr->status == DASD_CQR_QUEUED); -} - /* - * Remove all requests from the ccw queue (all = '1') or only block device - * requests in case all = '0'. - * Take care of the erp-chain (chained via cqr->refers) and remove either - * the whole erp-chain or none of the erp-requests. - * If a request is currently running, term_IO is called and the request - * is re-queued. Prior to removing the terminated request we need to wait - * for the clear-interrupt. - * In case termination is not possible we stop processing and just finishing - * the already moved requests. + * Remove requests from the ccw queue. */ -static int +static void dasd_flush_ccw_queue(struct dasd_device * device, int all) { - struct dasd_ccw_req *cqr, *orig, *n; - int rc, i; - struct list_head flush_queue; + struct list_head *l, *n; + struct dasd_ccw_req *cqr; INIT_LIST_HEAD(&flush_queue); spin_lock_irq(get_ccwdev_lock(device->cdev)); - rc = 0; -restart: - list_for_each_entry_safe(cqr, n, &device->ccw_queue, list) { - /* get original request of erp request-chain */ - for (orig = cqr; orig->refers != NULL; orig = orig->refers); - + list_for_each_safe(l, n, &device->ccw_queue) { + cqr = list_entry(l, struct dasd_ccw_req, list); /* Flush all request or only block device requests? */ - if (all == 0 && cqr->callback != dasd_end_request_cb && - orig->callback != dasd_end_request_cb) { + if (all == 0 && cqr->callback == dasd_end_request_cb) continue; - } - /* Check status and move request to flush_queue */ - switch (cqr->status) { - case DASD_CQR_IN_IO: - rc = device->discipline->term_IO(cqr); - if (rc) { - /* unable to terminate requeust */ - DEV_MESSAGE(KERN_ERR, device, - "dasd flush ccw_queue is unable " - " to terminate request %p", - cqr); - /* stop flush processing */ - goto finished; - } - break; - case DASD_CQR_QUEUED: - case DASD_CQR_ERROR: - /* set request to FAILED */ - cqr->stopclk = get_clock(); - cqr->status = DASD_CQR_FAILED; - break; - default: /* do not touch the others */ - break; - } - /* Rechain request (including erp chain) */ - for (i = 0; cqr != NULL; cqr = cqr->refers, i++) { - cqr->endclk = get_clock(); - list_move_tail(&cqr->list, &flush_queue); - } - if (i > 1) - /* moved more than one request - need to restart */ - goto restart; - } - -finished: - spin_unlock_irq(get_ccwdev_lock(device->cdev)); - /* Now call the callback function of flushed requests */ -restart_cb: - list_for_each_entry_safe(cqr, n, &flush_queue, list) { - if (cqr->status == DASD_CQR_CLEAR) { - /* wait for clear interrupt! */ - wait_event(dasd_flush_wq, _wait_for_clear(cqr)); + if (cqr->status == DASD_CQR_IN_IO) + device->discipline->term_IO(cqr); + if (cqr->status != DASD_CQR_DONE || + cqr->status != DASD_CQR_FAILED) { cqr->status = DASD_CQR_FAILED; + cqr->stopclk = get_clock(); } /* Process finished ERP request. */ if (cqr->refers) { __dasd_process_erp(device, cqr); - /* restart list_for_xx loop since dasd_process_erp - * might remove multiple elements */ - goto restart_cb; + continue; } - /* call the callback function */ + /* Rechain request on device request queue */ cqr->endclk = get_clock(); + list_move_tail(&cqr->list, &flush_queue); + } + spin_unlock_irq(get_ccwdev_lock(device->cdev)); + /* Now call the callback function of flushed requests */ + list_for_each_safe(l, n, &flush_queue) { + cqr = list_entry(l, struct dasd_ccw_req, list); if (cqr->callback != NULL) (cqr->callback)(cqr, cqr->callback_data); } - return rc; } /* @@ -1592,8 +1510,10 @@ dasd_sleep_on_interruptible(struct dasd_ccw_req * cqr) if (device->discipline->term_IO) { cqr->retries = -1; device->discipline->term_IO(cqr); - /* wait (non-interruptible) for final status - * because signal ist still pending */ + /*nished = + * wait (non-interruptible) for final status + * because signal ist still pending + */ spin_unlock_irq(get_ccwdev_lock(device->cdev)); wait_event(wait_q, _wait_for_wakeup(cqr)); spin_lock_irq(get_ccwdev_lock(device->cdev)); @@ -1626,11 +1546,19 @@ static inline int _dasd_term_running_cqr(struct dasd_device *device) { struct dasd_ccw_req *cqr; + int rc; if (list_empty(&device->ccw_queue)) return 0; cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); - return device->discipline->term_IO(cqr); + rc = device->discipline->term_IO(cqr); + if (rc == 0) { + /* termination successful */ + cqr->status = DASD_CQR_QUEUED; + cqr->startclk = cqr->stopclk = 0; + cqr->starttime = 0; + } + return rc; } int @@ -1798,9 +1726,12 @@ dasd_flush_request_queue(struct dasd_device * device) return; spin_lock_irq(&device->request_queue_lock); - while ((req = elv_next_request(device->request_queue))) { - blkdev_dequeue_request(req); + while (!list_empty(&device->request_queue->queue_head)) { + req = elv_next_request(device->request_queue); + if (req == NULL) + break; dasd_end_request(req, 0); + blkdev_dequeue_request(req); } spin_unlock_irq(&device->request_queue_lock); } @@ -2160,7 +2091,6 @@ dasd_init(void) int rc; init_waitqueue_head(&dasd_init_waitq); - init_waitqueue_head(&dasd_flush_wq); /* register 'common' DASD debug area, used for all DBF_XXX calls */ dasd_debug_area = debug_register("dasd", 1, 2, 8 * sizeof (long)); @@ -2169,7 +2099,7 @@ dasd_init(void) goto failed; } debug_register_view(dasd_debug_area, &debug_sprintf_view); - debug_set_level(dasd_debug_area, DBF_WARNING); + debug_set_level(dasd_debug_area, DBF_EMERG); DBF_EVENT(DBF_EMERG, "%s", "debug area created"); diff --git a/trunk/drivers/s390/block/dasd_devmap.c b/trunk/drivers/s390/block/dasd_devmap.c index 91cf971f0652..7f6fdac74706 100644 --- a/trunk/drivers/s390/block/dasd_devmap.c +++ b/trunk/drivers/s390/block/dasd_devmap.c @@ -48,20 +48,18 @@ struct dasd_devmap { }; /* - * dasd_server_ssid_map contains a globally unique storage server subsystem ID. - * dasd_server_ssid_list contains the list of all subsystem IDs accessed by - * the DASD device driver. + * dasd_servermap is used to store the server_id of all storage servers + * accessed by DASD device driver. */ -struct dasd_server_ssid_map { +struct dasd_servermap { struct list_head list; - struct system_id { + struct server_id { char vendor[4]; char serial[15]; - __u16 ssid; } sid; }; -static struct list_head dasd_server_ssid_list; +static struct list_head dasd_serverlist; /* * Parameter parsing functions for dasd= parameter. The syntax is: @@ -91,7 +89,7 @@ static char *dasd[256]; module_param_array(dasd, charp, NULL, 0); /* - * Single spinlock to protect devmap and servermap structures and lists. + * Single spinlock to protect devmap structures and lists. */ static DEFINE_SPINLOCK(dasd_devmap_lock); @@ -258,21 +256,16 @@ dasd_parse_keyword( char *parsestring ) { return residual_str; } if (strncmp("nopav", parsestring, length) == 0) { - if (MACHINE_IS_VM) - MESSAGE(KERN_INFO, "%s", "'nopav' not supported on VM"); - else { - dasd_nopav = 1; - MESSAGE(KERN_INFO, "%s", "disable PAV mode"); - } + dasd_nopav = 1; + MESSAGE(KERN_INFO, "%s", "disable PAV mode"); return residual_str; } if (strncmp("fixedbuffers", parsestring, length) == 0) { if (dasd_page_cache) return residual_str; dasd_page_cache = - kmem_cache_create("dasd_page_cache", PAGE_SIZE, - PAGE_SIZE, SLAB_CACHE_DMA, - NULL, NULL ); + kmem_cache_create("dasd_page_cache", PAGE_SIZE, 0, + SLAB_CACHE_DMA, NULL, NULL ); if (!dasd_page_cache) MESSAGE(KERN_WARNING, "%s", "Failed to create slab, " "fixed buffer mode disabled."); @@ -527,17 +520,17 @@ dasd_create_device(struct ccw_device *cdev) { struct dasd_devmap *devmap; struct dasd_device *device; - unsigned long flags; int rc; devmap = dasd_devmap_from_cdev(cdev); if (IS_ERR(devmap)) return (void *) devmap; + cdev->dev.driver_data = devmap; device = dasd_alloc_device(); if (IS_ERR(device)) return device; - atomic_set(&device->ref_count, 3); + atomic_set(&device->ref_count, 2); spin_lock(&dasd_devmap_lock); if (!devmap->device) { @@ -556,11 +549,6 @@ dasd_create_device(struct ccw_device *cdev) dasd_free_device(device); return ERR_PTR(rc); } - - spin_lock_irqsave(get_ccwdev_lock(cdev), flags); - cdev->dev.driver_data = device; - spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); - return device; } @@ -578,7 +566,6 @@ dasd_delete_device(struct dasd_device *device) { struct ccw_device *cdev; struct dasd_devmap *devmap; - unsigned long flags; /* First remove device pointer from devmap. */ devmap = dasd_find_busid(device->cdev->dev.bus_id); @@ -592,16 +579,9 @@ dasd_delete_device(struct dasd_device *device) devmap->device = NULL; spin_unlock(&dasd_devmap_lock); - /* Disconnect dasd_device structure from ccw_device structure. */ - spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); - device->cdev->dev.driver_data = NULL; - spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); - - /* - * Drop ref_count by 3, one for the devmap reference, one for - * the cdev reference and one for the passed reference. - */ - atomic_sub(3, &device->ref_count); + /* Drop ref_count by 2, one for the devmap reference and + * one for the passed reference. */ + atomic_sub(2, &device->ref_count); /* Wait for reference counter to drop to zero. */ wait_event(dasd_delete_wq, atomic_read(&device->ref_count) == 0); @@ -610,6 +590,9 @@ dasd_delete_device(struct dasd_device *device) cdev = device->cdev; device->cdev = NULL; + /* Disconnect dasd_devmap structure from ccw_device structure. */ + cdev->dev.driver_data = NULL; + /* Put ccw_device structure. */ put_device(&cdev->dev); @@ -627,34 +610,23 @@ dasd_put_device_wake(struct dasd_device *device) wake_up(&dasd_delete_wq); } -/* - * Return dasd_device structure associated with cdev. - * This function needs to be called with the ccw device - * lock held. It can be used from interrupt context. - */ -struct dasd_device * -dasd_device_from_cdev_locked(struct ccw_device *cdev) -{ - struct dasd_device *device = cdev->dev.driver_data; - - if (!device) - return ERR_PTR(-ENODEV); - dasd_get_device(device); - return device; -} - /* * Return dasd_device structure associated with cdev. */ struct dasd_device * dasd_device_from_cdev(struct ccw_device *cdev) { + struct dasd_devmap *devmap; struct dasd_device *device; - unsigned long flags; - spin_lock_irqsave(get_ccwdev_lock(cdev), flags); - device = dasd_device_from_cdev_locked(cdev); - spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); + device = ERR_PTR(-ENODEV); + spin_lock(&dasd_devmap_lock); + devmap = cdev->dev.driver_data; + if (devmap && devmap->device) { + device = devmap->device; + dasd_get_device(device); + } + spin_unlock(&dasd_devmap_lock); return device; } @@ -755,17 +727,16 @@ static ssize_t dasd_discipline_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct dasd_device *device; - ssize_t len; + struct dasd_devmap *devmap; + char *dname; - device = dasd_device_from_cdev(to_ccwdev(dev)); - if (!IS_ERR(device) && device->discipline) { - len = snprintf(buf, PAGE_SIZE, "%s\n", - device->discipline->name); - dasd_put_device(device); - } else - len = snprintf(buf, PAGE_SIZE, "none\n"); - return len; + spin_lock(&dasd_devmap_lock); + dname = "none"; + devmap = dev->driver_data; + if (devmap && devmap->device && devmap->device->discipline) + dname = devmap->device->discipline->name; + spin_unlock(&dasd_devmap_lock); + return snprintf(buf, PAGE_SIZE, "%s\n", dname); } static DEVICE_ATTR(discipline, 0444, dasd_discipline_show, NULL); @@ -887,6 +858,39 @@ static struct attribute_group dasd_attr_group = { .attrs = dasd_attrs, }; +/* + * Check if the related storage server is already contained in the + * dasd_serverlist. If server is not contained, create new entry. + * Return 0 if server was already in serverlist, + * 1 if the server was added successfully + * <0 in case of error. + */ +static int +dasd_add_server(struct dasd_uid *uid) +{ + struct dasd_servermap *new, *tmp; + + /* check if server is already contained */ + list_for_each_entry(tmp, &dasd_serverlist, list) + // normale cmp? + if (strncmp(tmp->sid.vendor, uid->vendor, + sizeof(tmp->sid.vendor)) == 0 + && strncmp(tmp->sid.serial, uid->serial, + sizeof(tmp->sid.serial)) == 0) + return 0; + + new = (struct dasd_servermap *) + kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL); + if (!new) + return -ENOMEM; + + strncpy(new->sid.vendor, uid->vendor, sizeof(new->sid.vendor)); + strncpy(new->sid.serial, uid->serial, sizeof(new->sid.serial)); + list_add(&new->list, &dasd_serverlist); + return 1; +} + + /* * Return copy of the device unique identifier. */ @@ -906,9 +910,6 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) /* * Register the given device unique identifier into devmap struct. - * In addition check if the related storage server subsystem ID is already - * contained in the dasd_server_ssid_list. If subsystem ID is not contained, - * create new entry. * Return 0 if server was already in serverlist, * 1 if the server was added successful * <0 in case of error. @@ -917,39 +918,16 @@ int dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) { struct dasd_devmap *devmap; - struct dasd_server_ssid_map *srv, *tmp; + int rc; devmap = dasd_find_busid(cdev->dev.bus_id); if (IS_ERR(devmap)) return PTR_ERR(devmap); - - /* generate entry for server_ssid_map */ - srv = (struct dasd_server_ssid_map *) - kzalloc(sizeof(struct dasd_server_ssid_map), GFP_KERNEL); - if (!srv) - return -ENOMEM; - strncpy(srv->sid.vendor, uid->vendor, sizeof(srv->sid.vendor) - 1); - strncpy(srv->sid.serial, uid->serial, sizeof(srv->sid.serial) - 1); - srv->sid.ssid = uid->ssid; - - /* server is already contained ? */ spin_lock(&dasd_devmap_lock); devmap->uid = *uid; - list_for_each_entry(tmp, &dasd_server_ssid_list, list) { - if (!memcmp(&srv->sid, &tmp->sid, - sizeof(struct system_id))) { - kfree(srv); - srv = NULL; - break; - } - } - - /* add servermap to serverlist */ - if (srv) - list_add(&srv->list, &dasd_server_ssid_list); + rc = dasd_add_server(uid); spin_unlock(&dasd_devmap_lock); - - return (srv ? 1 : 0); + return rc; } EXPORT_SYMBOL_GPL(dasd_set_uid); @@ -1017,7 +995,7 @@ dasd_devmap_init(void) INIT_LIST_HEAD(&dasd_hashlists[i]); /* Initialize servermap structure. */ - INIT_LIST_HEAD(&dasd_server_ssid_list); + INIT_LIST_HEAD(&dasd_serverlist); return 0; } diff --git a/trunk/drivers/s390/block/dasd_eckd.c b/trunk/drivers/s390/block/dasd_eckd.c index b7a7fac3f7c3..39c2281371b5 100644 --- a/trunk/drivers/s390/block/dasd_eckd.c +++ b/trunk/drivers/s390/block/dasd_eckd.c @@ -468,11 +468,11 @@ dasd_eckd_generate_uid(struct dasd_device *device, struct dasd_uid *uid) return -ENODEV; memset(uid, 0, sizeof(struct dasd_uid)); - memcpy(uid->vendor, confdata->ned1.HDA_manufacturer, - sizeof(uid->vendor) - 1); + strncpy(uid->vendor, confdata->ned1.HDA_manufacturer, + sizeof(uid->vendor) - 1); EBCASC(uid->vendor, sizeof(uid->vendor) - 1); - memcpy(uid->serial, confdata->ned1.HDA_location, - sizeof(uid->serial) - 1); + strncpy(uid->serial, confdata->ned1.HDA_location, + sizeof(uid->serial) - 1); EBCASC(uid->serial, sizeof(uid->serial) - 1); uid->ssid = confdata->neq.subsystemID; if (confdata->ned2.sneq.flags == 0x40) { @@ -607,7 +607,7 @@ dasd_eckd_psf_ssc(struct dasd_device *device) * Valide storage server of current device. */ static int -dasd_eckd_validate_server(struct dasd_device *device, struct dasd_uid *uid) +dasd_eckd_validate_server(struct dasd_device *device) { int rc; @@ -616,11 +616,11 @@ dasd_eckd_validate_server(struct dasd_device *device, struct dasd_uid *uid) return 0; rc = dasd_eckd_psf_ssc(device); - /* may be requested feature is not available on server, - * therefore just report error and go ahead */ - DEV_MESSAGE(KERN_INFO, device, - "PSF-SSC on storage subsystem %s.%s.%04x returned rc=%d", - uid->vendor, uid->serial, uid->ssid, rc); + if (rc) + /* may be requested feature is not available on server, + * therefore just report error and go ahead */ + DEV_MESSAGE(KERN_INFO, device, + "Perform Subsystem Function returned rc=%d", rc); /* RE-Read Configuration Data */ return dasd_eckd_read_conf(device); } @@ -666,7 +666,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) return rc; rc = dasd_set_uid(device->cdev, &uid); if (rc == 1) /* new server found */ - rc = dasd_eckd_validate_server(device, &uid); + rc = dasd_eckd_validate_server(device); if (rc) return rc; diff --git a/trunk/drivers/s390/block/dasd_eer.c b/trunk/drivers/s390/block/dasd_eer.c index e0bf30ebb215..da65f1b032f5 100644 --- a/trunk/drivers/s390/block/dasd_eer.c +++ b/trunk/drivers/s390/block/dasd_eer.c @@ -678,7 +678,7 @@ int __init dasd_eer_init(void) return 0; } -void dasd_eer_exit(void) +void __exit dasd_eer_exit(void) { WARN_ON(misc_deregister(&dasd_eer_dev) != 0); } diff --git a/trunk/drivers/s390/block/dasd_genhd.c b/trunk/drivers/s390/block/dasd_genhd.c index d163632101d2..4c272b70f41a 100644 --- a/trunk/drivers/s390/block/dasd_genhd.c +++ b/trunk/drivers/s390/block/dasd_genhd.c @@ -83,12 +83,10 @@ dasd_gendisk_alloc(struct dasd_device *device) void dasd_gendisk_free(struct dasd_device *device) { - if (device->gdp) { - del_gendisk(device->gdp); - device->gdp->queue = NULL; - put_disk(device->gdp); - device->gdp = NULL; - } + del_gendisk(device->gdp); + device->gdp->queue = NULL; + put_disk(device->gdp); + device->gdp = NULL; } /* diff --git a/trunk/drivers/s390/block/dasd_int.h b/trunk/drivers/s390/block/dasd_int.h index 9f52004f6fc2..3ccf06d28ba1 100644 --- a/trunk/drivers/s390/block/dasd_int.h +++ b/trunk/drivers/s390/block/dasd_int.h @@ -534,7 +534,6 @@ int dasd_add_sysfs_files(struct ccw_device *); void dasd_remove_sysfs_files(struct ccw_device *); struct dasd_device *dasd_device_from_cdev(struct ccw_device *); -struct dasd_device *dasd_device_from_cdev_locked(struct ccw_device *); struct dasd_device *dasd_device_from_devindex(int); int dasd_parse(void); diff --git a/trunk/drivers/s390/block/xpram.c b/trunk/drivers/s390/block/xpram.c index cab2c736683a..1140302ff11d 100644 --- a/trunk/drivers/s390/block/xpram.c +++ b/trunk/drivers/s390/block/xpram.c @@ -48,6 +48,15 @@ #define PRINT_ERR(x...) printk(KERN_ERR XPRAM_NAME " error:" x) +static struct sysdev_class xpram_sysclass = { + set_kset_name("xpram"), +}; + +static struct sys_device xpram_sys_device = { + .id = 0, + .cls = &xpram_sysclass, +}; + typedef struct { unsigned int size; /* size of xpram segment in pages */ unsigned int offset; /* start page of xpram segment */ @@ -442,6 +451,8 @@ static void __exit xpram_exit(void) } unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); blk_cleanup_queue(xpram_queue); + sysdev_unregister(&xpram_sys_device); + sysdev_class_unregister(&xpram_sysclass); } static int __init xpram_init(void) @@ -453,13 +464,25 @@ static int __init xpram_init(void) PRINT_WARN("No expanded memory available\n"); return -ENODEV; } - xpram_pages = xpram_highest_page_index() + 1; + xpram_pages = xpram_highest_page_index(); PRINT_INFO(" %u pages expanded memory found (%lu KB).\n", xpram_pages, (unsigned long) xpram_pages*4); rc = xpram_setup_sizes(xpram_pages); if (rc) return rc; - return xpram_setup_blkdev(); + rc = sysdev_class_register(&xpram_sysclass); + if (rc) + return rc; + + rc = sysdev_register(&xpram_sys_device); + if (rc) { + sysdev_class_unregister(&xpram_sysclass); + return rc; + } + rc = xpram_setup_blkdev(); + if (rc) + sysdev_unregister(&xpram_sys_device); + return rc; } module_init(xpram_init); diff --git a/trunk/drivers/s390/char/Makefile b/trunk/drivers/s390/char/Makefile index c3e97b4fc186..0c0162ff6c0c 100644 --- a/trunk/drivers/s390/char/Makefile +++ b/trunk/drivers/s390/char/Makefile @@ -28,4 +28,3 @@ obj-$(CONFIG_S390_TAPE) += tape.o tape_class.o obj-$(CONFIG_S390_TAPE_34XX) += tape_34xx.o obj-$(CONFIG_S390_TAPE_3590) += tape_3590.o obj-$(CONFIG_MONREADER) += monreader.o -obj-$(CONFIG_MONWRITER) += monwriter.o diff --git a/trunk/drivers/s390/char/monwriter.c b/trunk/drivers/s390/char/monwriter.c deleted file mode 100644 index 1e3939aeb8ab..000000000000 --- a/trunk/drivers/s390/char/monwriter.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * drivers/s390/char/monwriter.c - * - * Character device driver for writing z/VM *MONITOR service records. - * - * Copyright (C) IBM Corp. 2006 - * - * Author(s): Melissa Howland - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MONWRITE_MAX_DATALEN 4024 - -static int mon_max_bufs = 255; - -struct mon_buf { - struct list_head list; - struct monwrite_hdr hdr; - int diag_done; - char *data; -}; - -struct mon_private { - struct list_head list; - struct monwrite_hdr hdr; - size_t hdr_to_read; - size_t data_to_read; - struct mon_buf *current_buf; - int mon_buf_count; -}; - -/* - * helper functions - */ - -static int monwrite_diag(struct monwrite_hdr *myhdr, char *buffer, int fcn) -{ - struct appldata_product_id id; - int rc; - - strcpy(id.prod_nr, "LNXAPPL"); - id.prod_fn = myhdr->applid; - id.record_nr = myhdr->record_num; - id.version_nr = myhdr->version; - id.release_nr = myhdr->release; - id.mod_lvl = myhdr->mod_level; - rc = appldata_asm(&id, fcn, (void *) buffer, myhdr->datalen); - if (rc <= 0) - return rc; - if (rc == 5) - return -EPERM; - printk("DIAG X'DC' error with return code: %i\n", rc); - return -EINVAL; -} - -static inline struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv, - struct monwrite_hdr *monhdr) -{ - struct mon_buf *entry, *next; - - list_for_each_entry_safe(entry, next, &monpriv->list, list) - if (entry->hdr.applid == monhdr->applid && - entry->hdr.record_num == monhdr->record_num && - entry->hdr.version == monhdr->version && - entry->hdr.release == monhdr->release && - entry->hdr.mod_level == monhdr->mod_level) - return entry; - return NULL; -} - -static int monwrite_new_hdr(struct mon_private *monpriv) -{ - struct monwrite_hdr *monhdr = &monpriv->hdr; - struct mon_buf *monbuf; - int rc; - - if (monhdr->datalen > MONWRITE_MAX_DATALEN || - monhdr->mon_function > MONWRITE_START_CONFIG || - monhdr->hdrlen != sizeof(struct monwrite_hdr)) - return -EINVAL; - monbuf = monwrite_find_hdr(monpriv, monhdr); - if (monbuf) { - if (monhdr->mon_function == MONWRITE_STOP_INTERVAL) { - monhdr->datalen = monbuf->hdr.datalen; - rc = monwrite_diag(monhdr, monbuf->data, - APPLDATA_STOP_REC); - list_del(&monbuf->list); - monpriv->mon_buf_count--; - kfree(monbuf->data); - kfree(monbuf); - monbuf = NULL; - } - } else { - if (monpriv->mon_buf_count >= mon_max_bufs) - return -ENOSPC; - monbuf = kzalloc(sizeof(struct mon_buf), GFP_KERNEL); - if (!monbuf) - return -ENOMEM; - monbuf->data = kzalloc(monbuf->hdr.datalen, - GFP_KERNEL | GFP_DMA); - if (!monbuf->data) { - kfree(monbuf); - return -ENOMEM; - } - monbuf->hdr = *monhdr; - list_add_tail(&monbuf->list, &monpriv->list); - monpriv->mon_buf_count++; - } - monpriv->current_buf = monbuf; - return 0; -} - -static int monwrite_new_data(struct mon_private *monpriv) -{ - struct monwrite_hdr *monhdr = &monpriv->hdr; - struct mon_buf *monbuf = monpriv->current_buf; - int rc = 0; - - switch (monhdr->mon_function) { - case MONWRITE_START_INTERVAL: - if (!monbuf->diag_done) { - rc = monwrite_diag(monhdr, monbuf->data, - APPLDATA_START_INTERVAL_REC); - monbuf->diag_done = 1; - } - break; - case MONWRITE_START_CONFIG: - if (!monbuf->diag_done) { - rc = monwrite_diag(monhdr, monbuf->data, - APPLDATA_START_CONFIG_REC); - monbuf->diag_done = 1; - } - break; - case MONWRITE_GEN_EVENT: - rc = monwrite_diag(monhdr, monbuf->data, - APPLDATA_GEN_EVENT_REC); - list_del(&monpriv->current_buf->list); - kfree(monpriv->current_buf->data); - kfree(monpriv->current_buf); - monpriv->current_buf = NULL; - break; - default: - /* monhdr->mon_function is checked in monwrite_new_hdr */ - BUG(); - } - return rc; -} - -/* - * file operations - */ - -static int monwrite_open(struct inode *inode, struct file *filp) -{ - struct mon_private *monpriv; - - monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); - if (!monpriv) - return -ENOMEM; - INIT_LIST_HEAD(&monpriv->list); - monpriv->hdr_to_read = sizeof(monpriv->hdr); - filp->private_data = monpriv; - return nonseekable_open(inode, filp); -} - -static int monwrite_close(struct inode *inode, struct file *filp) -{ - struct mon_private *monpriv = filp->private_data; - struct mon_buf *entry, *next; - - list_for_each_entry_safe(entry, next, &monpriv->list, list) { - if (entry->hdr.mon_function != MONWRITE_GEN_EVENT) - monwrite_diag(&entry->hdr, entry->data, - APPLDATA_STOP_REC); - monpriv->mon_buf_count--; - list_del(&entry->list); - kfree(entry->data); - kfree(entry); - } - kfree(monpriv); - return 0; -} - -static ssize_t monwrite_write(struct file *filp, const char __user *data, - size_t count, loff_t *ppos) -{ - struct mon_private *monpriv = filp->private_data; - size_t len, written; - void *to; - int rc; - - for (written = 0; written < count; ) { - if (monpriv->hdr_to_read) { - len = min(count - written, monpriv->hdr_to_read); - to = (char *) &monpriv->hdr + - sizeof(monpriv->hdr) - monpriv->hdr_to_read; - if (copy_from_user(to, data + written, len)) { - rc = -EFAULT; - goto out_error; - } - monpriv->hdr_to_read -= len; - written += len; - if (monpriv->hdr_to_read > 0) - continue; - rc = monwrite_new_hdr(monpriv); - if (rc) - goto out_error; - monpriv->data_to_read = monpriv->current_buf ? - monpriv->current_buf->hdr.datalen : 0; - } - - if (monpriv->data_to_read) { - len = min(count - written, monpriv->data_to_read); - to = monpriv->current_buf->data + - monpriv->hdr.datalen - monpriv->data_to_read; - if (copy_from_user(to, data + written, len)) { - rc = -EFAULT; - goto out_error; - } - monpriv->data_to_read -= len; - written += len; - if (monpriv->data_to_read > 0) - continue; - rc = monwrite_new_data(monpriv); - if (rc) - goto out_error; - } - monpriv->hdr_to_read = sizeof(monpriv->hdr); - } - return written; - -out_error: - monpriv->data_to_read = 0; - monpriv->hdr_to_read = sizeof(struct monwrite_hdr); - return rc; -} - -static struct file_operations monwrite_fops = { - .owner = THIS_MODULE, - .open = &monwrite_open, - .release = &monwrite_close, - .write = &monwrite_write, -}; - -static struct miscdevice mon_dev = { - .name = "monwriter", - .fops = &monwrite_fops, - .minor = MISC_DYNAMIC_MINOR, -}; - -/* - * module init/exit - */ - -static int __init mon_init(void) -{ - if (MACHINE_IS_VM) - return misc_register(&mon_dev); - else - return -ENODEV; -} - -static void __exit mon_exit(void) -{ - WARN_ON(misc_deregister(&mon_dev) != 0); -} - -module_init(mon_init); -module_exit(mon_exit); - -module_param_named(max_bufs, mon_max_bufs, int, 0644); -MODULE_PARM_DESC(max_bufs, "Maximum number of sample monitor data buffers" - "that can be active at one time"); - -MODULE_AUTHOR("Melissa Howland "); -MODULE_DESCRIPTION("Character device driver for writing z/VM " - "APPLDATA monitor records."); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/s390/char/tape_class.c b/trunk/drivers/s390/char/tape_class.c index 56b87618b100..643b6d078563 100644 --- a/trunk/drivers/s390/char/tape_class.c +++ b/trunk/drivers/s390/char/tape_class.c @@ -76,7 +76,7 @@ struct tape_class_device *register_tape_dev( device, "%s", tcd->device_name ); - rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0; + rc = PTR_ERR(tcd->class_device); if (rc) goto fail_with_cdev; rc = sysfs_create_link( diff --git a/trunk/drivers/s390/char/vmcp.c b/trunk/drivers/s390/char/vmcp.c index 1678b6c757ec..19762f3476aa 100644 --- a/trunk/drivers/s390/char/vmcp.c +++ b/trunk/drivers/s390/char/vmcp.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2004,2005 IBM Corporation - * Interface implementation for communication with the z/VM control program + * Interface implementation for communication with the v/VM control program * Author(s): Christian Borntraeger * * diff --git a/trunk/drivers/s390/char/vmcp.h b/trunk/drivers/s390/char/vmcp.h index 8a5975f3dad7..87389e730465 100644 --- a/trunk/drivers/s390/char/vmcp.h +++ b/trunk/drivers/s390/char/vmcp.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2004, 2005 IBM Corporation - * Interface implementation for communication with the z/VM control program + * Interface implementation for communication with the v/VM control program * Version 1.0 * Author(s): Christian Borntraeger * diff --git a/trunk/drivers/s390/cio/ccwgroup.c b/trunk/drivers/s390/cio/ccwgroup.c index 38954f5cd14c..f26a2ee3aad8 100644 --- a/trunk/drivers/s390/cio/ccwgroup.c +++ b/trunk/drivers/s390/cio/ccwgroup.c @@ -152,6 +152,7 @@ ccwgroup_create(struct device *root, struct ccwgroup_device *gdev; int i; int rc; + int del_drvdata; if (argc > 256) /* disallow dumb users */ return -EINVAL; @@ -162,6 +163,7 @@ ccwgroup_create(struct device *root, atomic_set(&gdev->onoff, 0); + del_drvdata = 0; for (i = 0; i < argc; i++) { gdev->cdev[i] = get_ccwdev_by_busid(cdrv, argv[i]); @@ -178,14 +180,18 @@ ccwgroup_create(struct device *root, rc = -EINVAL; goto free_dev; } - gdev->cdev[i]->dev.driver_data = gdev; } + for (i = 0; i < argc; i++) + gdev->cdev[i]->dev.driver_data = gdev; + del_drvdata = 1; gdev->creator_id = creator_id; gdev->count = argc; - gdev->dev.bus = &ccwgroup_bus_type; - gdev->dev.parent = root; - gdev->dev.release = ccwgroup_release; + gdev->dev = (struct device ) { + .bus = &ccwgroup_bus_type, + .parent = root, + .release = ccwgroup_release, + }; snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s", gdev->cdev[0]->dev.bus_id); @@ -220,9 +226,9 @@ ccwgroup_create(struct device *root, free_dev: for (i = 0; i < argc; i++) if (gdev->cdev[i]) { - if (gdev->cdev[i]->dev.driver_data == gdev) - gdev->cdev[i]->dev.driver_data = NULL; put_device(&gdev->cdev[i]->dev); + if (del_drvdata) + gdev->cdev[i]->dev.driver_data = NULL; } kfree(gdev); return rc; @@ -389,8 +395,10 @@ int ccwgroup_driver_register (struct ccwgroup_driver *cdriver) { /* register our new driver with the core */ - cdriver->driver.bus = &ccwgroup_bus_type; - cdriver->driver.name = cdriver->name; + cdriver->driver = (struct device_driver) { + .bus = &ccwgroup_bus_type, + .name = cdriver->name, + }; return driver_register(&cdriver->driver); } diff --git a/trunk/drivers/s390/cio/chsc.c b/trunk/drivers/s390/cio/chsc.c index 3bb4e472d73d..61ce3f1d5228 100644 --- a/trunk/drivers/s390/cio/chsc.c +++ b/trunk/drivers/s390/cio/chsc.c @@ -238,6 +238,8 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) /* Check for single path devices. */ if (sch->schib.pmcw.pim == 0x80) goto out_unreg; + if (sch->vpm == mask) + goto out_unreg; if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) && (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) && @@ -256,8 +258,6 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) /* trigger path verification. */ if (sch->driver && sch->driver->verify) sch->driver->verify(&sch->dev); - else if (sch->lpm == mask) - goto out_unreg; out_unlock: spin_unlock_irq(&sch->lock); return 0; @@ -378,7 +378,6 @@ __s390_process_res_acc(struct subchannel_id schid, void *data) if (chp_mask == 0) { spin_unlock_irq(&sch->lock); - put_device(&sch->dev); return 0; } old_lpm = sch->lpm; @@ -393,7 +392,7 @@ __s390_process_res_acc(struct subchannel_id schid, void *data) spin_unlock_irq(&sch->lock); put_device(&sch->dev); - return 0; + return (res_data->fla_mask == 0xffff) ? -ENODEV : 0; } @@ -1392,8 +1391,10 @@ new_channel_path(int chpid) /* fill in status, etc. */ chp->id = chpid; chp->state = 1; - chp->dev.parent = &css[0]->device; - chp->dev.release = chp_release; + chp->dev = (struct device) { + .parent = &css[0]->device, + .release = chp_release, + }; snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp0.%x", chpid); /* Obtain channel path description and fill it in. */ diff --git a/trunk/drivers/s390/cio/cio.c b/trunk/drivers/s390/cio/cio.c index 2e2882daefbb..89320c1ad825 100644 --- a/trunk/drivers/s390/cio/cio.c +++ b/trunk/drivers/s390/cio/cio.c @@ -16,10 +16,11 @@ #include #include #include + #include #include #include -#include + #include "airq.h" #include "cio.h" #include "css.h" @@ -191,7 +192,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ sch->orb.pfch = sch->options.prefetch == 0; sch->orb.spnd = sch->options.suspend; sch->orb.ssic = sch->options.suspend && sch->options.inter; - sch->orb.lpm = (lpm != 0) ? lpm : sch->lpm; + sch->orb.lpm = (lpm != 0) ? (lpm & sch->opm) : sch->lpm; #ifdef CONFIG_64BIT /* * for 64 bit we always support 64 bit IDAWs with 4k page size only @@ -569,7 +570,10 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) sch->opm = 0xff; if (!cio_is_console(sch->schid)) chsc_validate_chpids(sch); - sch->lpm = sch->schib.pmcw.pam & sch->opm; + sch->lpm = sch->schib.pmcw.pim & + sch->schib.pmcw.pam & + sch->schib.pmcw.pom & + sch->opm; CIO_DEBUG(KERN_INFO, 0, "Detected device %04x on subchannel 0.%x.%04X" @@ -837,26 +841,14 @@ __clear_subchannel_easy(struct subchannel_id schid) return -EBUSY; } -struct sch_match_id { - struct subchannel_id schid; - struct ccw_dev_id devid; - int rc; -}; - -static int __shutdown_subchannel_easy_and_match(struct subchannel_id schid, - void *data) +extern void do_reipl(unsigned long devno); +static int +__shutdown_subchannel_easy(struct subchannel_id schid, void *data) { struct schib schib; - struct sch_match_id *match_id = data; if (stsch_err(schid, &schib)) return -ENXIO; - if (match_id && schib.pmcw.dnv && - (schib.pmcw.dev == match_id->devid.devno) && - (schid.ssid == match_id->devid.ssid)) { - match_id->schid = schid; - match_id->rc = 0; - } if (!schib.pmcw.ena) return 0; switch(__disable_subchannel_easy(schid, &schib)) { @@ -872,71 +864,18 @@ static int __shutdown_subchannel_easy_and_match(struct subchannel_id schid, return 0; } -static int clear_all_subchannels_and_match(struct ccw_dev_id *devid, - struct subchannel_id *schid) -{ - struct sch_match_id match_id; - - match_id.devid = *devid; - match_id.rc = -ENODEV; - local_irq_disable(); - for_each_subchannel(__shutdown_subchannel_easy_and_match, &match_id); - if (match_id.rc == 0) - *schid = match_id.schid; - return match_id.rc; -} - - -void clear_all_subchannels(void) +void +clear_all_subchannels(void) { local_irq_disable(); - for_each_subchannel(__shutdown_subchannel_easy_and_match, NULL); + for_each_subchannel(__shutdown_subchannel_easy, NULL); } -extern void do_reipl_asm(__u32 schid); - /* Make sure all subchannels are quiet before we re-ipl an lpar. */ -void reipl_ccw_dev(struct ccw_dev_id *devid) +void +reipl(unsigned long devno) { - struct subchannel_id schid; - - if (clear_all_subchannels_and_match(devid, &schid)) - panic("IPL Device not found\n"); + clear_all_subchannels(); cio_reset_channel_paths(); - do_reipl_asm(*((__u32*)&schid)); -} - -extern struct schib ipl_schib; - -/* - * ipl_save_parameters gets called very early. It is not allowed to access - * anything in the bss section at all. The bss section is not cleared yet, - * but may contain some ipl parameters written by the firmware. - * These parameters (if present) are copied to 0x2000. - * To avoid corruption of the ipl parameters, all variables used by this - * function must reside on the stack or in the data section. - */ -void ipl_save_parameters(void) -{ - struct subchannel_id schid; - unsigned int *ipl_ptr; - void *src, *dst; - - schid = *(struct subchannel_id *)__LC_SUBCHANNEL_ID; - if (!schid.one) - return; - if (stsch(schid, &ipl_schib)) - return; - if (!ipl_schib.pmcw.dnv) - return; - ipl_devno = ipl_schib.pmcw.dev; - ipl_flags |= IPL_DEVNO_VALID; - if (!ipl_schib.pmcw.qf) - return; - ipl_flags |= IPL_PARMBLOCK_VALID; - ipl_ptr = (unsigned int *)__LC_IPL_PARMBLOCK_PTR; - src = (void *)(unsigned long)*ipl_ptr; - dst = (void *)IPL_PARMBLOCK_ORIGIN; - memmove(dst, src, PAGE_SIZE); - *ipl_ptr = IPL_PARMBLOCK_ORIGIN; + do_reipl(devno); } diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index 7086a74e9871..13eeea3d547f 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -182,141 +182,136 @@ get_subchannel_by_schid(struct subchannel_id schid) return dev ? to_subchannel(dev) : NULL; } -static inline int css_get_subchannel_status(struct subchannel *sch) + +static inline int +css_get_subchannel_status(struct subchannel *sch, struct subchannel_id schid) { struct schib schib; + int cc; - if (stsch(sch->schid, &schib) || !schib.pmcw.dnv) + cc = stsch(schid, &schib); + if (cc) + return CIO_GONE; + if (!schib.pmcw.dnv) return CIO_GONE; - if (sch->schib.pmcw.dnv && (schib.pmcw.dev != sch->schib.pmcw.dev)) + if (sch && sch->schib.pmcw.dnv && + (schib.pmcw.dev != sch->schib.pmcw.dev)) return CIO_REVALIDATE; - if (!sch->lpm) + if (sch && !sch->lpm) return CIO_NO_PATH; return CIO_OPER; } - -static int css_evaluate_known_subchannel(struct subchannel *sch, int slow) + +static int +css_evaluate_subchannel(struct subchannel_id schid, int slow) { int event, ret, disc; + struct subchannel *sch; unsigned long flags; - enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE } action; - spin_lock_irqsave(&sch->lock, flags); - disc = device_is_disconnected(sch); + sch = get_subchannel_by_schid(schid); + disc = sch ? device_is_disconnected(sch) : 0; if (disc && slow) { - /* Disconnected devices are evaluated directly only.*/ - spin_unlock_irqrestore(&sch->lock, flags); - return 0; + if (sch) + put_device(&sch->dev); + return 0; /* Already processed. */ } - /* No interrupt after machine check - kill pending timers. */ - device_kill_pending_timer(sch); + /* + * We've got a machine check, so running I/O won't get an interrupt. + * Kill any pending timers. + */ + if (sch) + device_kill_pending_timer(sch); if (!disc && !slow) { - /* Non-disconnected devices are evaluated on the slow path. */ - spin_unlock_irqrestore(&sch->lock, flags); - return -EAGAIN; + if (sch) + put_device(&sch->dev); + return -EAGAIN; /* Will be done on the slow path. */ } - event = css_get_subchannel_status(sch); + event = css_get_subchannel_status(sch, schid); CIO_MSG_EVENT(4, "Evaluating schid 0.%x.%04x, event %d, %s, %s path.\n", - sch->schid.ssid, sch->schid.sch_no, event, - disc ? "disconnected" : "normal", - slow ? "slow" : "fast"); - /* Analyze subchannel status. */ - action = NONE; + schid.ssid, schid.sch_no, event, + sch?(disc?"disconnected":"normal"):"unknown", + slow?"slow":"fast"); switch (event) { case CIO_NO_PATH: - if (disc) { - /* Check if paths have become available. */ - action = REPROBE; + case CIO_GONE: + if (!sch) { + /* Never used this subchannel. Ignore. */ + ret = 0; break; } - /* fall through */ - case CIO_GONE: - /* Prevent unwanted effects when opening lock. */ - cio_disable_subchannel(sch); - device_set_disconnected(sch); - /* Ask driver what to do with device. */ - action = UNREGISTER; - if (sch->driver && sch->driver->notify) { - spin_unlock_irqrestore(&sch->lock, flags); - ret = sch->driver->notify(&sch->dev, event); + if (disc && (event == CIO_NO_PATH)) { + /* + * Uargh, hack again. Because we don't get a machine + * check on configure on, our path bookkeeping can + * be out of date here (it's fine while we only do + * logical varying or get chsc machine checks). We + * need to force reprobing or we might miss devices + * coming operational again. It won't do harm in real + * no path situations. + */ spin_lock_irqsave(&sch->lock, flags); - if (ret) - action = NONE; + device_trigger_reprobe(sch); + spin_unlock_irqrestore(&sch->lock, flags); + ret = 0; + break; } - break; - case CIO_REVALIDATE: - /* Device will be removed, so no notify necessary. */ - if (disc) - /* Reprobe because immediate unregister might block. */ - action = REPROBE; - else - action = UNREGISTER_PROBE; - break; - case CIO_OPER: - if (disc) - /* Get device operational again. */ - action = REPROBE; - break; - } - /* Perform action. */ - ret = 0; - switch (action) { - case UNREGISTER: - case UNREGISTER_PROBE: - /* Unregister device (will use subchannel lock). */ - spin_unlock_irqrestore(&sch->lock, flags); + if (sch->driver && sch->driver->notify && + sch->driver->notify(&sch->dev, event)) { + cio_disable_subchannel(sch); + device_set_disconnected(sch); + ret = 0; + break; + } + /* + * Unregister subchannel. + * The device will be killed automatically. + */ + cio_disable_subchannel(sch); css_sch_device_unregister(sch); - spin_lock_irqsave(&sch->lock, flags); - /* Reset intparm to zeroes. */ sch->schib.pmcw.intparm = 0; cio_modify(sch); - - /* Probe if necessary. */ - if (action == UNREGISTER_PROBE) - ret = css_probe_device(sch->schid); + put_device(&sch->dev); + ret = 0; break; - case REPROBE: - device_trigger_reprobe(sch); + case CIO_REVALIDATE: + /* + * Revalidation machine check. Sick. + * We don't notify the driver since we have to throw the device + * away in any case. + */ + if (!disc) { + css_sch_device_unregister(sch); + /* Reset intparm to zeroes. */ + sch->schib.pmcw.intparm = 0; + cio_modify(sch); + put_device(&sch->dev); + ret = css_probe_device(schid); + } else { + /* + * We can't immediately deregister the disconnected + * device since it might block. + */ + spin_lock_irqsave(&sch->lock, flags); + device_trigger_reprobe(sch); + spin_unlock_irqrestore(&sch->lock, flags); + ret = 0; + } break; - default: + case CIO_OPER: + if (disc) { + spin_lock_irqsave(&sch->lock, flags); + /* Get device operational again. */ + device_trigger_reprobe(sch); + spin_unlock_irqrestore(&sch->lock, flags); + } + ret = sch ? 0 : css_probe_device(schid); break; + default: + BUG(); + ret = 0; } - spin_unlock_irqrestore(&sch->lock, flags); - - return ret; -} - -static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow) -{ - struct schib schib; - - if (!slow) { - /* Will be done on the slow path. */ - return -EAGAIN; - } - if (stsch(schid, &schib) || !schib.pmcw.dnv) { - /* Unusable - ignore. */ - return 0; - } - CIO_MSG_EVENT(4, "Evaluating schid 0.%x.%04x, event %d, unknown, " - "slow path.\n", schid.ssid, schid.sch_no, CIO_OPER); - - return css_probe_device(schid); -} - -static int css_evaluate_subchannel(struct subchannel_id schid, int slow) -{ - struct subchannel *sch; - int ret; - - sch = get_subchannel_by_schid(schid); - if (sch) { - ret = css_evaluate_known_subchannel(sch, slow); - put_device(&sch->dev); - } else - ret = css_evaluate_new_subchannel(schid, slow); - return ret; } diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index 688945662c15..585fa04233c3 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -52,81 +52,53 @@ ccw_bus_match (struct device * dev, struct device_driver * drv) return 1; } -/* Store modalias string delimited by prefix/suffix string into buffer with - * specified size. Return length of resulting string (excluding trailing '\0') - * even if string doesn't fit buffer (snprintf semantics). */ -static int snprint_alias(char *buf, size_t size, const char *prefix, - struct ccw_device_id *id, const char *suffix) -{ - int len; - - len = snprintf(buf, size, "%sccw:t%04Xm%02X", prefix, id->cu_type, - id->cu_model); - if (len > size) - return len; - buf += len; - size -= len; - - if (id->dev_type != 0) - len += snprintf(buf, size, "dt%04Xdm%02X%s", id->dev_type, - id->dev_model, suffix); - else - len += snprintf(buf, size, "dtdm%s", suffix); - - return len; -} - -/* Set up environment variables for ccw device uevent. Return 0 on success, - * non-zero otherwise. */ -static int ccw_uevent(struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) +/* + * Hotplugging interface for ccw devices. + * Heavily modeled on pci and usb hotplug. + */ +static int +ccw_uevent (struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) { struct ccw_device *cdev = to_ccwdev(dev); - struct ccw_device_id *id = &(cdev->id); int i = 0; - int len; + int length = 0; - /* CU_TYPE= */ - len = snprintf(buffer, buffer_size, "CU_TYPE=%04X", id->cu_type) + 1; - if (len > buffer_size || i >= num_envp) - return -ENOMEM; - envp[i++] = buffer; - buffer += len; - buffer_size -= len; + if (!cdev) + return -ENODEV; - /* CU_MODEL= */ - len = snprintf(buffer, buffer_size, "CU_MODEL=%02X", id->cu_model) + 1; - if (len > buffer_size || i >= num_envp) + /* what we want to pass to /sbin/hotplug */ + + envp[i++] = buffer; + length += scnprintf(buffer, buffer_size - length, "CU_TYPE=%04X", + cdev->id.cu_type); + if ((buffer_size - length <= 0) || (i >= num_envp)) return -ENOMEM; + ++length; + buffer += length; + envp[i++] = buffer; - buffer += len; - buffer_size -= len; + length += scnprintf(buffer, buffer_size - length, "CU_MODEL=%02X", + cdev->id.cu_model); + if ((buffer_size - length <= 0) || (i >= num_envp)) + return -ENOMEM; + ++length; + buffer += length; /* The next two can be zero, that's ok for us */ - /* DEV_TYPE= */ - len = snprintf(buffer, buffer_size, "DEV_TYPE=%04X", id->dev_type) + 1; - if (len > buffer_size || i >= num_envp) - return -ENOMEM; envp[i++] = buffer; - buffer += len; - buffer_size -= len; - - /* DEV_MODEL= */ - len = snprintf(buffer, buffer_size, "DEV_MODEL=%02X", - (unsigned char) id->dev_model) + 1; - if (len > buffer_size || i >= num_envp) + length += scnprintf(buffer, buffer_size - length, "DEV_TYPE=%04X", + cdev->id.dev_type); + if ((buffer_size - length <= 0) || (i >= num_envp)) return -ENOMEM; - envp[i++] = buffer; - buffer += len; - buffer_size -= len; + ++length; + buffer += length; - /* MODALIAS= */ - len = snprint_alias(buffer, buffer_size, "MODALIAS=", id, "") + 1; - if (len > buffer_size || i >= num_envp) - return -ENOMEM; envp[i++] = buffer; - buffer += len; - buffer_size -= len; + length += scnprintf(buffer, buffer_size - length, "DEV_MODEL=%02X", + cdev->id.dev_model); + if ((buffer_size - length <= 0) || (i >= num_envp)) + return -ENOMEM; envp[i] = NULL; @@ -279,11 +251,16 @@ modalias_show (struct device *dev, struct device_attribute *attr, char *buf) { struct ccw_device *cdev = to_ccwdev(dev); struct ccw_device_id *id = &(cdev->id); - int len; - - len = snprint_alias(buf, PAGE_SIZE, "", id, "\n") + 1; + int ret; - return len > PAGE_SIZE ? PAGE_SIZE : len; + ret = sprintf(buf, "ccw:t%04Xm%02X", + id->cu_type, id->cu_model); + if (id->dev_type != 0) + ret += sprintf(buf + ret, "dt%04Xdm%02X\n", + id->dev_type, id->dev_model); + else + ret += sprintf(buf + ret, "dtdm\n"); + return ret; } static ssize_t @@ -579,11 +556,12 @@ get_disc_ccwdev_by_devno(unsigned int devno, unsigned int ssid, struct ccw_device *sibling) { struct device *dev; - struct match_data data; + struct match_data data = { + .devno = devno, + .ssid = ssid, + .sibling = sibling, + }; - data.devno = devno; - data.ssid = ssid; - data.sibling = sibling; dev = bus_find_device(&ccw_bus_type, NULL, &data, match_devno); return dev ? to_ccwdev(dev) : NULL; @@ -857,8 +835,10 @@ io_subchannel_probe (struct subchannel *sch) return -ENOMEM; } atomic_set(&cdev->private->onoff, 0); - cdev->dev.parent = &sch->dev; - cdev->dev.release = ccw_device_release; + cdev->dev = (struct device) { + .parent = &sch->dev, + .release = ccw_device_release, + }; INIT_LIST_HEAD(&cdev->private->kick_work.entry); /* Do first half of device_register. */ device_initialize(&cdev->dev); @@ -997,7 +977,9 @@ ccw_device_console_enable (struct ccw_device *cdev, struct subchannel *sch) int rc; /* Initialize the ccw_device structure. */ - cdev->dev.parent= &sch->dev; + cdev->dev = (struct device) { + .parent = &sch->dev, + }; rc = io_subchannel_recog(cdev, sch); if (rc) return rc; diff --git a/trunk/drivers/s390/cio/device_fsm.c b/trunk/drivers/s390/cio/device_fsm.c index dace46fc32e8..ac6e0c7e43d9 100644 --- a/trunk/drivers/s390/cio/device_fsm.c +++ b/trunk/drivers/s390/cio/device_fsm.c @@ -152,8 +152,7 @@ ccw_device_cancel_halt_clear(struct ccw_device *cdev) if (cdev->private->iretry) { cdev->private->iretry--; ret = cio_halt(sch); - if (ret != -EBUSY) - return (ret == 0) ? -EBUSY : ret; + return (ret == 0) ? -EBUSY : ret; } /* halt io unsuccessful. */ cdev->private->iretry = 255; /* 255 clear retries. */ @@ -232,7 +231,10 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) */ old_lpm = sch->lpm; stsch(sch->schid, &sch->schib); - sch->lpm = sch->schib.pmcw.pam & sch->opm; + sch->lpm = sch->schib.pmcw.pim & + sch->schib.pmcw.pam & + sch->schib.pmcw.pom & + sch->opm; /* Check since device may again have become not operational. */ if (!sch->schib.pmcw.dnv) state = DEV_STATE_NOT_OPER; @@ -264,11 +266,12 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) notify = 1; } /* fill out sense information */ - memset(&cdev->id, 0, sizeof(cdev->id)); - cdev->id.cu_type = cdev->private->senseid.cu_type; - cdev->id.cu_model = cdev->private->senseid.cu_model; - cdev->id.dev_type = cdev->private->senseid.dev_type; - cdev->id.dev_model = cdev->private->senseid.dev_model; + cdev->id = (struct ccw_device_id) { + .cu_type = cdev->private->senseid.cu_type, + .cu_model = cdev->private->senseid.cu_model, + .dev_type = cdev->private->senseid.dev_type, + .dev_model = cdev->private->senseid.dev_model, + }; if (notify) { cdev->private->state = DEV_STATE_OFFLINE; if (same_dev) { @@ -452,8 +455,8 @@ ccw_device_sense_pgid_done(struct ccw_device *cdev, int err) return; } /* Start Path Group verification. */ + sch->vpm = 0; /* Start with no path groups set. */ cdev->private->state = DEV_STATE_VERIFY; - cdev->private->flags.doverify = 0; ccw_device_verify_start(cdev); } @@ -553,19 +556,7 @@ ccw_device_nopath_notify(void *data) void ccw_device_verify_done(struct ccw_device *cdev, int err) { - struct subchannel *sch; - - sch = to_subchannel(cdev->dev.parent); - /* Update schib - pom may have changed. */ - stsch(sch->schid, &sch->schib); - /* Update lpm with verified path mask. */ - sch->lpm = sch->vpm; - /* Repeat path verification? */ - if (cdev->private->flags.doverify) { - cdev->private->flags.doverify = 0; - ccw_device_verify_start(cdev); - return; - } + cdev->private->flags.doverify = 0; switch (err) { case -EOPNOTSUPP: /* path grouping not supported, just set online. */ cdev->private->options.pgroup = 0; @@ -574,10 +565,12 @@ ccw_device_verify_done(struct ccw_device *cdev, int err) /* Deliver fake irb to device driver, if needed. */ if (cdev->private->flags.fake_irb) { memset(&cdev->private->irb, 0, sizeof(struct irb)); - cdev->private->irb.scsw.cc = 1; - cdev->private->irb.scsw.fctl = SCSW_FCTL_START_FUNC; - cdev->private->irb.scsw.actl = SCSW_ACTL_START_PEND; - cdev->private->irb.scsw.stctl = SCSW_STCTL_STATUS_PEND; + cdev->private->irb.scsw = (struct scsw) { + .cc = 1, + .fctl = SCSW_FCTL_START_FUNC, + .actl = SCSW_ACTL_START_PEND, + .stctl = SCSW_STCTL_STATUS_PEND, + }; cdev->private->flags.fake_irb = 0; if (cdev->handler) cdev->handler(cdev, cdev->private->intparm, @@ -623,7 +616,6 @@ ccw_device_online(struct ccw_device *cdev) if (!cdev->private->options.pgroup) { /* Start initial path verification. */ cdev->private->state = DEV_STATE_VERIFY; - cdev->private->flags.doverify = 0; ccw_device_verify_start(cdev); return 0; } @@ -670,6 +662,7 @@ ccw_device_offline(struct ccw_device *cdev) /* Are we doing path grouping? */ if (!cdev->private->options.pgroup) { /* No, set state offline immediately. */ + sch->vpm = 0; ccw_device_done(cdev, DEV_STATE_OFFLINE); return 0; } @@ -778,7 +771,6 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event) stsch(sch->schid, &sch->schib); if (sch->schib.scsw.actl != 0 || - (sch->schib.scsw.stctl & SCSW_STCTL_STATUS_PEND) || (cdev->private->irb.scsw.stctl & SCSW_STCTL_STATUS_PEND)) { /* * No final status yet or final status not yet delivered @@ -790,7 +782,6 @@ ccw_device_online_verify(struct ccw_device *cdev, enum dev_event dev_event) } /* Device is idle, we can do the path verification. */ cdev->private->state = DEV_STATE_VERIFY; - cdev->private->flags.doverify = 0; ccw_device_verify_start(cdev); } @@ -1053,9 +1044,9 @@ ccw_device_wait4io_timeout(struct ccw_device *cdev, enum dev_event dev_event) } static void -ccw_device_delay_verify(struct ccw_device *cdev, enum dev_event dev_event) +ccw_device_wait4io_verify(struct ccw_device *cdev, enum dev_event dev_event) { - /* Start verification after current task finished. */ + /* When the I/O has terminated, we have to start verification. */ cdev->private->flags.doverify = 1; } @@ -1121,7 +1112,10 @@ device_trigger_reprobe(struct subchannel *sch) * The pim, pam, pom values may not be accurate, but they are the best * we have before performing device selection :/ */ - sch->lpm = sch->schib.pmcw.pam & sch->opm; + sch->lpm = sch->schib.pmcw.pim & + sch->schib.pmcw.pam & + sch->schib.pmcw.pom & + sch->opm; /* Re-set some bits in the pmcw that were lost. */ sch->schib.pmcw.isc = 3; sch->schib.pmcw.csense = 1; @@ -1245,7 +1239,7 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, [DEV_EVENT_INTERRUPT] = ccw_device_verify_irq, [DEV_EVENT_TIMEOUT] = ccw_device_onoff_timeout, - [DEV_EVENT_VERIFY] = ccw_device_delay_verify, + [DEV_EVENT_VERIFY] = ccw_device_nop, }, [DEV_STATE_ONLINE] = { [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, @@ -1288,7 +1282,7 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, [DEV_EVENT_INTERRUPT] = ccw_device_wait4io_irq, [DEV_EVENT_TIMEOUT] = ccw_device_wait4io_timeout, - [DEV_EVENT_VERIFY] = ccw_device_delay_verify, + [DEV_EVENT_VERIFY] = ccw_device_wait4io_verify, }, [DEV_STATE_QUIESCE] = { [DEV_EVENT_NOTOPER] = ccw_device_quiesce_done, @@ -1301,7 +1295,7 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { [DEV_EVENT_NOTOPER] = ccw_device_nop, [DEV_EVENT_INTERRUPT] = ccw_device_start_id, [DEV_EVENT_TIMEOUT] = ccw_device_bug, - [DEV_EVENT_VERIFY] = ccw_device_start_id, + [DEV_EVENT_VERIFY] = ccw_device_nop, }, [DEV_STATE_DISCONNECTED_SENSE_ID] = { [DEV_EVENT_NOTOPER] = ccw_device_recog_notoper, diff --git a/trunk/drivers/s390/cio/device_ops.c b/trunk/drivers/s390/cio/device_ops.c index 93a897eebfff..a60124264bee 100644 --- a/trunk/drivers/s390/cio/device_ops.c +++ b/trunk/drivers/s390/cio/device_ops.c @@ -96,12 +96,6 @@ ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, ret = cio_set_options (sch, flags); if (ret) return ret; - /* Adjust requested path mask to excluded varied off paths. */ - if (lpm) { - lpm &= sch->opm; - if (lpm == 0) - return -EACCES; - } ret = cio_start_key (sch, cpa, lpm, key); if (ret == 0) cdev->private->intparm = intparm; @@ -256,7 +250,7 @@ ccw_device_get_path_mask(struct ccw_device *cdev) if (!sch) return 0; else - return sch->lpm; + return sch->vpm; } static void @@ -269,9 +263,6 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb) /* Abuse intparm for error reporting. */ if (IS_ERR(irb)) cdev->private->intparm = -EIO; - else if (irb->scsw.cc == 1) - /* Retry for deferred condition code. */ - cdev->private->intparm = -EAGAIN; else if ((irb->scsw.dstat != (DEV_STAT_CHN_END|DEV_STAT_DEV_END)) || (irb->scsw.cstat != 0)) { @@ -310,7 +301,7 @@ __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, _ sch = to_subchannel(cdev->dev.parent); do { ret = cio_start (sch, ccw, lpm); - if (ret == -EBUSY) { + if ((ret == -EBUSY) || (ret == -EACCES)) { /* Try again later. */ spin_unlock_irq(&sch->lock); msleep(10); @@ -439,13 +430,6 @@ read_conf_data_lpm (struct ccw_device *cdev, void **buffer, int *length, __u8 lp if (!ciw || ciw->cmd == 0) return -EOPNOTSUPP; - /* Adjust requested path mask to excluded varied off paths. */ - if (lpm) { - lpm &= sch->opm; - if (lpm == 0) - return -EACCES; - } - rcd_ccw = kzalloc(sizeof(struct ccw1), GFP_KERNEL | GFP_DMA); if (!rcd_ccw) return -ENOMEM; diff --git a/trunk/drivers/s390/cio/device_pgid.c b/trunk/drivers/s390/cio/device_pgid.c index 8ca2d078848c..32610fd8868e 100644 --- a/trunk/drivers/s390/cio/device_pgid.c +++ b/trunk/drivers/s390/cio/device_pgid.c @@ -23,21 +23,6 @@ #include "device.h" #include "ioasm.h" -/* - * Helper function called from interrupt context to decide whether an - * operation should be tried again. - */ -static int __ccw_device_should_retry(struct scsw *scsw) -{ - /* CC is only valid if start function bit is set. */ - if ((scsw->fctl & SCSW_FCTL_START_FUNC) && scsw->cc == 1) - return 1; - /* No more activity. For sense and set PGID we stubbornly try again. */ - if (!scsw->actl) - return 1; - return 0; -} - /* * Start Sense Path Group ID helper function. Used in ccw_device_recog * and ccw_device_sense_pgid. @@ -170,10 +155,10 @@ ccw_device_sense_pgid_irq(struct ccw_device *cdev, enum dev_event dev_event) int ret; irb = (struct irb *) __LC_IRB; - + /* Retry sense pgid for cc=1. */ if (irb->scsw.stctl == (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { - if (__ccw_device_should_retry(&irb->scsw)) { + if (irb->scsw.cc == 1) { ret = __ccw_device_sense_pgid_start(cdev); if (ret && ret != -EBUSY) ccw_device_sense_pgid_done(cdev, ret); @@ -245,17 +230,18 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func) memset(&cdev->private->irb, 0, sizeof(struct irb)); /* Try multiple times. */ - ret = -EACCES; + ret = -ENODEV; if (cdev->private->iretry > 0) { cdev->private->iretry--; ret = cio_start (sch, cdev->private->iccws, cdev->private->imask); - /* We expect an interrupt in case of success or busy - * indication. */ - if ((ret == 0) || (ret == -EBUSY)) + /* ret is 0, -EBUSY, -EACCES or -ENODEV */ + if ((ret != -EACCES) && (ret != -ENODEV)) return ret; } - /* PGID command failed on this path. */ + /* PGID command failed on this path. Switch it off. */ + sch->lpm &= ~cdev->private->imask; + sch->vpm &= ~cdev->private->imask; CIO_MSG_EVENT(2, "SPID - Device %04x on Subchannel " "0.%x.%04x, lpm %02X, became 'not operational'\n", cdev->private->devno, sch->schid.ssid, @@ -285,17 +271,18 @@ static int __ccw_device_do_nop(struct ccw_device *cdev) memset(&cdev->private->irb, 0, sizeof(struct irb)); /* Try multiple times. */ - ret = -EACCES; + ret = -ENODEV; if (cdev->private->iretry > 0) { cdev->private->iretry--; ret = cio_start (sch, cdev->private->iccws, cdev->private->imask); - /* We expect an interrupt in case of success or busy - * indication. */ - if ((ret == 0) || (ret == -EBUSY)) + /* ret is 0, -EBUSY, -EACCES or -ENODEV */ + if ((ret != -EACCES) && (ret != -ENODEV)) return ret; } - /* nop command failed on this path. */ + /* nop command failed on this path. Switch it off. */ + sch->lpm &= ~cdev->private->imask; + sch->vpm &= ~cdev->private->imask; CIO_MSG_EVENT(2, "NOP - Device %04x on Subchannel " "0.%x.%04x, lpm %02X, became 'not operational'\n", cdev->private->devno, sch->schid.ssid, @@ -370,32 +357,27 @@ static void __ccw_device_verify_start(struct ccw_device *cdev) { struct subchannel *sch; - __u8 func; + __u8 imask, func; int ret; sch = to_subchannel(cdev->dev.parent); - /* Repeat for all paths. */ - for (; cdev->private->imask; cdev->private->imask >>= 1, - cdev->private->iretry = 5) { - if ((cdev->private->imask & sch->schib.pmcw.pam) == 0) - /* Path not available, try next. */ - continue; + while (sch->vpm != sch->lpm) { + /* Find first unequal bit in vpm vs. lpm */ + for (imask = 0x80; imask != 0; imask >>= 1) + if ((sch->vpm & imask) != (sch->lpm & imask)) + break; + cdev->private->imask = imask; if (cdev->private->options.pgroup) { - if (sch->opm & cdev->private->imask) - func = SPID_FUNC_ESTABLISH; - else - func = SPID_FUNC_RESIGN; + func = (sch->vpm & imask) ? + SPID_FUNC_RESIGN : SPID_FUNC_ESTABLISH; ret = __ccw_device_do_pgid(cdev, func); } else ret = __ccw_device_do_nop(cdev); - /* We expect an interrupt in case of success or busy - * indication. */ if (ret == 0 || ret == -EBUSY) return; - /* Permanent path failure, try next. */ + cdev->private->iretry = 5; } - /* Done with all paths. */ - ccw_device_verify_done(cdev, (sch->vpm != 0) ? 0 : -ENODEV); + ccw_device_verify_done(cdev, (sch->lpm != 0) ? 0 : -ENODEV); } /* @@ -409,10 +391,10 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event) int ret; irb = (struct irb *) __LC_IRB; - + /* Retry set pgid for cc=1. */ if (irb->scsw.stctl == (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { - if (__ccw_device_should_retry(&irb->scsw)) + if (irb->scsw.cc == 1) __ccw_device_verify_start(cdev); return; } @@ -424,14 +406,14 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event) else ret = __ccw_device_check_nop(cdev); memset(&cdev->private->irb, 0, sizeof(struct irb)); - switch (ret) { /* 0, -ETIME, -EAGAIN, -EOPNOTSUPP or -EACCES */ case 0: - /* Path verification ccw finished successfully, update lpm. */ - sch->vpm |= sch->opm & cdev->private->imask; - /* Go on with next path. */ - cdev->private->imask >>= 1; + /* Establish or Resign Path Group done. Update vpm. */ + if ((sch->lpm & cdev->private->imask) != 0) + sch->vpm |= cdev->private->imask; + else + sch->vpm &= ~cdev->private->imask; cdev->private->iretry = 5; __ccw_device_verify_start(cdev); break; @@ -444,10 +426,6 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event) cdev->private->options.pgroup = 0; else cdev->private->flags.pgid_single = 1; - /* Retry */ - sch->vpm = 0; - cdev->private->imask = 0x80; - cdev->private->iretry = 5; /* fall through. */ case -EAGAIN: /* Try again. */ __ccw_device_verify_start(cdev); @@ -456,7 +434,8 @@ ccw_device_verify_irq(struct ccw_device *cdev, enum dev_event dev_event) ccw_device_verify_done(cdev, -ETIME); break; case -EACCES: /* channel is not operational. */ - cdev->private->imask >>= 1; + sch->lpm &= ~cdev->private->imask; + sch->vpm &= ~cdev->private->imask; cdev->private->iretry = 5; __ccw_device_verify_start(cdev); break; @@ -469,17 +448,19 @@ ccw_device_verify_start(struct ccw_device *cdev) struct subchannel *sch = to_subchannel(cdev->dev.parent); cdev->private->flags.pgid_single = 0; - cdev->private->imask = 0x80; cdev->private->iretry = 5; - - /* Start with empty vpm. */ - sch->vpm = 0; - - /* Get current pam. */ + /* + * Update sch->lpm with current values to catch paths becoming + * available again. + */ if (stsch(sch->schid, &sch->schib)) { ccw_device_verify_done(cdev, -ENODEV); return; } + sch->lpm = sch->schib.pmcw.pim & + sch->schib.pmcw.pam & + sch->schib.pmcw.pom & + sch->opm; __ccw_device_verify_start(cdev); } @@ -513,10 +494,10 @@ ccw_device_disband_irq(struct ccw_device *cdev, enum dev_event dev_event) int ret; irb = (struct irb *) __LC_IRB; - + /* Retry set pgid for cc=1. */ if (irb->scsw.stctl == (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) { - if (__ccw_device_should_retry(&irb->scsw)) + if (irb->scsw.cc == 1) __ccw_device_disband_start(cdev); return; } @@ -528,6 +509,7 @@ ccw_device_disband_irq(struct ccw_device *cdev, enum dev_event dev_event) switch (ret) { /* 0, -ETIME, -EAGAIN, -EOPNOTSUPP or -EACCES */ case 0: /* disband successful. */ + sch->vpm = 0; ccw_device_disband_done(cdev, ret); break; case -EOPNOTSUPP: diff --git a/trunk/drivers/s390/cio/qdio.c b/trunk/drivers/s390/cio/qdio.c index cde822d8b5c8..7c93a8798d23 100644 --- a/trunk/drivers/s390/cio/qdio.c +++ b/trunk/drivers/s390/cio/qdio.c @@ -115,7 +115,7 @@ qdio_min(int a,int b) static inline __u64 qdio_get_micros(void) { - return (get_clock() >> 12); /* time>>12 is microseconds */ + return (get_clock() >> 10); /* time>>12 is microseconds */ } /* @@ -1129,7 +1129,7 @@ qdio_get_inbound_buffer_frontier(struct qdio_q *q) #ifdef QDIO_USE_PROCESSING_STATE if (last_position>=0) - set_slsb(q, &last_position, SLSB_P_INPUT_PROCESSING, &count); + set_slsb(q, &last_position, SLSB_P_INPUT_NOT_INIT, &count); #endif /* QDIO_USE_PROCESSING_STATE */ QDIO_DBF_HEX4(0,trace,&q->first_to_check,sizeof(int)); diff --git a/trunk/drivers/s390/cio/qdio.h b/trunk/drivers/s390/cio/qdio.h index 124569362f02..ceb3ab31ee08 100644 --- a/trunk/drivers/s390/cio/qdio.h +++ b/trunk/drivers/s390/cio/qdio.h @@ -191,49 +191,49 @@ enum qdio_irq_states { #if QDIO_VERBOSE_LEVEL>8 #define QDIO_PRINT_STUPID(x...) printk( KERN_DEBUG QDIO_PRINTK_HEADER x) #else -#define QDIO_PRINT_STUPID(x...) do { } while (0) +#define QDIO_PRINT_STUPID(x...) #endif #if QDIO_VERBOSE_LEVEL>7 #define QDIO_PRINT_ALL(x...) printk( QDIO_PRINTK_HEADER x) #else -#define QDIO_PRINT_ALL(x...) do { } while (0) +#define QDIO_PRINT_ALL(x...) #endif #if QDIO_VERBOSE_LEVEL>6 #define QDIO_PRINT_INFO(x...) printk( QDIO_PRINTK_HEADER x) #else -#define QDIO_PRINT_INFO(x...) do { } while (0) +#define QDIO_PRINT_INFO(x...) #endif #if QDIO_VERBOSE_LEVEL>5 #define QDIO_PRINT_WARN(x...) printk( QDIO_PRINTK_HEADER x) #else -#define QDIO_PRINT_WARN(x...) do { } while (0) +#define QDIO_PRINT_WARN(x...) #endif #if QDIO_VERBOSE_LEVEL>4 #define QDIO_PRINT_ERR(x...) printk( QDIO_PRINTK_HEADER x) #else -#define QDIO_PRINT_ERR(x...) do { } while (0) +#define QDIO_PRINT_ERR(x...) #endif #if QDIO_VERBOSE_LEVEL>3 #define QDIO_PRINT_CRIT(x...) printk( QDIO_PRINTK_HEADER x) #else -#define QDIO_PRINT_CRIT(x...) do { } while (0) +#define QDIO_PRINT_CRIT(x...) #endif #if QDIO_VERBOSE_LEVEL>2 #define QDIO_PRINT_ALERT(x...) printk( QDIO_PRINTK_HEADER x) #else -#define QDIO_PRINT_ALERT(x...) do { } while (0) +#define QDIO_PRINT_ALERT(x...) #endif #if QDIO_VERBOSE_LEVEL>1 #define QDIO_PRINT_EMERG(x...) printk( QDIO_PRINTK_HEADER x) #else -#define QDIO_PRINT_EMERG(x...) do { } while (0) +#define QDIO_PRINT_EMERG(x...) #endif #define HEXDUMP16(importance,header,ptr) \ diff --git a/trunk/drivers/s390/crypto/Makefile b/trunk/drivers/s390/crypto/Makefile index f0a12d2eb780..15edebbead7f 100644 --- a/trunk/drivers/s390/crypto/Makefile +++ b/trunk/drivers/s390/crypto/Makefile @@ -2,16 +2,5 @@ # S/390 crypto devices # -ifdef CONFIG_ZCRYPT_MONOLITHIC - -z90crypt-objs := zcrypt_mono.o ap_bus.o zcrypt_api.o \ - zcrypt_pcica.o zcrypt_pcicc.o zcrypt_pcixcc.o zcrypt_cex2a.o -obj-$(CONFIG_ZCRYPT) += z90crypt.o - -else - -ap-objs := ap_bus.o -obj-$(CONFIG_ZCRYPT) += ap.o zcrypt_api.o zcrypt_pcicc.o zcrypt_pcixcc.o -obj-$(CONFIG_ZCRYPT) += zcrypt_pcica.o zcrypt_cex2a.o - -endif +z90crypt-objs := z90main.o z90hardware.o +obj-$(CONFIG_Z90CRYPT) += z90crypt.o diff --git a/trunk/drivers/s390/crypto/ap_bus.c b/trunk/drivers/s390/crypto/ap_bus.c deleted file mode 100644 index 6ed0985c0c91..000000000000 --- a/trunk/drivers/s390/crypto/ap_bus.c +++ /dev/null @@ -1,1221 +0,0 @@ -/* - * linux/drivers/s390/crypto/ap_bus.c - * - * Copyright (C) 2006 IBM Corporation - * Author(s): Cornelia Huck - * Martin Schwidefsky - * Ralph Wuerthner - * - * Adjunct processor bus. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ap_bus.h" - -/* Some prototypes. */ -static void ap_scan_bus(void *); -static void ap_poll_all(unsigned long); -static void ap_poll_timeout(unsigned long); -static int ap_poll_thread_start(void); -static void ap_poll_thread_stop(void); - -/** - * Module description. - */ -MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("Adjunct Processor Bus driver, " - "Copyright 2006 IBM Corporation"); -MODULE_LICENSE("GPL"); - -/** - * Module parameter - */ -int ap_domain_index = -1; /* Adjunct Processor Domain Index */ -module_param_named(domain, ap_domain_index, int, 0000); -MODULE_PARM_DESC(domain, "domain index for ap devices"); -EXPORT_SYMBOL(ap_domain_index); - -static int ap_thread_flag = 1; -module_param_named(poll_thread, ap_thread_flag, int, 0000); -MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 1 (on)."); - -static struct device *ap_root_device = NULL; - -/** - * Workqueue & timer for bus rescan. - */ -static struct workqueue_struct *ap_work_queue; -static struct timer_list ap_config_timer; -static int ap_config_time = AP_CONFIG_TIME; -static DECLARE_WORK(ap_config_work, ap_scan_bus, NULL); - -/** - * Tasklet & timer for AP request polling. - */ -static struct timer_list ap_poll_timer = TIMER_INITIALIZER(ap_poll_timeout,0,0); -static DECLARE_TASKLET(ap_tasklet, ap_poll_all, 0); -static atomic_t ap_poll_requests = ATOMIC_INIT(0); -static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait); -static struct task_struct *ap_poll_kthread = NULL; -static DEFINE_MUTEX(ap_poll_thread_mutex); - -/** - * Test if ap instructions are available. - * - * Returns 0 if the ap instructions are installed. - */ -static inline int ap_instructions_available(void) -{ - register unsigned long reg0 asm ("0") = AP_MKQID(0,0); - register unsigned long reg1 asm ("1") = -ENODEV; - register unsigned long reg2 asm ("2") = 0UL; - - asm volatile( - " .long 0xb2af0000\n" /* PQAP(TAPQ) */ - "0: la %1,0\n" - "1:\n" - EX_TABLE(0b, 1b) - : "+d" (reg0), "+d" (reg1), "+d" (reg2) : : "cc" ); - return reg1; -} - -/** - * Test adjunct processor queue. - * @qid: the ap queue number - * @queue_depth: pointer to queue depth value - * @device_type: pointer to device type value - * - * Returns ap queue status structure. - */ -static inline struct ap_queue_status -ap_test_queue(ap_qid_t qid, int *queue_depth, int *device_type) -{ - register unsigned long reg0 asm ("0") = qid; - register struct ap_queue_status reg1 asm ("1"); - register unsigned long reg2 asm ("2") = 0UL; - - asm volatile(".long 0xb2af0000" /* PQAP(TAPQ) */ - : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc"); - *device_type = (int) (reg2 >> 24); - *queue_depth = (int) (reg2 & 0xff); - return reg1; -} - -/** - * Reset adjunct processor queue. - * @qid: the ap queue number - * - * Returns ap queue status structure. - */ -static inline struct ap_queue_status ap_reset_queue(ap_qid_t qid) -{ - register unsigned long reg0 asm ("0") = qid | 0x01000000UL; - register struct ap_queue_status reg1 asm ("1"); - register unsigned long reg2 asm ("2") = 0UL; - - asm volatile( - ".long 0xb2af0000" /* PQAP(RAPQ) */ - : "+d" (reg0), "=d" (reg1), "+d" (reg2) : : "cc"); - return reg1; -} - -/** - * Send message to adjunct processor queue. - * @qid: the ap queue number - * @psmid: the program supplied message identifier - * @msg: the message text - * @length: the message length - * - * Returns ap queue status structure. - * - * Condition code 1 on NQAP can't happen because the L bit is 1. - * - * Condition code 2 on NQAP also means the send is incomplete, - * because a segment boundary was reached. The NQAP is repeated. - */ -static inline struct ap_queue_status -__ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length) -{ - typedef struct { char _[length]; } msgblock; - register unsigned long reg0 asm ("0") = qid | 0x40000000UL; - register struct ap_queue_status reg1 asm ("1"); - register unsigned long reg2 asm ("2") = (unsigned long) msg; - register unsigned long reg3 asm ("3") = (unsigned long) length; - register unsigned long reg4 asm ("4") = (unsigned int) (psmid >> 32); - register unsigned long reg5 asm ("5") = (unsigned int) psmid; - - asm volatile ( - "0: .long 0xb2ad0042\n" /* DQAP */ - " brc 2,0b" - : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3) - : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg) - : "cc" ); - return reg1; -} - -int ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length) -{ - struct ap_queue_status status; - - status = __ap_send(qid, psmid, msg, length); - switch (status.response_code) { - case AP_RESPONSE_NORMAL: - return 0; - case AP_RESPONSE_Q_FULL: - return -EBUSY; - default: /* Device is gone. */ - return -ENODEV; - } -} -EXPORT_SYMBOL(ap_send); - -/* - * Receive message from adjunct processor queue. - * @qid: the ap queue number - * @psmid: pointer to program supplied message identifier - * @msg: the message text - * @length: the message length - * - * Returns ap queue status structure. - * - * Condition code 1 on DQAP means the receive has taken place - * but only partially. The response is incomplete, hence the - * DQAP is repeated. - * - * Condition code 2 on DQAP also means the receive is incomplete, - * this time because a segment boundary was reached. Again, the - * DQAP is repeated. - * - * Note that gpr2 is used by the DQAP instruction to keep track of - * any 'residual' length, in case the instruction gets interrupted. - * Hence it gets zeroed before the instruction. - */ -static inline struct ap_queue_status -__ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length) -{ - typedef struct { char _[length]; } msgblock; - register unsigned long reg0 asm("0") = qid | 0x80000000UL; - register struct ap_queue_status reg1 asm ("1"); - register unsigned long reg2 asm("2") = 0UL; - register unsigned long reg4 asm("4") = (unsigned long) msg; - register unsigned long reg5 asm("5") = (unsigned long) length; - register unsigned long reg6 asm("6") = 0UL; - register unsigned long reg7 asm("7") = 0UL; - - - asm volatile( - "0: .long 0xb2ae0064\n" - " brc 6,0b\n" - : "+d" (reg0), "=d" (reg1), "+d" (reg2), - "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7), - "=m" (*(msgblock *) msg) : : "cc" ); - *psmid = (((unsigned long long) reg6) << 32) + reg7; - return reg1; -} - -int ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length) -{ - struct ap_queue_status status; - - status = __ap_recv(qid, psmid, msg, length); - switch (status.response_code) { - case AP_RESPONSE_NORMAL: - return 0; - case AP_RESPONSE_NO_PENDING_REPLY: - if (status.queue_empty) - return -ENOENT; - return -EBUSY; - default: - return -ENODEV; - } -} -EXPORT_SYMBOL(ap_recv); - -/** - * Check if an AP queue is available. The test is repeated for - * AP_MAX_RESET times. - * @qid: the ap queue number - * @queue_depth: pointer to queue depth value - * @device_type: pointer to device type value - */ -static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type) -{ - struct ap_queue_status status; - int t_depth, t_device_type, rc, i; - - rc = -EBUSY; - for (i = 0; i < AP_MAX_RESET; i++) { - status = ap_test_queue(qid, &t_depth, &t_device_type); - switch (status.response_code) { - case AP_RESPONSE_NORMAL: - *queue_depth = t_depth + 1; - *device_type = t_device_type; - rc = 0; - break; - case AP_RESPONSE_Q_NOT_AVAIL: - rc = -ENODEV; - break; - case AP_RESPONSE_RESET_IN_PROGRESS: - break; - case AP_RESPONSE_DECONFIGURED: - rc = -ENODEV; - break; - case AP_RESPONSE_CHECKSTOPPED: - rc = -ENODEV; - break; - case AP_RESPONSE_BUSY: - break; - default: - BUG(); - } - if (rc != -EBUSY) - break; - if (i < AP_MAX_RESET - 1) - udelay(5); - } - return rc; -} - -/** - * Reset an AP queue and wait for it to become available again. - * @qid: the ap queue number - */ -static int ap_init_queue(ap_qid_t qid) -{ - struct ap_queue_status status; - int rc, dummy, i; - - rc = -ENODEV; - status = ap_reset_queue(qid); - for (i = 0; i < AP_MAX_RESET; i++) { - switch (status.response_code) { - case AP_RESPONSE_NORMAL: - if (status.queue_empty) - rc = 0; - break; - case AP_RESPONSE_Q_NOT_AVAIL: - case AP_RESPONSE_DECONFIGURED: - case AP_RESPONSE_CHECKSTOPPED: - i = AP_MAX_RESET; /* return with -ENODEV */ - break; - case AP_RESPONSE_RESET_IN_PROGRESS: - case AP_RESPONSE_BUSY: - default: - break; - } - if (rc != -ENODEV) - break; - if (i < AP_MAX_RESET - 1) { - udelay(5); - status = ap_test_queue(qid, &dummy, &dummy); - } - } - return rc; -} - -/** - * AP device related attributes. - */ -static ssize_t ap_hwtype_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ap_device *ap_dev = to_ap_dev(dev); - return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->device_type); -} -static DEVICE_ATTR(hwtype, 0444, ap_hwtype_show, NULL); - -static ssize_t ap_depth_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct ap_device *ap_dev = to_ap_dev(dev); - return snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->queue_depth); -} -static DEVICE_ATTR(depth, 0444, ap_depth_show, NULL); - -static ssize_t ap_request_count_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ap_device *ap_dev = to_ap_dev(dev); - int rc; - - spin_lock_bh(&ap_dev->lock); - rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->total_request_count); - spin_unlock_bh(&ap_dev->lock); - return rc; -} - -static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL); - -static ssize_t ap_modalias_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "ap:t%02X", to_ap_dev(dev)->device_type); -} - -static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL); - -static struct attribute *ap_dev_attrs[] = { - &dev_attr_hwtype.attr, - &dev_attr_depth.attr, - &dev_attr_request_count.attr, - &dev_attr_modalias.attr, - NULL -}; -static struct attribute_group ap_dev_attr_group = { - .attrs = ap_dev_attrs -}; - -/** - * AP bus driver registration/unregistration. - */ -static int ap_bus_match(struct device *dev, struct device_driver *drv) -{ - struct ap_device *ap_dev = to_ap_dev(dev); - struct ap_driver *ap_drv = to_ap_drv(drv); - struct ap_device_id *id; - - /** - * Compare device type of the device with the list of - * supported types of the device_driver. - */ - for (id = ap_drv->ids; id->match_flags; id++) { - if ((id->match_flags & AP_DEVICE_ID_MATCH_DEVICE_TYPE) && - (id->dev_type != ap_dev->device_type)) - continue; - return 1; - } - return 0; -} - -/** - * uevent function for AP devices. It sets up a single environment - * variable DEV_TYPE which contains the hardware device type. - */ -static int ap_uevent (struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) -{ - struct ap_device *ap_dev = to_ap_dev(dev); - int length; - - if (!ap_dev) - return -ENODEV; - - /* Set up DEV_TYPE environment variable. */ - envp[0] = buffer; - length = scnprintf(buffer, buffer_size, "DEV_TYPE=%04X", - ap_dev->device_type); - if (buffer_size - length <= 0) - return -ENOMEM; - envp[1] = 0; - return 0; -} - -static struct bus_type ap_bus_type = { - .name = "ap", - .match = &ap_bus_match, - .uevent = &ap_uevent, -}; - -static int ap_device_probe(struct device *dev) -{ - struct ap_device *ap_dev = to_ap_dev(dev); - struct ap_driver *ap_drv = to_ap_drv(dev->driver); - int rc; - - ap_dev->drv = ap_drv; - rc = ap_drv->probe ? ap_drv->probe(ap_dev) : -ENODEV; - if (rc) - ap_dev->unregistered = 1; - return rc; -} - -/** - * Flush all requests from the request/pending queue of an AP device. - * @ap_dev: pointer to the AP device. - */ -static inline void __ap_flush_queue(struct ap_device *ap_dev) -{ - struct ap_message *ap_msg, *next; - - list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) { - list_del_init(&ap_msg->list); - ap_dev->pendingq_count--; - ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); - } - list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) { - list_del_init(&ap_msg->list); - ap_dev->requestq_count--; - ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); - } -} - -void ap_flush_queue(struct ap_device *ap_dev) -{ - spin_lock_bh(&ap_dev->lock); - __ap_flush_queue(ap_dev); - spin_unlock_bh(&ap_dev->lock); -} -EXPORT_SYMBOL(ap_flush_queue); - -static int ap_device_remove(struct device *dev) -{ - struct ap_device *ap_dev = to_ap_dev(dev); - struct ap_driver *ap_drv = ap_dev->drv; - - spin_lock_bh(&ap_dev->lock); - __ap_flush_queue(ap_dev); - /** - * set ->unregistered to 1 while holding the lock. This prevents - * new messages to be put on the queue from now on. - */ - ap_dev->unregistered = 1; - spin_unlock_bh(&ap_dev->lock); - if (ap_drv->remove) - ap_drv->remove(ap_dev); - return 0; -} - -int ap_driver_register(struct ap_driver *ap_drv, struct module *owner, - char *name) -{ - struct device_driver *drv = &ap_drv->driver; - - drv->bus = &ap_bus_type; - drv->probe = ap_device_probe; - drv->remove = ap_device_remove; - drv->owner = owner; - drv->name = name; - return driver_register(drv); -} -EXPORT_SYMBOL(ap_driver_register); - -void ap_driver_unregister(struct ap_driver *ap_drv) -{ - driver_unregister(&ap_drv->driver); -} -EXPORT_SYMBOL(ap_driver_unregister); - -/** - * AP bus attributes. - */ -static ssize_t ap_domain_show(struct bus_type *bus, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", ap_domain_index); -} - -static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL); - -static ssize_t ap_config_time_show(struct bus_type *bus, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time); -} - -static ssize_t ap_config_time_store(struct bus_type *bus, - const char *buf, size_t count) -{ - int time; - - if (sscanf(buf, "%d\n", &time) != 1 || time < 5 || time > 120) - return -EINVAL; - ap_config_time = time; - if (!timer_pending(&ap_config_timer) || - !mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ)) { - ap_config_timer.expires = jiffies + ap_config_time * HZ; - add_timer(&ap_config_timer); - } - return count; -} - -static BUS_ATTR(config_time, 0644, ap_config_time_show, ap_config_time_store); - -static ssize_t ap_poll_thread_show(struct bus_type *bus, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", ap_poll_kthread ? 1 : 0); -} - -static ssize_t ap_poll_thread_store(struct bus_type *bus, - const char *buf, size_t count) -{ - int flag, rc; - - if (sscanf(buf, "%d\n", &flag) != 1) - return -EINVAL; - if (flag) { - rc = ap_poll_thread_start(); - if (rc) - return rc; - } - else - ap_poll_thread_stop(); - return count; -} - -static BUS_ATTR(poll_thread, 0644, ap_poll_thread_show, ap_poll_thread_store); - -static struct bus_attribute *const ap_bus_attrs[] = { - &bus_attr_ap_domain, - &bus_attr_config_time, - &bus_attr_poll_thread, - NULL -}; - -/** - * Pick one of the 16 ap domains. - */ -static inline int ap_select_domain(void) -{ - int queue_depth, device_type, count, max_count, best_domain; - int rc, i, j; - - /** - * We want to use a single domain. Either the one specified with - * the "domain=" parameter or the domain with the maximum number - * of devices. - */ - if (ap_domain_index >= 0 && ap_domain_index < AP_DOMAINS) - /* Domain has already been selected. */ - return 0; - best_domain = -1; - max_count = 0; - for (i = 0; i < AP_DOMAINS; i++) { - count = 0; - for (j = 0; j < AP_DEVICES; j++) { - ap_qid_t qid = AP_MKQID(j, i); - rc = ap_query_queue(qid, &queue_depth, &device_type); - if (rc) - continue; - count++; - } - if (count > max_count) { - max_count = count; - best_domain = i; - } - } - if (best_domain >= 0){ - ap_domain_index = best_domain; - return 0; - } - return -ENODEV; -} - -/** - * Find the device type if query queue returned a device type of 0. - * @ap_dev: pointer to the AP device. - */ -static int ap_probe_device_type(struct ap_device *ap_dev) -{ - static unsigned char msg[] = { - 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0x43,0x43,0x41,0x2d,0x41,0x50, - 0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01, - 0x00,0x00,0x00,0x00,0x50,0x4b,0x00,0x00, - 0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x54,0x32,0x01,0x00,0xa0,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xb8,0x05,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00, - 0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20, - 0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53, - 0x2d,0x31,0x2e,0x32,0x37,0x00,0x11,0x22, - 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00, - 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88, - 0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66, - 0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44, - 0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22, - 0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00, - 0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77, - 0x88,0x1e,0x00,0x00,0x57,0x00,0x00,0x00, - 0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00, - 0x03,0x02,0x00,0x00,0x40,0x01,0x00,0x01, - 0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c, - 0xf6,0xd2,0x7b,0x58,0x4b,0xf9,0x28,0x68, - 0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66, - 0x63,0x42,0xef,0xf8,0xfd,0xa4,0xf8,0xb0, - 0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8, - 0x53,0x8c,0x6f,0x4e,0x72,0x8f,0x6c,0x04, - 0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57, - 0xf7,0xdd,0xfd,0x4f,0x11,0x36,0x95,0x5d, - }; - struct ap_queue_status status; - unsigned long long psmid; - char *reply; - int rc, i; - - reply = (void *) get_zeroed_page(GFP_KERNEL); - if (!reply) { - rc = -ENOMEM; - goto out; - } - - status = __ap_send(ap_dev->qid, 0x0102030405060708ULL, - msg, sizeof(msg)); - if (status.response_code != AP_RESPONSE_NORMAL) { - rc = -ENODEV; - goto out_free; - } - - /* Wait for the test message to complete. */ - for (i = 0; i < 6; i++) { - mdelay(300); - status = __ap_recv(ap_dev->qid, &psmid, reply, 4096); - if (status.response_code == AP_RESPONSE_NORMAL && - psmid == 0x0102030405060708ULL) - break; - } - if (i < 6) { - /* Got an answer. */ - if (reply[0] == 0x00 && reply[1] == 0x86) - ap_dev->device_type = AP_DEVICE_TYPE_PCICC; - else - ap_dev->device_type = AP_DEVICE_TYPE_PCICA; - rc = 0; - } else - rc = -ENODEV; - -out_free: - free_page((unsigned long) reply); -out: - return rc; -} - -/** - * Scan the ap bus for new devices. - */ -static int __ap_scan_bus(struct device *dev, void *data) -{ - return to_ap_dev(dev)->qid == (ap_qid_t)(unsigned long) data; -} - -static void ap_device_release(struct device *dev) -{ - struct ap_device *ap_dev = to_ap_dev(dev); - - kfree(ap_dev); -} - -static void ap_scan_bus(void *data) -{ - struct ap_device *ap_dev; - struct device *dev; - ap_qid_t qid; - int queue_depth, device_type; - int rc, i; - - if (ap_select_domain() != 0) - return; - for (i = 0; i < AP_DEVICES; i++) { - qid = AP_MKQID(i, ap_domain_index); - dev = bus_find_device(&ap_bus_type, NULL, - (void *)(unsigned long)qid, - __ap_scan_bus); - if (dev) { - put_device(dev); - continue; - } - rc = ap_query_queue(qid, &queue_depth, &device_type); - if (rc) - continue; - rc = ap_init_queue(qid); - if (rc) - continue; - ap_dev = kzalloc(sizeof(*ap_dev), GFP_KERNEL); - if (!ap_dev) - break; - ap_dev->qid = qid; - ap_dev->queue_depth = queue_depth; - spin_lock_init(&ap_dev->lock); - INIT_LIST_HEAD(&ap_dev->pendingq); - INIT_LIST_HEAD(&ap_dev->requestq); - if (device_type == 0) - ap_probe_device_type(ap_dev); - else - ap_dev->device_type = device_type; - - ap_dev->device.bus = &ap_bus_type; - ap_dev->device.parent = ap_root_device; - snprintf(ap_dev->device.bus_id, BUS_ID_SIZE, "card%02x", - AP_QID_DEVICE(ap_dev->qid)); - ap_dev->device.release = ap_device_release; - rc = device_register(&ap_dev->device); - if (rc) { - kfree(ap_dev); - continue; - } - /* Add device attributes. */ - rc = sysfs_create_group(&ap_dev->device.kobj, - &ap_dev_attr_group); - if (rc) - device_unregister(&ap_dev->device); - } -} - -static void -ap_config_timeout(unsigned long ptr) -{ - queue_work(ap_work_queue, &ap_config_work); - ap_config_timer.expires = jiffies + ap_config_time * HZ; - add_timer(&ap_config_timer); -} - -/** - * Set up the timer to run the poll tasklet - */ -static inline void ap_schedule_poll_timer(void) -{ - if (timer_pending(&ap_poll_timer)) - return; - mod_timer(&ap_poll_timer, jiffies + AP_POLL_TIME); -} - -/** - * Receive pending reply messages from an AP device. - * @ap_dev: pointer to the AP device - * @flags: pointer to control flags, bit 2^0 is set if another poll is - * required, bit 2^1 is set if the poll timer needs to get armed - * Returns 0 if the device is still present, -ENODEV if not. - */ -static inline int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags) -{ - struct ap_queue_status status; - struct ap_message *ap_msg; - - if (ap_dev->queue_count <= 0) - return 0; - status = __ap_recv(ap_dev->qid, &ap_dev->reply->psmid, - ap_dev->reply->message, ap_dev->reply->length); - switch (status.response_code) { - case AP_RESPONSE_NORMAL: - atomic_dec(&ap_poll_requests); - ap_dev->queue_count--; - list_for_each_entry(ap_msg, &ap_dev->pendingq, list) { - if (ap_msg->psmid != ap_dev->reply->psmid) - continue; - list_del_init(&ap_msg->list); - ap_dev->pendingq_count--; - ap_dev->drv->receive(ap_dev, ap_msg, ap_dev->reply); - break; - } - if (ap_dev->queue_count > 0) - *flags |= 1; - break; - case AP_RESPONSE_NO_PENDING_REPLY: - if (status.queue_empty) { - /* The card shouldn't forget requests but who knows. */ - ap_dev->queue_count = 0; - list_splice_init(&ap_dev->pendingq, &ap_dev->requestq); - ap_dev->requestq_count += ap_dev->pendingq_count; - ap_dev->pendingq_count = 0; - } else - *flags |= 2; - break; - default: - return -ENODEV; - } - return 0; -} - -/** - * Send messages from the request queue to an AP device. - * @ap_dev: pointer to the AP device - * @flags: pointer to control flags, bit 2^0 is set if another poll is - * required, bit 2^1 is set if the poll timer needs to get armed - * Returns 0 if the device is still present, -ENODEV if not. - */ -static inline int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags) -{ - struct ap_queue_status status; - struct ap_message *ap_msg; - - if (ap_dev->requestq_count <= 0 || - ap_dev->queue_count >= ap_dev->queue_depth) - return 0; - /* Start the next request on the queue. */ - ap_msg = list_entry(ap_dev->requestq.next, struct ap_message, list); - status = __ap_send(ap_dev->qid, ap_msg->psmid, - ap_msg->message, ap_msg->length); - switch (status.response_code) { - case AP_RESPONSE_NORMAL: - atomic_inc(&ap_poll_requests); - ap_dev->queue_count++; - list_move_tail(&ap_msg->list, &ap_dev->pendingq); - ap_dev->requestq_count--; - ap_dev->pendingq_count++; - if (ap_dev->queue_count < ap_dev->queue_depth && - ap_dev->requestq_count > 0) - *flags |= 1; - *flags |= 2; - break; - case AP_RESPONSE_Q_FULL: - *flags |= 2; - break; - case AP_RESPONSE_MESSAGE_TOO_BIG: - return -EINVAL; - default: - return -ENODEV; - } - return 0; -} - -/** - * Poll AP device for pending replies and send new messages. If either - * ap_poll_read or ap_poll_write returns -ENODEV unregister the device. - * @ap_dev: pointer to the bus device - * @flags: pointer to control flags, bit 2^0 is set if another poll is - * required, bit 2^1 is set if the poll timer needs to get armed - * Returns 0. - */ -static inline int ap_poll_queue(struct ap_device *ap_dev, unsigned long *flags) -{ - int rc; - - rc = ap_poll_read(ap_dev, flags); - if (rc) - return rc; - return ap_poll_write(ap_dev, flags); -} - -/** - * Queue a message to a device. - * @ap_dev: pointer to the AP device - * @ap_msg: the message to be queued - */ -static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg) -{ - struct ap_queue_status status; - - if (list_empty(&ap_dev->requestq) && - ap_dev->queue_count < ap_dev->queue_depth) { - status = __ap_send(ap_dev->qid, ap_msg->psmid, - ap_msg->message, ap_msg->length); - switch (status.response_code) { - case AP_RESPONSE_NORMAL: - list_add_tail(&ap_msg->list, &ap_dev->pendingq); - atomic_inc(&ap_poll_requests); - ap_dev->pendingq_count++; - ap_dev->queue_count++; - ap_dev->total_request_count++; - break; - case AP_RESPONSE_Q_FULL: - list_add_tail(&ap_msg->list, &ap_dev->requestq); - ap_dev->requestq_count++; - ap_dev->total_request_count++; - return -EBUSY; - case AP_RESPONSE_MESSAGE_TOO_BIG: - ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL)); - return -EINVAL; - default: /* Device is gone. */ - ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); - return -ENODEV; - } - } else { - list_add_tail(&ap_msg->list, &ap_dev->requestq); - ap_dev->requestq_count++; - ap_dev->total_request_count++; - return -EBUSY; - } - ap_schedule_poll_timer(); - return 0; -} - -void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg) -{ - unsigned long flags; - int rc; - - spin_lock_bh(&ap_dev->lock); - if (!ap_dev->unregistered) { - /* Make room on the queue by polling for finished requests. */ - rc = ap_poll_queue(ap_dev, &flags); - if (!rc) - rc = __ap_queue_message(ap_dev, ap_msg); - if (!rc) - wake_up(&ap_poll_wait); - } else { - ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); - rc = 0; - } - spin_unlock_bh(&ap_dev->lock); - if (rc == -ENODEV) - device_unregister(&ap_dev->device); -} -EXPORT_SYMBOL(ap_queue_message); - -/** - * Cancel a crypto request. This is done by removing the request - * from the devive pendingq or requestq queue. Note that the - * request stays on the AP queue. When it finishes the message - * reply will be discarded because the psmid can't be found. - * @ap_dev: AP device that has the message queued - * @ap_msg: the message that is to be removed - */ -void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg) -{ - struct ap_message *tmp; - - spin_lock_bh(&ap_dev->lock); - if (!list_empty(&ap_msg->list)) { - list_for_each_entry(tmp, &ap_dev->pendingq, list) - if (tmp->psmid == ap_msg->psmid) { - ap_dev->pendingq_count--; - goto found; - } - ap_dev->requestq_count--; - found: - list_del_init(&ap_msg->list); - } - spin_unlock_bh(&ap_dev->lock); -} -EXPORT_SYMBOL(ap_cancel_message); - -/** - * AP receive polling for finished AP requests - */ -static void ap_poll_timeout(unsigned long unused) -{ - tasklet_schedule(&ap_tasklet); -} - -/** - * Poll all AP devices on the bus in a round robin fashion. Continue - * polling until bit 2^0 of the control flags is not set. If bit 2^1 - * of the control flags has been set arm the poll timer. - */ -static int __ap_poll_all(struct device *dev, void *data) -{ - struct ap_device *ap_dev = to_ap_dev(dev); - int rc; - - spin_lock(&ap_dev->lock); - if (!ap_dev->unregistered) { - rc = ap_poll_queue(to_ap_dev(dev), (unsigned long *) data); - } else - rc = 0; - spin_unlock(&ap_dev->lock); - if (rc) - device_unregister(&ap_dev->device); - return 0; -} - -static void ap_poll_all(unsigned long dummy) -{ - unsigned long flags; - - do { - flags = 0; - bus_for_each_dev(&ap_bus_type, NULL, &flags, __ap_poll_all); - } while (flags & 1); - if (flags & 2) - ap_schedule_poll_timer(); -} - -/** - * AP bus poll thread. The purpose of this thread is to poll for - * finished requests in a loop if there is a "free" cpu - that is - * a cpu that doesn't have anything better to do. The polling stops - * as soon as there is another task or if all messages have been - * delivered. - */ -static int ap_poll_thread(void *data) -{ - DECLARE_WAITQUEUE(wait, current); - unsigned long flags; - int requests; - - set_user_nice(current, -20); - while (1) { - if (need_resched()) { - schedule(); - continue; - } - add_wait_queue(&ap_poll_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - if (kthread_should_stop()) - break; - requests = atomic_read(&ap_poll_requests); - if (requests <= 0) - schedule(); - set_current_state(TASK_RUNNING); - remove_wait_queue(&ap_poll_wait, &wait); - - local_bh_disable(); - flags = 0; - bus_for_each_dev(&ap_bus_type, NULL, &flags, __ap_poll_all); - local_bh_enable(); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&ap_poll_wait, &wait); - return 0; -} - -static int ap_poll_thread_start(void) -{ - int rc; - - mutex_lock(&ap_poll_thread_mutex); - if (!ap_poll_kthread) { - ap_poll_kthread = kthread_run(ap_poll_thread, NULL, "appoll"); - rc = IS_ERR(ap_poll_kthread) ? PTR_ERR(ap_poll_kthread) : 0; - if (rc) - ap_poll_kthread = NULL; - } - else - rc = 0; - mutex_unlock(&ap_poll_thread_mutex); - return rc; -} - -static void ap_poll_thread_stop(void) -{ - mutex_lock(&ap_poll_thread_mutex); - if (ap_poll_kthread) { - kthread_stop(ap_poll_kthread); - ap_poll_kthread = NULL; - } - mutex_unlock(&ap_poll_thread_mutex); -} - -/** - * The module initialization code. - */ -int __init ap_module_init(void) -{ - int rc, i; - - if (ap_domain_index < -1 || ap_domain_index >= AP_DOMAINS) { - printk(KERN_WARNING "Invalid param: domain = %d. " - " Not loading.\n", ap_domain_index); - return -EINVAL; - } - if (ap_instructions_available() != 0) { - printk(KERN_WARNING "AP instructions not installed.\n"); - return -ENODEV; - } - - /* Create /sys/bus/ap. */ - rc = bus_register(&ap_bus_type); - if (rc) - goto out; - for (i = 0; ap_bus_attrs[i]; i++) { - rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]); - if (rc) - goto out_bus; - } - - /* Create /sys/devices/ap. */ - ap_root_device = s390_root_dev_register("ap"); - rc = IS_ERR(ap_root_device) ? PTR_ERR(ap_root_device) : 0; - if (rc) - goto out_bus; - - ap_work_queue = create_singlethread_workqueue("kapwork"); - if (!ap_work_queue) { - rc = -ENOMEM; - goto out_root; - } - - if (ap_select_domain() == 0) - ap_scan_bus(NULL); - - /* Setup the ap bus rescan timer. */ - init_timer(&ap_config_timer); - ap_config_timer.function = ap_config_timeout; - ap_config_timer.data = 0; - ap_config_timer.expires = jiffies + ap_config_time * HZ; - add_timer(&ap_config_timer); - - /* Start the low priority AP bus poll thread. */ - if (ap_thread_flag) { - rc = ap_poll_thread_start(); - if (rc) - goto out_work; - } - - return 0; - -out_work: - del_timer_sync(&ap_config_timer); - del_timer_sync(&ap_poll_timer); - destroy_workqueue(ap_work_queue); -out_root: - s390_root_dev_unregister(ap_root_device); -out_bus: - while (i--) - bus_remove_file(&ap_bus_type, ap_bus_attrs[i]); - bus_unregister(&ap_bus_type); -out: - return rc; -} - -static int __ap_match_all(struct device *dev, void *data) -{ - return 1; -} - -/** - * The module termination code - */ -void ap_module_exit(void) -{ - int i; - struct device *dev; - - ap_poll_thread_stop(); - del_timer_sync(&ap_config_timer); - del_timer_sync(&ap_poll_timer); - destroy_workqueue(ap_work_queue); - s390_root_dev_unregister(ap_root_device); - while ((dev = bus_find_device(&ap_bus_type, NULL, NULL, - __ap_match_all))) - { - device_unregister(dev); - put_device(dev); - } - for (i = 0; ap_bus_attrs[i]; i++) - bus_remove_file(&ap_bus_type, ap_bus_attrs[i]); - bus_unregister(&ap_bus_type); -} - -#ifndef CONFIG_ZCRYPT_MONOLITHIC -module_init(ap_module_init); -module_exit(ap_module_exit); -#endif diff --git a/trunk/drivers/s390/crypto/ap_bus.h b/trunk/drivers/s390/crypto/ap_bus.h deleted file mode 100644 index 83b69c01cd6e..000000000000 --- a/trunk/drivers/s390/crypto/ap_bus.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * linux/drivers/s390/crypto/ap_bus.h - * - * Copyright (C) 2006 IBM Corporation - * Author(s): Cornelia Huck - * Martin Schwidefsky - * Ralph Wuerthner - * - * Adjunct processor bus header file. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _AP_BUS_H_ -#define _AP_BUS_H_ - -#include -#include -#include - -#define AP_DEVICES 64 /* Number of AP devices. */ -#define AP_DOMAINS 16 /* Number of AP domains. */ -#define AP_MAX_RESET 90 /* Maximum number of resets. */ -#define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */ -#define AP_POLL_TIME 1 /* Time in ticks between receive polls. */ - -extern int ap_domain_index; - -/** - * The ap_qid_t identifier of an ap queue. It contains a - * 6 bit device index and a 4 bit queue index (domain). - */ -typedef unsigned int ap_qid_t; - -#define AP_MKQID(_device,_queue) (((_device) & 63) << 8 | ((_queue) & 15)) -#define AP_QID_DEVICE(_qid) (((_qid) >> 8) & 63) -#define AP_QID_QUEUE(_qid) ((_qid) & 15) - -/** - * The ap queue status word is returned by all three AP functions - * (PQAP, NQAP and DQAP). There's a set of flags in the first - * byte, followed by a 1 byte response code. - */ -struct ap_queue_status { - unsigned int queue_empty : 1; - unsigned int replies_waiting : 1; - unsigned int queue_full : 1; - unsigned int pad1 : 5; - unsigned int response_code : 8; - unsigned int pad2 : 16; -}; - -#define AP_RESPONSE_NORMAL 0x00 -#define AP_RESPONSE_Q_NOT_AVAIL 0x01 -#define AP_RESPONSE_RESET_IN_PROGRESS 0x02 -#define AP_RESPONSE_DECONFIGURED 0x03 -#define AP_RESPONSE_CHECKSTOPPED 0x04 -#define AP_RESPONSE_BUSY 0x05 -#define AP_RESPONSE_Q_FULL 0x10 -#define AP_RESPONSE_NO_PENDING_REPLY 0x10 -#define AP_RESPONSE_INDEX_TOO_BIG 0x11 -#define AP_RESPONSE_NO_FIRST_PART 0x13 -#define AP_RESPONSE_MESSAGE_TOO_BIG 0x15 - -/** - * Known device types - */ -#define AP_DEVICE_TYPE_PCICC 3 -#define AP_DEVICE_TYPE_PCICA 4 -#define AP_DEVICE_TYPE_PCIXCC 5 -#define AP_DEVICE_TYPE_CEX2A 6 -#define AP_DEVICE_TYPE_CEX2C 7 - -struct ap_device; -struct ap_message; - -struct ap_driver { - struct device_driver driver; - struct ap_device_id *ids; - - int (*probe)(struct ap_device *); - void (*remove)(struct ap_device *); - /* receive is called from tasklet context */ - void (*receive)(struct ap_device *, struct ap_message *, - struct ap_message *); -}; - -#define to_ap_drv(x) container_of((x), struct ap_driver, driver) - -int ap_driver_register(struct ap_driver *, struct module *, char *); -void ap_driver_unregister(struct ap_driver *); - -struct ap_device { - struct device device; - struct ap_driver *drv; /* Pointer to AP device driver. */ - spinlock_t lock; /* Per device lock. */ - - ap_qid_t qid; /* AP queue id. */ - int queue_depth; /* AP queue depth.*/ - int device_type; /* AP device type. */ - int unregistered; /* marks AP device as unregistered */ - - int queue_count; /* # messages currently on AP queue. */ - - struct list_head pendingq; /* List of message sent to AP queue. */ - int pendingq_count; /* # requests on pendingq list. */ - struct list_head requestq; /* List of message yet to be sent. */ - int requestq_count; /* # requests on requestq list. */ - int total_request_count; /* # requests ever for this AP device. */ - - struct ap_message *reply; /* Per device reply message. */ - - void *private; /* ap driver private pointer. */ -}; - -#define to_ap_dev(x) container_of((x), struct ap_device, device) - -struct ap_message { - struct list_head list; /* Request queueing. */ - unsigned long long psmid; /* Message id. */ - void *message; /* Pointer to message buffer. */ - size_t length; /* Message length. */ - - void *private; /* ap driver private pointer. */ -}; - -#define AP_DEVICE(dt) \ - .dev_type=(dt), \ - .match_flags=AP_DEVICE_ID_MATCH_DEVICE_TYPE, - -/** - * Note: don't use ap_send/ap_recv after using ap_queue_message - * for the first time. Otherwise the ap message queue will get - * confused. - */ -int ap_send(ap_qid_t, unsigned long long, void *, size_t); -int ap_recv(ap_qid_t, unsigned long long *, void *, size_t); - -void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg); -void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg); -void ap_flush_queue(struct ap_device *ap_dev); - -int ap_module_init(void); -void ap_module_exit(void); - -#endif /* _AP_BUS_H_ */ diff --git a/trunk/drivers/s390/crypto/z90common.h b/trunk/drivers/s390/crypto/z90common.h new file mode 100644 index 000000000000..dbbcda3c846a --- /dev/null +++ b/trunk/drivers/s390/crypto/z90common.h @@ -0,0 +1,166 @@ +/* + * linux/drivers/s390/crypto/z90common.h + * + * z90crypt 1.3.3 + * + * Copyright (C) 2001, 2005 IBM Corporation + * Author(s): Robert Burroughs (burrough@us.ibm.com) + * Eric Rossman (edrossma@us.ibm.com) + * + * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _Z90COMMON_H_ +#define _Z90COMMON_H_ + + +#define RESPBUFFSIZE 256 +#define PCI_FUNC_KEY_DECRYPT 0x5044 +#define PCI_FUNC_KEY_ENCRYPT 0x504B +extern int ext_bitlens; + +enum devstat { + DEV_GONE, + DEV_ONLINE, + DEV_QUEUE_FULL, + DEV_EMPTY, + DEV_NO_WORK, + DEV_BAD_MESSAGE, + DEV_TSQ_EXCEPTION, + DEV_RSQ_EXCEPTION, + DEV_SEN_EXCEPTION, + DEV_REC_EXCEPTION +}; + +enum hdstat { + HD_NOT_THERE, + HD_BUSY, + HD_DECONFIGURED, + HD_CHECKSTOPPED, + HD_ONLINE, + HD_TSQ_EXCEPTION +}; + +#define Z90C_NO_DEVICES 1 +#define Z90C_AMBIGUOUS_DOMAIN 2 +#define Z90C_INCORRECT_DOMAIN 3 +#define ENOTINIT 4 + +#define SEN_BUSY 7 +#define SEN_USER_ERROR 8 +#define SEN_QUEUE_FULL 11 +#define SEN_NOT_AVAIL 16 +#define SEN_PAD_ERROR 17 +#define SEN_RETRY 18 +#define SEN_RELEASED 24 + +#define REC_EMPTY 4 +#define REC_BUSY 6 +#define REC_OPERAND_INV 8 +#define REC_OPERAND_SIZE 9 +#define REC_EVEN_MOD 10 +#define REC_NO_WORK 11 +#define REC_HARDWAR_ERR 12 +#define REC_NO_RESPONSE 13 +#define REC_RETRY_DEV 14 +#define REC_USER_GONE 15 +#define REC_BAD_MESSAGE 16 +#define REC_INVALID_PAD 17 +#define REC_USE_PCICA 18 + +#define WRONG_DEVICE_TYPE 20 + +#define REC_FATAL_ERROR 32 +#define SEN_FATAL_ERROR 33 +#define TSQ_FATAL_ERROR 34 +#define RSQ_FATAL_ERROR 35 + +#define Z90CRYPT_NUM_TYPES 6 +#define PCICA 0 +#define PCICC 1 +#define PCIXCC_MCL2 2 +#define PCIXCC_MCL3 3 +#define CEX2C 4 +#define CEX2A 5 +#define NILDEV -1 +#define ANYDEV -1 +#define PCIXCC_UNK -2 + +enum hdevice_type { + PCICC_HW = 3, + PCICA_HW = 4, + PCIXCC_HW = 5, + CEX2A_HW = 6, + CEX2C_HW = 7 +}; + +struct CPRBX { + unsigned short cprb_len; + unsigned char cprb_ver_id; + unsigned char pad_000[3]; + unsigned char func_id[2]; + unsigned char cprb_flags[4]; + unsigned int req_parml; + unsigned int req_datal; + unsigned int rpl_msgbl; + unsigned int rpld_parml; + unsigned int rpl_datal; + unsigned int rpld_datal; + unsigned int req_extbl; + unsigned char pad_001[4]; + unsigned int rpld_extbl; + unsigned char req_parmb[16]; + unsigned char req_datab[16]; + unsigned char rpl_parmb[16]; + unsigned char rpl_datab[16]; + unsigned char req_extb[16]; + unsigned char rpl_extb[16]; + unsigned short ccp_rtcode; + unsigned short ccp_rscode; + unsigned int mac_data_len; + unsigned char logon_id[8]; + unsigned char mac_value[8]; + unsigned char mac_content_flgs; + unsigned char pad_002; + unsigned short domain; + unsigned char pad_003[12]; + unsigned char pad_004[36]; +}; + +#ifndef DEV_NAME +#define DEV_NAME "z90crypt" +#endif +#define PRINTK(fmt, args...) \ + printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args) +#define PRINTKN(fmt, args...) \ + printk(KERN_DEBUG DEV_NAME ": " fmt, ## args) +#define PRINTKW(fmt, args...) \ + printk(KERN_WARNING DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args) +#define PRINTKC(fmt, args...) \ + printk(KERN_CRIT DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args) + +#ifdef Z90CRYPT_DEBUG +#define PDEBUG(fmt, args...) \ + printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args) +#else +#define PDEBUG(fmt, args...) do {} while (0) +#endif + +#define UMIN(a,b) ((a) < (b) ? (a) : (b)) +#define IS_EVEN(x) ((x) == (2 * ((x) / 2))) + +#endif diff --git a/trunk/drivers/s390/crypto/z90crypt.h b/trunk/drivers/s390/crypto/z90crypt.h new file mode 100644 index 000000000000..0ca1d126ccb6 --- /dev/null +++ b/trunk/drivers/s390/crypto/z90crypt.h @@ -0,0 +1,71 @@ +/* + * linux/drivers/s390/crypto/z90crypt.h + * + * z90crypt 1.3.3 (kernel-private header) + * + * Copyright (C) 2001, 2005 IBM Corporation + * Author(s): Robert Burroughs (burrough@us.ibm.com) + * Eric Rossman (edrossma@us.ibm.com) + * + * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _Z90CRYPT_H_ +#define _Z90CRYPT_H_ + +#include + +/** + * local errno definitions + */ +#define ENOBUFF 129 // filp->private_data->...>work_elem_p->buffer is NULL +#define EWORKPEND 130 // user issues ioctl while another pending +#define ERELEASED 131 // user released while ioctl pending +#define EQUIESCE 132 // z90crypt quiescing (no more work allowed) +#define ETIMEOUT 133 // request timed out +#define EUNKNOWN 134 // some unrecognized error occured (retry may succeed) +#define EGETBUFF 135 // Error getting buffer or hardware lacks capability + // (retry in software) + +/** + * DEPRECATED STRUCTURES + */ + +/** + * This structure is DEPRECATED and the corresponding ioctl() has been + * replaced with individual ioctl()s for each piece of data! + * This structure will NOT survive past version 1.3.1, so switch to the + * new ioctl()s. + */ +#define MASK_LENGTH 64 // mask length +struct ica_z90_status { + int totalcount; + int leedslitecount; // PCICA + int leeds2count; // PCICC + // int PCIXCCCount; is not in struct for backward compatibility + int requestqWaitCount; + int pendingqWaitCount; + int totalOpenCount; + int cryptoDomain; + // status: 0=not there, 1=PCICA, 2=PCICC, 3=PCIXCC_MCL2, 4=PCIXCC_MCL3, + // 5=CEX2C + unsigned char status[MASK_LENGTH]; + // qdepth: # work elements waiting for each device + unsigned char qdepth[MASK_LENGTH]; +}; + +#endif /* _Z90CRYPT_H_ */ diff --git a/trunk/drivers/s390/crypto/z90hardware.c b/trunk/drivers/s390/crypto/z90hardware.c new file mode 100644 index 000000000000..be60795f4a74 --- /dev/null +++ b/trunk/drivers/s390/crypto/z90hardware.c @@ -0,0 +1,2531 @@ +/* + * linux/drivers/s390/crypto/z90hardware.c + * + * z90crypt 1.3.3 + * + * Copyright (C) 2001, 2005 IBM Corporation + * Author(s): Robert Burroughs (burrough@us.ibm.com) + * Eric Rossman (edrossma@us.ibm.com) + * + * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include "z90crypt.h" +#include "z90common.h" + +struct cca_token_hdr { + unsigned char token_identifier; + unsigned char version; + unsigned short token_length; + unsigned char reserved[4]; +}; + +#define CCA_TKN_HDR_ID_EXT 0x1E + +struct cca_private_ext_ME_sec { + unsigned char section_identifier; + unsigned char version; + unsigned short section_length; + unsigned char private_key_hash[20]; + unsigned char reserved1[4]; + unsigned char key_format; + unsigned char reserved2; + unsigned char key_name_hash[20]; + unsigned char key_use_flags[4]; + unsigned char reserved3[6]; + unsigned char reserved4[24]; + unsigned char confounder[24]; + unsigned char exponent[128]; + unsigned char modulus[128]; +}; + +#define CCA_PVT_USAGE_ALL 0x80 + +struct cca_public_sec { + unsigned char section_identifier; + unsigned char version; + unsigned short section_length; + unsigned char reserved[2]; + unsigned short exponent_len; + unsigned short modulus_bit_len; + unsigned short modulus_byte_len; + unsigned char exponent[3]; +}; + +struct cca_private_ext_ME { + struct cca_token_hdr pvtMEHdr; + struct cca_private_ext_ME_sec pvtMESec; + struct cca_public_sec pubMESec; +}; + +struct cca_public_key { + struct cca_token_hdr pubHdr; + struct cca_public_sec pubSec; +}; + +struct cca_pvt_ext_CRT_sec { + unsigned char section_identifier; + unsigned char version; + unsigned short section_length; + unsigned char private_key_hash[20]; + unsigned char reserved1[4]; + unsigned char key_format; + unsigned char reserved2; + unsigned char key_name_hash[20]; + unsigned char key_use_flags[4]; + unsigned short p_len; + unsigned short q_len; + unsigned short dp_len; + unsigned short dq_len; + unsigned short u_len; + unsigned short mod_len; + unsigned char reserved3[4]; + unsigned short pad_len; + unsigned char reserved4[52]; + unsigned char confounder[8]; +}; + +#define CCA_PVT_EXT_CRT_SEC_ID_PVT 0x08 +#define CCA_PVT_EXT_CRT_SEC_FMT_CL 0x40 + +struct cca_private_ext_CRT { + struct cca_token_hdr pvtCrtHdr; + struct cca_pvt_ext_CRT_sec pvtCrtSec; + struct cca_public_sec pubCrtSec; +}; + +struct ap_status_word { + unsigned char q_stat_flags; + unsigned char response_code; + unsigned char reserved[2]; +}; + +#define AP_Q_STATUS_EMPTY 0x80 +#define AP_Q_STATUS_REPLIES_WAITING 0x40 +#define AP_Q_STATUS_ARRAY_FULL 0x20 + +#define AP_RESPONSE_NORMAL 0x00 +#define AP_RESPONSE_Q_NOT_AVAIL 0x01 +#define AP_RESPONSE_RESET_IN_PROGRESS 0x02 +#define AP_RESPONSE_DECONFIGURED 0x03 +#define AP_RESPONSE_CHECKSTOPPED 0x04 +#define AP_RESPONSE_BUSY 0x05 +#define AP_RESPONSE_Q_FULL 0x10 +#define AP_RESPONSE_NO_PENDING_REPLY 0x10 +#define AP_RESPONSE_INDEX_TOO_BIG 0x11 +#define AP_RESPONSE_NO_FIRST_PART 0x13 +#define AP_RESPONSE_MESSAGE_TOO_BIG 0x15 + +#define AP_MAX_CDX_BITL 4 +#define AP_RQID_RESERVED_BITL 4 +#define SKIP_BITL (AP_MAX_CDX_BITL + AP_RQID_RESERVED_BITL) + +struct type4_hdr { + unsigned char reserved1; + unsigned char msg_type_code; + unsigned short msg_len; + unsigned char request_code; + unsigned char msg_fmt; + unsigned short reserved2; +}; + +#define TYPE4_TYPE_CODE 0x04 +#define TYPE4_REQU_CODE 0x40 + +#define TYPE4_SME_LEN 0x0188 +#define TYPE4_LME_LEN 0x0308 +#define TYPE4_SCR_LEN 0x01E0 +#define TYPE4_LCR_LEN 0x03A0 + +#define TYPE4_SME_FMT 0x00 +#define TYPE4_LME_FMT 0x10 +#define TYPE4_SCR_FMT 0x40 +#define TYPE4_LCR_FMT 0x50 + +struct type4_sme { + struct type4_hdr header; + unsigned char message[128]; + unsigned char exponent[128]; + unsigned char modulus[128]; +}; + +struct type4_lme { + struct type4_hdr header; + unsigned char message[256]; + unsigned char exponent[256]; + unsigned char modulus[256]; +}; + +struct type4_scr { + struct type4_hdr header; + unsigned char message[128]; + unsigned char dp[72]; + unsigned char dq[64]; + unsigned char p[72]; + unsigned char q[64]; + unsigned char u[72]; +}; + +struct type4_lcr { + struct type4_hdr header; + unsigned char message[256]; + unsigned char dp[136]; + unsigned char dq[128]; + unsigned char p[136]; + unsigned char q[128]; + unsigned char u[136]; +}; + +union type4_msg { + struct type4_sme sme; + struct type4_lme lme; + struct type4_scr scr; + struct type4_lcr lcr; +}; + +struct type84_hdr { + unsigned char reserved1; + unsigned char code; + unsigned short len; + unsigned char reserved2[4]; +}; + +#define TYPE84_RSP_CODE 0x84 + +struct type6_hdr { + unsigned char reserved1; + unsigned char type; + unsigned char reserved2[2]; + unsigned char right[4]; + unsigned char reserved3[2]; + unsigned char reserved4[2]; + unsigned char apfs[4]; + unsigned int offset1; + unsigned int offset2; + unsigned int offset3; + unsigned int offset4; + unsigned char agent_id[16]; + unsigned char rqid[2]; + unsigned char reserved5[2]; + unsigned char function_code[2]; + unsigned char reserved6[2]; + unsigned int ToCardLen1; + unsigned int ToCardLen2; + unsigned int ToCardLen3; + unsigned int ToCardLen4; + unsigned int FromCardLen1; + unsigned int FromCardLen2; + unsigned int FromCardLen3; + unsigned int FromCardLen4; +}; + +struct CPRB { + unsigned char cprb_len[2]; + unsigned char cprb_ver_id; + unsigned char pad_000; + unsigned char srpi_rtcode[4]; + unsigned char srpi_verb; + unsigned char flags; + unsigned char func_id[2]; + unsigned char checkpoint_flag; + unsigned char resv2; + unsigned char req_parml[2]; + unsigned char req_parmp[4]; + unsigned char req_datal[4]; + unsigned char req_datap[4]; + unsigned char rpl_parml[2]; + unsigned char pad_001[2]; + unsigned char rpl_parmp[4]; + unsigned char rpl_datal[4]; + unsigned char rpl_datap[4]; + unsigned char ccp_rscode[2]; + unsigned char ccp_rtcode[2]; + unsigned char repd_parml[2]; + unsigned char mac_data_len[2]; + unsigned char repd_datal[4]; + unsigned char req_pc[2]; + unsigned char res_origin[8]; + unsigned char mac_value[8]; + unsigned char logon_id[8]; + unsigned char usage_domain[2]; + unsigned char resv3[18]; + unsigned char svr_namel[2]; + unsigned char svr_name[8]; +}; + +struct type6_msg { + struct type6_hdr header; + struct CPRB CPRB; +}; + +struct type86_hdr { + unsigned char reserved1; + unsigned char type; + unsigned char format; + unsigned char reserved2; + unsigned char reply_code; + unsigned char reserved3[3]; +}; + +#define TYPE86_RSP_CODE 0x86 +#define TYPE86_FMT2 0x02 + +struct type86_fmt2_msg { + struct type86_hdr header; + unsigned char reserved[4]; + unsigned char apfs[4]; + unsigned int count1; + unsigned int offset1; + unsigned int count2; + unsigned int offset2; + unsigned int count3; + unsigned int offset3; + unsigned int count4; + unsigned int offset4; +}; + +static struct type6_hdr static_type6_hdr = { + 0x00, + 0x06, + {0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00}, + {0x00,0x00}, + {0x00,0x00,0x00,0x00}, + 0x00000058, + 0x00000000, + 0x00000000, + 0x00000000, + {0x01,0x00,0x43,0x43,0x41,0x2D,0x41,0x50, + 0x50,0x4C,0x20,0x20,0x20,0x01,0x01,0x01}, + {0x00,0x00}, + {0x00,0x00}, + {0x50,0x44}, + {0x00,0x00}, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; + +static struct type6_hdr static_type6_hdrX = { + 0x00, + 0x06, + {0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00}, + {0x00,0x00}, + {0x00,0x00,0x00,0x00}, + 0x00000058, + 0x00000000, + 0x00000000, + 0x00000000, + {0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00}, + {0x00,0x00}, + {0x50,0x44}, + {0x00,0x00}, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; + +static struct CPRB static_cprb = { + {0x70,0x00}, + 0x41, + 0x00, + {0x00,0x00,0x00,0x00}, + 0x00, + 0x00, + {0x54,0x32}, + 0x01, + 0x00, + {0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00}, + {0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00}, + {0x00,0x00}, + {0x00,0x00}, + {0x00,0x00}, + {0x00,0x00,0x00,0x00}, + {0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00}, + {0x08,0x00}, + {0x49,0x43,0x53,0x46,0x20,0x20,0x20,0x20} +}; + +struct function_and_rules_block { + unsigned char function_code[2]; + unsigned char ulen[2]; + unsigned char only_rule[8]; +}; + +static struct function_and_rules_block static_pkd_function_and_rules = { + {0x50,0x44}, + {0x0A,0x00}, + {'P','K','C','S','-','1','.','2'} +}; + +static struct function_and_rules_block static_pke_function_and_rules = { + {0x50,0x4B}, + {0x0A,0x00}, + {'P','K','C','S','-','1','.','2'} +}; + +struct T6_keyBlock_hdr { + unsigned char blen[2]; + unsigned char ulen[2]; + unsigned char flags[2]; +}; + +static struct T6_keyBlock_hdr static_T6_keyBlock_hdr = { + {0x89,0x01}, + {0x87,0x01}, + {0x00} +}; + +static struct CPRBX static_cprbx = { + 0x00DC, + 0x02, + {0x00,0x00,0x00}, + {0x54,0x32}, + {0x00,0x00,0x00,0x00}, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + {0x00,0x00,0x00,0x00}, + 0x00000000, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 0x0000, + 0x0000, + 0x00000000, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 0x00, + 0x00, + 0x0000, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} +}; + +static struct function_and_rules_block static_pkd_function_and_rulesX_MCL2 = { + {0x50,0x44}, + {0x00,0x0A}, + {'P','K','C','S','-','1','.','2'} +}; + +static struct function_and_rules_block static_pke_function_and_rulesX_MCL2 = { + {0x50,0x4B}, + {0x00,0x0A}, + {'Z','E','R','O','-','P','A','D'} +}; + +static struct function_and_rules_block static_pkd_function_and_rulesX = { + {0x50,0x44}, + {0x00,0x0A}, + {'Z','E','R','O','-','P','A','D'} +}; + +static struct function_and_rules_block static_pke_function_and_rulesX = { + {0x50,0x4B}, + {0x00,0x0A}, + {'M','R','P',' ',' ',' ',' ',' '} +}; + +static unsigned char static_PKE_function_code[2] = {0x50, 0x4B}; + +struct T6_keyBlock_hdrX { + unsigned short blen; + unsigned short ulen; + unsigned char flags[2]; +}; + +static unsigned char static_pad[256] = { +0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57, +0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39, +0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D, +0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F, +0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45, +0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F, +0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D, +0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9, +0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B, +0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD, +0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1, +0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23, +0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43, +0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F, +0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD, +0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09 +}; + +static struct cca_private_ext_ME static_pvt_me_key = { + { + 0x1E, + 0x00, + 0x0183, + {0x00,0x00,0x00,0x00} + }, + + { + 0x02, + 0x00, + 0x016C, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00}, + 0x00, + 0x00, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00}, + {0x80,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} + }, + + { + 0x04, + 0x00, + 0x000F, + {0x00,0x00}, + 0x0003, + 0x0000, + 0x0000, + {0x01,0x00,0x01} + } +}; + +static struct cca_public_key static_public_key = { + { + 0x1E, + 0x00, + 0x0000, + {0x00,0x00,0x00,0x00} + }, + + { + 0x04, + 0x00, + 0x0000, + {0x00,0x00}, + 0x0000, + 0x0000, + 0x0000, + {0x01,0x00,0x01} + } +}; + +#define FIXED_TYPE6_ME_LEN 0x0000025F + +#define FIXED_TYPE6_ME_EN_LEN 0x000000F0 + +#define FIXED_TYPE6_ME_LENX 0x000002CB + +#define FIXED_TYPE6_ME_EN_LENX 0x0000015C + +static struct cca_public_sec static_cca_pub_sec = { + 0x04, + 0x00, + 0x000f, + {0x00,0x00}, + 0x0003, + 0x0000, + 0x0000, + {0x01,0x00,0x01} +}; + +#define FIXED_TYPE6_CR_LEN 0x00000177 + +#define FIXED_TYPE6_CR_LENX 0x000001E3 + +#define MAX_RESPONSE_SIZE 0x00000710 + +#define MAX_RESPONSEX_SIZE 0x0000077C + +#define RESPONSE_CPRB_SIZE 0x000006B8 +#define RESPONSE_CPRBX_SIZE 0x00000724 + +struct type50_hdr { + u8 reserved1; + u8 msg_type_code; + u16 msg_len; + u8 reserved2; + u8 ignored; + u16 reserved3; +}; + +#define TYPE50_TYPE_CODE 0x50 + +#define TYPE50_MEB1_LEN (sizeof(struct type50_meb1_msg)) +#define TYPE50_MEB2_LEN (sizeof(struct type50_meb2_msg)) +#define TYPE50_CRB1_LEN (sizeof(struct type50_crb1_msg)) +#define TYPE50_CRB2_LEN (sizeof(struct type50_crb2_msg)) + +#define TYPE50_MEB1_FMT 0x0001 +#define TYPE50_MEB2_FMT 0x0002 +#define TYPE50_CRB1_FMT 0x0011 +#define TYPE50_CRB2_FMT 0x0012 + +struct type50_meb1_msg { + struct type50_hdr header; + u16 keyblock_type; + u8 reserved[6]; + u8 exponent[128]; + u8 modulus[128]; + u8 message[128]; +}; + +struct type50_meb2_msg { + struct type50_hdr header; + u16 keyblock_type; + u8 reserved[6]; + u8 exponent[256]; + u8 modulus[256]; + u8 message[256]; +}; + +struct type50_crb1_msg { + struct type50_hdr header; + u16 keyblock_type; + u8 reserved[6]; + u8 p[64]; + u8 q[64]; + u8 dp[64]; + u8 dq[64]; + u8 u[64]; + u8 message[128]; +}; + +struct type50_crb2_msg { + struct type50_hdr header; + u16 keyblock_type; + u8 reserved[6]; + u8 p[128]; + u8 q[128]; + u8 dp[128]; + u8 dq[128]; + u8 u[128]; + u8 message[256]; +}; + +union type50_msg { + struct type50_meb1_msg meb1; + struct type50_meb2_msg meb2; + struct type50_crb1_msg crb1; + struct type50_crb2_msg crb2; +}; + +struct type80_hdr { + u8 reserved1; + u8 type; + u16 len; + u8 code; + u8 reserved2[3]; + u8 reserved3[8]; +}; + +#define TYPE80_RSP_CODE 0x80 + +struct error_hdr { + unsigned char reserved1; + unsigned char type; + unsigned char reserved2[2]; + unsigned char reply_code; + unsigned char reserved3[3]; +}; + +#define TYPE82_RSP_CODE 0x82 +#define TYPE88_RSP_CODE 0x88 + +#define REP82_ERROR_MACHINE_FAILURE 0x10 +#define REP82_ERROR_PREEMPT_FAILURE 0x12 +#define REP82_ERROR_CHECKPT_FAILURE 0x14 +#define REP82_ERROR_MESSAGE_TYPE 0x20 +#define REP82_ERROR_INVALID_COMM_CD 0x21 +#define REP82_ERROR_INVALID_MSG_LEN 0x23 +#define REP82_ERROR_RESERVD_FIELD 0x24 +#define REP82_ERROR_FORMAT_FIELD 0x29 +#define REP82_ERROR_INVALID_COMMAND 0x30 +#define REP82_ERROR_MALFORMED_MSG 0x40 +#define REP82_ERROR_RESERVED_FIELDO 0x50 +#define REP82_ERROR_WORD_ALIGNMENT 0x60 +#define REP82_ERROR_MESSAGE_LENGTH 0x80 +#define REP82_ERROR_OPERAND_INVALID 0x82 +#define REP82_ERROR_OPERAND_SIZE 0x84 +#define REP82_ERROR_EVEN_MOD_IN_OPND 0x85 +#define REP82_ERROR_RESERVED_FIELD 0x88 +#define REP82_ERROR_TRANSPORT_FAIL 0x90 +#define REP82_ERROR_PACKET_TRUNCATED 0xA0 +#define REP82_ERROR_ZERO_BUFFER_LEN 0xB0 + +#define REP88_ERROR_MODULE_FAILURE 0x10 +#define REP88_ERROR_MODULE_TIMEOUT 0x11 +#define REP88_ERROR_MODULE_NOTINIT 0x13 +#define REP88_ERROR_MODULE_NOTAVAIL 0x14 +#define REP88_ERROR_MODULE_DISABLED 0x15 +#define REP88_ERROR_MODULE_IN_DIAGN 0x17 +#define REP88_ERROR_FASTPATH_DISABLD 0x19 +#define REP88_ERROR_MESSAGE_TYPE 0x20 +#define REP88_ERROR_MESSAGE_MALFORMD 0x22 +#define REP88_ERROR_MESSAGE_LENGTH 0x23 +#define REP88_ERROR_RESERVED_FIELD 0x24 +#define REP88_ERROR_KEY_TYPE 0x34 +#define REP88_ERROR_INVALID_KEY 0x82 +#define REP88_ERROR_OPERAND 0x84 +#define REP88_ERROR_OPERAND_EVEN_MOD 0x85 + +#define CALLER_HEADER 12 + +static inline int +testq(int q_nr, int *q_depth, int *dev_type, struct ap_status_word *stat) +{ + int ccode; + + asm volatile +#ifdef CONFIG_64BIT + (" llgfr 0,%4 \n" + " slgr 1,1 \n" + " lgr 2,1 \n" + "0: .long 0xb2af0000 \n" + "1: ipm %0 \n" + " srl %0,28 \n" + " iihh %0,0 \n" + " iihl %0,0 \n" + " lgr %1,1 \n" + " lgr %3,2 \n" + " srl %3,24 \n" + " sll 2,24 \n" + " srl 2,24 \n" + " lgr %2,2 \n" + "2: \n" + ".section .fixup,\"ax\" \n" + "3: \n" + " lhi %0,%h5 \n" + " jg 2b \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + " .align 8 \n" + " .quad 0b,3b \n" + " .quad 1b,3b \n" + ".previous" + :"=d" (ccode),"=d" (*stat),"=d" (*q_depth), "=d" (*dev_type) + :"d" (q_nr), "K" (DEV_TSQ_EXCEPTION) + :"cc","0","1","2","memory"); +#else + (" lr 0,%4 \n" + " slr 1,1 \n" + " lr 2,1 \n" + "0: .long 0xb2af0000 \n" + "1: ipm %0 \n" + " srl %0,28 \n" + " lr %1,1 \n" + " lr %3,2 \n" + " srl %3,24 \n" + " sll 2,24 \n" + " srl 2,24 \n" + " lr %2,2 \n" + "2: \n" + ".section .fixup,\"ax\" \n" + "3: \n" + " lhi %0,%h5 \n" + " bras 1,4f \n" + " .long 2b \n" + "4: \n" + " l 1,0(1) \n" + " br 1 \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + " .align 4 \n" + " .long 0b,3b \n" + " .long 1b,3b \n" + ".previous" + :"=d" (ccode),"=d" (*stat),"=d" (*q_depth), "=d" (*dev_type) + :"d" (q_nr), "K" (DEV_TSQ_EXCEPTION) + :"cc","0","1","2","memory"); +#endif + return ccode; +} + +static inline int +resetq(int q_nr, struct ap_status_word *stat_p) +{ + int ccode; + + asm volatile +#ifdef CONFIG_64BIT + (" llgfr 0,%2 \n" + " lghi 1,1 \n" + " sll 1,24 \n" + " or 0,1 \n" + " slgr 1,1 \n" + " lgr 2,1 \n" + "0: .long 0xb2af0000 \n" + "1: ipm %0 \n" + " srl %0,28 \n" + " iihh %0,0 \n" + " iihl %0,0 \n" + " lgr %1,1 \n" + "2: \n" + ".section .fixup,\"ax\" \n" + "3: \n" + " lhi %0,%h3 \n" + " jg 2b \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + " .align 8 \n" + " .quad 0b,3b \n" + " .quad 1b,3b \n" + ".previous" + :"=d" (ccode),"=d" (*stat_p) + :"d" (q_nr), "K" (DEV_RSQ_EXCEPTION) + :"cc","0","1","2","memory"); +#else + (" lr 0,%2 \n" + " lhi 1,1 \n" + " sll 1,24 \n" + " or 0,1 \n" + " slr 1,1 \n" + " lr 2,1 \n" + "0: .long 0xb2af0000 \n" + "1: ipm %0 \n" + " srl %0,28 \n" + " lr %1,1 \n" + "2: \n" + ".section .fixup,\"ax\" \n" + "3: \n" + " lhi %0,%h3 \n" + " bras 1,4f \n" + " .long 2b \n" + "4: \n" + " l 1,0(1) \n" + " br 1 \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + " .align 4 \n" + " .long 0b,3b \n" + " .long 1b,3b \n" + ".previous" + :"=d" (ccode),"=d" (*stat_p) + :"d" (q_nr), "K" (DEV_RSQ_EXCEPTION) + :"cc","0","1","2","memory"); +#endif + return ccode; +} + +static inline int +sen(int msg_len, unsigned char *msg_ext, struct ap_status_word *stat) +{ + int ccode; + + asm volatile +#ifdef CONFIG_64BIT + (" lgr 6,%3 \n" + " llgfr 7,%2 \n" + " llgt 0,0(6) \n" + " lghi 1,64 \n" + " sll 1,24 \n" + " or 0,1 \n" + " la 6,4(6) \n" + " llgt 2,0(6) \n" + " llgt 3,4(6) \n" + " la 6,8(6) \n" + " slr 1,1 \n" + "0: .long 0xb2ad0026 \n" + "1: brc 2,0b \n" + " ipm %0 \n" + " srl %0,28 \n" + " iihh %0,0 \n" + " iihl %0,0 \n" + " lgr %1,1 \n" + "2: \n" + ".section .fixup,\"ax\" \n" + "3: \n" + " lhi %0,%h4 \n" + " jg 2b \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + " .align 8 \n" + " .quad 0b,3b \n" + " .quad 1b,3b \n" + ".previous" + :"=d" (ccode),"=d" (*stat) + :"d" (msg_len),"a" (msg_ext), "K" (DEV_SEN_EXCEPTION) + :"cc","0","1","2","3","6","7","memory"); +#else + (" lr 6,%3 \n" + " lr 7,%2 \n" + " l 0,0(6) \n" + " lhi 1,64 \n" + " sll 1,24 \n" + " or 0,1 \n" + " la 6,4(6) \n" + " l 2,0(6) \n" + " l 3,4(6) \n" + " la 6,8(6) \n" + " slr 1,1 \n" + "0: .long 0xb2ad0026 \n" + "1: brc 2,0b \n" + " ipm %0 \n" + " srl %0,28 \n" + " lr %1,1 \n" + "2: \n" + ".section .fixup,\"ax\" \n" + "3: \n" + " lhi %0,%h4 \n" + " bras 1,4f \n" + " .long 2b \n" + "4: \n" + " l 1,0(1) \n" + " br 1 \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + " .align 4 \n" + " .long 0b,3b \n" + " .long 1b,3b \n" + ".previous" + :"=d" (ccode),"=d" (*stat) + :"d" (msg_len),"a" (msg_ext), "K" (DEV_SEN_EXCEPTION) + :"cc","0","1","2","3","6","7","memory"); +#endif + return ccode; +} + +static inline int +rec(int q_nr, int buff_l, unsigned char *rsp, unsigned char *id, + struct ap_status_word *st) +{ + int ccode; + + asm volatile +#ifdef CONFIG_64BIT + (" llgfr 0,%2 \n" + " lgr 3,%4 \n" + " lgr 6,%3 \n" + " llgfr 7,%5 \n" + " lghi 1,128 \n" + " sll 1,24 \n" + " or 0,1 \n" + " slgr 1,1 \n" + " lgr 2,1 \n" + " lgr 4,1 \n" + " lgr 5,1 \n" + "0: .long 0xb2ae0046 \n" + "1: brc 2,0b \n" + " brc 4,0b \n" + " ipm %0 \n" + " srl %0,28 \n" + " iihh %0,0 \n" + " iihl %0,0 \n" + " lgr %1,1 \n" + " st 4,0(3) \n" + " st 5,4(3) \n" + "2: \n" + ".section .fixup,\"ax\" \n" + "3: \n" + " lhi %0,%h6 \n" + " jg 2b \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + " .align 8 \n" + " .quad 0b,3b \n" + " .quad 1b,3b \n" + ".previous" + :"=d"(ccode),"=d"(*st) + :"d" (q_nr), "d" (rsp), "d" (id), "d" (buff_l), "K" (DEV_REC_EXCEPTION) + :"cc","0","1","2","3","4","5","6","7","memory"); +#else + (" lr 0,%2 \n" + " lr 3,%4 \n" + " lr 6,%3 \n" + " lr 7,%5 \n" + " lhi 1,128 \n" + " sll 1,24 \n" + " or 0,1 \n" + " slr 1,1 \n" + " lr 2,1 \n" + " lr 4,1 \n" + " lr 5,1 \n" + "0: .long 0xb2ae0046 \n" + "1: brc 2,0b \n" + " brc 4,0b \n" + " ipm %0 \n" + " srl %0,28 \n" + " lr %1,1 \n" + " st 4,0(3) \n" + " st 5,4(3) \n" + "2: \n" + ".section .fixup,\"ax\" \n" + "3: \n" + " lhi %0,%h6 \n" + " bras 1,4f \n" + " .long 2b \n" + "4: \n" + " l 1,0(1) \n" + " br 1 \n" + ".previous \n" + ".section __ex_table,\"a\" \n" + " .align 4 \n" + " .long 0b,3b \n" + " .long 1b,3b \n" + ".previous" + :"=d"(ccode),"=d"(*st) + :"d" (q_nr), "d" (rsp), "d" (id), "d" (buff_l), "K" (DEV_REC_EXCEPTION) + :"cc","0","1","2","3","4","5","6","7","memory"); +#endif + return ccode; +} + +static inline void +itoLe2(int *i_p, unsigned char *lechars) +{ + *lechars = *((unsigned char *) i_p + sizeof(int) - 1); + *(lechars + 1) = *((unsigned char *) i_p + sizeof(int) - 2); +} + +static inline void +le2toI(unsigned char *lechars, int *i_p) +{ + unsigned char *ic_p; + *i_p = 0; + ic_p = (unsigned char *) i_p; + *(ic_p + 2) = *(lechars + 1); + *(ic_p + 3) = *(lechars); +} + +static inline int +is_empty(unsigned char *ptr, int len) +{ + return !memcmp(ptr, (unsigned char *) &static_pvt_me_key+60, len); +} + +enum hdstat +query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type) +{ + int q_nr, i, t_depth, t_dev_type; + enum devstat ccode; + struct ap_status_word stat_word; + enum hdstat stat; + int break_out; + + q_nr = (deviceNr << SKIP_BITL) + cdx; + stat = HD_BUSY; + ccode = testq(q_nr, &t_depth, &t_dev_type, &stat_word); + PDEBUG("ccode %d response_code %02X\n", ccode, stat_word.response_code); + break_out = 0; + for (i = 0; i < resetNr; i++) { + if (ccode > 3) { + PRINTKC("Exception testing device %d\n", i); + return HD_TSQ_EXCEPTION; + } + switch (ccode) { + case 0: + PDEBUG("t_dev_type %d\n", t_dev_type); + break_out = 1; + stat = HD_ONLINE; + *q_depth = t_depth + 1; + switch (t_dev_type) { + case PCICA_HW: + *dev_type = PCICA; + break; + case PCICC_HW: + *dev_type = PCICC; + break; + case PCIXCC_HW: + *dev_type = PCIXCC_UNK; + break; + case CEX2C_HW: + *dev_type = CEX2C; + break; + case CEX2A_HW: + *dev_type = CEX2A; + break; + default: + *dev_type = NILDEV; + break; + } + PDEBUG("available device %d: Q depth = %d, dev " + "type = %d, stat = %02X%02X%02X%02X\n", + deviceNr, *q_depth, *dev_type, + stat_word.q_stat_flags, + stat_word.response_code, + stat_word.reserved[0], + stat_word.reserved[1]); + break; + case 3: + switch (stat_word.response_code) { + case AP_RESPONSE_NORMAL: + stat = HD_ONLINE; + break_out = 1; + *q_depth = t_depth + 1; + *dev_type = t_dev_type; + PDEBUG("cc3, available device " + "%d: Q depth = %d, dev " + "type = %d, stat = " + "%02X%02X%02X%02X\n", + deviceNr, *q_depth, + *dev_type, + stat_word.q_stat_flags, + stat_word.response_code, + stat_word.reserved[0], + stat_word.reserved[1]); + break; + case AP_RESPONSE_Q_NOT_AVAIL: + stat = HD_NOT_THERE; + break_out = 1; + break; + case AP_RESPONSE_RESET_IN_PROGRESS: + PDEBUG("device %d in reset\n", + deviceNr); + break; + case AP_RESPONSE_DECONFIGURED: + stat = HD_DECONFIGURED; + break_out = 1; + break; + case AP_RESPONSE_CHECKSTOPPED: + stat = HD_CHECKSTOPPED; + break_out = 1; + break; + case AP_RESPONSE_BUSY: + PDEBUG("device %d busy\n", + deviceNr); + break; + default: + break; + } + break; + default: + stat = HD_NOT_THERE; + break_out = 1; + break; + } + if (break_out) + break; + + udelay(5); + + ccode = testq(q_nr, &t_depth, &t_dev_type, &stat_word); + } + return stat; +} + +enum devstat +reset_device(int deviceNr, int cdx, int resetNr) +{ + int q_nr, ccode = 0, dummy_qdepth, dummy_devType, i; + struct ap_status_word stat_word; + enum devstat stat; + int break_out; + + q_nr = (deviceNr << SKIP_BITL) + cdx; + stat = DEV_GONE; + ccode = resetq(q_nr, &stat_word); + if (ccode > 3) + return DEV_RSQ_EXCEPTION; + + break_out = 0; + for (i = 0; i < resetNr; i++) { + switch (ccode) { + case 0: + stat = DEV_ONLINE; + if (stat_word.q_stat_flags & AP_Q_STATUS_EMPTY) + break_out = 1; + break; + case 3: + switch (stat_word.response_code) { + case AP_RESPONSE_NORMAL: + stat = DEV_ONLINE; + if (stat_word.q_stat_flags & AP_Q_STATUS_EMPTY) + break_out = 1; + break; + case AP_RESPONSE_Q_NOT_AVAIL: + case AP_RESPONSE_DECONFIGURED: + case AP_RESPONSE_CHECKSTOPPED: + stat = DEV_GONE; + break_out = 1; + break; + case AP_RESPONSE_RESET_IN_PROGRESS: + case AP_RESPONSE_BUSY: + default: + break; + } + break; + default: + stat = DEV_GONE; + break_out = 1; + break; + } + if (break_out == 1) + break; + udelay(5); + + ccode = testq(q_nr, &dummy_qdepth, &dummy_devType, &stat_word); + if (ccode > 3) { + stat = DEV_TSQ_EXCEPTION; + break; + } + } + PDEBUG("Number of testq's needed for reset: %d\n", i); + + if (i >= resetNr) { + stat = DEV_GONE; + } + + return stat; +} + +#ifdef DEBUG_HYDRA_MSGS +static inline void +print_buffer(unsigned char *buffer, int bufflen) +{ + int i; + for (i = 0; i < bufflen; i += 16) { + PRINTK("%04X: %02X%02X%02X%02X %02X%02X%02X%02X " + "%02X%02X%02X%02X %02X%02X%02X%02X\n", i, + buffer[i+0], buffer[i+1], buffer[i+2], buffer[i+3], + buffer[i+4], buffer[i+5], buffer[i+6], buffer[i+7], + buffer[i+8], buffer[i+9], buffer[i+10], buffer[i+11], + buffer[i+12], buffer[i+13], buffer[i+14], buffer[i+15]); + } +} +#endif + +enum devstat +send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext) +{ + struct ap_status_word stat_word; + enum devstat stat; + int ccode; + u32 *q_nr_p = (u32 *)msg_ext; + + *q_nr_p = (dev_nr << SKIP_BITL) + cdx; + PDEBUG("msg_len passed to sen: %d\n", msg_len); + PDEBUG("q number passed to sen: %02x%02x%02x%02x\n", + msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3]); + stat = DEV_GONE; + +#ifdef DEBUG_HYDRA_MSGS + PRINTK("Request header: %02X%02X%02X%02X %02X%02X%02X%02X " + "%02X%02X%02X%02X\n", + msg_ext[0], msg_ext[1], msg_ext[2], msg_ext[3], + msg_ext[4], msg_ext[5], msg_ext[6], msg_ext[7], + msg_ext[8], msg_ext[9], msg_ext[10], msg_ext[11]); + print_buffer(msg_ext+CALLER_HEADER, msg_len); +#endif + + ccode = sen(msg_len, msg_ext, &stat_word); + if (ccode > 3) + return DEV_SEN_EXCEPTION; + + PDEBUG("nq cc: %u, st: %02x%02x%02x%02x\n", + ccode, stat_word.q_stat_flags, stat_word.response_code, + stat_word.reserved[0], stat_word.reserved[1]); + switch (ccode) { + case 0: + stat = DEV_ONLINE; + break; + case 1: + stat = DEV_GONE; + break; + case 3: + switch (stat_word.response_code) { + case AP_RESPONSE_NORMAL: + stat = DEV_ONLINE; + break; + case AP_RESPONSE_Q_FULL: + stat = DEV_QUEUE_FULL; + break; + default: + stat = DEV_GONE; + break; + } + break; + default: + stat = DEV_GONE; + break; + } + + return stat; +} + +enum devstat +receive_from_AP(int dev_nr, int cdx, int resplen, unsigned char *resp, + unsigned char *psmid) +{ + int ccode; + struct ap_status_word stat_word; + enum devstat stat; + + memset(resp, 0x00, 8); + + ccode = rec((dev_nr << SKIP_BITL) + cdx, resplen, resp, psmid, + &stat_word); + if (ccode > 3) + return DEV_REC_EXCEPTION; + + PDEBUG("dq cc: %u, st: %02x%02x%02x%02x\n", + ccode, stat_word.q_stat_flags, stat_word.response_code, + stat_word.reserved[0], stat_word.reserved[1]); + + stat = DEV_GONE; + switch (ccode) { + case 0: + stat = DEV_ONLINE; +#ifdef DEBUG_HYDRA_MSGS + print_buffer(resp, resplen); +#endif + break; + case 3: + switch (stat_word.response_code) { + case AP_RESPONSE_NORMAL: + stat = DEV_ONLINE; + break; + case AP_RESPONSE_NO_PENDING_REPLY: + if (stat_word.q_stat_flags & AP_Q_STATUS_EMPTY) + stat = DEV_EMPTY; + else + stat = DEV_NO_WORK; + break; + case AP_RESPONSE_INDEX_TOO_BIG: + case AP_RESPONSE_NO_FIRST_PART: + case AP_RESPONSE_MESSAGE_TOO_BIG: + stat = DEV_BAD_MESSAGE; + break; + default: + break; + } + break; + default: + break; + } + + return stat; +} + +static inline int +pad_msg(unsigned char *buffer, int totalLength, int msgLength) +{ + int pad_len; + + for (pad_len = 0; pad_len < (totalLength - msgLength); pad_len++) + if (buffer[pad_len] != 0x00) + break; + pad_len -= 3; + if (pad_len < 8) + return SEN_PAD_ERROR; + + buffer[0] = 0x00; + buffer[1] = 0x02; + + memcpy(buffer+2, static_pad, pad_len); + + buffer[pad_len + 2] = 0x00; + + return 0; +} + +static inline int +is_common_public_key(unsigned char *key, int len) +{ + int i; + + for (i = 0; i < len; i++) + if (key[i]) + break; + key += i; + len -= i; + if (((len == 1) && (key[0] == 3)) || + ((len == 3) && (key[0] == 1) && (key[1] == 0) && (key[2] == 1))) + return 1; + + return 0; +} + +static int +ICAMEX_msg_to_type4MEX_msg(struct ica_rsa_modexpo *icaMex_p, int *z90cMsg_l_p, + union type4_msg *z90cMsg_p) +{ + int mod_len, msg_size, mod_tgt_len, exp_tgt_len, inp_tgt_len; + unsigned char *mod_tgt, *exp_tgt, *inp_tgt; + union type4_msg *tmp_type4_msg; + + mod_len = icaMex_p->inputdatalength; + + msg_size = ((mod_len <= 128) ? TYPE4_SME_LEN : TYPE4_LME_LEN) + + CALLER_HEADER; + + memset(z90cMsg_p, 0, msg_size); + + tmp_type4_msg = (union type4_msg *) + ((unsigned char *) z90cMsg_p + CALLER_HEADER); + + tmp_type4_msg->sme.header.msg_type_code = TYPE4_TYPE_CODE; + tmp_type4_msg->sme.header.request_code = TYPE4_REQU_CODE; + + if (mod_len <= 128) { + tmp_type4_msg->sme.header.msg_fmt = TYPE4_SME_FMT; + tmp_type4_msg->sme.header.msg_len = TYPE4_SME_LEN; + mod_tgt = tmp_type4_msg->sme.modulus; + mod_tgt_len = sizeof(tmp_type4_msg->sme.modulus); + exp_tgt = tmp_type4_msg->sme.exponent; + exp_tgt_len = sizeof(tmp_type4_msg->sme.exponent); + inp_tgt = tmp_type4_msg->sme.message; + inp_tgt_len = sizeof(tmp_type4_msg->sme.message); + } else { + tmp_type4_msg->lme.header.msg_fmt = TYPE4_LME_FMT; + tmp_type4_msg->lme.header.msg_len = TYPE4_LME_LEN; + mod_tgt = tmp_type4_msg->lme.modulus; + mod_tgt_len = sizeof(tmp_type4_msg->lme.modulus); + exp_tgt = tmp_type4_msg->lme.exponent; + exp_tgt_len = sizeof(tmp_type4_msg->lme.exponent); + inp_tgt = tmp_type4_msg->lme.message; + inp_tgt_len = sizeof(tmp_type4_msg->lme.message); + } + + mod_tgt += (mod_tgt_len - mod_len); + if (copy_from_user(mod_tgt, icaMex_p->n_modulus, mod_len)) + return SEN_RELEASED; + if (is_empty(mod_tgt, mod_len)) + return SEN_USER_ERROR; + exp_tgt += (exp_tgt_len - mod_len); + if (copy_from_user(exp_tgt, icaMex_p->b_key, mod_len)) + return SEN_RELEASED; + if (is_empty(exp_tgt, mod_len)) + return SEN_USER_ERROR; + inp_tgt += (inp_tgt_len - mod_len); + if (copy_from_user(inp_tgt, icaMex_p->inputdata, mod_len)) + return SEN_RELEASED; + if (is_empty(inp_tgt, mod_len)) + return SEN_USER_ERROR; + + *z90cMsg_l_p = msg_size - CALLER_HEADER; + + return 0; +} + +static int +ICACRT_msg_to_type4CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p, + int *z90cMsg_l_p, union type4_msg *z90cMsg_p) +{ + int mod_len, short_len, long_len, tmp_size, p_tgt_len, q_tgt_len, + dp_tgt_len, dq_tgt_len, u_tgt_len, inp_tgt_len; + unsigned char *p_tgt, *q_tgt, *dp_tgt, *dq_tgt, *u_tgt, *inp_tgt; + union type4_msg *tmp_type4_msg; + + mod_len = icaMsg_p->inputdatalength; + short_len = mod_len / 2; + long_len = mod_len / 2 + 8; + + tmp_size = ((mod_len <= 128) ? TYPE4_SCR_LEN : TYPE4_LCR_LEN) + + CALLER_HEADER; + + memset(z90cMsg_p, 0, tmp_size); + + tmp_type4_msg = (union type4_msg *) + ((unsigned char *) z90cMsg_p + CALLER_HEADER); + + tmp_type4_msg->scr.header.msg_type_code = TYPE4_TYPE_CODE; + tmp_type4_msg->scr.header.request_code = TYPE4_REQU_CODE; + if (mod_len <= 128) { + tmp_type4_msg->scr.header.msg_fmt = TYPE4_SCR_FMT; + tmp_type4_msg->scr.header.msg_len = TYPE4_SCR_LEN; + p_tgt = tmp_type4_msg->scr.p; + p_tgt_len = sizeof(tmp_type4_msg->scr.p); + q_tgt = tmp_type4_msg->scr.q; + q_tgt_len = sizeof(tmp_type4_msg->scr.q); + dp_tgt = tmp_type4_msg->scr.dp; + dp_tgt_len = sizeof(tmp_type4_msg->scr.dp); + dq_tgt = tmp_type4_msg->scr.dq; + dq_tgt_len = sizeof(tmp_type4_msg->scr.dq); + u_tgt = tmp_type4_msg->scr.u; + u_tgt_len = sizeof(tmp_type4_msg->scr.u); + inp_tgt = tmp_type4_msg->scr.message; + inp_tgt_len = sizeof(tmp_type4_msg->scr.message); + } else { + tmp_type4_msg->lcr.header.msg_fmt = TYPE4_LCR_FMT; + tmp_type4_msg->lcr.header.msg_len = TYPE4_LCR_LEN; + p_tgt = tmp_type4_msg->lcr.p; + p_tgt_len = sizeof(tmp_type4_msg->lcr.p); + q_tgt = tmp_type4_msg->lcr.q; + q_tgt_len = sizeof(tmp_type4_msg->lcr.q); + dp_tgt = tmp_type4_msg->lcr.dp; + dp_tgt_len = sizeof(tmp_type4_msg->lcr.dp); + dq_tgt = tmp_type4_msg->lcr.dq; + dq_tgt_len = sizeof(tmp_type4_msg->lcr.dq); + u_tgt = tmp_type4_msg->lcr.u; + u_tgt_len = sizeof(tmp_type4_msg->lcr.u); + inp_tgt = tmp_type4_msg->lcr.message; + inp_tgt_len = sizeof(tmp_type4_msg->lcr.message); + } + + p_tgt += (p_tgt_len - long_len); + if (copy_from_user(p_tgt, icaMsg_p->np_prime, long_len)) + return SEN_RELEASED; + if (is_empty(p_tgt, long_len)) + return SEN_USER_ERROR; + q_tgt += (q_tgt_len - short_len); + if (copy_from_user(q_tgt, icaMsg_p->nq_prime, short_len)) + return SEN_RELEASED; + if (is_empty(q_tgt, short_len)) + return SEN_USER_ERROR; + dp_tgt += (dp_tgt_len - long_len); + if (copy_from_user(dp_tgt, icaMsg_p->bp_key, long_len)) + return SEN_RELEASED; + if (is_empty(dp_tgt, long_len)) + return SEN_USER_ERROR; + dq_tgt += (dq_tgt_len - short_len); + if (copy_from_user(dq_tgt, icaMsg_p->bq_key, short_len)) + return SEN_RELEASED; + if (is_empty(dq_tgt, short_len)) + return SEN_USER_ERROR; + u_tgt += (u_tgt_len - long_len); + if (copy_from_user(u_tgt, icaMsg_p->u_mult_inv, long_len)) + return SEN_RELEASED; + if (is_empty(u_tgt, long_len)) + return SEN_USER_ERROR; + inp_tgt += (inp_tgt_len - mod_len); + if (copy_from_user(inp_tgt, icaMsg_p->inputdata, mod_len)) + return SEN_RELEASED; + if (is_empty(inp_tgt, mod_len)) + return SEN_USER_ERROR; + + *z90cMsg_l_p = tmp_size - CALLER_HEADER; + + return 0; +} + +static int +ICAMEX_msg_to_type6MEX_de_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, + int *z90cMsg_l_p, struct type6_msg *z90cMsg_p) +{ + int mod_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l; + unsigned char *temp; + struct type6_hdr *tp6Hdr_p; + struct CPRB *cprb_p; + struct cca_private_ext_ME *key_p; + static int deprecated_msg_count = 0; + + mod_len = icaMsg_p->inputdatalength; + tmp_size = FIXED_TYPE6_ME_LEN + mod_len; + total_CPRB_len = tmp_size - sizeof(struct type6_hdr); + parmBlock_l = total_CPRB_len - sizeof(struct CPRB); + tmp_size = 4*((tmp_size + 3)/4) + CALLER_HEADER; + + memset(z90cMsg_p, 0, tmp_size); + + temp = (unsigned char *)z90cMsg_p + CALLER_HEADER; + memcpy(temp, &static_type6_hdr, sizeof(struct type6_hdr)); + tp6Hdr_p = (struct type6_hdr *)temp; + tp6Hdr_p->ToCardLen1 = 4*((total_CPRB_len+3)/4); + tp6Hdr_p->FromCardLen1 = RESPONSE_CPRB_SIZE; + + temp += sizeof(struct type6_hdr); + memcpy(temp, &static_cprb, sizeof(struct CPRB)); + cprb_p = (struct CPRB *) temp; + cprb_p->usage_domain[0]= (unsigned char)cdx; + itoLe2(&parmBlock_l, cprb_p->req_parml); + itoLe2((int *)&(tp6Hdr_p->FromCardLen1), cprb_p->rpl_parml); + + temp += sizeof(struct CPRB); + memcpy(temp, &static_pkd_function_and_rules, + sizeof(struct function_and_rules_block)); + + temp += sizeof(struct function_and_rules_block); + vud_len = 2 + icaMsg_p->inputdatalength; + itoLe2(&vud_len, temp); + + temp += 2; + if (copy_from_user(temp, icaMsg_p->inputdata, mod_len)) + return SEN_RELEASED; + if (is_empty(temp, mod_len)) + return SEN_USER_ERROR; + + temp += mod_len; + memcpy(temp, &static_T6_keyBlock_hdr, sizeof(struct T6_keyBlock_hdr)); + + temp += sizeof(struct T6_keyBlock_hdr); + memcpy(temp, &static_pvt_me_key, sizeof(struct cca_private_ext_ME)); + key_p = (struct cca_private_ext_ME *)temp; + temp = key_p->pvtMESec.exponent + sizeof(key_p->pvtMESec.exponent) + - mod_len; + if (copy_from_user(temp, icaMsg_p->b_key, mod_len)) + return SEN_RELEASED; + if (is_empty(temp, mod_len)) + return SEN_USER_ERROR; + + if (is_common_public_key(temp, mod_len)) { + if (deprecated_msg_count < 20) { + PRINTK("Common public key used for modex decrypt\n"); + deprecated_msg_count++; + if (deprecated_msg_count == 20) + PRINTK("No longer issuing messages about common" + " public key for modex decrypt.\n"); + } + return SEN_NOT_AVAIL; + } + + temp = key_p->pvtMESec.modulus + sizeof(key_p->pvtMESec.modulus) + - mod_len; + if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len)) + return SEN_RELEASED; + if (is_empty(temp, mod_len)) + return SEN_USER_ERROR; + + key_p->pubMESec.modulus_bit_len = 8 * mod_len; + + *z90cMsg_l_p = tmp_size - CALLER_HEADER; + + return 0; +} + +static int +ICAMEX_msg_to_type6MEX_en_msg(struct ica_rsa_modexpo *icaMsg_p, int cdx, + int *z90cMsg_l_p, struct type6_msg *z90cMsg_p) +{ + int mod_len, vud_len, exp_len, key_len; + int pad_len, tmp_size, total_CPRB_len, parmBlock_l, i; + unsigned char *temp_exp, *exp_p, *temp; + struct type6_hdr *tp6Hdr_p; + struct CPRB *cprb_p; + struct cca_public_key *key_p; + struct T6_keyBlock_hdr *keyb_p; + + temp_exp = kmalloc(256, GFP_KERNEL); + if (!temp_exp) + return EGETBUFF; + mod_len = icaMsg_p->inputdatalength; + if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) { + kfree(temp_exp); + return SEN_RELEASED; + } + if (is_empty(temp_exp, mod_len)) { + kfree(temp_exp); + return SEN_USER_ERROR; + } + + exp_p = temp_exp; + for (i = 0; i < mod_len; i++) + if (exp_p[i]) + break; + if (i >= mod_len) { + kfree(temp_exp); + return SEN_USER_ERROR; + } + + exp_len = mod_len - i; + exp_p += i; + + PDEBUG("exp_len after computation: %08x\n", exp_len); + tmp_size = FIXED_TYPE6_ME_EN_LEN + 2 * mod_len + exp_len; + total_CPRB_len = tmp_size - sizeof(struct type6_hdr); + parmBlock_l = total_CPRB_len - sizeof(struct CPRB); + tmp_size = 4*((tmp_size + 3)/4) + CALLER_HEADER; + + vud_len = 2 + mod_len; + memset(z90cMsg_p, 0, tmp_size); + + temp = (unsigned char *)z90cMsg_p + CALLER_HEADER; + memcpy(temp, &static_type6_hdr, sizeof(struct type6_hdr)); + tp6Hdr_p = (struct type6_hdr *)temp; + tp6Hdr_p->ToCardLen1 = 4*((total_CPRB_len+3)/4); + tp6Hdr_p->FromCardLen1 = RESPONSE_CPRB_SIZE; + memcpy(tp6Hdr_p->function_code, static_PKE_function_code, + sizeof(static_PKE_function_code)); + temp += sizeof(struct type6_hdr); + memcpy(temp, &static_cprb, sizeof(struct CPRB)); + cprb_p = (struct CPRB *) temp; + cprb_p->usage_domain[0]= (unsigned char)cdx; + itoLe2((int *)&(tp6Hdr_p->FromCardLen1), cprb_p->rpl_parml); + temp += sizeof(struct CPRB); + memcpy(temp, &static_pke_function_and_rules, + sizeof(struct function_and_rules_block)); + temp += sizeof(struct function_and_rules_block); + temp += 2; + if (copy_from_user(temp, icaMsg_p->inputdata, mod_len)) { + kfree(temp_exp); + return SEN_RELEASED; + } + if (is_empty(temp, mod_len)) { + kfree(temp_exp); + return SEN_USER_ERROR; + } + if ((temp[0] != 0x00) || (temp[1] != 0x02)) { + kfree(temp_exp); + return SEN_NOT_AVAIL; + } + for (i = 2; i < mod_len; i++) + if (temp[i] == 0x00) + break; + if ((i < 9) || (i > (mod_len - 2))) { + kfree(temp_exp); + return SEN_NOT_AVAIL; + } + pad_len = i + 1; + vud_len = mod_len - pad_len; + memmove(temp, temp+pad_len, vud_len); + temp -= 2; + vud_len += 2; + itoLe2(&vud_len, temp); + temp += (vud_len); + keyb_p = (struct T6_keyBlock_hdr *)temp; + temp += sizeof(struct T6_keyBlock_hdr); + memcpy(temp, &static_public_key, sizeof(static_public_key)); + key_p = (struct cca_public_key *)temp; + temp = key_p->pubSec.exponent; + memcpy(temp, exp_p, exp_len); + kfree(temp_exp); + temp += exp_len; + if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len)) + return SEN_RELEASED; + if (is_empty(temp, mod_len)) + return SEN_USER_ERROR; + key_p->pubSec.modulus_bit_len = 8 * mod_len; + key_p->pubSec.modulus_byte_len = mod_len; + key_p->pubSec.exponent_len = exp_len; + key_p->pubSec.section_length = CALLER_HEADER + mod_len + exp_len; + key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr); + key_p->pubHdr.token_length = key_len; + key_len += 4; + itoLe2(&key_len, keyb_p->ulen); + key_len += 2; + itoLe2(&key_len, keyb_p->blen); + parmBlock_l -= pad_len; + itoLe2(&parmBlock_l, cprb_p->req_parml); + *z90cMsg_l_p = tmp_size - CALLER_HEADER; + + return 0; +} + +static int +ICACRT_msg_to_type6CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx, + int *z90cMsg_l_p, struct type6_msg *z90cMsg_p) +{ + int mod_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l, short_len; + int long_len, pad_len, keyPartsLen, tmp_l; + unsigned char *tgt_p, *temp; + struct type6_hdr *tp6Hdr_p; + struct CPRB *cprb_p; + struct cca_token_hdr *keyHdr_p; + struct cca_pvt_ext_CRT_sec *pvtSec_p; + struct cca_public_sec *pubSec_p; + + mod_len = icaMsg_p->inputdatalength; + short_len = mod_len / 2; + long_len = 8 + short_len; + keyPartsLen = 3 * long_len + 2 * short_len; + pad_len = (8 - (keyPartsLen % 8)) % 8; + keyPartsLen += pad_len + mod_len; + tmp_size = FIXED_TYPE6_CR_LEN + keyPartsLen + mod_len; + total_CPRB_len = tmp_size - sizeof(struct type6_hdr); + parmBlock_l = total_CPRB_len - sizeof(struct CPRB); + vud_len = 2 + mod_len; + tmp_size = 4*((tmp_size + 3)/4) + CALLER_HEADER; + + memset(z90cMsg_p, 0, tmp_size); + tgt_p = (unsigned char *)z90cMsg_p + CALLER_HEADER; + memcpy(tgt_p, &static_type6_hdr, sizeof(struct type6_hdr)); + tp6Hdr_p = (struct type6_hdr *)tgt_p; + tp6Hdr_p->ToCardLen1 = 4*((total_CPRB_len+3)/4); + tp6Hdr_p->FromCardLen1 = RESPONSE_CPRB_SIZE; + tgt_p += sizeof(struct type6_hdr); + cprb_p = (struct CPRB *) tgt_p; + memcpy(tgt_p, &static_cprb, sizeof(struct CPRB)); + cprb_p->usage_domain[0]= *((unsigned char *)(&(cdx))+3); + itoLe2(&parmBlock_l, cprb_p->req_parml); + memcpy(cprb_p->rpl_parml, cprb_p->req_parml, + sizeof(cprb_p->req_parml)); + tgt_p += sizeof(struct CPRB); + memcpy(tgt_p, &static_pkd_function_and_rules, + sizeof(struct function_and_rules_block)); + tgt_p += sizeof(struct function_and_rules_block); + itoLe2(&vud_len, tgt_p); + tgt_p += 2; + if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len)) + return SEN_RELEASED; + if (is_empty(tgt_p, mod_len)) + return SEN_USER_ERROR; + tgt_p += mod_len; + tmp_l = sizeof(struct T6_keyBlock_hdr) + sizeof(struct cca_token_hdr) + + sizeof(struct cca_pvt_ext_CRT_sec) + 0x0F + keyPartsLen; + itoLe2(&tmp_l, tgt_p); + temp = tgt_p + 2; + tmp_l -= 2; + itoLe2(&tmp_l, temp); + tgt_p += sizeof(struct T6_keyBlock_hdr); + keyHdr_p = (struct cca_token_hdr *)tgt_p; + keyHdr_p->token_identifier = CCA_TKN_HDR_ID_EXT; + tmp_l -= 4; + keyHdr_p->token_length = tmp_l; + tgt_p += sizeof(struct cca_token_hdr); + pvtSec_p = (struct cca_pvt_ext_CRT_sec *)tgt_p; + pvtSec_p->section_identifier = CCA_PVT_EXT_CRT_SEC_ID_PVT; + pvtSec_p->section_length = + sizeof(struct cca_pvt_ext_CRT_sec) + keyPartsLen; + pvtSec_p->key_format = CCA_PVT_EXT_CRT_SEC_FMT_CL; + pvtSec_p->key_use_flags[0] = CCA_PVT_USAGE_ALL; + pvtSec_p->p_len = long_len; + pvtSec_p->q_len = short_len; + pvtSec_p->dp_len = long_len; + pvtSec_p->dq_len = short_len; + pvtSec_p->u_len = long_len; + pvtSec_p->mod_len = mod_len; + pvtSec_p->pad_len = pad_len; + tgt_p += sizeof(struct cca_pvt_ext_CRT_sec); + if (copy_from_user(tgt_p, icaMsg_p->np_prime, long_len)) + return SEN_RELEASED; + if (is_empty(tgt_p, long_len)) + return SEN_USER_ERROR; + tgt_p += long_len; + if (copy_from_user(tgt_p, icaMsg_p->nq_prime, short_len)) + return SEN_RELEASED; + if (is_empty(tgt_p, short_len)) + return SEN_USER_ERROR; + tgt_p += short_len; + if (copy_from_user(tgt_p, icaMsg_p->bp_key, long_len)) + return SEN_RELEASED; + if (is_empty(tgt_p, long_len)) + return SEN_USER_ERROR; + tgt_p += long_len; + if (copy_from_user(tgt_p, icaMsg_p->bq_key, short_len)) + return SEN_RELEASED; + if (is_empty(tgt_p, short_len)) + return SEN_USER_ERROR; + tgt_p += short_len; + if (copy_from_user(tgt_p, icaMsg_p->u_mult_inv, long_len)) + return SEN_RELEASED; + if (is_empty(tgt_p, long_len)) + return SEN_USER_ERROR; + tgt_p += long_len; + tgt_p += pad_len; + memset(tgt_p, 0xFF, mod_len); + tgt_p += mod_len; + memcpy(tgt_p, &static_cca_pub_sec, sizeof(struct cca_public_sec)); + pubSec_p = (struct cca_public_sec *) tgt_p; + pubSec_p->modulus_bit_len = 8 * mod_len; + *z90cMsg_l_p = tmp_size - CALLER_HEADER; + + return 0; +} + +static int +ICAMEX_msg_to_type6MEX_msgX(struct ica_rsa_modexpo *icaMsg_p, int cdx, + int *z90cMsg_l_p, struct type6_msg *z90cMsg_p, + int dev_type) +{ + int mod_len, exp_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l; + int key_len, i; + unsigned char *temp_exp, *tgt_p, *temp, *exp_p; + struct type6_hdr *tp6Hdr_p; + struct CPRBX *cprbx_p; + struct cca_public_key *key_p; + struct T6_keyBlock_hdrX *keyb_p; + + temp_exp = kmalloc(256, GFP_KERNEL); + if (!temp_exp) + return EGETBUFF; + mod_len = icaMsg_p->inputdatalength; + if (copy_from_user(temp_exp, icaMsg_p->b_key, mod_len)) { + kfree(temp_exp); + return SEN_RELEASED; + } + if (is_empty(temp_exp, mod_len)) { + kfree(temp_exp); + return SEN_USER_ERROR; + } + exp_p = temp_exp; + for (i = 0; i < mod_len; i++) + if (exp_p[i]) + break; + if (i >= mod_len) { + kfree(temp_exp); + return SEN_USER_ERROR; + } + exp_len = mod_len - i; + exp_p += i; + PDEBUG("exp_len after computation: %08x\n", exp_len); + tmp_size = FIXED_TYPE6_ME_EN_LENX + 2 * mod_len + exp_len; + total_CPRB_len = tmp_size - sizeof(struct type6_hdr); + parmBlock_l = total_CPRB_len - sizeof(struct CPRBX); + tmp_size = tmp_size + CALLER_HEADER; + vud_len = 2 + mod_len; + memset(z90cMsg_p, 0, tmp_size); + tgt_p = (unsigned char *)z90cMsg_p + CALLER_HEADER; + memcpy(tgt_p, &static_type6_hdrX, sizeof(struct type6_hdr)); + tp6Hdr_p = (struct type6_hdr *)tgt_p; + tp6Hdr_p->ToCardLen1 = total_CPRB_len; + tp6Hdr_p->FromCardLen1 = RESPONSE_CPRBX_SIZE; + memcpy(tp6Hdr_p->function_code, static_PKE_function_code, + sizeof(static_PKE_function_code)); + tgt_p += sizeof(struct type6_hdr); + memcpy(tgt_p, &static_cprbx, sizeof(struct CPRBX)); + cprbx_p = (struct CPRBX *) tgt_p; + cprbx_p->domain = (unsigned short)cdx; + cprbx_p->rpl_msgbl = RESPONSE_CPRBX_SIZE; + tgt_p += sizeof(struct CPRBX); + if (dev_type == PCIXCC_MCL2) + memcpy(tgt_p, &static_pke_function_and_rulesX_MCL2, + sizeof(struct function_and_rules_block)); + else + memcpy(tgt_p, &static_pke_function_and_rulesX, + sizeof(struct function_and_rules_block)); + tgt_p += sizeof(struct function_and_rules_block); + + tgt_p += 2; + if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len)) { + kfree(temp_exp); + return SEN_RELEASED; + } + if (is_empty(tgt_p, mod_len)) { + kfree(temp_exp); + return SEN_USER_ERROR; + } + tgt_p -= 2; + *((short *)tgt_p) = (short) vud_len; + tgt_p += vud_len; + keyb_p = (struct T6_keyBlock_hdrX *)tgt_p; + tgt_p += sizeof(struct T6_keyBlock_hdrX); + memcpy(tgt_p, &static_public_key, sizeof(static_public_key)); + key_p = (struct cca_public_key *)tgt_p; + temp = key_p->pubSec.exponent; + memcpy(temp, exp_p, exp_len); + kfree(temp_exp); + temp += exp_len; + if (copy_from_user(temp, icaMsg_p->n_modulus, mod_len)) + return SEN_RELEASED; + if (is_empty(temp, mod_len)) + return SEN_USER_ERROR; + key_p->pubSec.modulus_bit_len = 8 * mod_len; + key_p->pubSec.modulus_byte_len = mod_len; + key_p->pubSec.exponent_len = exp_len; + key_p->pubSec.section_length = CALLER_HEADER + mod_len + exp_len; + key_len = key_p->pubSec.section_length + sizeof(struct cca_token_hdr); + key_p->pubHdr.token_length = key_len; + key_len += 4; + keyb_p->ulen = (unsigned short)key_len; + key_len += 2; + keyb_p->blen = (unsigned short)key_len; + cprbx_p->req_parml = parmBlock_l; + *z90cMsg_l_p = tmp_size - CALLER_HEADER; + + return 0; +} + +static int +ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx, + int *z90cMsg_l_p, struct type6_msg *z90cMsg_p, + int dev_type) +{ + int mod_len, vud_len, tmp_size, total_CPRB_len, parmBlock_l, short_len; + int long_len, pad_len, keyPartsLen, tmp_l; + unsigned char *tgt_p, *temp; + struct type6_hdr *tp6Hdr_p; + struct CPRBX *cprbx_p; + struct cca_token_hdr *keyHdr_p; + struct cca_pvt_ext_CRT_sec *pvtSec_p; + struct cca_public_sec *pubSec_p; + + mod_len = icaMsg_p->inputdatalength; + short_len = mod_len / 2; + long_len = 8 + short_len; + keyPartsLen = 3 * long_len + 2 * short_len; + pad_len = (8 - (keyPartsLen % 8)) % 8; + keyPartsLen += pad_len + mod_len; + tmp_size = FIXED_TYPE6_CR_LENX + keyPartsLen + mod_len; + total_CPRB_len = tmp_size - sizeof(struct type6_hdr); + parmBlock_l = total_CPRB_len - sizeof(struct CPRBX); + vud_len = 2 + mod_len; + tmp_size = tmp_size + CALLER_HEADER; + memset(z90cMsg_p, 0, tmp_size); + tgt_p = (unsigned char *)z90cMsg_p + CALLER_HEADER; + memcpy(tgt_p, &static_type6_hdrX, sizeof(struct type6_hdr)); + tp6Hdr_p = (struct type6_hdr *)tgt_p; + tp6Hdr_p->ToCardLen1 = total_CPRB_len; + tp6Hdr_p->FromCardLen1 = RESPONSE_CPRBX_SIZE; + tgt_p += sizeof(struct type6_hdr); + cprbx_p = (struct CPRBX *) tgt_p; + memcpy(tgt_p, &static_cprbx, sizeof(struct CPRBX)); + cprbx_p->domain = (unsigned short)cdx; + cprbx_p->req_parml = parmBlock_l; + cprbx_p->rpl_msgbl = parmBlock_l; + tgt_p += sizeof(struct CPRBX); + if (dev_type == PCIXCC_MCL2) + memcpy(tgt_p, &static_pkd_function_and_rulesX_MCL2, + sizeof(struct function_and_rules_block)); + else + memcpy(tgt_p, &static_pkd_function_and_rulesX, + sizeof(struct function_and_rules_block)); + tgt_p += sizeof(struct function_and_rules_block); + *((short *)tgt_p) = (short) vud_len; + tgt_p += 2; + if (copy_from_user(tgt_p, icaMsg_p->inputdata, mod_len)) + return SEN_RELEASED; + if (is_empty(tgt_p, mod_len)) + return SEN_USER_ERROR; + tgt_p += mod_len; + tmp_l = sizeof(struct T6_keyBlock_hdr) + sizeof(struct cca_token_hdr) + + sizeof(struct cca_pvt_ext_CRT_sec) + 0x0F + keyPartsLen; + *((short *)tgt_p) = (short) tmp_l; + temp = tgt_p + 2; + tmp_l -= 2; + *((short *)temp) = (short) tmp_l; + tgt_p += sizeof(struct T6_keyBlock_hdr); + keyHdr_p = (struct cca_token_hdr *)tgt_p; + keyHdr_p->token_identifier = CCA_TKN_HDR_ID_EXT; + tmp_l -= 4; + keyHdr_p->token_length = tmp_l; + tgt_p += sizeof(struct cca_token_hdr); + pvtSec_p = (struct cca_pvt_ext_CRT_sec *)tgt_p; + pvtSec_p->section_identifier = CCA_PVT_EXT_CRT_SEC_ID_PVT; + pvtSec_p->section_length = + sizeof(struct cca_pvt_ext_CRT_sec) + keyPartsLen; + pvtSec_p->key_format = CCA_PVT_EXT_CRT_SEC_FMT_CL; + pvtSec_p->key_use_flags[0] = CCA_PVT_USAGE_ALL; + pvtSec_p->p_len = long_len; + pvtSec_p->q_len = short_len; + pvtSec_p->dp_len = long_len; + pvtSec_p->dq_len = short_len; + pvtSec_p->u_len = long_len; + pvtSec_p->mod_len = mod_len; + pvtSec_p->pad_len = pad_len; + tgt_p += sizeof(struct cca_pvt_ext_CRT_sec); + if (copy_from_user(tgt_p, icaMsg_p->np_prime, long_len)) + return SEN_RELEASED; + if (is_empty(tgt_p, long_len)) + return SEN_USER_ERROR; + tgt_p += long_len; + if (copy_from_user(tgt_p, icaMsg_p->nq_prime, short_len)) + return SEN_RELEASED; + if (is_empty(tgt_p, short_len)) + return SEN_USER_ERROR; + tgt_p += short_len; + if (copy_from_user(tgt_p, icaMsg_p->bp_key, long_len)) + return SEN_RELEASED; + if (is_empty(tgt_p, long_len)) + return SEN_USER_ERROR; + tgt_p += long_len; + if (copy_from_user(tgt_p, icaMsg_p->bq_key, short_len)) + return SEN_RELEASED; + if (is_empty(tgt_p, short_len)) + return SEN_USER_ERROR; + tgt_p += short_len; + if (copy_from_user(tgt_p, icaMsg_p->u_mult_inv, long_len)) + return SEN_RELEASED; + if (is_empty(tgt_p, long_len)) + return SEN_USER_ERROR; + tgt_p += long_len; + tgt_p += pad_len; + memset(tgt_p, 0xFF, mod_len); + tgt_p += mod_len; + memcpy(tgt_p, &static_cca_pub_sec, sizeof(struct cca_public_sec)); + pubSec_p = (struct cca_public_sec *) tgt_p; + pubSec_p->modulus_bit_len = 8 * mod_len; + *z90cMsg_l_p = tmp_size - CALLER_HEADER; + + return 0; +} + +static int +ICAMEX_msg_to_type50MEX_msg(struct ica_rsa_modexpo *icaMex_p, int *z90cMsg_l_p, + union type50_msg *z90cMsg_p) +{ + int mod_len, msg_size, mod_tgt_len, exp_tgt_len, inp_tgt_len; + unsigned char *mod_tgt, *exp_tgt, *inp_tgt; + union type50_msg *tmp_type50_msg; + + mod_len = icaMex_p->inputdatalength; + + msg_size = ((mod_len <= 128) ? TYPE50_MEB1_LEN : TYPE50_MEB2_LEN) + + CALLER_HEADER; + + memset(z90cMsg_p, 0, msg_size); + + tmp_type50_msg = (union type50_msg *) + ((unsigned char *) z90cMsg_p + CALLER_HEADER); + + tmp_type50_msg->meb1.header.msg_type_code = TYPE50_TYPE_CODE; + + if (mod_len <= 128) { + tmp_type50_msg->meb1.header.msg_len = TYPE50_MEB1_LEN; + tmp_type50_msg->meb1.keyblock_type = TYPE50_MEB1_FMT; + mod_tgt = tmp_type50_msg->meb1.modulus; + mod_tgt_len = sizeof(tmp_type50_msg->meb1.modulus); + exp_tgt = tmp_type50_msg->meb1.exponent; + exp_tgt_len = sizeof(tmp_type50_msg->meb1.exponent); + inp_tgt = tmp_type50_msg->meb1.message; + inp_tgt_len = sizeof(tmp_type50_msg->meb1.message); + } else { + tmp_type50_msg->meb2.header.msg_len = TYPE50_MEB2_LEN; + tmp_type50_msg->meb2.keyblock_type = TYPE50_MEB2_FMT; + mod_tgt = tmp_type50_msg->meb2.modulus; + mod_tgt_len = sizeof(tmp_type50_msg->meb2.modulus); + exp_tgt = tmp_type50_msg->meb2.exponent; + exp_tgt_len = sizeof(tmp_type50_msg->meb2.exponent); + inp_tgt = tmp_type50_msg->meb2.message; + inp_tgt_len = sizeof(tmp_type50_msg->meb2.message); + } + + mod_tgt += (mod_tgt_len - mod_len); + if (copy_from_user(mod_tgt, icaMex_p->n_modulus, mod_len)) + return SEN_RELEASED; + if (is_empty(mod_tgt, mod_len)) + return SEN_USER_ERROR; + exp_tgt += (exp_tgt_len - mod_len); + if (copy_from_user(exp_tgt, icaMex_p->b_key, mod_len)) + return SEN_RELEASED; + if (is_empty(exp_tgt, mod_len)) + return SEN_USER_ERROR; + inp_tgt += (inp_tgt_len - mod_len); + if (copy_from_user(inp_tgt, icaMex_p->inputdata, mod_len)) + return SEN_RELEASED; + if (is_empty(inp_tgt, mod_len)) + return SEN_USER_ERROR; + + *z90cMsg_l_p = msg_size - CALLER_HEADER; + + return 0; +} + +static int +ICACRT_msg_to_type50CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p, + int *z90cMsg_l_p, union type50_msg *z90cMsg_p) +{ + int mod_len, short_len, long_len, tmp_size, p_tgt_len, q_tgt_len, + dp_tgt_len, dq_tgt_len, u_tgt_len, inp_tgt_len, long_offset; + unsigned char *p_tgt, *q_tgt, *dp_tgt, *dq_tgt, *u_tgt, *inp_tgt, + temp[8]; + union type50_msg *tmp_type50_msg; + + mod_len = icaMsg_p->inputdatalength; + short_len = mod_len / 2; + long_len = mod_len / 2 + 8; + long_offset = 0; + + if (long_len > 128) { + memset(temp, 0x00, sizeof(temp)); + if (copy_from_user(temp, icaMsg_p->np_prime, long_len-128)) + return SEN_RELEASED; + if (!is_empty(temp, 8)) + return SEN_NOT_AVAIL; + if (copy_from_user(temp, icaMsg_p->bp_key, long_len-128)) + return SEN_RELEASED; + if (!is_empty(temp, 8)) + return SEN_NOT_AVAIL; + if (copy_from_user(temp, icaMsg_p->u_mult_inv, long_len-128)) + return SEN_RELEASED; + if (!is_empty(temp, 8)) + return SEN_NOT_AVAIL; + long_offset = long_len - 128; + long_len = 128; + } + + tmp_size = ((long_len <= 64) ? TYPE50_CRB1_LEN : TYPE50_CRB2_LEN) + + CALLER_HEADER; + + memset(z90cMsg_p, 0, tmp_size); + + tmp_type50_msg = (union type50_msg *) + ((unsigned char *) z90cMsg_p + CALLER_HEADER); + + tmp_type50_msg->crb1.header.msg_type_code = TYPE50_TYPE_CODE; + if (long_len <= 64) { + tmp_type50_msg->crb1.header.msg_len = TYPE50_CRB1_LEN; + tmp_type50_msg->crb1.keyblock_type = TYPE50_CRB1_FMT; + p_tgt = tmp_type50_msg->crb1.p; + p_tgt_len = sizeof(tmp_type50_msg->crb1.p); + q_tgt = tmp_type50_msg->crb1.q; + q_tgt_len = sizeof(tmp_type50_msg->crb1.q); + dp_tgt = tmp_type50_msg->crb1.dp; + dp_tgt_len = sizeof(tmp_type50_msg->crb1.dp); + dq_tgt = tmp_type50_msg->crb1.dq; + dq_tgt_len = sizeof(tmp_type50_msg->crb1.dq); + u_tgt = tmp_type50_msg->crb1.u; + u_tgt_len = sizeof(tmp_type50_msg->crb1.u); + inp_tgt = tmp_type50_msg->crb1.message; + inp_tgt_len = sizeof(tmp_type50_msg->crb1.message); + } else { + tmp_type50_msg->crb2.header.msg_len = TYPE50_CRB2_LEN; + tmp_type50_msg->crb2.keyblock_type = TYPE50_CRB2_FMT; + p_tgt = tmp_type50_msg->crb2.p; + p_tgt_len = sizeof(tmp_type50_msg->crb2.p); + q_tgt = tmp_type50_msg->crb2.q; + q_tgt_len = sizeof(tmp_type50_msg->crb2.q); + dp_tgt = tmp_type50_msg->crb2.dp; + dp_tgt_len = sizeof(tmp_type50_msg->crb2.dp); + dq_tgt = tmp_type50_msg->crb2.dq; + dq_tgt_len = sizeof(tmp_type50_msg->crb2.dq); + u_tgt = tmp_type50_msg->crb2.u; + u_tgt_len = sizeof(tmp_type50_msg->crb2.u); + inp_tgt = tmp_type50_msg->crb2.message; + inp_tgt_len = sizeof(tmp_type50_msg->crb2.message); + } + + p_tgt += (p_tgt_len - long_len); + if (copy_from_user(p_tgt, icaMsg_p->np_prime + long_offset, long_len)) + return SEN_RELEASED; + if (is_empty(p_tgt, long_len)) + return SEN_USER_ERROR; + q_tgt += (q_tgt_len - short_len); + if (copy_from_user(q_tgt, icaMsg_p->nq_prime, short_len)) + return SEN_RELEASED; + if (is_empty(q_tgt, short_len)) + return SEN_USER_ERROR; + dp_tgt += (dp_tgt_len - long_len); + if (copy_from_user(dp_tgt, icaMsg_p->bp_key + long_offset, long_len)) + return SEN_RELEASED; + if (is_empty(dp_tgt, long_len)) + return SEN_USER_ERROR; + dq_tgt += (dq_tgt_len - short_len); + if (copy_from_user(dq_tgt, icaMsg_p->bq_key, short_len)) + return SEN_RELEASED; + if (is_empty(dq_tgt, short_len)) + return SEN_USER_ERROR; + u_tgt += (u_tgt_len - long_len); + if (copy_from_user(u_tgt, icaMsg_p->u_mult_inv + long_offset, long_len)) + return SEN_RELEASED; + if (is_empty(u_tgt, long_len)) + return SEN_USER_ERROR; + inp_tgt += (inp_tgt_len - mod_len); + if (copy_from_user(inp_tgt, icaMsg_p->inputdata, mod_len)) + return SEN_RELEASED; + if (is_empty(inp_tgt, mod_len)) + return SEN_USER_ERROR; + + *z90cMsg_l_p = tmp_size - CALLER_HEADER; + + return 0; +} + +int +convert_request(unsigned char *buffer, int func, unsigned short function, + int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p) +{ + if (dev_type == PCICA) { + if (func == ICARSACRT) + return ICACRT_msg_to_type4CRT_msg( + (struct ica_rsa_modexpo_crt *) buffer, + msg_l_p, (union type4_msg *) msg_p); + else + return ICAMEX_msg_to_type4MEX_msg( + (struct ica_rsa_modexpo *) buffer, + msg_l_p, (union type4_msg *) msg_p); + } + if (dev_type == PCICC) { + if (func == ICARSACRT) + return ICACRT_msg_to_type6CRT_msg( + (struct ica_rsa_modexpo_crt *) buffer, + cdx, msg_l_p, (struct type6_msg *)msg_p); + if (function == PCI_FUNC_KEY_ENCRYPT) + return ICAMEX_msg_to_type6MEX_en_msg( + (struct ica_rsa_modexpo *) buffer, + cdx, msg_l_p, (struct type6_msg *) msg_p); + else + return ICAMEX_msg_to_type6MEX_de_msg( + (struct ica_rsa_modexpo *) buffer, + cdx, msg_l_p, (struct type6_msg *) msg_p); + } + if ((dev_type == PCIXCC_MCL2) || + (dev_type == PCIXCC_MCL3) || + (dev_type == CEX2C)) { + if (func == ICARSACRT) + return ICACRT_msg_to_type6CRT_msgX( + (struct ica_rsa_modexpo_crt *) buffer, + cdx, msg_l_p, (struct type6_msg *) msg_p, + dev_type); + else + return ICAMEX_msg_to_type6MEX_msgX( + (struct ica_rsa_modexpo *) buffer, + cdx, msg_l_p, (struct type6_msg *) msg_p, + dev_type); + } + if (dev_type == CEX2A) { + if (func == ICARSACRT) + return ICACRT_msg_to_type50CRT_msg( + (struct ica_rsa_modexpo_crt *) buffer, + msg_l_p, (union type50_msg *) msg_p); + else + return ICAMEX_msg_to_type50MEX_msg( + (struct ica_rsa_modexpo *) buffer, + msg_l_p, (union type50_msg *) msg_p); + } + + return 0; +} + +int ext_bitlens_msg_count = 0; +static inline void +unset_ext_bitlens(void) +{ + if (!ext_bitlens_msg_count) { + PRINTK("Unable to use coprocessors for extended bitlengths. " + "Using PCICAs/CEX2As (if present) for extended " + "bitlengths. This is not an error.\n"); + ext_bitlens_msg_count++; + } + ext_bitlens = 0; +} + +int +convert_response(unsigned char *response, unsigned char *buffer, + int *respbufflen_p, unsigned char *resp_buff) +{ + struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer; + struct error_hdr *errh_p = (struct error_hdr *) response; + struct type80_hdr *t80h_p = (struct type80_hdr *) response; + struct type84_hdr *t84h_p = (struct type84_hdr *) response; + struct type86_fmt2_msg *t86m_p = (struct type86_fmt2_msg *) response; + int reply_code, service_rc, service_rs, src_l; + unsigned char *src_p, *tgt_p; + struct CPRB *cprb_p; + struct CPRBX *cprbx_p; + + src_p = 0; + reply_code = 0; + service_rc = 0; + service_rs = 0; + src_l = 0; + switch (errh_p->type) { + case TYPE82_RSP_CODE: + case TYPE88_RSP_CODE: + reply_code = errh_p->reply_code; + src_p = (unsigned char *)errh_p; + PRINTK("Hardware error: Type %02X Message Header: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + errh_p->type, + src_p[0], src_p[1], src_p[2], src_p[3], + src_p[4], src_p[5], src_p[6], src_p[7]); + break; + case TYPE80_RSP_CODE: + src_l = icaMsg_p->outputdatalength; + src_p = response + (int)t80h_p->len - src_l; + break; + case TYPE84_RSP_CODE: + src_l = icaMsg_p->outputdatalength; + src_p = response + (int)t84h_p->len - src_l; + break; + case TYPE86_RSP_CODE: + reply_code = t86m_p->header.reply_code; + if (reply_code != 0) + break; + cprb_p = (struct CPRB *) + (response + sizeof(struct type86_fmt2_msg)); + cprbx_p = (struct CPRBX *) cprb_p; + if (cprb_p->cprb_ver_id != 0x02) { + le2toI(cprb_p->ccp_rtcode, &service_rc); + if (service_rc != 0) { + le2toI(cprb_p->ccp_rscode, &service_rs); + if ((service_rc == 8) && (service_rs == 66)) + PDEBUG("Bad block format on PCICC\n"); + else if ((service_rc == 8) && (service_rs == 65)) + PDEBUG("Probably an even modulus on " + "PCICC\n"); + else if ((service_rc == 8) && (service_rs == 770)) { + PDEBUG("Invalid key length on PCICC\n"); + unset_ext_bitlens(); + return REC_USE_PCICA; + } + else if ((service_rc == 8) && (service_rs == 783)) { + PDEBUG("Extended bitlengths not enabled" + "on PCICC\n"); + unset_ext_bitlens(); + return REC_USE_PCICA; + } + else + PRINTK("service rc/rs (PCICC): %d/%d\n", + service_rc, service_rs); + return REC_OPERAND_INV; + } + src_p = (unsigned char *)cprb_p + sizeof(struct CPRB); + src_p += 4; + le2toI(src_p, &src_l); + src_l -= 2; + src_p += 2; + } else { + service_rc = (int)cprbx_p->ccp_rtcode; + if (service_rc != 0) { + service_rs = (int) cprbx_p->ccp_rscode; + if ((service_rc == 8) && (service_rs == 66)) + PDEBUG("Bad block format on PCIXCC\n"); + else if ((service_rc == 8) && (service_rs == 65)) + PDEBUG("Probably an even modulus on " + "PCIXCC\n"); + else if ((service_rc == 8) && (service_rs == 770)) { + PDEBUG("Invalid key length on PCIXCC\n"); + unset_ext_bitlens(); + return REC_USE_PCICA; + } + else if ((service_rc == 8) && (service_rs == 783)) { + PDEBUG("Extended bitlengths not enabled" + "on PCIXCC\n"); + unset_ext_bitlens(); + return REC_USE_PCICA; + } + else + PRINTK("service rc/rs (PCIXCC): %d/%d\n", + service_rc, service_rs); + return REC_OPERAND_INV; + } + src_p = (unsigned char *) + cprbx_p + sizeof(struct CPRBX); + src_p += 4; + src_l = (int)(*((short *) src_p)); + src_l -= 2; + src_p += 2; + } + break; + default: + src_p = (unsigned char *)errh_p; + PRINTK("Unrecognized Message Header: " + "%02x%02x%02x%02x%02x%02x%02x%02x\n", + src_p[0], src_p[1], src_p[2], src_p[3], + src_p[4], src_p[5], src_p[6], src_p[7]); + return REC_BAD_MESSAGE; + } + + if (reply_code) + switch (reply_code) { + case REP82_ERROR_MACHINE_FAILURE: + if (errh_p->type == TYPE82_RSP_CODE) + PRINTKW("Machine check failure\n"); + else + PRINTKW("Module failure\n"); + return REC_HARDWAR_ERR; + case REP82_ERROR_OPERAND_INVALID: + return REC_OPERAND_INV; + case REP88_ERROR_MESSAGE_MALFORMD: + PRINTKW("Message malformed\n"); + return REC_OPERAND_INV; + case REP82_ERROR_OPERAND_SIZE: + return REC_OPERAND_SIZE; + case REP82_ERROR_EVEN_MOD_IN_OPND: + return REC_EVEN_MOD; + case REP82_ERROR_MESSAGE_TYPE: + return WRONG_DEVICE_TYPE; + case REP82_ERROR_TRANSPORT_FAIL: + PRINTKW("Transport failed (APFS = %02X%02X%02X%02X)\n", + t86m_p->apfs[0], t86m_p->apfs[1], + t86m_p->apfs[2], t86m_p->apfs[3]); + return REC_HARDWAR_ERR; + default: + PRINTKW("reply code = %d\n", reply_code); + return REC_HARDWAR_ERR; + } + + if (service_rc != 0) + return REC_OPERAND_INV; + + if ((src_l > icaMsg_p->outputdatalength) || + (src_l > RESPBUFFSIZE) || + (src_l <= 0)) + return REC_OPERAND_SIZE; + + PDEBUG("Length returned = %d\n", src_l); + tgt_p = resp_buff + icaMsg_p->outputdatalength - src_l; + memcpy(tgt_p, src_p, src_l); + if ((errh_p->type == TYPE86_RSP_CODE) && (resp_buff < tgt_p)) { + memset(resp_buff, 0, icaMsg_p->outputdatalength - src_l); + if (pad_msg(resp_buff, icaMsg_p->outputdatalength, src_l)) + return REC_INVALID_PAD; + } + *respbufflen_p = icaMsg_p->outputdatalength; + if (*respbufflen_p == 0) + PRINTK("Zero *respbufflen_p\n"); + + return 0; +} + diff --git a/trunk/drivers/s390/crypto/z90main.c b/trunk/drivers/s390/crypto/z90main.c new file mode 100644 index 000000000000..b2f20ab8431a --- /dev/null +++ b/trunk/drivers/s390/crypto/z90main.c @@ -0,0 +1,3379 @@ +/* + * linux/drivers/s390/crypto/z90main.c + * + * z90crypt 1.3.3 + * + * Copyright (C) 2001, 2005 IBM Corporation + * Author(s): Robert Burroughs (burrough@us.ibm.com) + * Eric Rossman (edrossma@us.ibm.com) + * + * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include // copy_(from|to)_user +#include +#include +#include // mdelay +#include +#include // for tasklets +#include +#include +#include +#include +#include +#include "z90crypt.h" +#include "z90common.h" + +/** + * Defaults that may be modified. + */ + +/** + * You can specify a different minor at compile time. + */ +#ifndef Z90CRYPT_MINOR +#define Z90CRYPT_MINOR MISC_DYNAMIC_MINOR +#endif + +/** + * You can specify a different domain at compile time or on the insmod + * command line. + */ +#ifndef DOMAIN_INDEX +#define DOMAIN_INDEX -1 +#endif + +/** + * This is the name under which the device is registered in /proc/modules. + */ +#define REG_NAME "z90crypt" + +/** + * Cleanup should run every CLEANUPTIME seconds and should clean up requests + * older than CLEANUPTIME seconds in the past. + */ +#ifndef CLEANUPTIME +#define CLEANUPTIME 15 +#endif + +/** + * Config should run every CONFIGTIME seconds + */ +#ifndef CONFIGTIME +#define CONFIGTIME 30 +#endif + +/** + * The first execution of the config task should take place + * immediately after initialization + */ +#ifndef INITIAL_CONFIGTIME +#define INITIAL_CONFIGTIME 1 +#endif + +/** + * Reader should run every READERTIME milliseconds + * With the 100Hz patch for s390, z90crypt can lock the system solid while + * under heavy load. We'll try to avoid that. + */ +#ifndef READERTIME +#if HZ > 1000 +#define READERTIME 2 +#else +#define READERTIME 10 +#endif +#endif + +/** + * turn long device array index into device pointer + */ +#define LONG2DEVPTR(ndx) (z90crypt.device_p[(ndx)]) + +/** + * turn short device array index into long device array index + */ +#define SHRT2LONG(ndx) (z90crypt.overall_device_x.device_index[(ndx)]) + +/** + * turn short device array index into device pointer + */ +#define SHRT2DEVPTR(ndx) LONG2DEVPTR(SHRT2LONG(ndx)) + +/** + * Status for a work-element + */ +#define STAT_DEFAULT 0x00 // request has not been processed + +#define STAT_ROUTED 0x80 // bit 7: requests get routed to specific device + // else, device is determined each write +#define STAT_FAILED 0x40 // bit 6: this bit is set if the request failed + // before being sent to the hardware. +#define STAT_WRITTEN 0x30 // bits 5-4: work to be done, not sent to device +// 0x20 // UNUSED state +#define STAT_READPEND 0x10 // bits 5-4: work done, we're returning data now +#define STAT_NOWORK 0x00 // bits off: no work on any queue +#define STAT_RDWRMASK 0x30 // mask for bits 5-4 + +/** + * Macros to check the status RDWRMASK + */ +#define CHK_RDWRMASK(statbyte) ((statbyte) & STAT_RDWRMASK) +#define SET_RDWRMASK(statbyte, newval) \ + {(statbyte) &= ~STAT_RDWRMASK; (statbyte) |= newval;} + +/** + * Audit Trail. Progress of a Work element + * audit[0]: Unless noted otherwise, these bits are all set by the process + */ +#define FP_COPYFROM 0x80 // Caller's buffer has been copied to work element +#define FP_BUFFREQ 0x40 // Low Level buffer requested +#define FP_BUFFGOT 0x20 // Low Level buffer obtained +#define FP_SENT 0x10 // Work element sent to a crypto device + // (may be set by process or by reader task) +#define FP_PENDING 0x08 // Work element placed on pending queue + // (may be set by process or by reader task) +#define FP_REQUEST 0x04 // Work element placed on request queue +#define FP_ASLEEP 0x02 // Work element about to sleep +#define FP_AWAKE 0x01 // Work element has been awakened + +/** + * audit[1]: These bits are set by the reader task and/or the cleanup task + */ +#define FP_NOTPENDING 0x80 // Work element removed from pending queue +#define FP_AWAKENING 0x40 // Caller about to be awakened +#define FP_TIMEDOUT 0x20 // Caller timed out +#define FP_RESPSIZESET 0x10 // Response size copied to work element +#define FP_RESPADDRCOPIED 0x08 // Response address copied to work element +#define FP_RESPBUFFCOPIED 0x04 // Response buffer copied to work element +#define FP_REMREQUEST 0x02 // Work element removed from request queue +#define FP_SIGNALED 0x01 // Work element was awakened by a signal + +/** + * audit[2]: unused + */ + +/** + * state of the file handle in private_data.status + */ +#define STAT_OPEN 0 +#define STAT_CLOSED 1 + +/** + * PID() expands to the process ID of the current process + */ +#define PID() (current->pid) + +/** + * Selected Constants. The number of APs and the number of devices + */ +#ifndef Z90CRYPT_NUM_APS +#define Z90CRYPT_NUM_APS 64 +#endif +#ifndef Z90CRYPT_NUM_DEVS +#define Z90CRYPT_NUM_DEVS Z90CRYPT_NUM_APS +#endif + +/** + * Buffer size for receiving responses. The maximum Response Size + * is actually the maximum request size, since in an error condition + * the request itself may be returned unchanged. + */ +#define MAX_RESPONSE_SIZE 0x0000077C + +/** + * A count and status-byte mask + */ +struct status { + int st_count; // # of enabled devices + int disabled_count; // # of disabled devices + int user_disabled_count; // # of devices disabled via proc fs + unsigned char st_mask[Z90CRYPT_NUM_APS]; // current status mask +}; + +/** + * The array of device indexes is a mechanism for fast indexing into + * a long (and sparse) array. For instance, if APs 3, 9 and 47 are + * installed, z90CDeviceIndex[0] is 3, z90CDeviceIndex[1] is 9, and + * z90CDeviceIndex[2] is 47. + */ +struct device_x { + int device_index[Z90CRYPT_NUM_DEVS]; +}; + +/** + * All devices are arranged in a single array: 64 APs + */ +struct device { + int dev_type; // PCICA, PCICC, PCIXCC_MCL2, + // PCIXCC_MCL3, CEX2C, CEX2A + enum devstat dev_stat; // current device status + int dev_self_x; // Index in array + int disabled; // Set when device is in error + int user_disabled; // Set when device is disabled by user + int dev_q_depth; // q depth + unsigned char * dev_resp_p; // Response buffer address + int dev_resp_l; // Response Buffer length + int dev_caller_count; // Number of callers + int dev_total_req_cnt; // # requests for device since load + struct list_head dev_caller_list; // List of callers +}; + +/** + * There's a struct status and a struct device_x for each device type. + */ +struct hdware_block { + struct status hdware_mask; + struct status type_mask[Z90CRYPT_NUM_TYPES]; + struct device_x type_x_addr[Z90CRYPT_NUM_TYPES]; + unsigned char device_type_array[Z90CRYPT_NUM_APS]; +}; + +/** + * z90crypt is the topmost data structure in the hierarchy. + */ +struct z90crypt { + int max_count; // Nr of possible crypto devices + struct status mask; + int q_depth_array[Z90CRYPT_NUM_DEVS]; + int dev_type_array[Z90CRYPT_NUM_DEVS]; + struct device_x overall_device_x; // array device indexes + struct device * device_p[Z90CRYPT_NUM_DEVS]; + int terminating; + int domain_established;// TRUE: domain has been found + int cdx; // Crypto Domain Index + int len; // Length of this data structure + struct hdware_block *hdware_info; +}; + +/** + * An array of these structures is pointed to from dev_caller + * The length of the array depends on the device type. For APs, + * there are 8. + * + * The caller buffer is allocated to the user at OPEN. At WRITE, + * it contains the request; at READ, the response. The function + * send_to_crypto_device converts the request to device-dependent + * form and use the caller's OPEN-allocated buffer for the response. + * + * For the contents of caller_dev_dep_req and caller_dev_dep_req_p + * because that points to it, see the discussion in z90hardware.c. + * Search for "extended request message block". + */ +struct caller { + int caller_buf_l; // length of original request + unsigned char * caller_buf_p; // Original request on WRITE + int caller_dev_dep_req_l; // len device dependent request + unsigned char * caller_dev_dep_req_p; // Device dependent form + unsigned char caller_id[8]; // caller-supplied message id + struct list_head caller_liste; + unsigned char caller_dev_dep_req[MAX_RESPONSE_SIZE]; +}; + +/** + * Function prototypes from z90hardware.c + */ +enum hdstat query_online(int deviceNr, int cdx, int resetNr, int *q_depth, + int *dev_type); +enum devstat reset_device(int deviceNr, int cdx, int resetNr); +enum devstat send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext); +enum devstat receive_from_AP(int dev_nr, int cdx, int resplen, + unsigned char *resp, unsigned char *psmid); +int convert_request(unsigned char *buffer, int func, unsigned short function, + int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p); +int convert_response(unsigned char *response, unsigned char *buffer, + int *respbufflen_p, unsigned char *resp_buff); + +/** + * Low level function prototypes + */ +static int create_z90crypt(int *cdx_p); +static int refresh_z90crypt(int *cdx_p); +static int find_crypto_devices(struct status *deviceMask); +static int create_crypto_device(int index); +static int destroy_crypto_device(int index); +static void destroy_z90crypt(void); +static int refresh_index_array(struct status *status_str, + struct device_x *index_array); +static int probe_device_type(struct device *devPtr); +static int probe_PCIXCC_type(struct device *devPtr); + +/** + * proc fs definitions + */ +static struct proc_dir_entry *z90crypt_entry; + +/** + * data structures + */ + +/** + * work_element.opener points back to this structure + */ +struct priv_data { + pid_t opener_pid; + unsigned char status; // 0: open 1: closed +}; + +/** + * A work element is allocated for each request + */ +struct work_element { + struct priv_data *priv_data; + pid_t pid; + int devindex; // index of device processing this w_e + // (If request did not specify device, + // -1 until placed onto a queue) + int devtype; + struct list_head liste; // used for requestq and pendingq + char buffer[128]; // local copy of user request + int buff_size; // size of the buffer for the request + char resp_buff[RESPBUFFSIZE]; + int resp_buff_size; + char __user * resp_addr; // address of response in user space + unsigned int funccode; // function code of request + wait_queue_head_t waitq; + unsigned long requestsent; // time at which the request was sent + atomic_t alarmrung; // wake-up signal + unsigned char caller_id[8]; // pid + counter, for this w_e + unsigned char status[1]; // bits to mark status of the request + unsigned char audit[3]; // record of work element's progress + unsigned char * requestptr; // address of request buffer + int retcode; // return code of request +}; + +/** + * High level function prototypes + */ +static int z90crypt_open(struct inode *, struct file *); +static int z90crypt_release(struct inode *, struct file *); +static ssize_t z90crypt_read(struct file *, char __user *, size_t, loff_t *); +static ssize_t z90crypt_write(struct file *, const char __user *, + size_t, loff_t *); +static long z90crypt_unlocked_ioctl(struct file *, unsigned int, unsigned long); +static long z90crypt_compat_ioctl(struct file *, unsigned int, unsigned long); + +static void z90crypt_reader_task(unsigned long); +static void z90crypt_schedule_reader_task(unsigned long); +static void z90crypt_config_task(unsigned long); +static void z90crypt_cleanup_task(unsigned long); + +static int z90crypt_status(char *, char **, off_t, int, int *, void *); +static int z90crypt_status_write(struct file *, const char __user *, + unsigned long, void *); + +/** + * Storage allocated at initialization and used throughout the life of + * this insmod + */ +static int domain = DOMAIN_INDEX; +static struct z90crypt z90crypt; +static int quiesce_z90crypt; +static spinlock_t queuespinlock; +static struct list_head request_list; +static int requestq_count; +static struct list_head pending_list; +static int pendingq_count; + +static struct tasklet_struct reader_tasklet; +static struct timer_list reader_timer; +static struct timer_list config_timer; +static struct timer_list cleanup_timer; +static atomic_t total_open; +static atomic_t z90crypt_step; + +static struct file_operations z90crypt_fops = { + .owner = THIS_MODULE, + .read = z90crypt_read, + .write = z90crypt_write, + .unlocked_ioctl = z90crypt_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = z90crypt_compat_ioctl, +#endif + .open = z90crypt_open, + .release = z90crypt_release +}; + +static struct miscdevice z90crypt_misc_device = { + .minor = Z90CRYPT_MINOR, + .name = DEV_NAME, + .fops = &z90crypt_fops, +}; + +/** + * Documentation values. + */ +MODULE_AUTHOR("zSeries Linux Crypto Team: Robert H. Burroughs, Eric D. Rossman" + "and Jochen Roehrig"); +MODULE_DESCRIPTION("zSeries Linux Cryptographic Coprocessor device driver, " + "Copyright 2001, 2005 IBM Corporation"); +MODULE_LICENSE("GPL"); +module_param(domain, int, 0); +MODULE_PARM_DESC(domain, "domain index for device"); + +#ifdef CONFIG_COMPAT +/** + * ioctl32 conversion routines + */ +struct ica_rsa_modexpo_32 { // For 32-bit callers + compat_uptr_t inputdata; + unsigned int inputdatalength; + compat_uptr_t outputdata; + unsigned int outputdatalength; + compat_uptr_t b_key; + compat_uptr_t n_modulus; +}; + +static long +trans_modexpo32(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct ica_rsa_modexpo_32 __user *mex32u = compat_ptr(arg); + struct ica_rsa_modexpo_32 mex32k; + struct ica_rsa_modexpo __user *mex64; + long ret = 0; + unsigned int i; + + if (!access_ok(VERIFY_WRITE, mex32u, sizeof(struct ica_rsa_modexpo_32))) + return -EFAULT; + mex64 = compat_alloc_user_space(sizeof(struct ica_rsa_modexpo)); + if (!access_ok(VERIFY_WRITE, mex64, sizeof(struct ica_rsa_modexpo))) + return -EFAULT; + if (copy_from_user(&mex32k, mex32u, sizeof(struct ica_rsa_modexpo_32))) + return -EFAULT; + if (__put_user(compat_ptr(mex32k.inputdata), &mex64->inputdata) || + __put_user(mex32k.inputdatalength, &mex64->inputdatalength) || + __put_user(compat_ptr(mex32k.outputdata), &mex64->outputdata) || + __put_user(mex32k.outputdatalength, &mex64->outputdatalength) || + __put_user(compat_ptr(mex32k.b_key), &mex64->b_key) || + __put_user(compat_ptr(mex32k.n_modulus), &mex64->n_modulus)) + return -EFAULT; + ret = z90crypt_unlocked_ioctl(filp, cmd, (unsigned long)mex64); + if (!ret) + if (__get_user(i, &mex64->outputdatalength) || + __put_user(i, &mex32u->outputdatalength)) + ret = -EFAULT; + return ret; +} + +struct ica_rsa_modexpo_crt_32 { // For 32-bit callers + compat_uptr_t inputdata; + unsigned int inputdatalength; + compat_uptr_t outputdata; + unsigned int outputdatalength; + compat_uptr_t bp_key; + compat_uptr_t bq_key; + compat_uptr_t np_prime; + compat_uptr_t nq_prime; + compat_uptr_t u_mult_inv; +}; + +static long +trans_modexpo_crt32(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct ica_rsa_modexpo_crt_32 __user *crt32u = compat_ptr(arg); + struct ica_rsa_modexpo_crt_32 crt32k; + struct ica_rsa_modexpo_crt __user *crt64; + long ret = 0; + unsigned int i; + + if (!access_ok(VERIFY_WRITE, crt32u, + sizeof(struct ica_rsa_modexpo_crt_32))) + return -EFAULT; + crt64 = compat_alloc_user_space(sizeof(struct ica_rsa_modexpo_crt)); + if (!access_ok(VERIFY_WRITE, crt64, sizeof(struct ica_rsa_modexpo_crt))) + return -EFAULT; + if (copy_from_user(&crt32k, crt32u, + sizeof(struct ica_rsa_modexpo_crt_32))) + return -EFAULT; + if (__put_user(compat_ptr(crt32k.inputdata), &crt64->inputdata) || + __put_user(crt32k.inputdatalength, &crt64->inputdatalength) || + __put_user(compat_ptr(crt32k.outputdata), &crt64->outputdata) || + __put_user(crt32k.outputdatalength, &crt64->outputdatalength) || + __put_user(compat_ptr(crt32k.bp_key), &crt64->bp_key) || + __put_user(compat_ptr(crt32k.bq_key), &crt64->bq_key) || + __put_user(compat_ptr(crt32k.np_prime), &crt64->np_prime) || + __put_user(compat_ptr(crt32k.nq_prime), &crt64->nq_prime) || + __put_user(compat_ptr(crt32k.u_mult_inv), &crt64->u_mult_inv)) + return -EFAULT; + ret = z90crypt_unlocked_ioctl(filp, cmd, (unsigned long)crt64); + if (!ret) + if (__get_user(i, &crt64->outputdatalength) || + __put_user(i, &crt32u->outputdatalength)) + ret = -EFAULT; + return ret; +} + +static long +z90crypt_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case ICAZ90STATUS: + case Z90QUIESCE: + case Z90STAT_TOTALCOUNT: + case Z90STAT_PCICACOUNT: + case Z90STAT_PCICCCOUNT: + case Z90STAT_PCIXCCCOUNT: + case Z90STAT_PCIXCCMCL2COUNT: + case Z90STAT_PCIXCCMCL3COUNT: + case Z90STAT_CEX2CCOUNT: + case Z90STAT_REQUESTQ_COUNT: + case Z90STAT_PENDINGQ_COUNT: + case Z90STAT_TOTALOPEN_COUNT: + case Z90STAT_DOMAIN_INDEX: + case Z90STAT_STATUS_MASK: + case Z90STAT_QDEPTH_MASK: + case Z90STAT_PERDEV_REQCNT: + return z90crypt_unlocked_ioctl(filp, cmd, arg); + case ICARSAMODEXPO: + return trans_modexpo32(filp, cmd, arg); + case ICARSACRT: + return trans_modexpo_crt32(filp, cmd, arg); + default: + return -ENOIOCTLCMD; + } +} +#endif + +/** + * The module initialization code. + */ +static int __init +z90crypt_init_module(void) +{ + int result, nresult; + struct proc_dir_entry *entry; + + PDEBUG("PID %d\n", PID()); + + if ((domain < -1) || (domain > 15)) { + PRINTKW("Invalid param: domain = %d. Not loading.\n", domain); + return -EINVAL; + } + + /* Register as misc device with given minor (or get a dynamic one). */ + result = misc_register(&z90crypt_misc_device); + if (result < 0) { + PRINTKW(KERN_ERR "misc_register (minor %d) failed with %d\n", + z90crypt_misc_device.minor, result); + return result; + } + + PDEBUG("Registered " DEV_NAME " with result %d\n", result); + + result = create_z90crypt(&domain); + if (result != 0) { + PRINTKW("create_z90crypt (domain index %d) failed with %d.\n", + domain, result); + result = -ENOMEM; + goto init_module_cleanup; + } + + if (result == 0) { + PRINTKN("Version %d.%d.%d loaded, built on %s %s\n", + z90crypt_VERSION, z90crypt_RELEASE, z90crypt_VARIANT, + __DATE__, __TIME__); + PDEBUG("create_z90crypt (domain index %d) successful.\n", + domain); + } else + PRINTK("No devices at startup\n"); + + /* Initialize globals. */ + spin_lock_init(&queuespinlock); + + INIT_LIST_HEAD(&pending_list); + pendingq_count = 0; + + INIT_LIST_HEAD(&request_list); + requestq_count = 0; + + quiesce_z90crypt = 0; + + atomic_set(&total_open, 0); + atomic_set(&z90crypt_step, 0); + + /* Set up the cleanup task. */ + init_timer(&cleanup_timer); + cleanup_timer.function = z90crypt_cleanup_task; + cleanup_timer.data = 0; + cleanup_timer.expires = jiffies + (CLEANUPTIME * HZ); + add_timer(&cleanup_timer); + + /* Set up the proc file system */ + entry = create_proc_entry("driver/z90crypt", 0644, 0); + if (entry) { + entry->nlink = 1; + entry->data = 0; + entry->read_proc = z90crypt_status; + entry->write_proc = z90crypt_status_write; + } + else + PRINTK("Couldn't create z90crypt proc entry\n"); + z90crypt_entry = entry; + + /* Set up the configuration task. */ + init_timer(&config_timer); + config_timer.function = z90crypt_config_task; + config_timer.data = 0; + config_timer.expires = jiffies + (INITIAL_CONFIGTIME * HZ); + add_timer(&config_timer); + + /* Set up the reader task */ + tasklet_init(&reader_tasklet, z90crypt_reader_task, 0); + init_timer(&reader_timer); + reader_timer.function = z90crypt_schedule_reader_task; + reader_timer.data = 0; + reader_timer.expires = jiffies + (READERTIME * HZ / 1000); + add_timer(&reader_timer); + + return 0; // success + +init_module_cleanup: + if ((nresult = misc_deregister(&z90crypt_misc_device))) + PRINTK("misc_deregister failed with %d.\n", nresult); + else + PDEBUG("misc_deregister successful.\n"); + + return result; // failure +} + +/** + * The module termination code + */ +static void __exit +z90crypt_cleanup_module(void) +{ + int nresult; + + PDEBUG("PID %d\n", PID()); + + remove_proc_entry("driver/z90crypt", 0); + + if ((nresult = misc_deregister(&z90crypt_misc_device))) + PRINTK("misc_deregister failed with %d.\n", nresult); + else + PDEBUG("misc_deregister successful.\n"); + + /* Remove the tasks */ + tasklet_kill(&reader_tasklet); + del_timer(&reader_timer); + del_timer(&config_timer); + del_timer(&cleanup_timer); + + destroy_z90crypt(); + + PRINTKN("Unloaded.\n"); +} + +/** + * Functions running under a process id + * + * The I/O functions: + * z90crypt_open + * z90crypt_release + * z90crypt_read + * z90crypt_write + * z90crypt_unlocked_ioctl + * z90crypt_status + * z90crypt_status_write + * disable_card + * enable_card + * + * Helper functions: + * z90crypt_rsa + * z90crypt_prepare + * z90crypt_send + * z90crypt_process_results + * + */ +static int +z90crypt_open(struct inode *inode, struct file *filp) +{ + struct priv_data *private_data_p; + + if (quiesce_z90crypt) + return -EQUIESCE; + + private_data_p = kzalloc(sizeof(struct priv_data), GFP_KERNEL); + if (!private_data_p) { + PRINTK("Memory allocate failed\n"); + return -ENOMEM; + } + + private_data_p->status = STAT_OPEN; + private_data_p->opener_pid = PID(); + filp->private_data = private_data_p; + atomic_inc(&total_open); + + return 0; +} + +static int +z90crypt_release(struct inode *inode, struct file *filp) +{ + struct priv_data *private_data_p = filp->private_data; + + PDEBUG("PID %d (filp %p)\n", PID(), filp); + + private_data_p->status = STAT_CLOSED; + memset(private_data_p, 0, sizeof(struct priv_data)); + kfree(private_data_p); + atomic_dec(&total_open); + + return 0; +} + +/* + * there are two read functions, of which compile options will choose one + * without USE_GET_RANDOM_BYTES + * => read() always returns -EPERM; + * otherwise + * => read() uses get_random_bytes() kernel function + */ +#ifndef USE_GET_RANDOM_BYTES +/** + * z90crypt_read will not be supported beyond z90crypt 1.3.1 + */ +static ssize_t +z90crypt_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + PDEBUG("filp %p (PID %d)\n", filp, PID()); + return -EPERM; +} +#else // we want to use get_random_bytes +/** + * read() just returns a string of random bytes. Since we have no way + * to generate these cryptographically, we just execute get_random_bytes + * for the length specified. + */ +#include +static ssize_t +z90crypt_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + unsigned char *temp_buff; + + PDEBUG("filp %p (PID %d)\n", filp, PID()); + + if (quiesce_z90crypt) + return -EQUIESCE; + if (count < 0) { + PRINTK("Requested random byte count negative: %ld\n", count); + return -EINVAL; + } + if (count > RESPBUFFSIZE) { + PDEBUG("count[%d] > RESPBUFFSIZE", count); + return -EINVAL; + } + if (count == 0) + return 0; + temp_buff = kmalloc(RESPBUFFSIZE, GFP_KERNEL); + if (!temp_buff) { + PRINTK("Memory allocate failed\n"); + return -ENOMEM; + } + get_random_bytes(temp_buff, count); + + if (copy_to_user(buf, temp_buff, count) != 0) { + kfree(temp_buff); + return -EFAULT; + } + kfree(temp_buff); + return count; +} +#endif + +/** + * Write is is not allowed + */ +static ssize_t +z90crypt_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + PDEBUG("filp %p (PID %d)\n", filp, PID()); + return -EPERM; +} + +/** + * New status functions + */ +static inline int +get_status_totalcount(void) +{ + return z90crypt.hdware_info->hdware_mask.st_count; +} + +static inline int +get_status_PCICAcount(void) +{ + return z90crypt.hdware_info->type_mask[PCICA].st_count; +} + +static inline int +get_status_PCICCcount(void) +{ + return z90crypt.hdware_info->type_mask[PCICC].st_count; +} + +static inline int +get_status_PCIXCCcount(void) +{ + return z90crypt.hdware_info->type_mask[PCIXCC_MCL2].st_count + + z90crypt.hdware_info->type_mask[PCIXCC_MCL3].st_count; +} + +static inline int +get_status_PCIXCCMCL2count(void) +{ + return z90crypt.hdware_info->type_mask[PCIXCC_MCL2].st_count; +} + +static inline int +get_status_PCIXCCMCL3count(void) +{ + return z90crypt.hdware_info->type_mask[PCIXCC_MCL3].st_count; +} + +static inline int +get_status_CEX2Ccount(void) +{ + return z90crypt.hdware_info->type_mask[CEX2C].st_count; +} + +static inline int +get_status_CEX2Acount(void) +{ + return z90crypt.hdware_info->type_mask[CEX2A].st_count; +} + +static inline int +get_status_requestq_count(void) +{ + return requestq_count; +} + +static inline int +get_status_pendingq_count(void) +{ + return pendingq_count; +} + +static inline int +get_status_totalopen_count(void) +{ + return atomic_read(&total_open); +} + +static inline int +get_status_domain_index(void) +{ + return z90crypt.cdx; +} + +static inline unsigned char * +get_status_status_mask(unsigned char status[Z90CRYPT_NUM_APS]) +{ + int i, ix; + + memcpy(status, z90crypt.hdware_info->device_type_array, + Z90CRYPT_NUM_APS); + + for (i = 0; i < get_status_totalcount(); i++) { + ix = SHRT2LONG(i); + if (LONG2DEVPTR(ix)->user_disabled) + status[ix] = 0x0d; + } + + return status; +} + +static inline unsigned char * +get_status_qdepth_mask(unsigned char qdepth[Z90CRYPT_NUM_APS]) +{ + int i, ix; + + memset(qdepth, 0, Z90CRYPT_NUM_APS); + + for (i = 0; i < get_status_totalcount(); i++) { + ix = SHRT2LONG(i); + qdepth[ix] = LONG2DEVPTR(ix)->dev_caller_count; + } + + return qdepth; +} + +static inline unsigned int * +get_status_perdevice_reqcnt(unsigned int reqcnt[Z90CRYPT_NUM_APS]) +{ + int i, ix; + + memset(reqcnt, 0, Z90CRYPT_NUM_APS * sizeof(int)); + + for (i = 0; i < get_status_totalcount(); i++) { + ix = SHRT2LONG(i); + reqcnt[ix] = LONG2DEVPTR(ix)->dev_total_req_cnt; + } + + return reqcnt; +} + +static inline void +init_work_element(struct work_element *we_p, + struct priv_data *priv_data, pid_t pid) +{ + int step; + + we_p->requestptr = (unsigned char *)we_p + sizeof(struct work_element); + /* Come up with a unique id for this caller. */ + step = atomic_inc_return(&z90crypt_step); + memcpy(we_p->caller_id+0, (void *) &pid, sizeof(pid)); + memcpy(we_p->caller_id+4, (void *) &step, sizeof(step)); + we_p->pid = pid; + we_p->priv_data = priv_data; + we_p->status[0] = STAT_DEFAULT; + we_p->audit[0] = 0x00; + we_p->audit[1] = 0x00; + we_p->audit[2] = 0x00; + we_p->resp_buff_size = 0; + we_p->retcode = 0; + we_p->devindex = -1; + we_p->devtype = -1; + atomic_set(&we_p->alarmrung, 0); + init_waitqueue_head(&we_p->waitq); + INIT_LIST_HEAD(&(we_p->liste)); +} + +static inline int +allocate_work_element(struct work_element **we_pp, + struct priv_data *priv_data_p, pid_t pid) +{ + struct work_element *we_p; + + we_p = (struct work_element *) get_zeroed_page(GFP_KERNEL); + if (!we_p) + return -ENOMEM; + init_work_element(we_p, priv_data_p, pid); + *we_pp = we_p; + return 0; +} + +static inline void +remove_device(struct device *device_p) +{ + if (!device_p || (device_p->disabled != 0)) + return; + device_p->disabled = 1; + z90crypt.hdware_info->type_mask[device_p->dev_type].disabled_count++; + z90crypt.hdware_info->hdware_mask.disabled_count++; +} + +/** + * Bitlength limits for each card + * + * There are new MCLs which allow more bitlengths. See the table for details. + * The MCL must be applied and the newer bitlengths enabled for these to work. + * + * Card Type Old limit New limit + * PCICA ??-2048 same (the lower limit is less than 128 bit...) + * PCICC 512-1024 512-2048 + * PCIXCC_MCL2 512-2048 ----- (applying any GA LIC will make an MCL3 card) + * PCIXCC_MCL3 ----- 128-2048 + * CEX2C 512-2048 128-2048 + * CEX2A ??-2048 same (the lower limit is less than 128 bit...) + * + * ext_bitlens (extended bitlengths) is a global, since you should not apply an + * MCL to just one card in a machine. We assume, at first, that all cards have + * these capabilities. + */ +int ext_bitlens = 1; // This is global +#define PCIXCC_MIN_MOD_SIZE 16 // 128 bits +#define OLD_PCIXCC_MIN_MOD_SIZE 64 // 512 bits +#define PCICC_MIN_MOD_SIZE 64 // 512 bits +#define OLD_PCICC_MAX_MOD_SIZE 128 // 1024 bits +#define MAX_MOD_SIZE 256 // 2048 bits + +static inline int +select_device_type(int *dev_type_p, int bytelength) +{ + static int count = 0; + int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, CEX2A_avail, + index_to_use; + struct status *stat; + if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) && + (*dev_type_p != PCIXCC_MCL2) && (*dev_type_p != PCIXCC_MCL3) && + (*dev_type_p != CEX2C) && (*dev_type_p != CEX2A) && + (*dev_type_p != ANYDEV)) + return -1; + if (*dev_type_p != ANYDEV) { + stat = &z90crypt.hdware_info->type_mask[*dev_type_p]; + if (stat->st_count > + (stat->disabled_count + stat->user_disabled_count)) + return 0; + return -1; + } + + /** + * Assumption: PCICA, PCIXCC_MCL3, CEX2C, and CEX2A are all similar in + * speed. + * + * PCICA and CEX2A do NOT co-exist, so it would be either one or the + * other present. + */ + stat = &z90crypt.hdware_info->type_mask[PCICA]; + PCICA_avail = stat->st_count - + (stat->disabled_count + stat->user_disabled_count); + stat = &z90crypt.hdware_info->type_mask[PCIXCC_MCL3]; + PCIXCC_MCL3_avail = stat->st_count - + (stat->disabled_count + stat->user_disabled_count); + stat = &z90crypt.hdware_info->type_mask[CEX2C]; + CEX2C_avail = stat->st_count - + (stat->disabled_count + stat->user_disabled_count); + stat = &z90crypt.hdware_info->type_mask[CEX2A]; + CEX2A_avail = stat->st_count - + (stat->disabled_count + stat->user_disabled_count); + if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail || CEX2A_avail) { + /** + * bitlength is a factor, PCICA or CEX2A are the most capable, + * even with the new MCL for PCIXCC. + */ + if ((bytelength < PCIXCC_MIN_MOD_SIZE) || + (!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) { + if (PCICA_avail) { + *dev_type_p = PCICA; + return 0; + } + if (CEX2A_avail) { + *dev_type_p = CEX2A; + return 0; + } + return -1; + } + + index_to_use = count % (PCICA_avail + PCIXCC_MCL3_avail + + CEX2C_avail + CEX2A_avail); + if (index_to_use < PCICA_avail) + *dev_type_p = PCICA; + else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail)) + *dev_type_p = PCIXCC_MCL3; + else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail + + CEX2C_avail)) + *dev_type_p = CEX2C; + else + *dev_type_p = CEX2A; + count++; + return 0; + } + + /* Less than OLD_PCIXCC_MIN_MOD_SIZE cannot go to a PCIXCC_MCL2 */ + if (bytelength < OLD_PCIXCC_MIN_MOD_SIZE) + return -1; + stat = &z90crypt.hdware_info->type_mask[PCIXCC_MCL2]; + if (stat->st_count > + (stat->disabled_count + stat->user_disabled_count)) { + *dev_type_p = PCIXCC_MCL2; + return 0; + } + + /** + * Less than PCICC_MIN_MOD_SIZE or more than OLD_PCICC_MAX_MOD_SIZE + * (if we don't have the MCL applied and the newer bitlengths enabled) + * cannot go to a PCICC + */ + if ((bytelength < PCICC_MIN_MOD_SIZE) || + (!ext_bitlens && (bytelength > OLD_PCICC_MAX_MOD_SIZE))) { + return -1; + } + stat = &z90crypt.hdware_info->type_mask[PCICC]; + if (stat->st_count > + (stat->disabled_count + stat->user_disabled_count)) { + *dev_type_p = PCICC; + return 0; + } + + return -1; +} + +/** + * Try the selected number, then the selected type (can be ANYDEV) + */ +static inline int +select_device(int *dev_type_p, int *device_nr_p, int bytelength) +{ + int i, indx, devTp, low_count, low_indx; + struct device_x *index_p; + struct device *dev_ptr; + + PDEBUG("device type = %d, index = %d\n", *dev_type_p, *device_nr_p); + if ((*device_nr_p >= 0) && (*device_nr_p < Z90CRYPT_NUM_DEVS)) { + PDEBUG("trying index = %d\n", *device_nr_p); + dev_ptr = z90crypt.device_p[*device_nr_p]; + + if (dev_ptr && + (dev_ptr->dev_stat != DEV_GONE) && + (dev_ptr->disabled == 0) && + (dev_ptr->user_disabled == 0)) { + PDEBUG("selected by number, index = %d\n", + *device_nr_p); + *dev_type_p = dev_ptr->dev_type; + return *device_nr_p; + } + } + *device_nr_p = -1; + PDEBUG("trying type = %d\n", *dev_type_p); + devTp = *dev_type_p; + if (select_device_type(&devTp, bytelength) == -1) { + PDEBUG("failed to select by type\n"); + return -1; + } + PDEBUG("selected type = %d\n", devTp); + index_p = &z90crypt.hdware_info->type_x_addr[devTp]; + low_count = 0x0000FFFF; + low_indx = -1; + for (i = 0; i < z90crypt.hdware_info->type_mask[devTp].st_count; i++) { + indx = index_p->device_index[i]; + dev_ptr = z90crypt.device_p[indx]; + if (dev_ptr && + (dev_ptr->dev_stat != DEV_GONE) && + (dev_ptr->disabled == 0) && + (dev_ptr->user_disabled == 0) && + (devTp == dev_ptr->dev_type) && + (low_count > dev_ptr->dev_caller_count)) { + low_count = dev_ptr->dev_caller_count; + low_indx = indx; + } + } + *device_nr_p = low_indx; + return low_indx; +} + +static inline int +send_to_crypto_device(struct work_element *we_p) +{ + struct caller *caller_p; + struct device *device_p; + int dev_nr; + int bytelen = ((struct ica_rsa_modexpo *)we_p->buffer)->inputdatalength; + + if (!we_p->requestptr) + return SEN_FATAL_ERROR; + caller_p = (struct caller *)we_p->requestptr; + dev_nr = we_p->devindex; + if (select_device(&we_p->devtype, &dev_nr, bytelen) == -1) { + if (z90crypt.hdware_info->hdware_mask.st_count != 0) + return SEN_RETRY; + else + return SEN_NOT_AVAIL; + } + we_p->devindex = dev_nr; + device_p = z90crypt.device_p[dev_nr]; + if (!device_p) + return SEN_NOT_AVAIL; + if (device_p->dev_type != we_p->devtype) + return SEN_RETRY; + if (device_p->dev_caller_count >= device_p->dev_q_depth) + return SEN_QUEUE_FULL; + PDEBUG("device number prior to send: %d\n", dev_nr); + switch (send_to_AP(dev_nr, z90crypt.cdx, + caller_p->caller_dev_dep_req_l, + caller_p->caller_dev_dep_req_p)) { + case DEV_SEN_EXCEPTION: + PRINTKC("Exception during send to device %d\n", dev_nr); + z90crypt.terminating = 1; + return SEN_FATAL_ERROR; + case DEV_GONE: + PRINTK("Device %d not available\n", dev_nr); + remove_device(device_p); + return SEN_NOT_AVAIL; + case DEV_EMPTY: + return SEN_NOT_AVAIL; + case DEV_NO_WORK: + return SEN_FATAL_ERROR; + case DEV_BAD_MESSAGE: + return SEN_USER_ERROR; + case DEV_QUEUE_FULL: + return SEN_QUEUE_FULL; + default: + case DEV_ONLINE: + break; + } + list_add_tail(&(caller_p->caller_liste), &(device_p->dev_caller_list)); + device_p->dev_caller_count++; + return 0; +} + +/** + * Send puts the user's work on one of two queues: + * the pending queue if the send was successful + * the request queue if the send failed because device full or busy + */ +static inline int +z90crypt_send(struct work_element *we_p, const char *buf) +{ + int rv; + + PDEBUG("PID %d\n", PID()); + + if (CHK_RDWRMASK(we_p->status[0]) != STAT_NOWORK) { + PDEBUG("PID %d tried to send more work but has outstanding " + "work.\n", PID()); + return -EWORKPEND; + } + we_p->devindex = -1; // Reset device number + spin_lock_irq(&queuespinlock); + rv = send_to_crypto_device(we_p); + switch (rv) { + case 0: + we_p->requestsent = jiffies; + we_p->audit[0] |= FP_SENT; + list_add_tail(&we_p->liste, &pending_list); + ++pendingq_count; + we_p->audit[0] |= FP_PENDING; + break; + case SEN_BUSY: + case SEN_QUEUE_FULL: + rv = 0; + we_p->devindex = -1; // any device will do + we_p->requestsent = jiffies; + list_add_tail(&we_p->liste, &request_list); + ++requestq_count; + we_p->audit[0] |= FP_REQUEST; + break; + case SEN_RETRY: + rv = -ERESTARTSYS; + break; + case SEN_NOT_AVAIL: + PRINTK("*** No devices available.\n"); + rv = we_p->retcode = -ENODEV; + we_p->status[0] |= STAT_FAILED; + break; + case REC_OPERAND_INV: + case REC_OPERAND_SIZE: + case REC_EVEN_MOD: + case REC_INVALID_PAD: + rv = we_p->retcode = -EINVAL; + we_p->status[0] |= STAT_FAILED; + break; + default: + we_p->retcode = rv; + we_p->status[0] |= STAT_FAILED; + break; + } + if (rv != -ERESTARTSYS) + SET_RDWRMASK(we_p->status[0], STAT_WRITTEN); + spin_unlock_irq(&queuespinlock); + if (rv == 0) + tasklet_schedule(&reader_tasklet); + return rv; +} + +/** + * process_results copies the user's work from kernel space. + */ +static inline int +z90crypt_process_results(struct work_element *we_p, char __user *buf) +{ + int rv; + + PDEBUG("we_p %p (PID %d)\n", we_p, PID()); + + LONG2DEVPTR(we_p->devindex)->dev_total_req_cnt++; + SET_RDWRMASK(we_p->status[0], STAT_READPEND); + + rv = 0; + if (!we_p->buffer) { + PRINTK("we_p %p PID %d in STAT_READPEND: buffer NULL.\n", + we_p, PID()); + rv = -ENOBUFF; + } + + if (!rv) + if ((rv = copy_to_user(buf, we_p->buffer, we_p->buff_size))) { + PDEBUG("copy_to_user failed: rv = %d\n", rv); + rv = -EFAULT; + } + + if (!rv) + rv = we_p->retcode; + if (!rv) + if (we_p->resp_buff_size + && copy_to_user(we_p->resp_addr, we_p->resp_buff, + we_p->resp_buff_size)) + rv = -EFAULT; + + SET_RDWRMASK(we_p->status[0], STAT_NOWORK); + return rv; +} + +static unsigned char NULL_psmid[8] = +{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +/** + * Used in device configuration functions + */ +#define MAX_RESET 90 + +/** + * This is used only for PCICC support + */ +static inline int +is_PKCS11_padded(unsigned char *buffer, int length) +{ + int i; + if ((buffer[0] != 0x00) || (buffer[1] != 0x01)) + return 0; + for (i = 2; i < length; i++) + if (buffer[i] != 0xFF) + break; + if ((i < 10) || (i == length)) + return 0; + if (buffer[i] != 0x00) + return 0; + return 1; +} + +/** + * This is used only for PCICC support + */ +static inline int +is_PKCS12_padded(unsigned char *buffer, int length) +{ + int i; + if ((buffer[0] != 0x00) || (buffer[1] != 0x02)) + return 0; + for (i = 2; i < length; i++) + if (buffer[i] == 0x00) + break; + if ((i < 10) || (i == length)) + return 0; + if (buffer[i] != 0x00) + return 0; + return 1; +} + +/** + * builds struct caller and converts message from generic format to + * device-dependent format + * func is ICARSAMODEXPO or ICARSACRT + * function is PCI_FUNC_KEY_ENCRYPT or PCI_FUNC_KEY_DECRYPT + */ +static inline int +build_caller(struct work_element *we_p, short function) +{ + int rv; + struct caller *caller_p = (struct caller *)we_p->requestptr; + + if ((we_p->devtype != PCICC) && (we_p->devtype != PCICA) && + (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) && + (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A)) + return SEN_NOT_AVAIL; + + memcpy(caller_p->caller_id, we_p->caller_id, + sizeof(caller_p->caller_id)); + caller_p->caller_dev_dep_req_p = caller_p->caller_dev_dep_req; + caller_p->caller_dev_dep_req_l = MAX_RESPONSE_SIZE; + caller_p->caller_buf_p = we_p->buffer; + INIT_LIST_HEAD(&(caller_p->caller_liste)); + + rv = convert_request(we_p->buffer, we_p->funccode, function, + z90crypt.cdx, we_p->devtype, + &caller_p->caller_dev_dep_req_l, + caller_p->caller_dev_dep_req_p); + if (rv) { + if (rv == SEN_NOT_AVAIL) + PDEBUG("request can't be processed on hdwr avail\n"); + else + PRINTK("Error from convert_request: %d\n", rv); + } + else + memcpy(&(caller_p->caller_dev_dep_req_p[4]), we_p->caller_id,8); + return rv; +} + +static inline void +unbuild_caller(struct device *device_p, struct caller *caller_p) +{ + if (!caller_p) + return; + if (caller_p->caller_liste.next && caller_p->caller_liste.prev) + if (!list_empty(&caller_p->caller_liste)) { + list_del_init(&caller_p->caller_liste); + device_p->dev_caller_count--; + } + memset(caller_p->caller_id, 0, sizeof(caller_p->caller_id)); +} + +static inline int +get_crypto_request_buffer(struct work_element *we_p) +{ + struct ica_rsa_modexpo *mex_p; + struct ica_rsa_modexpo_crt *crt_p; + unsigned char *temp_buffer; + short function; + int rv; + + mex_p = (struct ica_rsa_modexpo *) we_p->buffer; + crt_p = (struct ica_rsa_modexpo_crt *) we_p->buffer; + + PDEBUG("device type input = %d\n", we_p->devtype); + + if (z90crypt.terminating) + return REC_NO_RESPONSE; + if (memcmp(we_p->caller_id, NULL_psmid, 8) == 0) { + PRINTK("psmid zeroes\n"); + return SEN_FATAL_ERROR; + } + if (!we_p->buffer) { + PRINTK("buffer pointer NULL\n"); + return SEN_USER_ERROR; + } + if (!we_p->requestptr) { + PRINTK("caller pointer NULL\n"); + return SEN_USER_ERROR; + } + + if ((we_p->devtype != PCICA) && (we_p->devtype != PCICC) && + (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) && + (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A) && + (we_p->devtype != ANYDEV)) { + PRINTK("invalid device type\n"); + return SEN_USER_ERROR; + } + + if ((mex_p->inputdatalength < 1) || + (mex_p->inputdatalength > MAX_MOD_SIZE)) { + PRINTK("inputdatalength[%d] is not valid\n", + mex_p->inputdatalength); + return SEN_USER_ERROR; + } + + if (mex_p->outputdatalength < mex_p->inputdatalength) { + PRINTK("outputdatalength[%d] < inputdatalength[%d]\n", + mex_p->outputdatalength, mex_p->inputdatalength); + return SEN_USER_ERROR; + } + + if (!mex_p->inputdata || !mex_p->outputdata) { + PRINTK("inputdata[%p] or outputdata[%p] is NULL\n", + mex_p->outputdata, mex_p->inputdata); + return SEN_USER_ERROR; + } + + /** + * As long as outputdatalength is big enough, we can set the + * outputdatalength equal to the inputdatalength, since that is the + * number of bytes we will copy in any case + */ + mex_p->outputdatalength = mex_p->inputdatalength; + + rv = 0; + switch (we_p->funccode) { + case ICARSAMODEXPO: + if (!mex_p->b_key || !mex_p->n_modulus) + rv = SEN_USER_ERROR; + break; + case ICARSACRT: + if (!IS_EVEN(crt_p->inputdatalength)) { + PRINTK("inputdatalength[%d] is odd, CRT form\n", + crt_p->inputdatalength); + rv = SEN_USER_ERROR; + break; + } + if (!crt_p->bp_key || + !crt_p->bq_key || + !crt_p->np_prime || + !crt_p->nq_prime || + !crt_p->u_mult_inv) { + PRINTK("CRT form, bad data: %p/%p/%p/%p/%p\n", + crt_p->bp_key, crt_p->bq_key, + crt_p->np_prime, crt_p->nq_prime, + crt_p->u_mult_inv); + rv = SEN_USER_ERROR; + } + break; + default: + PRINTK("bad func = %d\n", we_p->funccode); + rv = SEN_USER_ERROR; + break; + } + if (rv != 0) + return rv; + + if (select_device_type(&we_p->devtype, mex_p->inputdatalength) < 0) + return SEN_NOT_AVAIL; + + temp_buffer = (unsigned char *)we_p + sizeof(struct work_element) + + sizeof(struct caller); + if (copy_from_user(temp_buffer, mex_p->inputdata, + mex_p->inputdatalength) != 0) + return SEN_RELEASED; + + function = PCI_FUNC_KEY_ENCRYPT; + switch (we_p->devtype) { + /* PCICA and CEX2A do everything with a simple RSA mod-expo operation */ + case PCICA: + case CEX2A: + function = PCI_FUNC_KEY_ENCRYPT; + break; + /** + * PCIXCC_MCL2 does all Mod-Expo form with a simple RSA mod-expo + * operation, and all CRT forms with a PKCS-1.2 format decrypt. + * PCIXCC_MCL3 and CEX2C do all Mod-Expo and CRT forms with a simple RSA + * mod-expo operation + */ + case PCIXCC_MCL2: + if (we_p->funccode == ICARSAMODEXPO) + function = PCI_FUNC_KEY_ENCRYPT; + else + function = PCI_FUNC_KEY_DECRYPT; + break; + case PCIXCC_MCL3: + case CEX2C: + if (we_p->funccode == ICARSAMODEXPO) + function = PCI_FUNC_KEY_ENCRYPT; + else + function = PCI_FUNC_KEY_DECRYPT; + break; + /** + * PCICC does everything as a PKCS-1.2 format request + */ + case PCICC: + /* PCICC cannot handle input that is is PKCS#1.1 padded */ + if (is_PKCS11_padded(temp_buffer, mex_p->inputdatalength)) { + return SEN_NOT_AVAIL; + } + if (we_p->funccode == ICARSAMODEXPO) { + if (is_PKCS12_padded(temp_buffer, + mex_p->inputdatalength)) + function = PCI_FUNC_KEY_ENCRYPT; + else + function = PCI_FUNC_KEY_DECRYPT; + } else + /* all CRT forms are decrypts */ + function = PCI_FUNC_KEY_DECRYPT; + break; + } + PDEBUG("function: %04x\n", function); + rv = build_caller(we_p, function); + PDEBUG("rv from build_caller = %d\n", rv); + return rv; +} + +static inline int +z90crypt_prepare(struct work_element *we_p, unsigned int funccode, + const char __user *buffer) +{ + int rv; + + we_p->devindex = -1; + if (funccode == ICARSAMODEXPO) + we_p->buff_size = sizeof(struct ica_rsa_modexpo); + else + we_p->buff_size = sizeof(struct ica_rsa_modexpo_crt); + + if (copy_from_user(we_p->buffer, buffer, we_p->buff_size)) + return -EFAULT; + + we_p->audit[0] |= FP_COPYFROM; + SET_RDWRMASK(we_p->status[0], STAT_WRITTEN); + we_p->funccode = funccode; + we_p->devtype = -1; + we_p->audit[0] |= FP_BUFFREQ; + rv = get_crypto_request_buffer(we_p); + switch (rv) { + case 0: + we_p->audit[0] |= FP_BUFFGOT; + break; + case SEN_USER_ERROR: + rv = -EINVAL; + break; + case SEN_QUEUE_FULL: + rv = 0; + break; + case SEN_RELEASED: + rv = -EFAULT; + break; + case REC_NO_RESPONSE: + rv = -ENODEV; + break; + case SEN_NOT_AVAIL: + case EGETBUFF: + rv = -EGETBUFF; + break; + default: + PRINTK("rv = %d\n", rv); + rv = -EGETBUFF; + break; + } + if (CHK_RDWRMASK(we_p->status[0]) == STAT_WRITTEN) + SET_RDWRMASK(we_p->status[0], STAT_DEFAULT); + return rv; +} + +static inline void +purge_work_element(struct work_element *we_p) +{ + struct list_head *lptr; + + spin_lock_irq(&queuespinlock); + list_for_each(lptr, &request_list) { + if (lptr == &we_p->liste) { + list_del_init(lptr); + requestq_count--; + break; + } + } + list_for_each(lptr, &pending_list) { + if (lptr == &we_p->liste) { + list_del_init(lptr); + pendingq_count--; + break; + } + } + spin_unlock_irq(&queuespinlock); +} + +/** + * Build the request and send it. + */ +static inline int +z90crypt_rsa(struct priv_data *private_data_p, pid_t pid, + unsigned int cmd, unsigned long arg) +{ + struct work_element *we_p; + int rv; + + if ((rv = allocate_work_element(&we_p, private_data_p, pid))) { + PDEBUG("PID %d: allocate_work_element returned ENOMEM\n", pid); + return rv; + } + if ((rv = z90crypt_prepare(we_p, cmd, (const char __user *)arg))) + PDEBUG("PID %d: rv = %d from z90crypt_prepare\n", pid, rv); + if (!rv) + if ((rv = z90crypt_send(we_p, (const char *)arg))) + PDEBUG("PID %d: rv %d from z90crypt_send.\n", pid, rv); + if (!rv) { + we_p->audit[0] |= FP_ASLEEP; + wait_event(we_p->waitq, atomic_read(&we_p->alarmrung)); + we_p->audit[0] |= FP_AWAKE; + rv = we_p->retcode; + } + if (!rv) + rv = z90crypt_process_results(we_p, (char __user *)arg); + + if ((we_p->status[0] & STAT_FAILED)) { + switch (rv) { + /** + * EINVAL *after* receive is almost always a padding error or + * length error issued by a coprocessor (not an accelerator). + * We convert this return value to -EGETBUFF which should + * trigger a fallback to software. + */ + case -EINVAL: + if ((we_p->devtype != PCICA) && + (we_p->devtype != CEX2A)) + rv = -EGETBUFF; + break; + case -ETIMEOUT: + if (z90crypt.mask.st_count > 0) + rv = -ERESTARTSYS; // retry with another + else + rv = -ENODEV; // no cards left + /* fall through to clean up request queue */ + case -ERESTARTSYS: + case -ERELEASED: + switch (CHK_RDWRMASK(we_p->status[0])) { + case STAT_WRITTEN: + purge_work_element(we_p); + break; + case STAT_READPEND: + case STAT_NOWORK: + default: + break; + } + break; + default: + we_p->status[0] ^= STAT_FAILED; + break; + } + } + free_page((long)we_p); + return rv; +} + +/** + * This function is a little long, but it's really just one large switch + * statement. + */ +static long +z90crypt_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct priv_data *private_data_p = filp->private_data; + unsigned char *status; + unsigned char *qdepth; + unsigned int *reqcnt; + struct ica_z90_status *pstat; + int ret, i, loopLim, tempstat; + static int deprecated_msg_count1 = 0; + static int deprecated_msg_count2 = 0; + + PDEBUG("filp %p (PID %d), cmd 0x%08X\n", filp, PID(), cmd); + PDEBUG("cmd 0x%08X: dir %s, size 0x%04X, type 0x%02X, nr 0x%02X\n", + cmd, + !_IOC_DIR(cmd) ? "NO" + : ((_IOC_DIR(cmd) == (_IOC_READ|_IOC_WRITE)) ? "RW" + : ((_IOC_DIR(cmd) == _IOC_READ) ? "RD" + : "WR")), + _IOC_SIZE(cmd), _IOC_TYPE(cmd), _IOC_NR(cmd)); + + if (_IOC_TYPE(cmd) != Z90_IOCTL_MAGIC) { + PRINTK("cmd 0x%08X contains bad magic\n", cmd); + return -ENOTTY; + } + + ret = 0; + switch (cmd) { + case ICARSAMODEXPO: + case ICARSACRT: + if (quiesce_z90crypt) { + ret = -EQUIESCE; + break; + } + ret = -ENODEV; // Default if no devices + loopLim = z90crypt.hdware_info->hdware_mask.st_count - + (z90crypt.hdware_info->hdware_mask.disabled_count + + z90crypt.hdware_info->hdware_mask.user_disabled_count); + for (i = 0; i < loopLim; i++) { + ret = z90crypt_rsa(private_data_p, PID(), cmd, arg); + if (ret != -ERESTARTSYS) + break; + } + if (ret == -ERESTARTSYS) + ret = -ENODEV; + break; + + case Z90STAT_TOTALCOUNT: + tempstat = get_status_totalcount(); + if (copy_to_user((int __user *)arg, &tempstat,sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90STAT_PCICACOUNT: + tempstat = get_status_PCICAcount(); + if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90STAT_PCICCCOUNT: + tempstat = get_status_PCICCcount(); + if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90STAT_PCIXCCMCL2COUNT: + tempstat = get_status_PCIXCCMCL2count(); + if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90STAT_PCIXCCMCL3COUNT: + tempstat = get_status_PCIXCCMCL3count(); + if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90STAT_CEX2CCOUNT: + tempstat = get_status_CEX2Ccount(); + if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90STAT_CEX2ACOUNT: + tempstat = get_status_CEX2Acount(); + if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90STAT_REQUESTQ_COUNT: + tempstat = get_status_requestq_count(); + if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90STAT_PENDINGQ_COUNT: + tempstat = get_status_pendingq_count(); + if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90STAT_TOTALOPEN_COUNT: + tempstat = get_status_totalopen_count(); + if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90STAT_DOMAIN_INDEX: + tempstat = get_status_domain_index(); + if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90STAT_STATUS_MASK: + status = kmalloc(Z90CRYPT_NUM_APS, GFP_KERNEL); + if (!status) { + PRINTK("kmalloc for status failed!\n"); + ret = -ENOMEM; + break; + } + get_status_status_mask(status); + if (copy_to_user((char __user *) arg, status, Z90CRYPT_NUM_APS) + != 0) + ret = -EFAULT; + kfree(status); + break; + + case Z90STAT_QDEPTH_MASK: + qdepth = kmalloc(Z90CRYPT_NUM_APS, GFP_KERNEL); + if (!qdepth) { + PRINTK("kmalloc for qdepth failed!\n"); + ret = -ENOMEM; + break; + } + get_status_qdepth_mask(qdepth); + if (copy_to_user((char __user *) arg, qdepth, Z90CRYPT_NUM_APS) != 0) + ret = -EFAULT; + kfree(qdepth); + break; + + case Z90STAT_PERDEV_REQCNT: + reqcnt = kmalloc(sizeof(int) * Z90CRYPT_NUM_APS, GFP_KERNEL); + if (!reqcnt) { + PRINTK("kmalloc for reqcnt failed!\n"); + ret = -ENOMEM; + break; + } + get_status_perdevice_reqcnt(reqcnt); + if (copy_to_user((char __user *) arg, reqcnt, + Z90CRYPT_NUM_APS * sizeof(int)) != 0) + ret = -EFAULT; + kfree(reqcnt); + break; + + /* THIS IS DEPRECATED. USE THE NEW STATUS CALLS */ + case ICAZ90STATUS: + if (deprecated_msg_count1 < 20) { + PRINTK("deprecated call to ioctl (ICAZ90STATUS)!\n"); + deprecated_msg_count1++; + if (deprecated_msg_count1 == 20) + PRINTK("No longer issuing messages related to " + "deprecated call to ICAZ90STATUS.\n"); + } + + pstat = kmalloc(sizeof(struct ica_z90_status), GFP_KERNEL); + if (!pstat) { + PRINTK("kmalloc for pstat failed!\n"); + ret = -ENOMEM; + break; + } + + pstat->totalcount = get_status_totalcount(); + pstat->leedslitecount = get_status_PCICAcount(); + pstat->leeds2count = get_status_PCICCcount(); + pstat->requestqWaitCount = get_status_requestq_count(); + pstat->pendingqWaitCount = get_status_pendingq_count(); + pstat->totalOpenCount = get_status_totalopen_count(); + pstat->cryptoDomain = get_status_domain_index(); + get_status_status_mask(pstat->status); + get_status_qdepth_mask(pstat->qdepth); + + if (copy_to_user((struct ica_z90_status __user *) arg, pstat, + sizeof(struct ica_z90_status)) != 0) + ret = -EFAULT; + kfree(pstat); + break; + + /* THIS IS DEPRECATED. USE THE NEW STATUS CALLS */ + case Z90STAT_PCIXCCCOUNT: + if (deprecated_msg_count2 < 20) { + PRINTK("deprecated ioctl (Z90STAT_PCIXCCCOUNT)!\n"); + deprecated_msg_count2++; + if (deprecated_msg_count2 == 20) + PRINTK("No longer issuing messages about depre" + "cated ioctl Z90STAT_PCIXCCCOUNT.\n"); + } + + tempstat = get_status_PCIXCCcount(); + if (copy_to_user((int *)arg, &tempstat, sizeof(int)) != 0) + ret = -EFAULT; + break; + + case Z90QUIESCE: + if (current->euid != 0) { + PRINTK("QUIESCE fails: euid %d\n", + current->euid); + ret = -EACCES; + } else { + PRINTK("QUIESCE device from PID %d\n", PID()); + quiesce_z90crypt = 1; + } + break; + + default: + /* user passed an invalid IOCTL number */ + PDEBUG("cmd 0x%08X contains invalid ioctl code\n", cmd); + ret = -ENOTTY; + break; + } + + return ret; +} + +static inline int +sprintcl(unsigned char *outaddr, unsigned char *addr, unsigned int len) +{ + int hl, i; + + hl = 0; + for (i = 0; i < len; i++) + hl += sprintf(outaddr+hl, "%01x", (unsigned int) addr[i]); + hl += sprintf(outaddr+hl, " "); + + return hl; +} + +static inline int +sprintrw(unsigned char *outaddr, unsigned char *addr, unsigned int len) +{ + int hl, inl, c, cx; + + hl = sprintf(outaddr, " "); + inl = 0; + for (c = 0; c < (len / 16); c++) { + hl += sprintcl(outaddr+hl, addr+inl, 16); + inl += 16; + } + + cx = len%16; + if (cx) { + hl += sprintcl(outaddr+hl, addr+inl, cx); + inl += cx; + } + + hl += sprintf(outaddr+hl, "\n"); + + return hl; +} + +static inline int +sprinthx(unsigned char *title, unsigned char *outaddr, + unsigned char *addr, unsigned int len) +{ + int hl, inl, r, rx; + + hl = sprintf(outaddr, "\n%s\n", title); + inl = 0; + for (r = 0; r < (len / 64); r++) { + hl += sprintrw(outaddr+hl, addr+inl, 64); + inl += 64; + } + rx = len % 64; + if (rx) { + hl += sprintrw(outaddr+hl, addr+inl, rx); + inl += rx; + } + + hl += sprintf(outaddr+hl, "\n"); + + return hl; +} + +static inline int +sprinthx4(unsigned char *title, unsigned char *outaddr, + unsigned int *array, unsigned int len) +{ + int hl, r; + + hl = sprintf(outaddr, "\n%s\n", title); + + for (r = 0; r < len; r++) { + if ((r % 8) == 0) + hl += sprintf(outaddr+hl, " "); + hl += sprintf(outaddr+hl, "%08X ", array[r]); + if ((r % 8) == 7) + hl += sprintf(outaddr+hl, "\n"); + } + + hl += sprintf(outaddr+hl, "\n"); + + return hl; +} + +static int +z90crypt_status(char *resp_buff, char **start, off_t offset, + int count, int *eof, void *data) +{ + unsigned char *workarea; + int len; + + /* resp_buff is a page. Use the right half for a work area */ + workarea = resp_buff+2000; + len = 0; + len += sprintf(resp_buff+len, "\nz90crypt version: %d.%d.%d\n", + z90crypt_VERSION, z90crypt_RELEASE, z90crypt_VARIANT); + len += sprintf(resp_buff+len, "Cryptographic domain: %d\n", + get_status_domain_index()); + len += sprintf(resp_buff+len, "Total device count: %d\n", + get_status_totalcount()); + len += sprintf(resp_buff+len, "PCICA count: %d\n", + get_status_PCICAcount()); + len += sprintf(resp_buff+len, "PCICC count: %d\n", + get_status_PCICCcount()); + len += sprintf(resp_buff+len, "PCIXCC MCL2 count: %d\n", + get_status_PCIXCCMCL2count()); + len += sprintf(resp_buff+len, "PCIXCC MCL3 count: %d\n", + get_status_PCIXCCMCL3count()); + len += sprintf(resp_buff+len, "CEX2C count: %d\n", + get_status_CEX2Ccount()); + len += sprintf(resp_buff+len, "CEX2A count: %d\n", + get_status_CEX2Acount()); + len += sprintf(resp_buff+len, "requestq count: %d\n", + get_status_requestq_count()); + len += sprintf(resp_buff+len, "pendingq count: %d\n", + get_status_pendingq_count()); + len += sprintf(resp_buff+len, "Total open handles: %d\n\n", + get_status_totalopen_count()); + len += sprinthx( + "Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) " + "4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A", + resp_buff+len, + get_status_status_mask(workarea), + Z90CRYPT_NUM_APS); + len += sprinthx("Waiting work element counts", + resp_buff+len, + get_status_qdepth_mask(workarea), + Z90CRYPT_NUM_APS); + len += sprinthx4( + "Per-device successfully completed request counts", + resp_buff+len, + get_status_perdevice_reqcnt((unsigned int *)workarea), + Z90CRYPT_NUM_APS); + *eof = 1; + memset(workarea, 0, Z90CRYPT_NUM_APS * sizeof(unsigned int)); + return len; +} + +static inline void +disable_card(int card_index) +{ + struct device *devp; + + devp = LONG2DEVPTR(card_index); + if (!devp || devp->user_disabled) + return; + devp->user_disabled = 1; + z90crypt.hdware_info->hdware_mask.user_disabled_count++; + if (devp->dev_type == -1) + return; + z90crypt.hdware_info->type_mask[devp->dev_type].user_disabled_count++; +} + +static inline void +enable_card(int card_index) +{ + struct device *devp; + + devp = LONG2DEVPTR(card_index); + if (!devp || !devp->user_disabled) + return; + devp->user_disabled = 0; + z90crypt.hdware_info->hdware_mask.user_disabled_count--; + if (devp->dev_type == -1) + return; + z90crypt.hdware_info->type_mask[devp->dev_type].user_disabled_count--; +} + +static int +z90crypt_status_write(struct file *file, const char __user *buffer, + unsigned long count, void *data) +{ + int j, eol; + unsigned char *lbuf, *ptr; + unsigned int local_count; + +#define LBUFSIZE 1200 + lbuf = kmalloc(LBUFSIZE, GFP_KERNEL); + if (!lbuf) { + PRINTK("kmalloc failed!\n"); + return 0; + } + + if (count <= 0) + return 0; + + local_count = UMIN((unsigned int)count, LBUFSIZE-1); + + if (copy_from_user(lbuf, buffer, local_count) != 0) { + kfree(lbuf); + return -EFAULT; + } + + lbuf[local_count] = '\0'; + + ptr = strstr(lbuf, "Online devices"); + if (ptr == 0) { + PRINTK("Unable to parse data (missing \"Online devices\")\n"); + kfree(lbuf); + return count; + } + + ptr = strstr(ptr, "\n"); + if (ptr == 0) { + PRINTK("Unable to parse data (missing newline after \"Online devices\")\n"); + kfree(lbuf); + return count; + } + ptr++; + + if (strstr(ptr, "Waiting work element counts") == NULL) { + PRINTK("Unable to parse data (missing \"Waiting work element counts\")\n"); + kfree(lbuf); + return count; + } + + j = 0; + eol = 0; + while ((j < 64) && (*ptr != '\0')) { + switch (*ptr) { + case '\t': + case ' ': + break; + case '\n': + default: + eol = 1; + break; + case '0': // no device + case '1': // PCICA + case '2': // PCICC + case '3': // PCIXCC_MCL2 + case '4': // PCIXCC_MCL3 + case '5': // CEX2C + case '6': // CEX2A + j++; + break; + case 'd': + case 'D': + disable_card(j); + j++; + break; + case 'e': + case 'E': + enable_card(j); + j++; + break; + } + if (eol) + break; + ptr++; + } + + kfree(lbuf); + return count; +} + +/** + * Functions that run under a timer, with no process id + * + * The task functions: + * z90crypt_reader_task + * helper_send_work + * helper_handle_work_element + * helper_receive_rc + * z90crypt_config_task + * z90crypt_cleanup_task + * + * Helper functions: + * z90crypt_schedule_reader_timer + * z90crypt_schedule_reader_task + * z90crypt_schedule_config_task + * z90crypt_schedule_cleanup_task + */ +static inline int +receive_from_crypto_device(int index, unsigned char *psmid, int *buff_len_p, + unsigned char *buff, unsigned char __user **dest_p_p) +{ + int dv, rv; + struct device *dev_ptr; + struct caller *caller_p; + struct ica_rsa_modexpo *icaMsg_p; + struct list_head *ptr, *tptr; + + memcpy(psmid, NULL_psmid, sizeof(NULL_psmid)); + + if (z90crypt.terminating) + return REC_FATAL_ERROR; + + caller_p = 0; + dev_ptr = z90crypt.device_p[index]; + rv = 0; + do { + if (!dev_ptr || dev_ptr->disabled) { + rv = REC_NO_WORK; // a disabled device can't return work + break; + } + if (dev_ptr->dev_self_x != index) { + PRINTKC("Corrupt dev ptr\n"); + z90crypt.terminating = 1; + rv = REC_FATAL_ERROR; + break; + } + if (!dev_ptr->dev_resp_l || !dev_ptr->dev_resp_p) { + dv = DEV_REC_EXCEPTION; + PRINTK("dev_resp_l = %d, dev_resp_p = %p\n", + dev_ptr->dev_resp_l, dev_ptr->dev_resp_p); + } else { + PDEBUG("Dequeue called for device %d\n", index); + dv = receive_from_AP(index, z90crypt.cdx, + dev_ptr->dev_resp_l, + dev_ptr->dev_resp_p, psmid); + } + switch (dv) { + case DEV_REC_EXCEPTION: + rv = REC_FATAL_ERROR; + z90crypt.terminating = 1; + PRINTKC("Exception in receive from device %d\n", + index); + break; + case DEV_ONLINE: + rv = 0; + break; + case DEV_EMPTY: + rv = REC_EMPTY; + break; + case DEV_NO_WORK: + rv = REC_NO_WORK; + break; + case DEV_BAD_MESSAGE: + case DEV_GONE: + case REC_HARDWAR_ERR: + default: + rv = REC_NO_RESPONSE; + break; + } + if (rv) + break; + if (dev_ptr->dev_caller_count <= 0) { + rv = REC_USER_GONE; + break; + } + + list_for_each_safe(ptr, tptr, &dev_ptr->dev_caller_list) { + caller_p = list_entry(ptr, struct caller, caller_liste); + if (!memcmp(caller_p->caller_id, psmid, + sizeof(caller_p->caller_id))) { + if (!list_empty(&caller_p->caller_liste)) { + list_del_init(ptr); + dev_ptr->dev_caller_count--; + break; + } + } + caller_p = 0; + } + if (!caller_p) { + PRINTKW("Unable to locate PSMID %02X%02X%02X%02X%02X" + "%02X%02X%02X in device list\n", + psmid[0], psmid[1], psmid[2], psmid[3], + psmid[4], psmid[5], psmid[6], psmid[7]); + rv = REC_USER_GONE; + break; + } + + PDEBUG("caller_p after successful receive: %p\n", caller_p); + rv = convert_response(dev_ptr->dev_resp_p, + caller_p->caller_buf_p, buff_len_p, buff); + switch (rv) { + case REC_USE_PCICA: + break; + case REC_OPERAND_INV: + case REC_OPERAND_SIZE: + case REC_EVEN_MOD: + case REC_INVALID_PAD: + PDEBUG("device %d: 'user error' %d\n", index, rv); + break; + case WRONG_DEVICE_TYPE: + case REC_HARDWAR_ERR: + case REC_BAD_MESSAGE: + PRINTKW("device %d: hardware error %d\n", index, rv); + rv = REC_NO_RESPONSE; + break; + default: + PDEBUG("device %d: rv = %d\n", index, rv); + break; + } + } while (0); + + switch (rv) { + case 0: + PDEBUG("Successful receive from device %d\n", index); + icaMsg_p = (struct ica_rsa_modexpo *)caller_p->caller_buf_p; + *dest_p_p = icaMsg_p->outputdata; + if (*buff_len_p == 0) + PRINTK("Zero *buff_len_p\n"); + break; + case REC_NO_RESPONSE: + PRINTKW("Removing device %d from availability\n", index); + remove_device(dev_ptr); + break; + } + + if (caller_p) + unbuild_caller(dev_ptr, caller_p); + + return rv; +} + +static inline void +helper_send_work(int index) +{ + struct work_element *rq_p; + int rv; + + if (list_empty(&request_list)) + return; + requestq_count--; + rq_p = list_entry(request_list.next, struct work_element, liste); + list_del_init(&rq_p->liste); + rq_p->audit[1] |= FP_REMREQUEST; + if (rq_p->devtype == SHRT2DEVPTR(index)->dev_type) { + rq_p->devindex = SHRT2LONG(index); + rv = send_to_crypto_device(rq_p); + if (rv == 0) { + rq_p->requestsent = jiffies; + rq_p->audit[0] |= FP_SENT; + list_add_tail(&rq_p->liste, &pending_list); + ++pendingq_count; + rq_p->audit[0] |= FP_PENDING; + } else { + switch (rv) { + case REC_OPERAND_INV: + case REC_OPERAND_SIZE: + case REC_EVEN_MOD: + case REC_INVALID_PAD: + rq_p->retcode = -EINVAL; + break; + case SEN_NOT_AVAIL: + case SEN_RETRY: + case REC_NO_RESPONSE: + default: + if (z90crypt.mask.st_count > 1) + rq_p->retcode = + -ERESTARTSYS; + else + rq_p->retcode = -ENODEV; + break; + } + rq_p->status[0] |= STAT_FAILED; + rq_p->audit[1] |= FP_AWAKENING; + atomic_set(&rq_p->alarmrung, 1); + wake_up(&rq_p->waitq); + } + } else { + if (z90crypt.mask.st_count > 1) + rq_p->retcode = -ERESTARTSYS; + else + rq_p->retcode = -ENODEV; + rq_p->status[0] |= STAT_FAILED; + rq_p->audit[1] |= FP_AWAKENING; + atomic_set(&rq_p->alarmrung, 1); + wake_up(&rq_p->waitq); + } +} + +static inline void +helper_handle_work_element(int index, unsigned char psmid[8], int rc, + int buff_len, unsigned char *buff, + unsigned char __user *resp_addr) +{ + struct work_element *pq_p; + struct list_head *lptr, *tptr; + + pq_p = 0; + list_for_each_safe(lptr, tptr, &pending_list) { + pq_p = list_entry(lptr, struct work_element, liste); + if (!memcmp(pq_p->caller_id, psmid, sizeof(pq_p->caller_id))) { + list_del_init(lptr); + pendingq_count--; + pq_p->audit[1] |= FP_NOTPENDING; + break; + } + pq_p = 0; + } + + if (!pq_p) { + PRINTK("device %d has work but no caller exists on pending Q\n", + SHRT2LONG(index)); + return; + } + + switch (rc) { + case 0: + pq_p->resp_buff_size = buff_len; + pq_p->audit[1] |= FP_RESPSIZESET; + if (buff_len) { + pq_p->resp_addr = resp_addr; + pq_p->audit[1] |= FP_RESPADDRCOPIED; + memcpy(pq_p->resp_buff, buff, buff_len); + pq_p->audit[1] |= FP_RESPBUFFCOPIED; + } + break; + case REC_OPERAND_INV: + case REC_OPERAND_SIZE: + case REC_EVEN_MOD: + case REC_INVALID_PAD: + PDEBUG("-EINVAL after application error %d\n", rc); + pq_p->retcode = -EINVAL; + pq_p->status[0] |= STAT_FAILED; + break; + case REC_USE_PCICA: + pq_p->retcode = -ERESTARTSYS; + pq_p->status[0] |= STAT_FAILED; + break; + case REC_NO_RESPONSE: + default: + if (z90crypt.mask.st_count > 1) + pq_p->retcode = -ERESTARTSYS; + else + pq_p->retcode = -ENODEV; + pq_p->status[0] |= STAT_FAILED; + break; + } + if ((pq_p->status[0] != STAT_FAILED) || (pq_p->retcode != -ERELEASED)) { + pq_p->audit[1] |= FP_AWAKENING; + atomic_set(&pq_p->alarmrung, 1); + wake_up(&pq_p->waitq); + } +} + +/** + * return TRUE if the work element should be removed from the queue + */ +static inline int +helper_receive_rc(int index, int *rc_p) +{ + switch (*rc_p) { + case 0: + case REC_OPERAND_INV: + case REC_OPERAND_SIZE: + case REC_EVEN_MOD: + case REC_INVALID_PAD: + case REC_USE_PCICA: + break; + + case REC_BUSY: + case REC_NO_WORK: + case REC_EMPTY: + case REC_RETRY_DEV: + case REC_FATAL_ERROR: + return 0; + + case REC_NO_RESPONSE: + break; + + default: + PRINTK("rc %d, device %d converted to REC_NO_RESPONSE\n", + *rc_p, SHRT2LONG(index)); + *rc_p = REC_NO_RESPONSE; + break; + } + return 1; +} + +static inline void +z90crypt_schedule_reader_timer(void) +{ + if (timer_pending(&reader_timer)) + return; + if (mod_timer(&reader_timer, jiffies+(READERTIME*HZ/1000)) != 0) + PRINTK("Timer pending while modifying reader timer\n"); +} + +static void +z90crypt_reader_task(unsigned long ptr) +{ + int workavail, index, rc, buff_len; + unsigned char psmid[8]; + unsigned char __user *resp_addr; + static unsigned char buff[1024]; + + /** + * we use workavail = 2 to ensure 2 passes with nothing dequeued before + * exiting the loop. If (pendingq_count+requestq_count) == 0 after the + * loop, there is no work remaining on the queues. + */ + resp_addr = 0; + workavail = 2; + buff_len = 0; + while (workavail) { + workavail--; + rc = 0; + spin_lock_irq(&queuespinlock); + memset(buff, 0x00, sizeof(buff)); + + /* Dequeue once from each device in round robin. */ + for (index = 0; index < z90crypt.mask.st_count; index++) { + PDEBUG("About to receive.\n"); + rc = receive_from_crypto_device(SHRT2LONG(index), + psmid, + &buff_len, + buff, + &resp_addr); + PDEBUG("Dequeued: rc = %d.\n", rc); + + if (helper_receive_rc(index, &rc)) { + if (rc != REC_NO_RESPONSE) { + helper_send_work(index); + workavail = 2; + } + + helper_handle_work_element(index, psmid, rc, + buff_len, buff, + resp_addr); + } + + if (rc == REC_FATAL_ERROR) + PRINTKW("REC_FATAL_ERROR from device %d!\n", + SHRT2LONG(index)); + } + spin_unlock_irq(&queuespinlock); + } + + if (pendingq_count + requestq_count) + z90crypt_schedule_reader_timer(); +} + +static inline void +z90crypt_schedule_config_task(unsigned int expiration) +{ + if (timer_pending(&config_timer)) + return; + if (mod_timer(&config_timer, jiffies+(expiration*HZ)) != 0) + PRINTK("Timer pending while modifying config timer\n"); +} + +static void +z90crypt_config_task(unsigned long ptr) +{ + int rc; + + PDEBUG("jiffies %ld\n", jiffies); + + if ((rc = refresh_z90crypt(&z90crypt.cdx))) + PRINTK("Error %d detected in refresh_z90crypt.\n", rc); + /* If return was fatal, don't bother reconfiguring */ + if ((rc != TSQ_FATAL_ERROR) && (rc != RSQ_FATAL_ERROR)) + z90crypt_schedule_config_task(CONFIGTIME); +} + +static inline void +z90crypt_schedule_cleanup_task(void) +{ + if (timer_pending(&cleanup_timer)) + return; + if (mod_timer(&cleanup_timer, jiffies+(CLEANUPTIME*HZ)) != 0) + PRINTK("Timer pending while modifying cleanup timer\n"); +} + +static inline void +helper_drain_queues(void) +{ + struct work_element *pq_p; + struct list_head *lptr, *tptr; + + list_for_each_safe(lptr, tptr, &pending_list) { + pq_p = list_entry(lptr, struct work_element, liste); + pq_p->retcode = -ENODEV; + pq_p->status[0] |= STAT_FAILED; + unbuild_caller(LONG2DEVPTR(pq_p->devindex), + (struct caller *)pq_p->requestptr); + list_del_init(lptr); + pendingq_count--; + pq_p->audit[1] |= FP_NOTPENDING; + pq_p->audit[1] |= FP_AWAKENING; + atomic_set(&pq_p->alarmrung, 1); + wake_up(&pq_p->waitq); + } + + list_for_each_safe(lptr, tptr, &request_list) { + pq_p = list_entry(lptr, struct work_element, liste); + pq_p->retcode = -ENODEV; + pq_p->status[0] |= STAT_FAILED; + list_del_init(lptr); + requestq_count--; + pq_p->audit[1] |= FP_REMREQUEST; + pq_p->audit[1] |= FP_AWAKENING; + atomic_set(&pq_p->alarmrung, 1); + wake_up(&pq_p->waitq); + } +} + +static inline void +helper_timeout_requests(void) +{ + struct work_element *pq_p; + struct list_head *lptr, *tptr; + long timelimit; + + timelimit = jiffies - (CLEANUPTIME * HZ); + /* The list is in strict chronological order */ + list_for_each_safe(lptr, tptr, &pending_list) { + pq_p = list_entry(lptr, struct work_element, liste); + if (pq_p->requestsent >= timelimit) + break; + PRINTKW("Purging(PQ) PSMID %02X%02X%02X%02X%02X%02X%02X%02X\n", + ((struct caller *)pq_p->requestptr)->caller_id[0], + ((struct caller *)pq_p->requestptr)->caller_id[1], + ((struct caller *)pq_p->requestptr)->caller_id[2], + ((struct caller *)pq_p->requestptr)->caller_id[3], + ((struct caller *)pq_p->requestptr)->caller_id[4], + ((struct caller *)pq_p->requestptr)->caller_id[5], + ((struct caller *)pq_p->requestptr)->caller_id[6], + ((struct caller *)pq_p->requestptr)->caller_id[7]); + pq_p->retcode = -ETIMEOUT; + pq_p->status[0] |= STAT_FAILED; + /* get this off any caller queue it may be on */ + unbuild_caller(LONG2DEVPTR(pq_p->devindex), + (struct caller *) pq_p->requestptr); + list_del_init(lptr); + pendingq_count--; + pq_p->audit[1] |= FP_TIMEDOUT; + pq_p->audit[1] |= FP_NOTPENDING; + pq_p->audit[1] |= FP_AWAKENING; + atomic_set(&pq_p->alarmrung, 1); + wake_up(&pq_p->waitq); + } + + /** + * If pending count is zero, items left on the request queue may + * never be processed. + */ + if (pendingq_count <= 0) { + list_for_each_safe(lptr, tptr, &request_list) { + pq_p = list_entry(lptr, struct work_element, liste); + if (pq_p->requestsent >= timelimit) + break; + PRINTKW("Purging(RQ) PSMID %02X%02X%02X%02X%02X%02X%02X%02X\n", + ((struct caller *)pq_p->requestptr)->caller_id[0], + ((struct caller *)pq_p->requestptr)->caller_id[1], + ((struct caller *)pq_p->requestptr)->caller_id[2], + ((struct caller *)pq_p->requestptr)->caller_id[3], + ((struct caller *)pq_p->requestptr)->caller_id[4], + ((struct caller *)pq_p->requestptr)->caller_id[5], + ((struct caller *)pq_p->requestptr)->caller_id[6], + ((struct caller *)pq_p->requestptr)->caller_id[7]); + pq_p->retcode = -ETIMEOUT; + pq_p->status[0] |= STAT_FAILED; + list_del_init(lptr); + requestq_count--; + pq_p->audit[1] |= FP_TIMEDOUT; + pq_p->audit[1] |= FP_REMREQUEST; + pq_p->audit[1] |= FP_AWAKENING; + atomic_set(&pq_p->alarmrung, 1); + wake_up(&pq_p->waitq); + } + } +} + +static void +z90crypt_cleanup_task(unsigned long ptr) +{ + PDEBUG("jiffies %ld\n", jiffies); + spin_lock_irq(&queuespinlock); + if (z90crypt.mask.st_count <= 0) // no devices! + helper_drain_queues(); + else + helper_timeout_requests(); + spin_unlock_irq(&queuespinlock); + z90crypt_schedule_cleanup_task(); +} + +static void +z90crypt_schedule_reader_task(unsigned long ptr) +{ + tasklet_schedule(&reader_tasklet); +} + +/** + * Lowlevel Functions: + * + * create_z90crypt: creates and initializes basic data structures + * refresh_z90crypt: re-initializes basic data structures + * find_crypto_devices: returns a count and mask of hardware status + * create_crypto_device: builds the descriptor for a device + * destroy_crypto_device: unallocates the descriptor for a device + * destroy_z90crypt: drains all work, unallocates structs + */ + +/** + * build the z90crypt root structure using the given domain index + */ +static int +create_z90crypt(int *cdx_p) +{ + struct hdware_block *hdware_blk_p; + + memset(&z90crypt, 0x00, sizeof(struct z90crypt)); + z90crypt.domain_established = 0; + z90crypt.len = sizeof(struct z90crypt); + z90crypt.max_count = Z90CRYPT_NUM_DEVS; + z90crypt.cdx = *cdx_p; + + hdware_blk_p = kzalloc(sizeof(struct hdware_block), GFP_ATOMIC); + if (!hdware_blk_p) { + PDEBUG("kmalloc for hardware block failed\n"); + return ENOMEM; + } + z90crypt.hdware_info = hdware_blk_p; + + return 0; +} + +static inline int +helper_scan_devices(int cdx_array[16], int *cdx_p, int *correct_cdx_found) +{ + enum hdstat hd_stat; + int q_depth, dev_type; + int indx, chkdom, numdomains; + + q_depth = dev_type = numdomains = 0; + for (chkdom = 0; chkdom <= 15; cdx_array[chkdom++] = -1); + for (indx = 0; indx < z90crypt.max_count; indx++) { + hd_stat = HD_NOT_THERE; + numdomains = 0; + for (chkdom = 0; chkdom <= 15; chkdom++) { + hd_stat = query_online(indx, chkdom, MAX_RESET, + &q_depth, &dev_type); + if (hd_stat == HD_TSQ_EXCEPTION) { + z90crypt.terminating = 1; + PRINTKC("exception taken!\n"); + break; + } + if (hd_stat == HD_ONLINE) { + cdx_array[numdomains++] = chkdom; + if (*cdx_p == chkdom) { + *correct_cdx_found = 1; + break; + } + } + } + if ((*correct_cdx_found == 1) || (numdomains != 0)) + break; + if (z90crypt.terminating) + break; + } + return numdomains; +} + +static inline int +probe_crypto_domain(int *cdx_p) +{ + int cdx_array[16]; + char cdx_array_text[53], temp[5]; + int correct_cdx_found, numdomains; + + correct_cdx_found = 0; + numdomains = helper_scan_devices(cdx_array, cdx_p, &correct_cdx_found); + + if (z90crypt.terminating) + return TSQ_FATAL_ERROR; + + if (correct_cdx_found) + return 0; + + if (numdomains == 0) { + PRINTKW("Unable to find crypto domain: No devices found\n"); + return Z90C_NO_DEVICES; + } + + if (numdomains == 1) { + if (*cdx_p == -1) { + *cdx_p = cdx_array[0]; + return 0; + } + PRINTKW("incorrect domain: specified = %d, found = %d\n", + *cdx_p, cdx_array[0]); + return Z90C_INCORRECT_DOMAIN; + } + + numdomains--; + sprintf(cdx_array_text, "%d", cdx_array[numdomains]); + while (numdomains) { + numdomains--; + sprintf(temp, ", %d", cdx_array[numdomains]); + strcat(cdx_array_text, temp); + } + + PRINTKW("ambiguous domain detected: specified = %d, found array = %s\n", + *cdx_p, cdx_array_text); + return Z90C_AMBIGUOUS_DOMAIN; +} + +static int +refresh_z90crypt(int *cdx_p) +{ + int i, j, indx, rv; + static struct status local_mask; + struct device *devPtr; + unsigned char oldStat, newStat; + int return_unchanged; + + if (z90crypt.len != sizeof(z90crypt)) + return ENOTINIT; + if (z90crypt.terminating) + return TSQ_FATAL_ERROR; + rv = 0; + if (!z90crypt.hdware_info->hdware_mask.st_count && + !z90crypt.domain_established) { + rv = probe_crypto_domain(cdx_p); + if (z90crypt.terminating) + return TSQ_FATAL_ERROR; + if (rv == Z90C_NO_DEVICES) + return 0; // try later + if (rv) + return rv; + z90crypt.cdx = *cdx_p; + z90crypt.domain_established = 1; + } + rv = find_crypto_devices(&local_mask); + if (rv) { + PRINTK("find crypto devices returned %d\n", rv); + return rv; + } + if (!memcmp(&local_mask, &z90crypt.hdware_info->hdware_mask, + sizeof(struct status))) { + return_unchanged = 1; + for (i = 0; i < Z90CRYPT_NUM_TYPES; i++) { + /** + * Check for disabled cards. If any device is marked + * disabled, destroy it. + */ + for (j = 0; + j < z90crypt.hdware_info->type_mask[i].st_count; + j++) { + indx = z90crypt.hdware_info->type_x_addr[i]. + device_index[j]; + devPtr = z90crypt.device_p[indx]; + if (devPtr && devPtr->disabled) { + local_mask.st_mask[indx] = HD_NOT_THERE; + return_unchanged = 0; + } + } + } + if (return_unchanged == 1) + return 0; + } + + spin_lock_irq(&queuespinlock); + for (i = 0; i < z90crypt.max_count; i++) { + oldStat = z90crypt.hdware_info->hdware_mask.st_mask[i]; + newStat = local_mask.st_mask[i]; + if ((oldStat == HD_ONLINE) && (newStat != HD_ONLINE)) + destroy_crypto_device(i); + else if ((oldStat != HD_ONLINE) && (newStat == HD_ONLINE)) { + rv = create_crypto_device(i); + if (rv >= REC_FATAL_ERROR) + return rv; + if (rv != 0) { + local_mask.st_mask[i] = HD_NOT_THERE; + local_mask.st_count--; + } + } + } + memcpy(z90crypt.hdware_info->hdware_mask.st_mask, local_mask.st_mask, + sizeof(local_mask.st_mask)); + z90crypt.hdware_info->hdware_mask.st_count = local_mask.st_count; + z90crypt.hdware_info->hdware_mask.disabled_count = + local_mask.disabled_count; + refresh_index_array(&z90crypt.mask, &z90crypt.overall_device_x); + for (i = 0; i < Z90CRYPT_NUM_TYPES; i++) + refresh_index_array(&(z90crypt.hdware_info->type_mask[i]), + &(z90crypt.hdware_info->type_x_addr[i])); + spin_unlock_irq(&queuespinlock); + + return rv; +} + +static int +find_crypto_devices(struct status *deviceMask) +{ + int i, q_depth, dev_type; + enum hdstat hd_stat; + + deviceMask->st_count = 0; + deviceMask->disabled_count = 0; + deviceMask->user_disabled_count = 0; + + for (i = 0; i < z90crypt.max_count; i++) { + hd_stat = query_online(i, z90crypt.cdx, MAX_RESET, &q_depth, + &dev_type); + if (hd_stat == HD_TSQ_EXCEPTION) { + z90crypt.terminating = 1; + PRINTKC("Exception during probe for crypto devices\n"); + return TSQ_FATAL_ERROR; + } + deviceMask->st_mask[i] = hd_stat; + if (hd_stat == HD_ONLINE) { + PDEBUG("Got an online crypto!: %d\n", i); + PDEBUG("Got a queue depth of %d\n", q_depth); + PDEBUG("Got a device type of %d\n", dev_type); + if (q_depth <= 0) + return TSQ_FATAL_ERROR; + deviceMask->st_count++; + z90crypt.q_depth_array[i] = q_depth; + z90crypt.dev_type_array[i] = dev_type; + } + } + + return 0; +} + +static int +refresh_index_array(struct status *status_str, struct device_x *index_array) +{ + int i, count; + enum devstat stat; + + i = -1; + count = 0; + do { + stat = status_str->st_mask[++i]; + if (stat == DEV_ONLINE) + index_array->device_index[count++] = i; + } while ((i < Z90CRYPT_NUM_DEVS) && (count < status_str->st_count)); + + return count; +} + +static int +create_crypto_device(int index) +{ + int rv, devstat, total_size; + struct device *dev_ptr; + struct status *type_str_p; + int deviceType; + + dev_ptr = z90crypt.device_p[index]; + if (!dev_ptr) { + total_size = sizeof(struct device) + + z90crypt.q_depth_array[index] * sizeof(int); + + dev_ptr = kzalloc(total_size, GFP_ATOMIC); + if (!dev_ptr) { + PRINTK("kmalloc device %d failed\n", index); + return ENOMEM; + } + dev_ptr->dev_resp_p = kmalloc(MAX_RESPONSE_SIZE, GFP_ATOMIC); + if (!dev_ptr->dev_resp_p) { + kfree(dev_ptr); + PRINTK("kmalloc device %d rec buffer failed\n", index); + return ENOMEM; + } + dev_ptr->dev_resp_l = MAX_RESPONSE_SIZE; + INIT_LIST_HEAD(&(dev_ptr->dev_caller_list)); + } + + devstat = reset_device(index, z90crypt.cdx, MAX_RESET); + if (devstat == DEV_RSQ_EXCEPTION) { + PRINTK("exception during reset device %d\n", index); + kfree(dev_ptr->dev_resp_p); + kfree(dev_ptr); + return RSQ_FATAL_ERROR; + } + if (devstat == DEV_ONLINE) { + dev_ptr->dev_self_x = index; + dev_ptr->dev_type = z90crypt.dev_type_array[index]; + if (dev_ptr->dev_type == NILDEV) { + rv = probe_device_type(dev_ptr); + if (rv) { + PRINTK("rv = %d from probe_device_type %d\n", + rv, index); + kfree(dev_ptr->dev_resp_p); + kfree(dev_ptr); + return rv; + } + } + if (dev_ptr->dev_type == PCIXCC_UNK) { + rv = probe_PCIXCC_type(dev_ptr); + if (rv) { + PRINTK("rv = %d from probe_PCIXCC_type %d\n", + rv, index); + kfree(dev_ptr->dev_resp_p); + kfree(dev_ptr); + return rv; + } + } + deviceType = dev_ptr->dev_type; + z90crypt.dev_type_array[index] = deviceType; + if (deviceType == PCICA) + z90crypt.hdware_info->device_type_array[index] = 1; + else if (deviceType == PCICC) + z90crypt.hdware_info->device_type_array[index] = 2; + else if (deviceType == PCIXCC_MCL2) + z90crypt.hdware_info->device_type_array[index] = 3; + else if (deviceType == PCIXCC_MCL3) + z90crypt.hdware_info->device_type_array[index] = 4; + else if (deviceType == CEX2C) + z90crypt.hdware_info->device_type_array[index] = 5; + else if (deviceType == CEX2A) + z90crypt.hdware_info->device_type_array[index] = 6; + else // No idea how this would happen. + z90crypt.hdware_info->device_type_array[index] = -1; + } + + /** + * 'q_depth' returned by the hardware is one less than + * the actual depth + */ + dev_ptr->dev_q_depth = z90crypt.q_depth_array[index]; + dev_ptr->dev_type = z90crypt.dev_type_array[index]; + dev_ptr->dev_stat = devstat; + dev_ptr->disabled = 0; + z90crypt.device_p[index] = dev_ptr; + + if (devstat == DEV_ONLINE) { + if (z90crypt.mask.st_mask[index] != DEV_ONLINE) { + z90crypt.mask.st_mask[index] = DEV_ONLINE; + z90crypt.mask.st_count++; + } + deviceType = dev_ptr->dev_type; + type_str_p = &z90crypt.hdware_info->type_mask[deviceType]; + if (type_str_p->st_mask[index] != DEV_ONLINE) { + type_str_p->st_mask[index] = DEV_ONLINE; + type_str_p->st_count++; + } + } + + return 0; +} + +static int +destroy_crypto_device(int index) +{ + struct device *dev_ptr; + int t, disabledFlag; + + dev_ptr = z90crypt.device_p[index]; + + /* remember device type; get rid of device struct */ + if (dev_ptr) { + disabledFlag = dev_ptr->disabled; + t = dev_ptr->dev_type; + kfree(dev_ptr->dev_resp_p); + kfree(dev_ptr); + } else { + disabledFlag = 0; + t = -1; + } + z90crypt.device_p[index] = 0; + + /* if the type is valid, remove the device from the type_mask */ + if ((t != -1) && z90crypt.hdware_info->type_mask[t].st_mask[index]) { + z90crypt.hdware_info->type_mask[t].st_mask[index] = 0x00; + z90crypt.hdware_info->type_mask[t].st_count--; + if (disabledFlag == 1) + z90crypt.hdware_info->type_mask[t].disabled_count--; + } + if (z90crypt.mask.st_mask[index] != DEV_GONE) { + z90crypt.mask.st_mask[index] = DEV_GONE; + z90crypt.mask.st_count--; + } + z90crypt.hdware_info->device_type_array[index] = 0; + + return 0; +} + +static void +destroy_z90crypt(void) +{ + int i; + + for (i = 0; i < z90crypt.max_count; i++) + if (z90crypt.device_p[i]) + destroy_crypto_device(i); + kfree(z90crypt.hdware_info); + memset((void *)&z90crypt, 0, sizeof(z90crypt)); +} + +static unsigned char static_testmsg[384] = { +0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x00,0x06,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x58, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x43,0x43, +0x41,0x2d,0x41,0x50,0x50,0x4c,0x20,0x20,0x20,0x01,0x01,0x01,0x00,0x00,0x00,0x00, +0x50,0x4b,0x00,0x00,0x00,0x00,0x01,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x70,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x32, +0x01,0x00,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xb8,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x49,0x43,0x53,0x46, +0x20,0x20,0x20,0x20,0x50,0x4b,0x0a,0x00,0x50,0x4b,0x43,0x53,0x2d,0x31,0x2e,0x32, +0x37,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44, +0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00, +0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x44,0x55,0x66, +0x77,0x88,0x99,0x00,0x11,0x22,0x33,0x5d,0x00,0x5b,0x00,0x77,0x88,0x1e,0x00,0x00, +0x57,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x4f,0x00,0x00,0x00,0x03,0x02,0x00,0x00, +0x40,0x01,0x00,0x01,0xce,0x02,0x68,0x2d,0x5f,0xa9,0xde,0x0c,0xf6,0xd2,0x7b,0x58, +0x4b,0xf9,0x28,0x68,0x3d,0xb4,0xf4,0xef,0x78,0xd5,0xbe,0x66,0x63,0x42,0xef,0xf8, +0xfd,0xa4,0xf8,0xb0,0x8e,0x29,0xc2,0xc9,0x2e,0xd8,0x45,0xb8,0x53,0x8c,0x6f,0x4e, +0x72,0x8f,0x6c,0x04,0x9c,0x88,0xfc,0x1e,0xc5,0x83,0x55,0x57,0xf7,0xdd,0xfd,0x4f, +0x11,0x36,0x95,0x5d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; + +static int +probe_device_type(struct device *devPtr) +{ + int rv, dv, i, index, length; + unsigned char psmid[8]; + static unsigned char loc_testmsg[sizeof(static_testmsg)]; + + index = devPtr->dev_self_x; + rv = 0; + do { + memcpy(loc_testmsg, static_testmsg, sizeof(static_testmsg)); + length = sizeof(static_testmsg) - 24; + /* the -24 allows for the header */ + dv = send_to_AP(index, z90crypt.cdx, length, loc_testmsg); + if (dv) { + PDEBUG("dv returned by send during probe: %d\n", dv); + if (dv == DEV_SEN_EXCEPTION) { + rv = SEN_FATAL_ERROR; + PRINTKC("exception in send to AP %d\n", index); + break; + } + PDEBUG("return value from send_to_AP: %d\n", rv); + switch (dv) { + case DEV_GONE: + PDEBUG("dev %d not available\n", index); + rv = SEN_NOT_AVAIL; + break; + case DEV_ONLINE: + rv = 0; + break; + case DEV_EMPTY: + rv = SEN_NOT_AVAIL; + break; + case DEV_NO_WORK: + rv = SEN_FATAL_ERROR; + break; + case DEV_BAD_MESSAGE: + rv = SEN_USER_ERROR; + break; + case DEV_QUEUE_FULL: + rv = SEN_QUEUE_FULL; + break; + default: + PRINTK("unknown dv=%d for dev %d\n", dv, index); + rv = SEN_NOT_AVAIL; + break; + } + } + + if (rv) + break; + + for (i = 0; i < 6; i++) { + mdelay(300); + dv = receive_from_AP(index, z90crypt.cdx, + devPtr->dev_resp_l, + devPtr->dev_resp_p, psmid); + PDEBUG("dv returned by DQ = %d\n", dv); + if (dv == DEV_REC_EXCEPTION) { + rv = REC_FATAL_ERROR; + PRINTKC("exception in dequeue %d\n", + index); + break; + } + switch (dv) { + case DEV_ONLINE: + rv = 0; + break; + case DEV_EMPTY: + rv = REC_EMPTY; + break; + case DEV_NO_WORK: + rv = REC_NO_WORK; + break; + case DEV_BAD_MESSAGE: + case DEV_GONE: + default: + rv = REC_NO_RESPONSE; + break; + } + if ((rv != 0) && (rv != REC_NO_WORK)) + break; + if (rv == 0) + break; + } + if (rv) + break; + rv = (devPtr->dev_resp_p[0] == 0x00) && + (devPtr->dev_resp_p[1] == 0x86); + if (rv) + devPtr->dev_type = PCICC; + else + devPtr->dev_type = PCICA; + rv = 0; + } while (0); + /* In a general error case, the card is not marked online */ + return rv; +} + +static unsigned char MCL3_testmsg[] = { +0x00,0x00,0x00,0x00,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE, +0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00,0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x0A,0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20, +0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D, +0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD, +0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22, +0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54, +0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00,0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00, +0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40,0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C, +0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF,0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9, +0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63,0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5, +0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A,0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01, +0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28,0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91, +0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5,0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C, +0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98,0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96, +0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19,0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47, +0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36,0xF1,0x3D,0x93,0x53 +}; + +static int +probe_PCIXCC_type(struct device *devPtr) +{ + int rv, dv, i, index, length; + unsigned char psmid[8]; + static unsigned char loc_testmsg[548]; + struct CPRBX *cprbx_p; + + index = devPtr->dev_self_x; + rv = 0; + do { + memcpy(loc_testmsg, MCL3_testmsg, sizeof(MCL3_testmsg)); + length = sizeof(MCL3_testmsg) - 0x0C; + dv = send_to_AP(index, z90crypt.cdx, length, loc_testmsg); + if (dv) { + PDEBUG("dv returned = %d\n", dv); + if (dv == DEV_SEN_EXCEPTION) { + rv = SEN_FATAL_ERROR; + PRINTKC("exception in send to AP %d\n", index); + break; + } + PDEBUG("return value from send_to_AP: %d\n", rv); + switch (dv) { + case DEV_GONE: + PDEBUG("dev %d not available\n", index); + rv = SEN_NOT_AVAIL; + break; + case DEV_ONLINE: + rv = 0; + break; + case DEV_EMPTY: + rv = SEN_NOT_AVAIL; + break; + case DEV_NO_WORK: + rv = SEN_FATAL_ERROR; + break; + case DEV_BAD_MESSAGE: + rv = SEN_USER_ERROR; + break; + case DEV_QUEUE_FULL: + rv = SEN_QUEUE_FULL; + break; + default: + PRINTK("unknown dv=%d for dev %d\n", dv, index); + rv = SEN_NOT_AVAIL; + break; + } + } + + if (rv) + break; + + for (i = 0; i < 6; i++) { + mdelay(300); + dv = receive_from_AP(index, z90crypt.cdx, + devPtr->dev_resp_l, + devPtr->dev_resp_p, psmid); + PDEBUG("dv returned by DQ = %d\n", dv); + if (dv == DEV_REC_EXCEPTION) { + rv = REC_FATAL_ERROR; + PRINTKC("exception in dequeue %d\n", + index); + break; + } + switch (dv) { + case DEV_ONLINE: + rv = 0; + break; + case DEV_EMPTY: + rv = REC_EMPTY; + break; + case DEV_NO_WORK: + rv = REC_NO_WORK; + break; + case DEV_BAD_MESSAGE: + case DEV_GONE: + default: + rv = REC_NO_RESPONSE; + break; + } + if ((rv != 0) && (rv != REC_NO_WORK)) + break; + if (rv == 0) + break; + } + if (rv) + break; + cprbx_p = (struct CPRBX *) (devPtr->dev_resp_p + 48); + if ((cprbx_p->ccp_rtcode == 8) && (cprbx_p->ccp_rscode == 33)) { + devPtr->dev_type = PCIXCC_MCL2; + PDEBUG("device %d is MCL2\n", index); + } else { + devPtr->dev_type = PCIXCC_MCL3; + PDEBUG("device %d is MCL3\n", index); + } + } while (0); + /* In a general error case, the card is not marked online */ + return rv; +} + +module_init(z90crypt_init_module); +module_exit(z90crypt_cleanup_module); diff --git a/trunk/drivers/s390/crypto/zcrypt_api.c b/trunk/drivers/s390/crypto/zcrypt_api.c deleted file mode 100644 index 1edc10a7a6f2..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_api.c +++ /dev/null @@ -1,1091 +0,0 @@ -/* - * linux/drivers/s390/crypto/zcrypt_api.c - * - * zcrypt 2.1.0 - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * Cornelia Huck - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * Ralph Wuerthner - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "zcrypt_api.h" - -/** - * Module description. - */ -MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("Cryptographic Coprocessor interface, " - "Copyright 2001, 2006 IBM Corporation"); -MODULE_LICENSE("GPL"); - -static DEFINE_SPINLOCK(zcrypt_device_lock); -static LIST_HEAD(zcrypt_device_list); -static int zcrypt_device_count = 0; -static atomic_t zcrypt_open_count = ATOMIC_INIT(0); - -/** - * Device attributes common for all crypto devices. - */ -static ssize_t zcrypt_type_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct zcrypt_device *zdev = to_ap_dev(dev)->private; - return snprintf(buf, PAGE_SIZE, "%s\n", zdev->type_string); -} - -static DEVICE_ATTR(type, 0444, zcrypt_type_show, NULL); - -static ssize_t zcrypt_online_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct zcrypt_device *zdev = to_ap_dev(dev)->private; - return snprintf(buf, PAGE_SIZE, "%d\n", zdev->online); -} - -static ssize_t zcrypt_online_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct zcrypt_device *zdev = to_ap_dev(dev)->private; - int online; - - if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1) - return -EINVAL; - zdev->online = online; - if (!online) - ap_flush_queue(zdev->ap_dev); - return count; -} - -static DEVICE_ATTR(online, 0644, zcrypt_online_show, zcrypt_online_store); - -static struct attribute * zcrypt_device_attrs[] = { - &dev_attr_type.attr, - &dev_attr_online.attr, - NULL, -}; - -static struct attribute_group zcrypt_device_attr_group = { - .attrs = zcrypt_device_attrs, -}; - -/** - * Move the device towards the head of the device list. - * Need to be called while holding the zcrypt device list lock. - * Note: cards with speed_rating of 0 are kept at the end of the list. - */ -static void __zcrypt_increase_preference(struct zcrypt_device *zdev) -{ - struct zcrypt_device *tmp; - struct list_head *l; - - if (zdev->speed_rating == 0) - return; - for (l = zdev->list.prev; l != &zcrypt_device_list; l = l->prev) { - tmp = list_entry(l, struct zcrypt_device, list); - if ((tmp->request_count + 1) * tmp->speed_rating <= - (zdev->request_count + 1) * zdev->speed_rating && - tmp->speed_rating != 0) - break; - } - if (l == zdev->list.prev) - return; - /* Move zdev behind l */ - list_del(&zdev->list); - list_add(&zdev->list, l); -} - -/** - * Move the device towards the tail of the device list. - * Need to be called while holding the zcrypt device list lock. - * Note: cards with speed_rating of 0 are kept at the end of the list. - */ -static void __zcrypt_decrease_preference(struct zcrypt_device *zdev) -{ - struct zcrypt_device *tmp; - struct list_head *l; - - if (zdev->speed_rating == 0) - return; - for (l = zdev->list.next; l != &zcrypt_device_list; l = l->next) { - tmp = list_entry(l, struct zcrypt_device, list); - if ((tmp->request_count + 1) * tmp->speed_rating > - (zdev->request_count + 1) * zdev->speed_rating || - tmp->speed_rating == 0) - break; - } - if (l == zdev->list.next) - return; - /* Move zdev before l */ - list_del(&zdev->list); - list_add_tail(&zdev->list, l); -} - -static void zcrypt_device_release(struct kref *kref) -{ - struct zcrypt_device *zdev = - container_of(kref, struct zcrypt_device, refcount); - zcrypt_device_free(zdev); -} - -void zcrypt_device_get(struct zcrypt_device *zdev) -{ - kref_get(&zdev->refcount); -} -EXPORT_SYMBOL(zcrypt_device_get); - -int zcrypt_device_put(struct zcrypt_device *zdev) -{ - return kref_put(&zdev->refcount, zcrypt_device_release); -} -EXPORT_SYMBOL(zcrypt_device_put); - -struct zcrypt_device *zcrypt_device_alloc(size_t max_response_size) -{ - struct zcrypt_device *zdev; - - zdev = kzalloc(sizeof(struct zcrypt_device), GFP_KERNEL); - if (!zdev) - return NULL; - zdev->reply.message = kmalloc(max_response_size, GFP_KERNEL); - if (!zdev->reply.message) - goto out_free; - zdev->reply.length = max_response_size; - spin_lock_init(&zdev->lock); - INIT_LIST_HEAD(&zdev->list); - return zdev; - -out_free: - kfree(zdev); - return NULL; -} -EXPORT_SYMBOL(zcrypt_device_alloc); - -void zcrypt_device_free(struct zcrypt_device *zdev) -{ - kfree(zdev->reply.message); - kfree(zdev); -} -EXPORT_SYMBOL(zcrypt_device_free); - -/** - * Register a crypto device. - */ -int zcrypt_device_register(struct zcrypt_device *zdev) -{ - int rc; - - rc = sysfs_create_group(&zdev->ap_dev->device.kobj, - &zcrypt_device_attr_group); - if (rc) - goto out; - get_device(&zdev->ap_dev->device); - kref_init(&zdev->refcount); - spin_lock_bh(&zcrypt_device_lock); - zdev->online = 1; /* New devices are online by default. */ - list_add_tail(&zdev->list, &zcrypt_device_list); - __zcrypt_increase_preference(zdev); - zcrypt_device_count++; - spin_unlock_bh(&zcrypt_device_lock); -out: - return rc; -} -EXPORT_SYMBOL(zcrypt_device_register); - -/** - * Unregister a crypto device. - */ -void zcrypt_device_unregister(struct zcrypt_device *zdev) -{ - spin_lock_bh(&zcrypt_device_lock); - zcrypt_device_count--; - list_del_init(&zdev->list); - spin_unlock_bh(&zcrypt_device_lock); - sysfs_remove_group(&zdev->ap_dev->device.kobj, - &zcrypt_device_attr_group); - put_device(&zdev->ap_dev->device); - zcrypt_device_put(zdev); -} -EXPORT_SYMBOL(zcrypt_device_unregister); - -/** - * zcrypt_read is not be supported beyond zcrypt 1.3.1 - */ -static ssize_t zcrypt_read(struct file *filp, char __user *buf, - size_t count, loff_t *f_pos) -{ - return -EPERM; -} - -/** - * Write is is not allowed - */ -static ssize_t zcrypt_write(struct file *filp, const char __user *buf, - size_t count, loff_t *f_pos) -{ - return -EPERM; -} - -/** - * Device open/close functions to count number of users. - */ -static int zcrypt_open(struct inode *inode, struct file *filp) -{ - atomic_inc(&zcrypt_open_count); - return 0; -} - -static int zcrypt_release(struct inode *inode, struct file *filp) -{ - atomic_dec(&zcrypt_open_count); - return 0; -} - -/** - * zcrypt ioctls. - */ -static long zcrypt_rsa_modexpo(struct ica_rsa_modexpo *mex) -{ - struct zcrypt_device *zdev; - int rc; - - if (mex->outputdatalength < mex->inputdatalength) - return -EINVAL; - /** - * As long as outputdatalength is big enough, we can set the - * outputdatalength equal to the inputdatalength, since that is the - * number of bytes we will copy in any case - */ - mex->outputdatalength = mex->inputdatalength; - - spin_lock_bh(&zcrypt_device_lock); - list_for_each_entry(zdev, &zcrypt_device_list, list) { - if (!zdev->online || - !zdev->ops->rsa_modexpo || - zdev->min_mod_size > mex->inputdatalength || - zdev->max_mod_size < mex->inputdatalength) - continue; - zcrypt_device_get(zdev); - get_device(&zdev->ap_dev->device); - zdev->request_count++; - __zcrypt_decrease_preference(zdev); - spin_unlock_bh(&zcrypt_device_lock); - if (try_module_get(zdev->ap_dev->drv->driver.owner)) { - rc = zdev->ops->rsa_modexpo(zdev, mex); - module_put(zdev->ap_dev->drv->driver.owner); - } - else - rc = -EAGAIN; - spin_lock_bh(&zcrypt_device_lock); - zdev->request_count--; - __zcrypt_increase_preference(zdev); - put_device(&zdev->ap_dev->device); - zcrypt_device_put(zdev); - spin_unlock_bh(&zcrypt_device_lock); - return rc; - } - spin_unlock_bh(&zcrypt_device_lock); - return -ENODEV; -} - -static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt) -{ - struct zcrypt_device *zdev; - unsigned long long z1, z2, z3; - int rc, copied; - - if (crt->outputdatalength < crt->inputdatalength || - (crt->inputdatalength & 1)) - return -EINVAL; - /** - * As long as outputdatalength is big enough, we can set the - * outputdatalength equal to the inputdatalength, since that is the - * number of bytes we will copy in any case - */ - crt->outputdatalength = crt->inputdatalength; - - copied = 0; - restart: - spin_lock_bh(&zcrypt_device_lock); - list_for_each_entry(zdev, &zcrypt_device_list, list) { - if (!zdev->online || - !zdev->ops->rsa_modexpo_crt || - zdev->min_mod_size > crt->inputdatalength || - zdev->max_mod_size < crt->inputdatalength) - continue; - if (zdev->short_crt && crt->inputdatalength > 240) { - /** - * Check inputdata for leading zeros for cards - * that can't handle np_prime, bp_key, or - * u_mult_inv > 128 bytes. - */ - if (copied == 0) { - int len; - spin_unlock_bh(&zcrypt_device_lock); - /* len is max 256 / 2 - 120 = 8 */ - len = crt->inputdatalength / 2 - 120; - z1 = z2 = z3 = 0; - if (copy_from_user(&z1, crt->np_prime, len) || - copy_from_user(&z2, crt->bp_key, len) || - copy_from_user(&z3, crt->u_mult_inv, len)) - return -EFAULT; - copied = 1; - /** - * We have to restart device lookup - - * the device list may have changed by now. - */ - goto restart; - } - if (z1 != 0ULL || z2 != 0ULL || z3 != 0ULL) - /* The device can't handle this request. */ - continue; - } - zcrypt_device_get(zdev); - get_device(&zdev->ap_dev->device); - zdev->request_count++; - __zcrypt_decrease_preference(zdev); - spin_unlock_bh(&zcrypt_device_lock); - if (try_module_get(zdev->ap_dev->drv->driver.owner)) { - rc = zdev->ops->rsa_modexpo_crt(zdev, crt); - module_put(zdev->ap_dev->drv->driver.owner); - } - else - rc = -EAGAIN; - spin_lock_bh(&zcrypt_device_lock); - zdev->request_count--; - __zcrypt_increase_preference(zdev); - put_device(&zdev->ap_dev->device); - zcrypt_device_put(zdev); - spin_unlock_bh(&zcrypt_device_lock); - return rc; - } - spin_unlock_bh(&zcrypt_device_lock); - return -ENODEV; -} - -static long zcrypt_send_cprb(struct ica_xcRB *xcRB) -{ - struct zcrypt_device *zdev; - int rc; - - spin_lock_bh(&zcrypt_device_lock); - list_for_each_entry(zdev, &zcrypt_device_list, list) { - if (!zdev->online || !zdev->ops->send_cprb || - (xcRB->user_defined != AUTOSELECT && - AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined) - ) - continue; - zcrypt_device_get(zdev); - get_device(&zdev->ap_dev->device); - zdev->request_count++; - __zcrypt_decrease_preference(zdev); - spin_unlock_bh(&zcrypt_device_lock); - if (try_module_get(zdev->ap_dev->drv->driver.owner)) { - rc = zdev->ops->send_cprb(zdev, xcRB); - module_put(zdev->ap_dev->drv->driver.owner); - } - else - rc = -EAGAIN; - spin_lock_bh(&zcrypt_device_lock); - zdev->request_count--; - __zcrypt_increase_preference(zdev); - put_device(&zdev->ap_dev->device); - zcrypt_device_put(zdev); - spin_unlock_bh(&zcrypt_device_lock); - return rc; - } - spin_unlock_bh(&zcrypt_device_lock); - return -ENODEV; -} - -static void zcrypt_status_mask(char status[AP_DEVICES]) -{ - struct zcrypt_device *zdev; - - memset(status, 0, sizeof(char) * AP_DEVICES); - spin_lock_bh(&zcrypt_device_lock); - list_for_each_entry(zdev, &zcrypt_device_list, list) - status[AP_QID_DEVICE(zdev->ap_dev->qid)] = - zdev->online ? zdev->user_space_type : 0x0d; - spin_unlock_bh(&zcrypt_device_lock); -} - -static void zcrypt_qdepth_mask(char qdepth[AP_DEVICES]) -{ - struct zcrypt_device *zdev; - - memset(qdepth, 0, sizeof(char) * AP_DEVICES); - spin_lock_bh(&zcrypt_device_lock); - list_for_each_entry(zdev, &zcrypt_device_list, list) { - spin_lock(&zdev->ap_dev->lock); - qdepth[AP_QID_DEVICE(zdev->ap_dev->qid)] = - zdev->ap_dev->pendingq_count + - zdev->ap_dev->requestq_count; - spin_unlock(&zdev->ap_dev->lock); - } - spin_unlock_bh(&zcrypt_device_lock); -} - -static void zcrypt_perdev_reqcnt(int reqcnt[AP_DEVICES]) -{ - struct zcrypt_device *zdev; - - memset(reqcnt, 0, sizeof(int) * AP_DEVICES); - spin_lock_bh(&zcrypt_device_lock); - list_for_each_entry(zdev, &zcrypt_device_list, list) { - spin_lock(&zdev->ap_dev->lock); - reqcnt[AP_QID_DEVICE(zdev->ap_dev->qid)] = - zdev->ap_dev->total_request_count; - spin_unlock(&zdev->ap_dev->lock); - } - spin_unlock_bh(&zcrypt_device_lock); -} - -static int zcrypt_pendingq_count(void) -{ - struct zcrypt_device *zdev; - int pendingq_count = 0; - - spin_lock_bh(&zcrypt_device_lock); - list_for_each_entry(zdev, &zcrypt_device_list, list) { - spin_lock(&zdev->ap_dev->lock); - pendingq_count += zdev->ap_dev->pendingq_count; - spin_unlock(&zdev->ap_dev->lock); - } - spin_unlock_bh(&zcrypt_device_lock); - return pendingq_count; -} - -static int zcrypt_requestq_count(void) -{ - struct zcrypt_device *zdev; - int requestq_count = 0; - - spin_lock_bh(&zcrypt_device_lock); - list_for_each_entry(zdev, &zcrypt_device_list, list) { - spin_lock(&zdev->ap_dev->lock); - requestq_count += zdev->ap_dev->requestq_count; - spin_unlock(&zdev->ap_dev->lock); - } - spin_unlock_bh(&zcrypt_device_lock); - return requestq_count; -} - -static int zcrypt_count_type(int type) -{ - struct zcrypt_device *zdev; - int device_count = 0; - - spin_lock_bh(&zcrypt_device_lock); - list_for_each_entry(zdev, &zcrypt_device_list, list) - if (zdev->user_space_type == type) - device_count++; - spin_unlock_bh(&zcrypt_device_lock); - return device_count; -} - -/** - * Old, deprecated combi status call. - */ -static long zcrypt_ica_status(struct file *filp, unsigned long arg) -{ - struct ica_z90_status *pstat; - int ret; - - pstat = kzalloc(sizeof(*pstat), GFP_KERNEL); - if (!pstat) - return -ENOMEM; - pstat->totalcount = zcrypt_device_count; - pstat->leedslitecount = zcrypt_count_type(ZCRYPT_PCICA); - pstat->leeds2count = zcrypt_count_type(ZCRYPT_PCICC); - pstat->requestqWaitCount = zcrypt_requestq_count(); - pstat->pendingqWaitCount = zcrypt_pendingq_count(); - pstat->totalOpenCount = atomic_read(&zcrypt_open_count); - pstat->cryptoDomain = ap_domain_index; - zcrypt_status_mask(pstat->status); - zcrypt_qdepth_mask(pstat->qdepth); - ret = 0; - if (copy_to_user((void __user *) arg, pstat, sizeof(*pstat))) - ret = -EFAULT; - kfree(pstat); - return ret; -} - -static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - int rc; - - switch (cmd) { - case ICARSAMODEXPO: { - struct ica_rsa_modexpo __user *umex = (void __user *) arg; - struct ica_rsa_modexpo mex; - if (copy_from_user(&mex, umex, sizeof(mex))) - return -EFAULT; - do { - rc = zcrypt_rsa_modexpo(&mex); - } while (rc == -EAGAIN); - if (rc) - return rc; - return put_user(mex.outputdatalength, &umex->outputdatalength); - } - case ICARSACRT: { - struct ica_rsa_modexpo_crt __user *ucrt = (void __user *) arg; - struct ica_rsa_modexpo_crt crt; - if (copy_from_user(&crt, ucrt, sizeof(crt))) - return -EFAULT; - do { - rc = zcrypt_rsa_crt(&crt); - } while (rc == -EAGAIN); - if (rc) - return rc; - return put_user(crt.outputdatalength, &ucrt->outputdatalength); - } - case ZSECSENDCPRB: { - struct ica_xcRB __user *uxcRB = (void __user *) arg; - struct ica_xcRB xcRB; - if (copy_from_user(&xcRB, uxcRB, sizeof(xcRB))) - return -EFAULT; - do { - rc = zcrypt_send_cprb(&xcRB); - } while (rc == -EAGAIN); - if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB))) - return -EFAULT; - return rc; - } - case Z90STAT_STATUS_MASK: { - char status[AP_DEVICES]; - zcrypt_status_mask(status); - if (copy_to_user((char __user *) arg, status, - sizeof(char) * AP_DEVICES)) - return -EFAULT; - return 0; - } - case Z90STAT_QDEPTH_MASK: { - char qdepth[AP_DEVICES]; - zcrypt_qdepth_mask(qdepth); - if (copy_to_user((char __user *) arg, qdepth, - sizeof(char) * AP_DEVICES)) - return -EFAULT; - return 0; - } - case Z90STAT_PERDEV_REQCNT: { - int reqcnt[AP_DEVICES]; - zcrypt_perdev_reqcnt(reqcnt); - if (copy_to_user((int __user *) arg, reqcnt, - sizeof(int) * AP_DEVICES)) - return -EFAULT; - return 0; - } - case Z90STAT_REQUESTQ_COUNT: - return put_user(zcrypt_requestq_count(), (int __user *) arg); - case Z90STAT_PENDINGQ_COUNT: - return put_user(zcrypt_pendingq_count(), (int __user *) arg); - case Z90STAT_TOTALOPEN_COUNT: - return put_user(atomic_read(&zcrypt_open_count), - (int __user *) arg); - case Z90STAT_DOMAIN_INDEX: - return put_user(ap_domain_index, (int __user *) arg); - /** - * Deprecated ioctls. Don't add another device count ioctl, - * you can count them yourself in the user space with the - * output of the Z90STAT_STATUS_MASK ioctl. - */ - case ICAZ90STATUS: - return zcrypt_ica_status(filp, arg); - case Z90STAT_TOTALCOUNT: - return put_user(zcrypt_device_count, (int __user *) arg); - case Z90STAT_PCICACOUNT: - return put_user(zcrypt_count_type(ZCRYPT_PCICA), - (int __user *) arg); - case Z90STAT_PCICCCOUNT: - return put_user(zcrypt_count_type(ZCRYPT_PCICC), - (int __user *) arg); - case Z90STAT_PCIXCCMCL2COUNT: - return put_user(zcrypt_count_type(ZCRYPT_PCIXCC_MCL2), - (int __user *) arg); - case Z90STAT_PCIXCCMCL3COUNT: - return put_user(zcrypt_count_type(ZCRYPT_PCIXCC_MCL3), - (int __user *) arg); - case Z90STAT_PCIXCCCOUNT: - return put_user(zcrypt_count_type(ZCRYPT_PCIXCC_MCL2) + - zcrypt_count_type(ZCRYPT_PCIXCC_MCL3), - (int __user *) arg); - case Z90STAT_CEX2CCOUNT: - return put_user(zcrypt_count_type(ZCRYPT_CEX2C), - (int __user *) arg); - case Z90STAT_CEX2ACOUNT: - return put_user(zcrypt_count_type(ZCRYPT_CEX2A), - (int __user *) arg); - default: - /* unknown ioctl number */ - return -ENOIOCTLCMD; - } -} - -#ifdef CONFIG_COMPAT -/** - * ioctl32 conversion routines - */ -struct compat_ica_rsa_modexpo { - compat_uptr_t inputdata; - unsigned int inputdatalength; - compat_uptr_t outputdata; - unsigned int outputdatalength; - compat_uptr_t b_key; - compat_uptr_t n_modulus; -}; - -static long trans_modexpo32(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct compat_ica_rsa_modexpo __user *umex32 = compat_ptr(arg); - struct compat_ica_rsa_modexpo mex32; - struct ica_rsa_modexpo mex64; - long rc; - - if (copy_from_user(&mex32, umex32, sizeof(mex32))) - return -EFAULT; - mex64.inputdata = compat_ptr(mex32.inputdata); - mex64.inputdatalength = mex32.inputdatalength; - mex64.outputdata = compat_ptr(mex32.outputdata); - mex64.outputdatalength = mex32.outputdatalength; - mex64.b_key = compat_ptr(mex32.b_key); - mex64.n_modulus = compat_ptr(mex32.n_modulus); - do { - rc = zcrypt_rsa_modexpo(&mex64); - } while (rc == -EAGAIN); - if (!rc) - rc = put_user(mex64.outputdatalength, - &umex32->outputdatalength); - return rc; -} - -struct compat_ica_rsa_modexpo_crt { - compat_uptr_t inputdata; - unsigned int inputdatalength; - compat_uptr_t outputdata; - unsigned int outputdatalength; - compat_uptr_t bp_key; - compat_uptr_t bq_key; - compat_uptr_t np_prime; - compat_uptr_t nq_prime; - compat_uptr_t u_mult_inv; -}; - -static long trans_modexpo_crt32(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct compat_ica_rsa_modexpo_crt __user *ucrt32 = compat_ptr(arg); - struct compat_ica_rsa_modexpo_crt crt32; - struct ica_rsa_modexpo_crt crt64; - long rc; - - if (copy_from_user(&crt32, ucrt32, sizeof(crt32))) - return -EFAULT; - crt64.inputdata = compat_ptr(crt32.inputdata); - crt64.inputdatalength = crt32.inputdatalength; - crt64.outputdata= compat_ptr(crt32.outputdata); - crt64.outputdatalength = crt32.outputdatalength; - crt64.bp_key = compat_ptr(crt32.bp_key); - crt64.bq_key = compat_ptr(crt32.bq_key); - crt64.np_prime = compat_ptr(crt32.np_prime); - crt64.nq_prime = compat_ptr(crt32.nq_prime); - crt64.u_mult_inv = compat_ptr(crt32.u_mult_inv); - do { - rc = zcrypt_rsa_crt(&crt64); - } while (rc == -EAGAIN); - if (!rc) - rc = put_user(crt64.outputdatalength, - &ucrt32->outputdatalength); - return rc; -} - -struct compat_ica_xcRB { - unsigned short agent_ID; - unsigned int user_defined; - unsigned short request_ID; - unsigned int request_control_blk_length; - unsigned char padding1[16 - sizeof (compat_uptr_t)]; - compat_uptr_t request_control_blk_addr; - unsigned int request_data_length; - char padding2[16 - sizeof (compat_uptr_t)]; - compat_uptr_t request_data_address; - unsigned int reply_control_blk_length; - char padding3[16 - sizeof (compat_uptr_t)]; - compat_uptr_t reply_control_blk_addr; - unsigned int reply_data_length; - char padding4[16 - sizeof (compat_uptr_t)]; - compat_uptr_t reply_data_addr; - unsigned short priority_window; - unsigned int status; -} __attribute__((packed)); - -static long trans_xcRB32(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct compat_ica_xcRB __user *uxcRB32 = compat_ptr(arg); - struct compat_ica_xcRB xcRB32; - struct ica_xcRB xcRB64; - long rc; - - if (copy_from_user(&xcRB32, uxcRB32, sizeof(xcRB32))) - return -EFAULT; - xcRB64.agent_ID = xcRB32.agent_ID; - xcRB64.user_defined = xcRB32.user_defined; - xcRB64.request_ID = xcRB32.request_ID; - xcRB64.request_control_blk_length = - xcRB32.request_control_blk_length; - xcRB64.request_control_blk_addr = - compat_ptr(xcRB32.request_control_blk_addr); - xcRB64.request_data_length = - xcRB32.request_data_length; - xcRB64.request_data_address = - compat_ptr(xcRB32.request_data_address); - xcRB64.reply_control_blk_length = - xcRB32.reply_control_blk_length; - xcRB64.reply_control_blk_addr = - compat_ptr(xcRB32.reply_control_blk_addr); - xcRB64.reply_data_length = xcRB32.reply_data_length; - xcRB64.reply_data_addr = - compat_ptr(xcRB32.reply_data_addr); - xcRB64.priority_window = xcRB32.priority_window; - xcRB64.status = xcRB32.status; - do { - rc = zcrypt_send_cprb(&xcRB64); - } while (rc == -EAGAIN); - xcRB32.reply_control_blk_length = xcRB64.reply_control_blk_length; - xcRB32.reply_data_length = xcRB64.reply_data_length; - xcRB32.status = xcRB64.status; - if (copy_to_user(uxcRB32, &xcRB32, sizeof(xcRB32))) - return -EFAULT; - return rc; -} - -long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - if (cmd == ICARSAMODEXPO) - return trans_modexpo32(filp, cmd, arg); - if (cmd == ICARSACRT) - return trans_modexpo_crt32(filp, cmd, arg); - if (cmd == ZSECSENDCPRB) - return trans_xcRB32(filp, cmd, arg); - return zcrypt_unlocked_ioctl(filp, cmd, arg); -} -#endif - -/** - * Misc device file operations. - */ -static struct file_operations zcrypt_fops = { - .owner = THIS_MODULE, - .read = zcrypt_read, - .write = zcrypt_write, - .unlocked_ioctl = zcrypt_unlocked_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = zcrypt_compat_ioctl, -#endif - .open = zcrypt_open, - .release = zcrypt_release -}; - -/** - * Misc device. - */ -static struct miscdevice zcrypt_misc_device = { - .minor = MISC_DYNAMIC_MINOR, - .name = "z90crypt", - .fops = &zcrypt_fops, -}; - -/** - * Deprecated /proc entry support. - */ -static struct proc_dir_entry *zcrypt_entry; - -static inline int sprintcl(unsigned char *outaddr, unsigned char *addr, - unsigned int len) -{ - int hl, i; - - hl = 0; - for (i = 0; i < len; i++) - hl += sprintf(outaddr+hl, "%01x", (unsigned int) addr[i]); - hl += sprintf(outaddr+hl, " "); - return hl; -} - -static inline int sprintrw(unsigned char *outaddr, unsigned char *addr, - unsigned int len) -{ - int hl, inl, c, cx; - - hl = sprintf(outaddr, " "); - inl = 0; - for (c = 0; c < (len / 16); c++) { - hl += sprintcl(outaddr+hl, addr+inl, 16); - inl += 16; - } - cx = len%16; - if (cx) { - hl += sprintcl(outaddr+hl, addr+inl, cx); - inl += cx; - } - hl += sprintf(outaddr+hl, "\n"); - return hl; -} - -static inline int sprinthx(unsigned char *title, unsigned char *outaddr, - unsigned char *addr, unsigned int len) -{ - int hl, inl, r, rx; - - hl = sprintf(outaddr, "\n%s\n", title); - inl = 0; - for (r = 0; r < (len / 64); r++) { - hl += sprintrw(outaddr+hl, addr+inl, 64); - inl += 64; - } - rx = len % 64; - if (rx) { - hl += sprintrw(outaddr+hl, addr+inl, rx); - inl += rx; - } - hl += sprintf(outaddr+hl, "\n"); - return hl; -} - -static inline int sprinthx4(unsigned char *title, unsigned char *outaddr, - unsigned int *array, unsigned int len) -{ - int hl, r; - - hl = sprintf(outaddr, "\n%s\n", title); - for (r = 0; r < len; r++) { - if ((r % 8) == 0) - hl += sprintf(outaddr+hl, " "); - hl += sprintf(outaddr+hl, "%08X ", array[r]); - if ((r % 8) == 7) - hl += sprintf(outaddr+hl, "\n"); - } - hl += sprintf(outaddr+hl, "\n"); - return hl; -} - -static int zcrypt_status_read(char *resp_buff, char **start, off_t offset, - int count, int *eof, void *data) -{ - unsigned char *workarea; - int len; - - len = 0; - - /* resp_buff is a page. Use the right half for a work area */ - workarea = resp_buff + 2000; - len += sprintf(resp_buff + len, "\nzcrypt version: %d.%d.%d\n", - ZCRYPT_VERSION, ZCRYPT_RELEASE, ZCRYPT_VARIANT); - len += sprintf(resp_buff + len, "Cryptographic domain: %d\n", - ap_domain_index); - len += sprintf(resp_buff + len, "Total device count: %d\n", - zcrypt_device_count); - len += sprintf(resp_buff + len, "PCICA count: %d\n", - zcrypt_count_type(ZCRYPT_PCICA)); - len += sprintf(resp_buff + len, "PCICC count: %d\n", - zcrypt_count_type(ZCRYPT_PCICC)); - len += sprintf(resp_buff + len, "PCIXCC MCL2 count: %d\n", - zcrypt_count_type(ZCRYPT_PCIXCC_MCL2)); - len += sprintf(resp_buff + len, "PCIXCC MCL3 count: %d\n", - zcrypt_count_type(ZCRYPT_PCIXCC_MCL3)); - len += sprintf(resp_buff + len, "CEX2C count: %d\n", - zcrypt_count_type(ZCRYPT_CEX2C)); - len += sprintf(resp_buff + len, "CEX2A count: %d\n", - zcrypt_count_type(ZCRYPT_CEX2A)); - len += sprintf(resp_buff + len, "requestq count: %d\n", - zcrypt_requestq_count()); - len += sprintf(resp_buff + len, "pendingq count: %d\n", - zcrypt_pendingq_count()); - len += sprintf(resp_buff + len, "Total open handles: %d\n\n", - atomic_read(&zcrypt_open_count)); - zcrypt_status_mask(workarea); - len += sprinthx("Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) " - "4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A", - resp_buff+len, workarea, AP_DEVICES); - zcrypt_qdepth_mask(workarea); - len += sprinthx("Waiting work element counts", - resp_buff+len, workarea, AP_DEVICES); - zcrypt_perdev_reqcnt((unsigned int *) workarea); - len += sprinthx4("Per-device successfully completed request counts", - resp_buff+len,(unsigned int *) workarea, AP_DEVICES); - *eof = 1; - memset((void *) workarea, 0x00, AP_DEVICES * sizeof(unsigned int)); - return len; -} - -static void zcrypt_disable_card(int index) -{ - struct zcrypt_device *zdev; - - spin_lock_bh(&zcrypt_device_lock); - list_for_each_entry(zdev, &zcrypt_device_list, list) - if (AP_QID_DEVICE(zdev->ap_dev->qid) == index) { - zdev->online = 0; - ap_flush_queue(zdev->ap_dev); - break; - } - spin_unlock_bh(&zcrypt_device_lock); -} - -static void zcrypt_enable_card(int index) -{ - struct zcrypt_device *zdev; - - spin_lock_bh(&zcrypt_device_lock); - list_for_each_entry(zdev, &zcrypt_device_list, list) - if (AP_QID_DEVICE(zdev->ap_dev->qid) == index) { - zdev->online = 1; - break; - } - spin_unlock_bh(&zcrypt_device_lock); -} - -static int zcrypt_status_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - unsigned char *lbuf, *ptr; - unsigned long local_count; - int j; - - if (count <= 0) - return 0; - -#define LBUFSIZE 1200UL - lbuf = kmalloc(LBUFSIZE, GFP_KERNEL); - if (!lbuf) { - PRINTK("kmalloc failed!\n"); - return 0; - } - - local_count = min(LBUFSIZE - 1, count); - if (copy_from_user(lbuf, buffer, local_count) != 0) { - kfree(lbuf); - return -EFAULT; - } - lbuf[local_count] = '\0'; - - ptr = strstr(lbuf, "Online devices"); - if (!ptr) { - PRINTK("Unable to parse data (missing \"Online devices\")\n"); - goto out; - } - ptr = strstr(ptr, "\n"); - if (!ptr) { - PRINTK("Unable to parse data (missing newline " - "after \"Online devices\")\n"); - goto out; - } - ptr++; - - if (strstr(ptr, "Waiting work element counts") == NULL) { - PRINTK("Unable to parse data (missing " - "\"Waiting work element counts\")\n"); - goto out; - } - - for (j = 0; j < 64 && *ptr; ptr++) { - /** - * '0' for no device, '1' for PCICA, '2' for PCICC, - * '3' for PCIXCC_MCL2, '4' for PCIXCC_MCL3, - * '5' for CEX2C and '6' for CEX2A' - */ - if (*ptr >= '0' && *ptr <= '6') - j++; - else if (*ptr == 'd' || *ptr == 'D') - zcrypt_disable_card(j++); - else if (*ptr == 'e' || *ptr == 'E') - zcrypt_enable_card(j++); - else if (*ptr != ' ' && *ptr != '\t') - break; - } -out: - kfree(lbuf); - return count; -} - -/** - * The module initialization code. - */ -int __init zcrypt_api_init(void) -{ - int rc; - - /* Register the request sprayer. */ - rc = misc_register(&zcrypt_misc_device); - if (rc < 0) { - PRINTKW(KERN_ERR "misc_register (minor %d) failed with %d\n", - zcrypt_misc_device.minor, rc); - goto out; - } - - /* Set up the proc file system */ - zcrypt_entry = create_proc_entry("driver/z90crypt", 0644, NULL); - if (!zcrypt_entry) { - PRINTK("Couldn't create z90crypt proc entry\n"); - rc = -ENOMEM; - goto out_misc; - } - zcrypt_entry->nlink = 1; - zcrypt_entry->data = NULL; - zcrypt_entry->read_proc = zcrypt_status_read; - zcrypt_entry->write_proc = zcrypt_status_write; - - return 0; - -out_misc: - misc_deregister(&zcrypt_misc_device); -out: - return rc; -} - -/** - * The module termination code. - */ -void zcrypt_api_exit(void) -{ - remove_proc_entry("driver/z90crypt", NULL); - misc_deregister(&zcrypt_misc_device); -} - -#ifndef CONFIG_ZCRYPT_MONOLITHIC -module_init(zcrypt_api_init); -module_exit(zcrypt_api_exit); -#endif diff --git a/trunk/drivers/s390/crypto/zcrypt_api.h b/trunk/drivers/s390/crypto/zcrypt_api.h deleted file mode 100644 index de4877ee618f..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_api.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * linux/drivers/s390/crypto/zcrypt_api.h - * - * zcrypt 2.1.0 - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * Cornelia Huck - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * Ralph Wuerthner - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _ZCRYPT_API_H_ -#define _ZCRYPT_API_H_ - -/** - * Macro definitions - * - * PDEBUG debugs in the form "zcrypt: function_name -> message" - * - * PRINTK is like PDEBUG, except that it is always enabled - * PRINTKN is like PRINTK, except that it does not include the function name - * PRINTKW is like PRINTK, except that it uses KERN_WARNING - * PRINTKC is like PRINTK, except that it uses KERN_CRIT - */ -#define DEV_NAME "zcrypt" - -#define PRINTK(fmt, args...) \ - printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args) -#define PRINTKN(fmt, args...) \ - printk(KERN_DEBUG DEV_NAME ": " fmt, ## args) -#define PRINTKW(fmt, args...) \ - printk(KERN_WARNING DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args) -#define PRINTKC(fmt, args...) \ - printk(KERN_CRIT DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args) - -#ifdef ZCRYPT_DEBUG -#define PDEBUG(fmt, args...) \ - printk(KERN_DEBUG DEV_NAME ": %s -> " fmt, __FUNCTION__ , ## args) -#else -#define PDEBUG(fmt, args...) do {} while (0) -#endif - -#include "ap_bus.h" -#include - -/* deprecated status calls */ -#define ICAZ90STATUS _IOR(ZCRYPT_IOCTL_MAGIC, 0x10, struct ica_z90_status) -#define Z90STAT_PCIXCCCOUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x43, int) - -/** - * This structure is deprecated and the corresponding ioctl() has been - * replaced with individual ioctl()s for each piece of data! - */ -struct ica_z90_status { - int totalcount; - int leedslitecount; // PCICA - int leeds2count; // PCICC - // int PCIXCCCount; is not in struct for backward compatibility - int requestqWaitCount; - int pendingqWaitCount; - int totalOpenCount; - int cryptoDomain; - // status: 0=not there, 1=PCICA, 2=PCICC, 3=PCIXCC_MCL2, 4=PCIXCC_MCL3, - // 5=CEX2C - unsigned char status[64]; - // qdepth: # work elements waiting for each device - unsigned char qdepth[64]; -}; - -/** - * device type for an actual device is either PCICA, PCICC, PCIXCC_MCL2, - * PCIXCC_MCL3, CEX2C, or CEX2A - * - * NOTE: PCIXCC_MCL3 refers to a PCIXCC with May 2004 version of Licensed - * Internal Code (LIC) (EC J12220 level 29). - * PCIXCC_MCL2 refers to any LIC before this level. - */ -#define ZCRYPT_PCICA 1 -#define ZCRYPT_PCICC 2 -#define ZCRYPT_PCIXCC_MCL2 3 -#define ZCRYPT_PCIXCC_MCL3 4 -#define ZCRYPT_CEX2C 5 -#define ZCRYPT_CEX2A 6 - -struct zcrypt_device; - -struct zcrypt_ops { - long (*rsa_modexpo)(struct zcrypt_device *, struct ica_rsa_modexpo *); - long (*rsa_modexpo_crt)(struct zcrypt_device *, - struct ica_rsa_modexpo_crt *); - long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *); -}; - -struct zcrypt_device { - struct list_head list; /* Device list. */ - spinlock_t lock; /* Per device lock. */ - struct kref refcount; /* device refcounting */ - struct ap_device *ap_dev; /* The "real" ap device. */ - struct zcrypt_ops *ops; /* Crypto operations. */ - int online; /* User online/offline */ - - int user_space_type; /* User space device id. */ - char *type_string; /* User space device name. */ - int min_mod_size; /* Min number of bits. */ - int max_mod_size; /* Max number of bits. */ - int short_crt; /* Card has crt length restriction. */ - int speed_rating; /* Speed of the crypto device. */ - - int request_count; /* # current requests. */ - - struct ap_message reply; /* Per-device reply structure. */ -}; - -struct zcrypt_device *zcrypt_device_alloc(size_t); -void zcrypt_device_free(struct zcrypt_device *); -void zcrypt_device_get(struct zcrypt_device *); -int zcrypt_device_put(struct zcrypt_device *); -int zcrypt_device_register(struct zcrypt_device *); -void zcrypt_device_unregister(struct zcrypt_device *); -int zcrypt_api_init(void); -void zcrypt_api_exit(void); - -#endif /* _ZCRYPT_API_H_ */ diff --git a/trunk/drivers/s390/crypto/zcrypt_cca_key.h b/trunk/drivers/s390/crypto/zcrypt_cca_key.h deleted file mode 100644 index 8dbcf0eef3e5..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_cca_key.h +++ /dev/null @@ -1,350 +0,0 @@ -/* - * linux/drivers/s390/crypto/zcrypt_cca_key.h - * - * zcrypt 2.1.0 - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _ZCRYPT_CCA_KEY_H_ -#define _ZCRYPT_CCA_KEY_H_ - -struct T6_keyBlock_hdr { - unsigned short blen; - unsigned short ulen; - unsigned short flags; -}; - -/** - * mapping for the cca private ME key token. - * Three parts of interest here: the header, the private section and - * the public section. - * - * mapping for the cca key token header - */ -struct cca_token_hdr { - unsigned char token_identifier; - unsigned char version; - unsigned short token_length; - unsigned char reserved[4]; -} __attribute__((packed)); - -#define CCA_TKN_HDR_ID_EXT 0x1E - -/** - * mapping for the cca private ME section - */ -struct cca_private_ext_ME_sec { - unsigned char section_identifier; - unsigned char version; - unsigned short section_length; - unsigned char private_key_hash[20]; - unsigned char reserved1[4]; - unsigned char key_format; - unsigned char reserved2; - unsigned char key_name_hash[20]; - unsigned char key_use_flags[4]; - unsigned char reserved3[6]; - unsigned char reserved4[24]; - unsigned char confounder[24]; - unsigned char exponent[128]; - unsigned char modulus[128]; -} __attribute__((packed)); - -#define CCA_PVT_USAGE_ALL 0x80 - -/** - * mapping for the cca public section - * In a private key, the modulus doesn't appear in the public - * section. So, an arbitrary public exponent of 0x010001 will be - * used, for a section length of 0x0F always. - */ -struct cca_public_sec { - unsigned char section_identifier; - unsigned char version; - unsigned short section_length; - unsigned char reserved[2]; - unsigned short exponent_len; - unsigned short modulus_bit_len; - unsigned short modulus_byte_len; /* In a private key, this is 0 */ -} __attribute__((packed)); - -/** - * mapping for the cca private CRT key 'token' - * The first three parts (the only parts considered in this release) - * are: the header, the private section and the public section. - * The header and public section are the same as for the - * struct cca_private_ext_ME - * - * Following the structure are the quantities p, q, dp, dq, u, pad, - * and modulus, in that order, where pad_len is the modulo 8 - * complement of the residue modulo 8 of the sum of - * (p_len + q_len + dp_len + dq_len + u_len). - */ -struct cca_pvt_ext_CRT_sec { - unsigned char section_identifier; - unsigned char version; - unsigned short section_length; - unsigned char private_key_hash[20]; - unsigned char reserved1[4]; - unsigned char key_format; - unsigned char reserved2; - unsigned char key_name_hash[20]; - unsigned char key_use_flags[4]; - unsigned short p_len; - unsigned short q_len; - unsigned short dp_len; - unsigned short dq_len; - unsigned short u_len; - unsigned short mod_len; - unsigned char reserved3[4]; - unsigned short pad_len; - unsigned char reserved4[52]; - unsigned char confounder[8]; -} __attribute__((packed)); - -#define CCA_PVT_EXT_CRT_SEC_ID_PVT 0x08 -#define CCA_PVT_EXT_CRT_SEC_FMT_CL 0x40 - -/** - * Set up private key fields of a type6 MEX message. - * Note that all numerics in the key token are big-endian, - * while the entries in the key block header are little-endian. - * - * @mex: pointer to user input data - * @p: pointer to memory area for the key - * - * Returns the size of the key area or -EFAULT - */ -static inline int zcrypt_type6_mex_key_de(struct ica_rsa_modexpo *mex, - void *p, int big_endian) -{ - static struct cca_token_hdr static_pvt_me_hdr = { - .token_identifier = 0x1E, - .token_length = 0x0183, - }; - static struct cca_private_ext_ME_sec static_pvt_me_sec = { - .section_identifier = 0x02, - .section_length = 0x016C, - .key_use_flags = {0x80,0x00,0x00,0x00}, - }; - static struct cca_public_sec static_pub_me_sec = { - .section_identifier = 0x04, - .section_length = 0x000F, - .exponent_len = 0x0003, - }; - static char pk_exponent[3] = { 0x01, 0x00, 0x01 }; - struct { - struct T6_keyBlock_hdr t6_hdr; - struct cca_token_hdr pvtMeHdr; - struct cca_private_ext_ME_sec pvtMeSec; - struct cca_public_sec pubMeSec; - char exponent[3]; - } __attribute__((packed)) *key = p; - unsigned char *temp; - - memset(key, 0, sizeof(*key)); - - if (big_endian) { - key->t6_hdr.blen = cpu_to_be16(0x189); - key->t6_hdr.ulen = cpu_to_be16(0x189 - 2); - } else { - key->t6_hdr.blen = cpu_to_le16(0x189); - key->t6_hdr.ulen = cpu_to_le16(0x189 - 2); - } - key->pvtMeHdr = static_pvt_me_hdr; - key->pvtMeSec = static_pvt_me_sec; - key->pubMeSec = static_pub_me_sec; - /** - * In a private key, the modulus doesn't appear in the public - * section. So, an arbitrary public exponent of 0x010001 will be - * used. - */ - memcpy(key->exponent, pk_exponent, 3); - - /* key parameter block */ - temp = key->pvtMeSec.exponent + - sizeof(key->pvtMeSec.exponent) - mex->inputdatalength; - if (copy_from_user(temp, mex->b_key, mex->inputdatalength)) - return -EFAULT; - - /* modulus */ - temp = key->pvtMeSec.modulus + - sizeof(key->pvtMeSec.modulus) - mex->inputdatalength; - if (copy_from_user(temp, mex->n_modulus, mex->inputdatalength)) - return -EFAULT; - key->pubMeSec.modulus_bit_len = 8 * mex->inputdatalength; - return sizeof(*key); -} - -/** - * Set up private key fields of a type6 MEX message. The _pad variant - * strips leading zeroes from the b_key. - * Note that all numerics in the key token are big-endian, - * while the entries in the key block header are little-endian. - * - * @mex: pointer to user input data - * @p: pointer to memory area for the key - * - * Returns the size of the key area or -EFAULT - */ -static inline int zcrypt_type6_mex_key_en(struct ica_rsa_modexpo *mex, - void *p, int big_endian) -{ - static struct cca_token_hdr static_pub_hdr = { - .token_identifier = 0x1E, - }; - static struct cca_public_sec static_pub_sec = { - .section_identifier = 0x04, - }; - struct { - struct T6_keyBlock_hdr t6_hdr; - struct cca_token_hdr pubHdr; - struct cca_public_sec pubSec; - char exponent[0]; - } __attribute__((packed)) *key = p; - unsigned char *temp; - int i; - - memset(key, 0, sizeof(*key)); - - key->pubHdr = static_pub_hdr; - key->pubSec = static_pub_sec; - - /* key parameter block */ - temp = key->exponent; - if (copy_from_user(temp, mex->b_key, mex->inputdatalength)) - return -EFAULT; - /* Strip leading zeroes from b_key. */ - for (i = 0; i < mex->inputdatalength; i++) - if (temp[i]) - break; - if (i >= mex->inputdatalength) - return -EINVAL; - memmove(temp, temp + i, mex->inputdatalength - i); - temp += mex->inputdatalength - i; - /* modulus */ - if (copy_from_user(temp, mex->n_modulus, mex->inputdatalength)) - return -EFAULT; - - key->pubSec.modulus_bit_len = 8 * mex->inputdatalength; - key->pubSec.modulus_byte_len = mex->inputdatalength; - key->pubSec.exponent_len = mex->inputdatalength - i; - key->pubSec.section_length = sizeof(key->pubSec) + - 2*mex->inputdatalength - i; - key->pubHdr.token_length = - key->pubSec.section_length + sizeof(key->pubHdr); - if (big_endian) { - key->t6_hdr.ulen = cpu_to_be16(key->pubHdr.token_length + 4); - key->t6_hdr.blen = cpu_to_be16(key->pubHdr.token_length + 6); - } else { - key->t6_hdr.ulen = cpu_to_le16(key->pubHdr.token_length + 4); - key->t6_hdr.blen = cpu_to_le16(key->pubHdr.token_length + 6); - } - return sizeof(*key) + 2*mex->inputdatalength - i; -} - -/** - * Set up private key fields of a type6 CRT message. - * Note that all numerics in the key token are big-endian, - * while the entries in the key block header are little-endian. - * - * @mex: pointer to user input data - * @p: pointer to memory area for the key - * - * Returns the size of the key area or -EFAULT - */ -static inline int zcrypt_type6_crt_key(struct ica_rsa_modexpo_crt *crt, - void *p, int big_endian) -{ - static struct cca_public_sec static_cca_pub_sec = { - .section_identifier = 4, - .section_length = 0x000f, - .exponent_len = 0x0003, - }; - static char pk_exponent[3] = { 0x01, 0x00, 0x01 }; - struct { - struct T6_keyBlock_hdr t6_hdr; - struct cca_token_hdr token; - struct cca_pvt_ext_CRT_sec pvt; - char key_parts[0]; - } __attribute__((packed)) *key = p; - struct cca_public_sec *pub; - int short_len, long_len, pad_len, key_len, size; - - memset(key, 0, sizeof(*key)); - - short_len = crt->inputdatalength / 2; - long_len = short_len + 8; - pad_len = -(3*long_len + 2*short_len) & 7; - key_len = 3*long_len + 2*short_len + pad_len + crt->inputdatalength; - size = sizeof(*key) + key_len + sizeof(*pub) + 3; - - /* parameter block.key block */ - if (big_endian) { - key->t6_hdr.blen = cpu_to_be16(size); - key->t6_hdr.ulen = cpu_to_be16(size - 2); - } else { - key->t6_hdr.blen = cpu_to_le16(size); - key->t6_hdr.ulen = cpu_to_le16(size - 2); - } - - /* key token header */ - key->token.token_identifier = CCA_TKN_HDR_ID_EXT; - key->token.token_length = size - 6; - - /* private section */ - key->pvt.section_identifier = CCA_PVT_EXT_CRT_SEC_ID_PVT; - key->pvt.section_length = sizeof(key->pvt) + key_len; - key->pvt.key_format = CCA_PVT_EXT_CRT_SEC_FMT_CL; - key->pvt.key_use_flags[0] = CCA_PVT_USAGE_ALL; - key->pvt.p_len = key->pvt.dp_len = key->pvt.u_len = long_len; - key->pvt.q_len = key->pvt.dq_len = short_len; - key->pvt.mod_len = crt->inputdatalength; - key->pvt.pad_len = pad_len; - - /* key parts */ - if (copy_from_user(key->key_parts, crt->np_prime, long_len) || - copy_from_user(key->key_parts + long_len, - crt->nq_prime, short_len) || - copy_from_user(key->key_parts + long_len + short_len, - crt->bp_key, long_len) || - copy_from_user(key->key_parts + 2*long_len + short_len, - crt->bq_key, short_len) || - copy_from_user(key->key_parts + 2*long_len + 2*short_len, - crt->u_mult_inv, long_len)) - return -EFAULT; - memset(key->key_parts + 3*long_len + 2*short_len + pad_len, - 0xff, crt->inputdatalength); - pub = (struct cca_public_sec *)(key->key_parts + key_len); - *pub = static_cca_pub_sec; - pub->modulus_bit_len = 8 * crt->inputdatalength; - /** - * In a private key, the modulus doesn't appear in the public - * section. So, an arbitrary public exponent of 0x010001 will be - * used. - */ - memcpy((char *) (pub + 1), pk_exponent, 3); - return size; -} - -#endif /* _ZCRYPT_CCA_KEY_H_ */ diff --git a/trunk/drivers/s390/crypto/zcrypt_cex2a.c b/trunk/drivers/s390/crypto/zcrypt_cex2a.c deleted file mode 100644 index a62b00083d0c..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_cex2a.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * linux/drivers/s390/crypto/zcrypt_cex2a.c - * - * zcrypt 2.1.0 - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * Ralph Wuerthner - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include - -#include "ap_bus.h" -#include "zcrypt_api.h" -#include "zcrypt_error.h" -#include "zcrypt_cex2a.h" - -#define CEX2A_MIN_MOD_SIZE 1 /* 8 bits */ -#define CEX2A_MAX_MOD_SIZE 256 /* 2048 bits */ - -#define CEX2A_SPEED_RATING 970 - -#define CEX2A_MAX_MESSAGE_SIZE 0x390 /* sizeof(struct type50_crb2_msg) */ -#define CEX2A_MAX_RESPONSE_SIZE 0x110 /* max outputdatalength + type80_hdr */ - -#define CEX2A_CLEANUP_TIME (15*HZ) - -static struct ap_device_id zcrypt_cex2a_ids[] = { - { AP_DEVICE(AP_DEVICE_TYPE_CEX2A) }, - { /* end of list */ }, -}; - -#ifndef CONFIG_ZCRYPT_MONOLITHIC -MODULE_DEVICE_TABLE(ap, zcrypt_cex2a_ids); -MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("CEX2A Cryptographic Coprocessor device driver, " - "Copyright 2001, 2006 IBM Corporation"); -MODULE_LICENSE("GPL"); -#endif - -static int zcrypt_cex2a_probe(struct ap_device *ap_dev); -static void zcrypt_cex2a_remove(struct ap_device *ap_dev); -static void zcrypt_cex2a_receive(struct ap_device *, struct ap_message *, - struct ap_message *); - -static struct ap_driver zcrypt_cex2a_driver = { - .probe = zcrypt_cex2a_probe, - .remove = zcrypt_cex2a_remove, - .receive = zcrypt_cex2a_receive, - .ids = zcrypt_cex2a_ids, -}; - -/** - * Convert a ICAMEX message to a type50 MEX message. - * - * @zdev: crypto device pointer - * @zreq: crypto request pointer - * @mex: pointer to user input data - * - * Returns 0 on success or -EFAULT. - */ -static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_rsa_modexpo *mex) -{ - unsigned char *mod, *exp, *inp; - int mod_len; - - mod_len = mex->inputdatalength; - - if (mod_len <= 128) { - struct type50_meb1_msg *meb1 = ap_msg->message; - memset(meb1, 0, sizeof(*meb1)); - ap_msg->length = sizeof(*meb1); - meb1->header.msg_type_code = TYPE50_TYPE_CODE; - meb1->header.msg_len = sizeof(*meb1); - meb1->keyblock_type = TYPE50_MEB1_FMT; - mod = meb1->modulus + sizeof(meb1->modulus) - mod_len; - exp = meb1->exponent + sizeof(meb1->exponent) - mod_len; - inp = meb1->message + sizeof(meb1->message) - mod_len; - } else { - struct type50_meb2_msg *meb2 = ap_msg->message; - memset(meb2, 0, sizeof(*meb2)); - ap_msg->length = sizeof(*meb2); - meb2->header.msg_type_code = TYPE50_TYPE_CODE; - meb2->header.msg_len = sizeof(*meb2); - meb2->keyblock_type = TYPE50_MEB2_FMT; - mod = meb2->modulus + sizeof(meb2->modulus) - mod_len; - exp = meb2->exponent + sizeof(meb2->exponent) - mod_len; - inp = meb2->message + sizeof(meb2->message) - mod_len; - } - - if (copy_from_user(mod, mex->n_modulus, mod_len) || - copy_from_user(exp, mex->b_key, mod_len) || - copy_from_user(inp, mex->inputdata, mod_len)) - return -EFAULT; - return 0; -} - -/** - * Convert a ICACRT message to a type50 CRT message. - * - * @zdev: crypto device pointer - * @zreq: crypto request pointer - * @crt: pointer to user input data - * - * Returns 0 on success or -EFAULT. - */ -static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_rsa_modexpo_crt *crt) -{ - int mod_len, short_len, long_len, long_offset; - unsigned char *p, *q, *dp, *dq, *u, *inp; - - mod_len = crt->inputdatalength; - short_len = mod_len / 2; - long_len = mod_len / 2 + 8; - - /* - * CEX2A cannot handle p, dp, or U > 128 bytes. - * If we have one of these, we need to do extra checking. - */ - if (long_len > 128) { - /* - * zcrypt_rsa_crt already checked for the leading - * zeroes of np_prime, bp_key and u_mult_inc. - */ - long_offset = long_len - 128; - long_len = 128; - } else - long_offset = 0; - - /* - * Instead of doing extra work for p, dp, U > 64 bytes, we'll just use - * the larger message structure. - */ - if (long_len <= 64) { - struct type50_crb1_msg *crb1 = ap_msg->message; - memset(crb1, 0, sizeof(*crb1)); - ap_msg->length = sizeof(*crb1); - crb1->header.msg_type_code = TYPE50_TYPE_CODE; - crb1->header.msg_len = sizeof(*crb1); - crb1->keyblock_type = TYPE50_CRB1_FMT; - p = crb1->p + sizeof(crb1->p) - long_len; - q = crb1->q + sizeof(crb1->q) - short_len; - dp = crb1->dp + sizeof(crb1->dp) - long_len; - dq = crb1->dq + sizeof(crb1->dq) - short_len; - u = crb1->u + sizeof(crb1->u) - long_len; - inp = crb1->message + sizeof(crb1->message) - mod_len; - } else { - struct type50_crb2_msg *crb2 = ap_msg->message; - memset(crb2, 0, sizeof(*crb2)); - ap_msg->length = sizeof(*crb2); - crb2->header.msg_type_code = TYPE50_TYPE_CODE; - crb2->header.msg_len = sizeof(*crb2); - crb2->keyblock_type = TYPE50_CRB2_FMT; - p = crb2->p + sizeof(crb2->p) - long_len; - q = crb2->q + sizeof(crb2->q) - short_len; - dp = crb2->dp + sizeof(crb2->dp) - long_len; - dq = crb2->dq + sizeof(crb2->dq) - short_len; - u = crb2->u + sizeof(crb2->u) - long_len; - inp = crb2->message + sizeof(crb2->message) - mod_len; - } - - if (copy_from_user(p, crt->np_prime + long_offset, long_len) || - copy_from_user(q, crt->nq_prime, short_len) || - copy_from_user(dp, crt->bp_key + long_offset, long_len) || - copy_from_user(dq, crt->bq_key, short_len) || - copy_from_user(u, crt->u_mult_inv + long_offset, long_len) || - copy_from_user(inp, crt->inputdata, mod_len)) - return -EFAULT; - - - return 0; -} - -/** - * Copy results from a type 80 reply message back to user space. - * - * @zdev: crypto device pointer - * @reply: reply AP message. - * @data: pointer to user output data - * @length: size of user output data - * - * Returns 0 on success or -EFAULT. - */ -static int convert_type80(struct zcrypt_device *zdev, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) -{ - struct type80_hdr *t80h = reply->message; - unsigned char *data; - - if (t80h->len < sizeof(*t80h) + outputdatalength) { - /* The result is too short, the CEX2A card may not do that.. */ - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } - BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE); - data = reply->message + t80h->len - outputdatalength; - if (copy_to_user(outputdata, data, outputdatalength)) - return -EFAULT; - return 0; -} - -static int convert_response(struct zcrypt_device *zdev, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) -{ - /* Response type byte is the second byte in the response. */ - switch (((unsigned char *) reply->message)[1]) { - case TYPE82_RSP_CODE: - case TYPE88_RSP_CODE: - return convert_error(zdev, reply); - case TYPE80_RSP_CODE: - return convert_type80(zdev, reply, - outputdata, outputdatalength); - default: /* Unknown response type, this should NEVER EVER happen */ - PRINTK("Unrecognized Message Header: %08x%08x\n", - *(unsigned int *) reply->message, - *(unsigned int *) (reply->message+4)); - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } -} - -/** - * This function is called from the AP bus code after a crypto request - * "msg" has finished with the reply message "reply". - * It is called from tasklet context. - * @ap_dev: pointer to the AP device - * @msg: pointer to the AP message - * @reply: pointer to the AP reply message - */ -static void zcrypt_cex2a_receive(struct ap_device *ap_dev, - struct ap_message *msg, - struct ap_message *reply) -{ - static struct error_hdr error_reply = { - .type = TYPE82_RSP_CODE, - .reply_code = REP82_ERROR_MACHINE_FAILURE, - }; - struct type80_hdr *t80h = reply->message; - int length; - - /* Copy the reply message to the request message buffer. */ - if (IS_ERR(reply)) - memcpy(msg->message, &error_reply, sizeof(error_reply)); - else if (t80h->type == TYPE80_RSP_CODE) { - length = min(CEX2A_MAX_RESPONSE_SIZE, (int) t80h->len); - memcpy(msg->message, reply->message, length); - } else - memcpy(msg->message, reply->message, sizeof error_reply); - complete((struct completion *) msg->private); -} - -static atomic_t zcrypt_step = ATOMIC_INIT(0); - -/** - * The request distributor calls this function if it picked the CEX2A - * device to handle a modexpo request. - * @zdev: pointer to zcrypt_device structure that identifies the - * CEX2A device to the request distributor - * @mex: pointer to the modexpo request buffer - */ -static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev, - struct ica_rsa_modexpo *mex) -{ - struct ap_message ap_msg; - struct completion work; - int rc; - - ap_msg.message = (void *) kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &work; - rc = ICAMEX_msg_to_type50MEX_msg(zdev, &ap_msg, mex); - if (rc) - goto out_free; - init_completion(&work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible_timeout( - &work, CEX2A_CLEANUP_TIME); - if (rc > 0) - rc = convert_response(zdev, &ap_msg, mex->outputdata, - mex->outputdatalength); - else { - /* Signal pending or message timed out. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); - if (rc == 0) - /* Message timed out. */ - rc = -ETIME; - } -out_free: - kfree(ap_msg.message); - return rc; -} - -/** - * The request distributor calls this function if it picked the CEX2A - * device to handle a modexpo_crt request. - * @zdev: pointer to zcrypt_device structure that identifies the - * CEX2A device to the request distributor - * @crt: pointer to the modexpoc_crt request buffer - */ -static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev, - struct ica_rsa_modexpo_crt *crt) -{ - struct ap_message ap_msg; - struct completion work; - int rc; - - ap_msg.message = (void *) kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &work; - rc = ICACRT_msg_to_type50CRT_msg(zdev, &ap_msg, crt); - if (rc) - goto out_free; - init_completion(&work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible_timeout( - &work, CEX2A_CLEANUP_TIME); - if (rc > 0) - rc = convert_response(zdev, &ap_msg, crt->outputdata, - crt->outputdatalength); - else { - /* Signal pending or message timed out. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); - if (rc == 0) - /* Message timed out. */ - rc = -ETIME; - } -out_free: - kfree(ap_msg.message); - return rc; -} - -/** - * The crypto operations for a CEX2A card. - */ -static struct zcrypt_ops zcrypt_cex2a_ops = { - .rsa_modexpo = zcrypt_cex2a_modexpo, - .rsa_modexpo_crt = zcrypt_cex2a_modexpo_crt, -}; - -/** - * Probe function for CEX2A cards. It always accepts the AP device - * since the bus_match already checked the hardware type. - * @ap_dev: pointer to the AP device. - */ -static int zcrypt_cex2a_probe(struct ap_device *ap_dev) -{ - struct zcrypt_device *zdev; - int rc; - - zdev = zcrypt_device_alloc(CEX2A_MAX_RESPONSE_SIZE); - if (!zdev) - return -ENOMEM; - zdev->ap_dev = ap_dev; - zdev->ops = &zcrypt_cex2a_ops; - zdev->online = 1; - zdev->user_space_type = ZCRYPT_CEX2A; - zdev->type_string = "CEX2A"; - zdev->min_mod_size = CEX2A_MIN_MOD_SIZE; - zdev->max_mod_size = CEX2A_MAX_MOD_SIZE; - zdev->short_crt = 1; - zdev->speed_rating = CEX2A_SPEED_RATING; - ap_dev->reply = &zdev->reply; - ap_dev->private = zdev; - rc = zcrypt_device_register(zdev); - if (rc) - goto out_free; - return 0; - -out_free: - ap_dev->private = NULL; - zcrypt_device_free(zdev); - return rc; -} - -/** - * This is called to remove the extended CEX2A driver information - * if an AP device is removed. - */ -static void zcrypt_cex2a_remove(struct ap_device *ap_dev) -{ - struct zcrypt_device *zdev = ap_dev->private; - - zcrypt_device_unregister(zdev); -} - -int __init zcrypt_cex2a_init(void) -{ - return ap_driver_register(&zcrypt_cex2a_driver, THIS_MODULE, "cex2a"); -} - -void __exit zcrypt_cex2a_exit(void) -{ - ap_driver_unregister(&zcrypt_cex2a_driver); -} - -#ifndef CONFIG_ZCRYPT_MONOLITHIC -module_init(zcrypt_cex2a_init); -module_exit(zcrypt_cex2a_exit); -#endif diff --git a/trunk/drivers/s390/crypto/zcrypt_cex2a.h b/trunk/drivers/s390/crypto/zcrypt_cex2a.h deleted file mode 100644 index 8f69d1dacab8..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_cex2a.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * linux/drivers/s390/crypto/zcrypt_cex2a.h - * - * zcrypt 2.1.0 - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _ZCRYPT_CEX2A_H_ -#define _ZCRYPT_CEX2A_H_ - -/** - * The type 50 message family is associated with a CEX2A card. - * - * The four members of the family are described below. - * - * Note that all unsigned char arrays are right-justified and left-padded - * with zeroes. - * - * Note that all reserved fields must be zeroes. - */ -struct type50_hdr { - unsigned char reserved1; - unsigned char msg_type_code; /* 0x50 */ - unsigned short msg_len; - unsigned char reserved2; - unsigned char ignored; - unsigned short reserved3; -} __attribute__((packed)); - -#define TYPE50_TYPE_CODE 0x50 - -#define TYPE50_MEB1_FMT 0x0001 -#define TYPE50_MEB2_FMT 0x0002 -#define TYPE50_CRB1_FMT 0x0011 -#define TYPE50_CRB2_FMT 0x0012 - -/* Mod-Exp, with a small modulus */ -struct type50_meb1_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0001 */ - unsigned char reserved[6]; - unsigned char exponent[128]; - unsigned char modulus[128]; - unsigned char message[128]; -} __attribute__((packed)); - -/* Mod-Exp, with a large modulus */ -struct type50_meb2_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0002 */ - unsigned char reserved[6]; - unsigned char exponent[256]; - unsigned char modulus[256]; - unsigned char message[256]; -} __attribute__((packed)); - -/* CRT, with a small modulus */ -struct type50_crb1_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0011 */ - unsigned char reserved[6]; - unsigned char p[64]; - unsigned char q[64]; - unsigned char dp[64]; - unsigned char dq[64]; - unsigned char u[64]; - unsigned char message[128]; -} __attribute__((packed)); - -/* CRT, with a large modulus */ -struct type50_crb2_msg { - struct type50_hdr header; - unsigned short keyblock_type; /* 0x0012 */ - unsigned char reserved[6]; - unsigned char p[128]; - unsigned char q[128]; - unsigned char dp[128]; - unsigned char dq[128]; - unsigned char u[128]; - unsigned char message[256]; -} __attribute__((packed)); - -/** - * The type 80 response family is associated with a CEX2A card. - * - * Note that all unsigned char arrays are right-justified and left-padded - * with zeroes. - * - * Note that all reserved fields must be zeroes. - */ - -#define TYPE80_RSP_CODE 0x80 - -struct type80_hdr { - unsigned char reserved1; - unsigned char type; /* 0x80 */ - unsigned short len; - unsigned char code; /* 0x00 */ - unsigned char reserved2[3]; - unsigned char reserved3[8]; -} __attribute__((packed)); - -int zcrypt_cex2a_init(void); -void zcrypt_cex2a_exit(void); - -#endif /* _ZCRYPT_CEX2A_H_ */ diff --git a/trunk/drivers/s390/crypto/zcrypt_error.h b/trunk/drivers/s390/crypto/zcrypt_error.h deleted file mode 100644 index 2cb616ba8bec..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_error.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * linux/drivers/s390/crypto/zcrypt_error.h - * - * zcrypt 2.1.0 - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _ZCRYPT_ERROR_H_ -#define _ZCRYPT_ERROR_H_ - -#include "zcrypt_api.h" - -/** - * Reply Messages - * - * Error reply messages are of two types: - * 82: Error (see below) - * 88: Error (see below) - * Both type 82 and type 88 have the same structure in the header. - * - * Request reply messages are of three known types: - * 80: Reply from a Type 50 Request (see CEX2A-RELATED STRUCTS) - * 84: Reply from a Type 4 Request (see PCICA-RELATED STRUCTS) - * 86: Reply from a Type 6 Request (see PCICC/PCIXCC/CEX2C-RELATED STRUCTS) - * - */ -struct error_hdr { - unsigned char reserved1; /* 0x00 */ - unsigned char type; /* 0x82 or 0x88 */ - unsigned char reserved2[2]; /* 0x0000 */ - unsigned char reply_code; /* reply code */ - unsigned char reserved3[3]; /* 0x000000 */ -}; - -#define TYPE82_RSP_CODE 0x82 -#define TYPE88_RSP_CODE 0x88 - -#define REP82_ERROR_MACHINE_FAILURE 0x10 -#define REP82_ERROR_PREEMPT_FAILURE 0x12 -#define REP82_ERROR_CHECKPT_FAILURE 0x14 -#define REP82_ERROR_MESSAGE_TYPE 0x20 -#define REP82_ERROR_INVALID_COMM_CD 0x21 /* Type 84 */ -#define REP82_ERROR_INVALID_MSG_LEN 0x23 -#define REP82_ERROR_RESERVD_FIELD 0x24 /* was 0x50 */ -#define REP82_ERROR_FORMAT_FIELD 0x29 -#define REP82_ERROR_INVALID_COMMAND 0x30 -#define REP82_ERROR_MALFORMED_MSG 0x40 -#define REP82_ERROR_RESERVED_FIELDO 0x50 /* old value */ -#define REP82_ERROR_WORD_ALIGNMENT 0x60 -#define REP82_ERROR_MESSAGE_LENGTH 0x80 -#define REP82_ERROR_OPERAND_INVALID 0x82 -#define REP82_ERROR_OPERAND_SIZE 0x84 -#define REP82_ERROR_EVEN_MOD_IN_OPND 0x85 -#define REP82_ERROR_RESERVED_FIELD 0x88 -#define REP82_ERROR_TRANSPORT_FAIL 0x90 -#define REP82_ERROR_PACKET_TRUNCATED 0xA0 -#define REP82_ERROR_ZERO_BUFFER_LEN 0xB0 - -#define REP88_ERROR_MODULE_FAILURE 0x10 - -#define REP88_ERROR_MESSAGE_TYPE 0x20 -#define REP88_ERROR_MESSAGE_MALFORMD 0x22 -#define REP88_ERROR_MESSAGE_LENGTH 0x23 -#define REP88_ERROR_RESERVED_FIELD 0x24 -#define REP88_ERROR_KEY_TYPE 0x34 -#define REP88_ERROR_INVALID_KEY 0x82 /* CEX2A */ -#define REP88_ERROR_OPERAND 0x84 /* CEX2A */ -#define REP88_ERROR_OPERAND_EVEN_MOD 0x85 /* CEX2A */ - -static inline int convert_error(struct zcrypt_device *zdev, - struct ap_message *reply) -{ - struct error_hdr *ehdr = reply->message; - - PRINTK("Hardware error : Type %02x Message Header: %08x%08x\n", - ehdr->type, *(unsigned int *) reply->message, - *(unsigned int *) (reply->message + 4)); - - switch (ehdr->reply_code) { - case REP82_ERROR_OPERAND_INVALID: - case REP82_ERROR_OPERAND_SIZE: - case REP82_ERROR_EVEN_MOD_IN_OPND: - case REP88_ERROR_MESSAGE_MALFORMD: - // REP88_ERROR_INVALID_KEY // '82' CEX2A - // REP88_ERROR_OPERAND // '84' CEX2A - // REP88_ERROR_OPERAND_EVEN_MOD // '85' CEX2A - /* Invalid input data. */ - return -EINVAL; - case REP82_ERROR_MESSAGE_TYPE: - // REP88_ERROR_MESSAGE_TYPE // '20' CEX2A - /** - * To sent a message of the wrong type is a bug in the - * device driver. Warn about it, disable the device - * and then repeat the request. - */ - WARN_ON(1); - zdev->online = 0; - return -EAGAIN; - case REP82_ERROR_TRANSPORT_FAIL: - case REP82_ERROR_MACHINE_FAILURE: - // REP88_ERROR_MODULE_FAILURE // '10' CEX2A - /* If a card fails disable it and repeat the request. */ - zdev->online = 0; - return -EAGAIN; - default: - PRINTKW("unknown type %02x reply code = %d\n", - ehdr->type, ehdr->reply_code); - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } -} - -#endif /* _ZCRYPT_ERROR_H_ */ diff --git a/trunk/drivers/s390/crypto/zcrypt_mono.c b/trunk/drivers/s390/crypto/zcrypt_mono.c deleted file mode 100644 index 2a9349ad68b7..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_mono.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * linux/drivers/s390/crypto/zcrypt_mono.c - * - * zcrypt 2.1.0 - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ap_bus.h" -#include "zcrypt_api.h" -#include "zcrypt_pcica.h" -#include "zcrypt_pcicc.h" -#include "zcrypt_pcixcc.h" -#include "zcrypt_cex2a.h" - -/** - * The module initialization code. - */ -int __init zcrypt_init(void) -{ - int rc; - - rc = ap_module_init(); - if (rc) - goto out; - rc = zcrypt_api_init(); - if (rc) - goto out_ap; - rc = zcrypt_pcica_init(); - if (rc) - goto out_api; - rc = zcrypt_pcicc_init(); - if (rc) - goto out_pcica; - rc = zcrypt_pcixcc_init(); - if (rc) - goto out_pcicc; - rc = zcrypt_cex2a_init(); - if (rc) - goto out_pcixcc; - return 0; - -out_pcixcc: - zcrypt_pcixcc_exit(); -out_pcicc: - zcrypt_pcicc_exit(); -out_pcica: - zcrypt_pcica_exit(); -out_api: - zcrypt_api_exit(); -out_ap: - ap_module_exit(); -out: - return rc; -} - -/** - * The module termination code. - */ -void __exit zcrypt_exit(void) -{ - zcrypt_cex2a_exit(); - zcrypt_pcixcc_exit(); - zcrypt_pcicc_exit(); - zcrypt_pcica_exit(); - zcrypt_api_exit(); - ap_module_exit(); -} - -module_init(zcrypt_init); -module_exit(zcrypt_exit); diff --git a/trunk/drivers/s390/crypto/zcrypt_pcica.c b/trunk/drivers/s390/crypto/zcrypt_pcica.c deleted file mode 100644 index b6a4ecdc8025..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_pcica.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * linux/drivers/s390/crypto/zcrypt_pcica.c - * - * zcrypt 2.1.0 - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * Ralph Wuerthner - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include - -#include "ap_bus.h" -#include "zcrypt_api.h" -#include "zcrypt_error.h" -#include "zcrypt_pcica.h" - -#define PCICA_MIN_MOD_SIZE 1 /* 8 bits */ -#define PCICA_MAX_MOD_SIZE 256 /* 2048 bits */ - -#define PCICA_SPEED_RATING 2800 - -#define PCICA_MAX_MESSAGE_SIZE 0x3a0 /* sizeof(struct type4_lcr) */ -#define PCICA_MAX_RESPONSE_SIZE 0x110 /* max outputdatalength + type80_hdr */ - -#define PCICA_CLEANUP_TIME (15*HZ) - -static struct ap_device_id zcrypt_pcica_ids[] = { - { AP_DEVICE(AP_DEVICE_TYPE_PCICA) }, - { /* end of list */ }, -}; - -#ifndef CONFIG_ZCRYPT_MONOLITHIC -MODULE_DEVICE_TABLE(ap, zcrypt_pcica_ids); -MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("PCICA Cryptographic Coprocessor device driver, " - "Copyright 2001, 2006 IBM Corporation"); -MODULE_LICENSE("GPL"); -#endif - -static int zcrypt_pcica_probe(struct ap_device *ap_dev); -static void zcrypt_pcica_remove(struct ap_device *ap_dev); -static void zcrypt_pcica_receive(struct ap_device *, struct ap_message *, - struct ap_message *); - -static struct ap_driver zcrypt_pcica_driver = { - .probe = zcrypt_pcica_probe, - .remove = zcrypt_pcica_remove, - .receive = zcrypt_pcica_receive, - .ids = zcrypt_pcica_ids, -}; - -/** - * Convert a ICAMEX message to a type4 MEX message. - * - * @zdev: crypto device pointer - * @zreq: crypto request pointer - * @mex: pointer to user input data - * - * Returns 0 on success or -EFAULT. - */ -static int ICAMEX_msg_to_type4MEX_msg(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_rsa_modexpo *mex) -{ - unsigned char *modulus, *exponent, *message; - int mod_len; - - mod_len = mex->inputdatalength; - - if (mod_len <= 128) { - struct type4_sme *sme = ap_msg->message; - memset(sme, 0, sizeof(*sme)); - ap_msg->length = sizeof(*sme); - sme->header.msg_fmt = TYPE4_SME_FMT; - sme->header.msg_len = sizeof(*sme); - sme->header.msg_type_code = TYPE4_TYPE_CODE; - sme->header.request_code = TYPE4_REQU_CODE; - modulus = sme->modulus + sizeof(sme->modulus) - mod_len; - exponent = sme->exponent + sizeof(sme->exponent) - mod_len; - message = sme->message + sizeof(sme->message) - mod_len; - } else { - struct type4_lme *lme = ap_msg->message; - memset(lme, 0, sizeof(*lme)); - ap_msg->length = sizeof(*lme); - lme->header.msg_fmt = TYPE4_LME_FMT; - lme->header.msg_len = sizeof(*lme); - lme->header.msg_type_code = TYPE4_TYPE_CODE; - lme->header.request_code = TYPE4_REQU_CODE; - modulus = lme->modulus + sizeof(lme->modulus) - mod_len; - exponent = lme->exponent + sizeof(lme->exponent) - mod_len; - message = lme->message + sizeof(lme->message) - mod_len; - } - - if (copy_from_user(modulus, mex->n_modulus, mod_len) || - copy_from_user(exponent, mex->b_key, mod_len) || - copy_from_user(message, mex->inputdata, mod_len)) - return -EFAULT; - return 0; -} - -/** - * Convert a ICACRT message to a type4 CRT message. - * - * @zdev: crypto device pointer - * @zreq: crypto request pointer - * @crt: pointer to user input data - * - * Returns 0 on success or -EFAULT. - */ -static int ICACRT_msg_to_type4CRT_msg(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_rsa_modexpo_crt *crt) -{ - unsigned char *p, *q, *dp, *dq, *u, *inp; - int mod_len, short_len, long_len; - - mod_len = crt->inputdatalength; - short_len = mod_len / 2; - long_len = mod_len / 2 + 8; - - if (mod_len <= 128) { - struct type4_scr *scr = ap_msg->message; - memset(scr, 0, sizeof(*scr)); - ap_msg->length = sizeof(*scr); - scr->header.msg_type_code = TYPE4_TYPE_CODE; - scr->header.request_code = TYPE4_REQU_CODE; - scr->header.msg_fmt = TYPE4_SCR_FMT; - scr->header.msg_len = sizeof(*scr); - p = scr->p + sizeof(scr->p) - long_len; - q = scr->q + sizeof(scr->q) - short_len; - dp = scr->dp + sizeof(scr->dp) - long_len; - dq = scr->dq + sizeof(scr->dq) - short_len; - u = scr->u + sizeof(scr->u) - long_len; - inp = scr->message + sizeof(scr->message) - mod_len; - } else { - struct type4_lcr *lcr = ap_msg->message; - memset(lcr, 0, sizeof(*lcr)); - ap_msg->length = sizeof(*lcr); - lcr->header.msg_type_code = TYPE4_TYPE_CODE; - lcr->header.request_code = TYPE4_REQU_CODE; - lcr->header.msg_fmt = TYPE4_LCR_FMT; - lcr->header.msg_len = sizeof(*lcr); - p = lcr->p + sizeof(lcr->p) - long_len; - q = lcr->q + sizeof(lcr->q) - short_len; - dp = lcr->dp + sizeof(lcr->dp) - long_len; - dq = lcr->dq + sizeof(lcr->dq) - short_len; - u = lcr->u + sizeof(lcr->u) - long_len; - inp = lcr->message + sizeof(lcr->message) - mod_len; - } - - if (copy_from_user(p, crt->np_prime, long_len) || - copy_from_user(q, crt->nq_prime, short_len) || - copy_from_user(dp, crt->bp_key, long_len) || - copy_from_user(dq, crt->bq_key, short_len) || - copy_from_user(u, crt->u_mult_inv, long_len) || - copy_from_user(inp, crt->inputdata, mod_len)) - return -EFAULT; - return 0; -} - -/** - * Copy results from a type 84 reply message back to user space. - * - * @zdev: crypto device pointer - * @reply: reply AP message. - * @data: pointer to user output data - * @length: size of user output data - * - * Returns 0 on success or -EFAULT. - */ -static inline int convert_type84(struct zcrypt_device *zdev, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) -{ - struct type84_hdr *t84h = reply->message; - char *data; - - if (t84h->len < sizeof(*t84h) + outputdatalength) { - /* The result is too short, the PCICA card may not do that.. */ - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } - BUG_ON(t84h->len > PCICA_MAX_RESPONSE_SIZE); - data = reply->message + t84h->len - outputdatalength; - if (copy_to_user(outputdata, data, outputdatalength)) - return -EFAULT; - return 0; -} - -static int convert_response(struct zcrypt_device *zdev, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) -{ - /* Response type byte is the second byte in the response. */ - switch (((unsigned char *) reply->message)[1]) { - case TYPE82_RSP_CODE: - case TYPE88_RSP_CODE: - return convert_error(zdev, reply); - case TYPE84_RSP_CODE: - return convert_type84(zdev, reply, - outputdata, outputdatalength); - default: /* Unknown response type, this should NEVER EVER happen */ - PRINTK("Unrecognized Message Header: %08x%08x\n", - *(unsigned int *) reply->message, - *(unsigned int *) (reply->message+4)); - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } -} - -/** - * This function is called from the AP bus code after a crypto request - * "msg" has finished with the reply message "reply". - * It is called from tasklet context. - * @ap_dev: pointer to the AP device - * @msg: pointer to the AP message - * @reply: pointer to the AP reply message - */ -static void zcrypt_pcica_receive(struct ap_device *ap_dev, - struct ap_message *msg, - struct ap_message *reply) -{ - static struct error_hdr error_reply = { - .type = TYPE82_RSP_CODE, - .reply_code = REP82_ERROR_MACHINE_FAILURE, - }; - struct type84_hdr *t84h = reply->message; - int length; - - /* Copy the reply message to the request message buffer. */ - if (IS_ERR(reply)) - memcpy(msg->message, &error_reply, sizeof(error_reply)); - else if (t84h->code == TYPE84_RSP_CODE) { - length = min(PCICA_MAX_RESPONSE_SIZE, (int) t84h->len); - memcpy(msg->message, reply->message, length); - } else - memcpy(msg->message, reply->message, sizeof error_reply); - complete((struct completion *) msg->private); -} - -static atomic_t zcrypt_step = ATOMIC_INIT(0); - -/** - * The request distributor calls this function if it picked the PCICA - * device to handle a modexpo request. - * @zdev: pointer to zcrypt_device structure that identifies the - * PCICA device to the request distributor - * @mex: pointer to the modexpo request buffer - */ -static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev, - struct ica_rsa_modexpo *mex) -{ - struct ap_message ap_msg; - struct completion work; - int rc; - - ap_msg.message = (void *) kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &work; - rc = ICAMEX_msg_to_type4MEX_msg(zdev, &ap_msg, mex); - if (rc) - goto out_free; - init_completion(&work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible_timeout( - &work, PCICA_CLEANUP_TIME); - if (rc > 0) - rc = convert_response(zdev, &ap_msg, mex->outputdata, - mex->outputdatalength); - else { - /* Signal pending or message timed out. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); - if (rc == 0) - /* Message timed out. */ - rc = -ETIME; - } -out_free: - kfree(ap_msg.message); - return rc; -} - -/** - * The request distributor calls this function if it picked the PCICA - * device to handle a modexpo_crt request. - * @zdev: pointer to zcrypt_device structure that identifies the - * PCICA device to the request distributor - * @crt: pointer to the modexpoc_crt request buffer - */ -static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev, - struct ica_rsa_modexpo_crt *crt) -{ - struct ap_message ap_msg; - struct completion work; - int rc; - - ap_msg.message = (void *) kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &work; - rc = ICACRT_msg_to_type4CRT_msg(zdev, &ap_msg, crt); - if (rc) - goto out_free; - init_completion(&work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible_timeout( - &work, PCICA_CLEANUP_TIME); - if (rc > 0) - rc = convert_response(zdev, &ap_msg, crt->outputdata, - crt->outputdatalength); - else { - /* Signal pending or message timed out. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); - if (rc == 0) - /* Message timed out. */ - rc = -ETIME; - } -out_free: - kfree(ap_msg.message); - return rc; -} - -/** - * The crypto operations for a PCICA card. - */ -static struct zcrypt_ops zcrypt_pcica_ops = { - .rsa_modexpo = zcrypt_pcica_modexpo, - .rsa_modexpo_crt = zcrypt_pcica_modexpo_crt, -}; - -/** - * Probe function for PCICA cards. It always accepts the AP device - * since the bus_match already checked the hardware type. - * @ap_dev: pointer to the AP device. - */ -static int zcrypt_pcica_probe(struct ap_device *ap_dev) -{ - struct zcrypt_device *zdev; - int rc; - - zdev = zcrypt_device_alloc(PCICA_MAX_RESPONSE_SIZE); - if (!zdev) - return -ENOMEM; - zdev->ap_dev = ap_dev; - zdev->ops = &zcrypt_pcica_ops; - zdev->online = 1; - zdev->user_space_type = ZCRYPT_PCICA; - zdev->type_string = "PCICA"; - zdev->min_mod_size = PCICA_MIN_MOD_SIZE; - zdev->max_mod_size = PCICA_MAX_MOD_SIZE; - zdev->speed_rating = PCICA_SPEED_RATING; - ap_dev->reply = &zdev->reply; - ap_dev->private = zdev; - rc = zcrypt_device_register(zdev); - if (rc) - goto out_free; - return 0; - -out_free: - ap_dev->private = NULL; - zcrypt_device_free(zdev); - return rc; -} - -/** - * This is called to remove the extended PCICA driver information - * if an AP device is removed. - */ -static void zcrypt_pcica_remove(struct ap_device *ap_dev) -{ - struct zcrypt_device *zdev = ap_dev->private; - - zcrypt_device_unregister(zdev); -} - -int __init zcrypt_pcica_init(void) -{ - return ap_driver_register(&zcrypt_pcica_driver, THIS_MODULE, "pcica"); -} - -void zcrypt_pcica_exit(void) -{ - ap_driver_unregister(&zcrypt_pcica_driver); -} - -#ifndef CONFIG_ZCRYPT_MONOLITHIC -module_init(zcrypt_pcica_init); -module_exit(zcrypt_pcica_exit); -#endif diff --git a/trunk/drivers/s390/crypto/zcrypt_pcica.h b/trunk/drivers/s390/crypto/zcrypt_pcica.h deleted file mode 100644 index 3be11187f6df..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_pcica.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * linux/drivers/s390/crypto/zcrypt_pcica.h - * - * zcrypt 2.1.0 - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _ZCRYPT_PCICA_H_ -#define _ZCRYPT_PCICA_H_ - -/** - * The type 4 message family is associated with a PCICA card. - * - * The four members of the family are described below. - * - * Note that all unsigned char arrays are right-justified and left-padded - * with zeroes. - * - * Note that all reserved fields must be zeroes. - */ -struct type4_hdr { - unsigned char reserved1; - unsigned char msg_type_code; /* 0x04 */ - unsigned short msg_len; - unsigned char request_code; /* 0x40 */ - unsigned char msg_fmt; - unsigned short reserved2; -} __attribute__((packed)); - -#define TYPE4_TYPE_CODE 0x04 -#define TYPE4_REQU_CODE 0x40 - -#define TYPE4_SME_FMT 0x00 -#define TYPE4_LME_FMT 0x10 -#define TYPE4_SCR_FMT 0x40 -#define TYPE4_LCR_FMT 0x50 - -/* Mod-Exp, with a small modulus */ -struct type4_sme { - struct type4_hdr header; - unsigned char message[128]; - unsigned char exponent[128]; - unsigned char modulus[128]; -} __attribute__((packed)); - -/* Mod-Exp, with a large modulus */ -struct type4_lme { - struct type4_hdr header; - unsigned char message[256]; - unsigned char exponent[256]; - unsigned char modulus[256]; -} __attribute__((packed)); - -/* CRT, with a small modulus */ -struct type4_scr { - struct type4_hdr header; - unsigned char message[128]; - unsigned char dp[72]; - unsigned char dq[64]; - unsigned char p[72]; - unsigned char q[64]; - unsigned char u[72]; -} __attribute__((packed)); - -/* CRT, with a large modulus */ -struct type4_lcr { - struct type4_hdr header; - unsigned char message[256]; - unsigned char dp[136]; - unsigned char dq[128]; - unsigned char p[136]; - unsigned char q[128]; - unsigned char u[136]; -} __attribute__((packed)); - -/** - * The type 84 response family is associated with a PCICA card. - * - * Note that all unsigned char arrays are right-justified and left-padded - * with zeroes. - * - * Note that all reserved fields must be zeroes. - */ - -struct type84_hdr { - unsigned char reserved1; - unsigned char code; - unsigned short len; - unsigned char reserved2[4]; -} __attribute__((packed)); - -#define TYPE84_RSP_CODE 0x84 - -int zcrypt_pcica_init(void); -void zcrypt_pcica_exit(void); - -#endif /* _ZCRYPT_PCICA_H_ */ diff --git a/trunk/drivers/s390/crypto/zcrypt_pcicc.c b/trunk/drivers/s390/crypto/zcrypt_pcicc.c deleted file mode 100644 index f295a403b29a..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_pcicc.c +++ /dev/null @@ -1,630 +0,0 @@ -/* - * linux/drivers/s390/crypto/zcrypt_pcicc.c - * - * zcrypt 2.1.0 - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * Ralph Wuerthner - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include - -#include "ap_bus.h" -#include "zcrypt_api.h" -#include "zcrypt_error.h" -#include "zcrypt_pcicc.h" -#include "zcrypt_cca_key.h" - -#define PCICC_MIN_MOD_SIZE 64 /* 512 bits */ -#define PCICC_MAX_MOD_SIZE_OLD 128 /* 1024 bits */ -#define PCICC_MAX_MOD_SIZE 256 /* 2048 bits */ - -/** - * PCICC cards need a speed rating of 0. This keeps them at the end of - * the zcrypt device list (see zcrypt_api.c). PCICC cards are only - * used if no other cards are present because they are slow and can only - * cope with PKCS12 padded requests. The logic is queer. PKCS11 padded - * requests are rejected. The modexpo function encrypts PKCS12 padded data - * and decrypts any non-PKCS12 padded data (except PKCS11) in the assumption - * that it's encrypted PKCS12 data. The modexpo_crt function always decrypts - * the data in the assumption that its PKCS12 encrypted data. - */ -#define PCICC_SPEED_RATING 0 - -#define PCICC_MAX_MESSAGE_SIZE 0x710 /* max size type6 v1 crt message */ -#define PCICC_MAX_RESPONSE_SIZE 0x710 /* max size type86 v1 reply */ - -#define PCICC_CLEANUP_TIME (15*HZ) - -static struct ap_device_id zcrypt_pcicc_ids[] = { - { AP_DEVICE(AP_DEVICE_TYPE_PCICC) }, - { /* end of list */ }, -}; - -#ifndef CONFIG_ZCRYPT_MONOLITHIC -MODULE_DEVICE_TABLE(ap, zcrypt_pcicc_ids); -MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("PCICC Cryptographic Coprocessor device driver, " - "Copyright 2001, 2006 IBM Corporation"); -MODULE_LICENSE("GPL"); -#endif - -static int zcrypt_pcicc_probe(struct ap_device *ap_dev); -static void zcrypt_pcicc_remove(struct ap_device *ap_dev); -static void zcrypt_pcicc_receive(struct ap_device *, struct ap_message *, - struct ap_message *); - -static struct ap_driver zcrypt_pcicc_driver = { - .probe = zcrypt_pcicc_probe, - .remove = zcrypt_pcicc_remove, - .receive = zcrypt_pcicc_receive, - .ids = zcrypt_pcicc_ids, -}; - -/** - * The following is used to initialize the CPRB passed to the PCICC card - * in a type6 message. The 3 fields that must be filled in at execution - * time are req_parml, rpl_parml and usage_domain. Note that all three - * fields are *little*-endian. Actually, everything about this interface - * is ascii/little-endian, since the device has 'Intel inside'. - * - * The CPRB is followed immediately by the parm block. - * The parm block contains: - * - function code ('PD' 0x5044 or 'PK' 0x504B) - * - rule block (0x0A00 'PKCS-1.2' or 0x0A00 'ZERO-PAD') - * - VUD block - */ -static struct CPRB static_cprb = { - .cprb_len = __constant_cpu_to_le16(0x0070), - .cprb_ver_id = 0x41, - .func_id = {0x54,0x32}, - .checkpoint_flag= 0x01, - .svr_namel = __constant_cpu_to_le16(0x0008), - .svr_name = {'I','C','S','F',' ',' ',' ',' '} -}; - -/** - * Check the message for PKCS11 padding. - */ -static inline int is_PKCS11_padded(unsigned char *buffer, int length) -{ - int i; - if ((buffer[0] != 0x00) || (buffer[1] != 0x01)) - return 0; - for (i = 2; i < length; i++) - if (buffer[i] != 0xFF) - break; - if (i < 10 || i == length) - return 0; - if (buffer[i] != 0x00) - return 0; - return 1; -} - -/** - * Check the message for PKCS12 padding. - */ -static inline int is_PKCS12_padded(unsigned char *buffer, int length) -{ - int i; - if ((buffer[0] != 0x00) || (buffer[1] != 0x02)) - return 0; - for (i = 2; i < length; i++) - if (buffer[i] == 0x00) - break; - if ((i < 10) || (i == length)) - return 0; - if (buffer[i] != 0x00) - return 0; - return 1; -} - -/** - * Convert a ICAMEX message to a type6 MEX message. - * - * @zdev: crypto device pointer - * @zreq: crypto request pointer - * @mex: pointer to user input data - * - * Returns 0 on success or -EFAULT. - */ -static int ICAMEX_msg_to_type6MEX_msg(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_rsa_modexpo *mex) -{ - static struct type6_hdr static_type6_hdr = { - .type = 0x06, - .offset1 = 0x00000058, - .agent_id = {0x01,0x00,0x43,0x43,0x41,0x2D,0x41,0x50, - 0x50,0x4C,0x20,0x20,0x20,0x01,0x01,0x01}, - .function_code = {'P','K'}, - }; - static struct function_and_rules_block static_pke_function_and_rules ={ - .function_code = {'P','K'}, - .ulen = __constant_cpu_to_le16(10), - .only_rule = {'P','K','C','S','-','1','.','2'} - }; - struct { - struct type6_hdr hdr; - struct CPRB cprb; - struct function_and_rules_block fr; - unsigned short length; - char text[0]; - } __attribute__((packed)) *msg = ap_msg->message; - int vud_len, pad_len, size; - - /* VUD.ciphertext */ - if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength)) - return -EFAULT; - - if (is_PKCS11_padded(msg->text, mex->inputdatalength)) - return -EINVAL; - - /* static message header and f&r */ - msg->hdr = static_type6_hdr; - msg->fr = static_pke_function_and_rules; - - if (is_PKCS12_padded(msg->text, mex->inputdatalength)) { - /* strip the padding and adjust the data length */ - pad_len = strnlen(msg->text + 2, mex->inputdatalength - 2) + 3; - if (pad_len <= 9 || pad_len >= mex->inputdatalength) - return -ENODEV; - vud_len = mex->inputdatalength - pad_len; - memmove(msg->text, msg->text + pad_len, vud_len); - msg->length = cpu_to_le16(vud_len + 2); - - /* Set up key after the variable length text. */ - size = zcrypt_type6_mex_key_en(mex, msg->text + vud_len, 0); - if (size < 0) - return size; - size += sizeof(*msg) + vud_len; /* total size of msg */ - } else { - vud_len = mex->inputdatalength; - msg->length = cpu_to_le16(2 + vud_len); - - msg->hdr.function_code[1] = 'D'; - msg->fr.function_code[1] = 'D'; - - /* Set up key after the variable length text. */ - size = zcrypt_type6_mex_key_de(mex, msg->text + vud_len, 0); - if (size < 0) - return size; - size += sizeof(*msg) + vud_len; /* total size of msg */ - } - - /* message header, cprb and f&r */ - msg->hdr.ToCardLen1 = (size - sizeof(msg->hdr) + 3) & -4; - msg->hdr.FromCardLen1 = PCICC_MAX_RESPONSE_SIZE - sizeof(msg->hdr); - - msg->cprb = static_cprb; - msg->cprb.usage_domain[0]= AP_QID_QUEUE(zdev->ap_dev->qid); - msg->cprb.req_parml = cpu_to_le16(size - sizeof(msg->hdr) - - sizeof(msg->cprb)); - msg->cprb.rpl_parml = cpu_to_le16(msg->hdr.FromCardLen1); - - ap_msg->length = (size + 3) & -4; - return 0; -} - -/** - * Convert a ICACRT message to a type6 CRT message. - * - * @zdev: crypto device pointer - * @zreq: crypto request pointer - * @crt: pointer to user input data - * - * Returns 0 on success or -EFAULT. - */ -static int ICACRT_msg_to_type6CRT_msg(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_rsa_modexpo_crt *crt) -{ - static struct type6_hdr static_type6_hdr = { - .type = 0x06, - .offset1 = 0x00000058, - .agent_id = {0x01,0x00,0x43,0x43,0x41,0x2D,0x41,0x50, - 0x50,0x4C,0x20,0x20,0x20,0x01,0x01,0x01}, - .function_code = {'P','D'}, - }; - static struct function_and_rules_block static_pkd_function_and_rules ={ - .function_code = {'P','D'}, - .ulen = __constant_cpu_to_le16(10), - .only_rule = {'P','K','C','S','-','1','.','2'} - }; - struct { - struct type6_hdr hdr; - struct CPRB cprb; - struct function_and_rules_block fr; - unsigned short length; - char text[0]; - } __attribute__((packed)) *msg = ap_msg->message; - int size; - - /* VUD.ciphertext */ - msg->length = cpu_to_le16(2 + crt->inputdatalength); - if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength)) - return -EFAULT; - - if (is_PKCS11_padded(msg->text, crt->inputdatalength)) - return -EINVAL; - - /* Set up key after the variable length text. */ - size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 0); - if (size < 0) - return size; - size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */ - - /* message header, cprb and f&r */ - msg->hdr = static_type6_hdr; - msg->hdr.ToCardLen1 = (size - sizeof(msg->hdr) + 3) & -4; - msg->hdr.FromCardLen1 = PCICC_MAX_RESPONSE_SIZE - sizeof(msg->hdr); - - msg->cprb = static_cprb; - msg->cprb.usage_domain[0] = AP_QID_QUEUE(zdev->ap_dev->qid); - msg->cprb.req_parml = msg->cprb.rpl_parml = - cpu_to_le16(size - sizeof(msg->hdr) - sizeof(msg->cprb)); - - msg->fr = static_pkd_function_and_rules; - - ap_msg->length = (size + 3) & -4; - return 0; -} - -/** - * Copy results from a type 86 reply message back to user space. - * - * @zdev: crypto device pointer - * @reply: reply AP message. - * @data: pointer to user output data - * @length: size of user output data - * - * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error. - */ -struct type86_reply { - struct type86_hdr hdr; - struct type86_fmt2_ext fmt2; - struct CPRB cprb; - unsigned char pad[4]; /* 4 byte function code/rules block ? */ - unsigned short length; - char text[0]; -} __attribute__((packed)); - -static int convert_type86(struct zcrypt_device *zdev, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) -{ - static unsigned char static_pad[] = { - 0x00,0x02, - 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD, - 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57, - 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B, - 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39, - 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5, - 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D, - 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB, - 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F, - 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9, - 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45, - 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9, - 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F, - 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD, - 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D, - 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD, - 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9, - 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B, - 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B, - 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B, - 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD, - 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7, - 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1, - 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3, - 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23, - 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55, - 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43, - 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F, - 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F, - 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5, - 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD, - 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41, - 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09 - }; - struct type86_reply *msg = reply->message; - unsigned short service_rc, service_rs; - unsigned int reply_len, pad_len; - char *data; - - service_rc = le16_to_cpu(msg->cprb.ccp_rtcode); - if (unlikely(service_rc != 0)) { - service_rs = le16_to_cpu(msg->cprb.ccp_rscode); - if (service_rc == 8 && service_rs == 66) { - PDEBUG("Bad block format on PCICC\n"); - return -EINVAL; - } - if (service_rc == 8 && service_rs == 65) { - PDEBUG("Probably an even modulus on PCICC\n"); - return -EINVAL; - } - if (service_rc == 8 && service_rs == 770) { - PDEBUG("Invalid key length on PCICC\n"); - zdev->max_mod_size = PCICC_MAX_MOD_SIZE_OLD; - return -EAGAIN; - } - if (service_rc == 8 && service_rs == 783) { - PDEBUG("Extended bitlengths not enabled on PCICC\n"); - zdev->max_mod_size = PCICC_MAX_MOD_SIZE_OLD; - return -EAGAIN; - } - PRINTK("Unknown service rc/rs (PCICC): %d/%d\n", - service_rc, service_rs); - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } - data = msg->text; - reply_len = le16_to_cpu(msg->length) - 2; - if (reply_len > outputdatalength) - return -EINVAL; - /** - * For all encipher requests, the length of the ciphertext (reply_len) - * will always equal the modulus length. For MEX decipher requests - * the output needs to get padded. Minimum pad size is 10. - * - * Currently, the cases where padding will be added is for: - * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support - * ZERO-PAD and CRT is only supported for PKD requests) - * - PCICC, always - */ - pad_len = outputdatalength - reply_len; - if (pad_len > 0) { - if (pad_len < 10) - return -EINVAL; - /* 'restore' padding left in the PCICC/PCIXCC card. */ - if (copy_to_user(outputdata, static_pad, pad_len - 1)) - return -EFAULT; - if (put_user(0, outputdata + pad_len - 1)) - return -EFAULT; - } - /* Copy the crypto response to user space. */ - if (copy_to_user(outputdata + pad_len, data, reply_len)) - return -EFAULT; - return 0; -} - -static int convert_response(struct zcrypt_device *zdev, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) -{ - struct type86_reply *msg = reply->message; - - /* Response type byte is the second byte in the response. */ - switch (msg->hdr.type) { - case TYPE82_RSP_CODE: - case TYPE88_RSP_CODE: - return convert_error(zdev, reply); - case TYPE86_RSP_CODE: - if (msg->hdr.reply_code) - return convert_error(zdev, reply); - if (msg->cprb.cprb_ver_id == 0x01) - return convert_type86(zdev, reply, - outputdata, outputdatalength); - /* no break, incorrect cprb version is an unknown response */ - default: /* Unknown response type, this should NEVER EVER happen */ - PRINTK("Unrecognized Message Header: %08x%08x\n", - *(unsigned int *) reply->message, - *(unsigned int *) (reply->message+4)); - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } -} - -/** - * This function is called from the AP bus code after a crypto request - * "msg" has finished with the reply message "reply". - * It is called from tasklet context. - * @ap_dev: pointer to the AP device - * @msg: pointer to the AP message - * @reply: pointer to the AP reply message - */ -static void zcrypt_pcicc_receive(struct ap_device *ap_dev, - struct ap_message *msg, - struct ap_message *reply) -{ - static struct error_hdr error_reply = { - .type = TYPE82_RSP_CODE, - .reply_code = REP82_ERROR_MACHINE_FAILURE, - }; - struct type86_reply *t86r = reply->message; - int length; - - /* Copy the reply message to the request message buffer. */ - if (IS_ERR(reply)) - memcpy(msg->message, &error_reply, sizeof(error_reply)); - else if (t86r->hdr.type == TYPE86_RSP_CODE && - t86r->cprb.cprb_ver_id == 0x01) { - length = sizeof(struct type86_reply) + t86r->length - 2; - length = min(PCICC_MAX_RESPONSE_SIZE, length); - memcpy(msg->message, reply->message, length); - } else - memcpy(msg->message, reply->message, sizeof error_reply); - complete((struct completion *) msg->private); -} - -static atomic_t zcrypt_step = ATOMIC_INIT(0); - -/** - * The request distributor calls this function if it picked the PCICC - * device to handle a modexpo request. - * @zdev: pointer to zcrypt_device structure that identifies the - * PCICC device to the request distributor - * @mex: pointer to the modexpo request buffer - */ -static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev, - struct ica_rsa_modexpo *mex) -{ - struct ap_message ap_msg; - struct completion work; - int rc; - - ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.length = PAGE_SIZE; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &work; - rc = ICAMEX_msg_to_type6MEX_msg(zdev, &ap_msg, mex); - if (rc) - goto out_free; - init_completion(&work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible_timeout( - &work, PCICC_CLEANUP_TIME); - if (rc > 0) - rc = convert_response(zdev, &ap_msg, mex->outputdata, - mex->outputdatalength); - else { - /* Signal pending or message timed out. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); - if (rc == 0) - /* Message timed out. */ - rc = -ETIME; - } -out_free: - free_page((unsigned long) ap_msg.message); - return rc; -} - -/** - * The request distributor calls this function if it picked the PCICC - * device to handle a modexpo_crt request. - * @zdev: pointer to zcrypt_device structure that identifies the - * PCICC device to the request distributor - * @crt: pointer to the modexpoc_crt request buffer - */ -static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev, - struct ica_rsa_modexpo_crt *crt) -{ - struct ap_message ap_msg; - struct completion work; - int rc; - - ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.length = PAGE_SIZE; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &work; - rc = ICACRT_msg_to_type6CRT_msg(zdev, &ap_msg, crt); - if (rc) - goto out_free; - init_completion(&work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible_timeout( - &work, PCICC_CLEANUP_TIME); - if (rc > 0) - rc = convert_response(zdev, &ap_msg, crt->outputdata, - crt->outputdatalength); - else { - /* Signal pending or message timed out. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); - if (rc == 0) - /* Message timed out. */ - rc = -ETIME; - } -out_free: - free_page((unsigned long) ap_msg.message); - return rc; -} - -/** - * The crypto operations for a PCICC card. - */ -static struct zcrypt_ops zcrypt_pcicc_ops = { - .rsa_modexpo = zcrypt_pcicc_modexpo, - .rsa_modexpo_crt = zcrypt_pcicc_modexpo_crt, -}; - -/** - * Probe function for PCICC cards. It always accepts the AP device - * since the bus_match already checked the hardware type. - * @ap_dev: pointer to the AP device. - */ -static int zcrypt_pcicc_probe(struct ap_device *ap_dev) -{ - struct zcrypt_device *zdev; - int rc; - - zdev = zcrypt_device_alloc(PCICC_MAX_RESPONSE_SIZE); - if (!zdev) - return -ENOMEM; - zdev->ap_dev = ap_dev; - zdev->ops = &zcrypt_pcicc_ops; - zdev->online = 1; - zdev->user_space_type = ZCRYPT_PCICC; - zdev->type_string = "PCICC"; - zdev->min_mod_size = PCICC_MIN_MOD_SIZE; - zdev->max_mod_size = PCICC_MAX_MOD_SIZE; - zdev->speed_rating = PCICC_SPEED_RATING; - ap_dev->reply = &zdev->reply; - ap_dev->private = zdev; - rc = zcrypt_device_register(zdev); - if (rc) - goto out_free; - return 0; - - out_free: - ap_dev->private = NULL; - zcrypt_device_free(zdev); - return rc; -} - -/** - * This is called to remove the extended PCICC driver information - * if an AP device is removed. - */ -static void zcrypt_pcicc_remove(struct ap_device *ap_dev) -{ - struct zcrypt_device *zdev = ap_dev->private; - - zcrypt_device_unregister(zdev); -} - -int __init zcrypt_pcicc_init(void) -{ - return ap_driver_register(&zcrypt_pcicc_driver, THIS_MODULE, "pcicc"); -} - -void zcrypt_pcicc_exit(void) -{ - ap_driver_unregister(&zcrypt_pcicc_driver); -} - -#ifndef CONFIG_ZCRYPT_MONOLITHIC -module_init(zcrypt_pcicc_init); -module_exit(zcrypt_pcicc_exit); -#endif diff --git a/trunk/drivers/s390/crypto/zcrypt_pcicc.h b/trunk/drivers/s390/crypto/zcrypt_pcicc.h deleted file mode 100644 index 6d4454846c8f..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_pcicc.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * linux/drivers/s390/crypto/zcrypt_pcicc.h - * - * zcrypt 2.1.0 - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _ZCRYPT_PCICC_H_ -#define _ZCRYPT_PCICC_H_ - -/** - * The type 6 message family is associated with PCICC or PCIXCC cards. - * - * It contains a message header followed by a CPRB, both of which - * are described below. - * - * Note that all reserved fields must be zeroes. - */ -struct type6_hdr { - unsigned char reserved1; /* 0x00 */ - unsigned char type; /* 0x06 */ - unsigned char reserved2[2]; /* 0x0000 */ - unsigned char right[4]; /* 0x00000000 */ - unsigned char reserved3[2]; /* 0x0000 */ - unsigned char reserved4[2]; /* 0x0000 */ - unsigned char apfs[4]; /* 0x00000000 */ - unsigned int offset1; /* 0x00000058 (offset to CPRB) */ - unsigned int offset2; /* 0x00000000 */ - unsigned int offset3; /* 0x00000000 */ - unsigned int offset4; /* 0x00000000 */ - unsigned char agent_id[16]; /* PCICC: */ - /* 0x0100 */ - /* 0x4343412d4150504c202020 */ - /* 0x010101 */ - /* PCIXCC: */ - /* 0x4341000000000000 */ - /* 0x0000000000000000 */ - unsigned char rqid[2]; /* rqid. internal to 603 */ - unsigned char reserved5[2]; /* 0x0000 */ - unsigned char function_code[2]; /* for PKD, 0x5044 (ascii 'PD') */ - unsigned char reserved6[2]; /* 0x0000 */ - unsigned int ToCardLen1; /* (request CPRB len + 3) & -4 */ - unsigned int ToCardLen2; /* db len 0x00000000 for PKD */ - unsigned int ToCardLen3; /* 0x00000000 */ - unsigned int ToCardLen4; /* 0x00000000 */ - unsigned int FromCardLen1; /* response buffer length */ - unsigned int FromCardLen2; /* db len 0x00000000 for PKD */ - unsigned int FromCardLen3; /* 0x00000000 */ - unsigned int FromCardLen4; /* 0x00000000 */ -} __attribute__((packed)); - -/** - * CPRB - * Note that all shorts, ints and longs are little-endian. - * All pointer fields are 32-bits long, and mean nothing - * - * A request CPRB is followed by a request_parameter_block. - * - * The request (or reply) parameter block is organized thus: - * function code - * VUD block - * key block - */ -struct CPRB { - unsigned short cprb_len; /* CPRB length */ - unsigned char cprb_ver_id; /* CPRB version id. */ - unsigned char pad_000; /* Alignment pad byte. */ - unsigned char srpi_rtcode[4]; /* SRPI return code LELONG */ - unsigned char srpi_verb; /* SRPI verb type */ - unsigned char flags; /* flags */ - unsigned char func_id[2]; /* function id */ - unsigned char checkpoint_flag; /* */ - unsigned char resv2; /* reserved */ - unsigned short req_parml; /* request parameter buffer */ - /* length 16-bit little endian */ - unsigned char req_parmp[4]; /* request parameter buffer * - * pointer (means nothing: the * - * parameter buffer follows * - * the CPRB). */ - unsigned char req_datal[4]; /* request data buffer */ - /* length ULELONG */ - unsigned char req_datap[4]; /* request data buffer */ - /* pointer */ - unsigned short rpl_parml; /* reply parameter buffer */ - /* length 16-bit little endian */ - unsigned char pad_001[2]; /* Alignment pad bytes. ULESHORT */ - unsigned char rpl_parmp[4]; /* reply parameter buffer * - * pointer (means nothing: the * - * parameter buffer follows * - * the CPRB). */ - unsigned char rpl_datal[4]; /* reply data buffer len ULELONG */ - unsigned char rpl_datap[4]; /* reply data buffer */ - /* pointer */ - unsigned short ccp_rscode; /* server reason code ULESHORT */ - unsigned short ccp_rtcode; /* server return code ULESHORT */ - unsigned char repd_parml[2]; /* replied parameter len ULESHORT*/ - unsigned char mac_data_len[2]; /* Mac Data Length ULESHORT */ - unsigned char repd_datal[4]; /* replied data length ULELONG */ - unsigned char req_pc[2]; /* PC identifier */ - unsigned char res_origin[8]; /* resource origin */ - unsigned char mac_value[8]; /* Mac Value */ - unsigned char logon_id[8]; /* Logon Identifier */ - unsigned char usage_domain[2]; /* cdx */ - unsigned char resv3[18]; /* reserved for requestor */ - unsigned short svr_namel; /* server name length ULESHORT */ - unsigned char svr_name[8]; /* server name */ -} __attribute__((packed)); - -/** - * The type 86 message family is associated with PCICC and PCIXCC cards. - * - * It contains a message header followed by a CPRB. The CPRB is - * the same as the request CPRB, which is described above. - * - * If format is 1, an error condition exists and no data beyond - * the 8-byte message header is of interest. - * - * The non-error message is shown below. - * - * Note that all reserved fields must be zeroes. - */ -struct type86_hdr { - unsigned char reserved1; /* 0x00 */ - unsigned char type; /* 0x86 */ - unsigned char format; /* 0x01 (error) or 0x02 (ok) */ - unsigned char reserved2; /* 0x00 */ - unsigned char reply_code; /* reply code (see above) */ - unsigned char reserved3[3]; /* 0x000000 */ -} __attribute__((packed)); - -#define TYPE86_RSP_CODE 0x86 -#define TYPE86_FMT2 0x02 - -struct type86_fmt2_ext { - unsigned char reserved[4]; /* 0x00000000 */ - unsigned char apfs[4]; /* final status */ - unsigned int count1; /* length of CPRB + parameters */ - unsigned int offset1; /* offset to CPRB */ - unsigned int count2; /* 0x00000000 */ - unsigned int offset2; /* db offset 0x00000000 for PKD */ - unsigned int count3; /* 0x00000000 */ - unsigned int offset3; /* 0x00000000 */ - unsigned int count4; /* 0x00000000 */ - unsigned int offset4; /* 0x00000000 */ -} __attribute__((packed)); - -struct function_and_rules_block { - unsigned char function_code[2]; - unsigned short ulen; - unsigned char only_rule[8]; -} __attribute__((packed)); - -int zcrypt_pcicc_init(void); -void zcrypt_pcicc_exit(void); - -#endif /* _ZCRYPT_PCICC_H_ */ diff --git a/trunk/drivers/s390/crypto/zcrypt_pcixcc.c b/trunk/drivers/s390/crypto/zcrypt_pcixcc.c deleted file mode 100644 index 2da8b9381407..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_pcixcc.c +++ /dev/null @@ -1,951 +0,0 @@ -/* - * linux/drivers/s390/crypto/zcrypt_pcixcc.c - * - * zcrypt 2.1.0 - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * Ralph Wuerthner - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include - -#include "ap_bus.h" -#include "zcrypt_api.h" -#include "zcrypt_error.h" -#include "zcrypt_pcicc.h" -#include "zcrypt_pcixcc.h" -#include "zcrypt_cca_key.h" - -#define PCIXCC_MIN_MOD_SIZE 16 /* 128 bits */ -#define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */ -#define PCIXCC_MAX_MOD_SIZE 256 /* 2048 bits */ - -#define PCIXCC_MCL2_SPEED_RATING 7870 /* FIXME: needs finetuning */ -#define PCIXCC_MCL3_SPEED_RATING 7870 -#define CEX2C_SPEED_RATING 8540 - -#define PCIXCC_MAX_ICA_MESSAGE_SIZE 0x77c /* max size type6 v2 crt message */ -#define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */ - -#define PCIXCC_MAX_XCRB_MESSAGE_SIZE (12*1024) -#define PCIXCC_MAX_XCRB_RESPONSE_SIZE PCIXCC_MAX_XCRB_MESSAGE_SIZE -#define PCIXCC_MAX_XCRB_DATA_SIZE (11*1024) -#define PCIXCC_MAX_XCRB_REPLY_SIZE (5*1024) - -#define PCIXCC_MAX_RESPONSE_SIZE PCIXCC_MAX_XCRB_RESPONSE_SIZE - -#define PCIXCC_CLEANUP_TIME (15*HZ) - -#define CEIL4(x) ((((x)+3)/4)*4) - -struct response_type { - struct completion work; - int type; -}; -#define PCIXCC_RESPONSE_TYPE_ICA 0 -#define PCIXCC_RESPONSE_TYPE_XCRB 1 - -static struct ap_device_id zcrypt_pcixcc_ids[] = { - { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) }, - { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) }, - { /* end of list */ }, -}; - -#ifndef CONFIG_ZCRYPT_MONOLITHIC -MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids); -MODULE_AUTHOR("IBM Corporation"); -MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, " - "Copyright 2001, 2006 IBM Corporation"); -MODULE_LICENSE("GPL"); -#endif - -static int zcrypt_pcixcc_probe(struct ap_device *ap_dev); -static void zcrypt_pcixcc_remove(struct ap_device *ap_dev); -static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *, - struct ap_message *); - -static struct ap_driver zcrypt_pcixcc_driver = { - .probe = zcrypt_pcixcc_probe, - .remove = zcrypt_pcixcc_remove, - .receive = zcrypt_pcixcc_receive, - .ids = zcrypt_pcixcc_ids, -}; - -/** - * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C - * card in a type6 message. The 3 fields that must be filled in at execution - * time are req_parml, rpl_parml and usage_domain. - * Everything about this interface is ascii/big-endian, since the - * device does *not* have 'Intel inside'. - * - * The CPRBX is followed immediately by the parm block. - * The parm block contains: - * - function code ('PD' 0x5044 or 'PK' 0x504B) - * - rule block (one of:) - * + 0x000A 'PKCS-1.2' (MCL2 'PD') - * + 0x000A 'ZERO-PAD' (MCL2 'PK') - * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD') - * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK') - * - VUD block - */ -static struct CPRBX static_cprbx = { - .cprb_len = 0x00DC, - .cprb_ver_id = 0x02, - .func_id = {0x54,0x32}, -}; - -/** - * Convert a ICAMEX message to a type6 MEX message. - * - * @zdev: crypto device pointer - * @ap_msg: pointer to AP message - * @mex: pointer to user input data - * - * Returns 0 on success or -EFAULT. - */ -static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_rsa_modexpo *mex) -{ - static struct type6_hdr static_type6_hdrX = { - .type = 0x06, - .offset1 = 0x00000058, - .agent_id = {'C','A',}, - .function_code = {'P','K'}, - }; - static struct function_and_rules_block static_pke_fnr = { - .function_code = {'P','K'}, - .ulen = 10, - .only_rule = {'M','R','P',' ',' ',' ',' ',' '} - }; - static struct function_and_rules_block static_pke_fnr_MCL2 = { - .function_code = {'P','K'}, - .ulen = 10, - .only_rule = {'Z','E','R','O','-','P','A','D'} - }; - struct { - struct type6_hdr hdr; - struct CPRBX cprbx; - struct function_and_rules_block fr; - unsigned short length; - char text[0]; - } __attribute__((packed)) *msg = ap_msg->message; - int size; - - /* VUD.ciphertext */ - msg->length = mex->inputdatalength + 2; - if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength)) - return -EFAULT; - - /* Set up key which is located after the variable length text. */ - size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1); - if (size < 0) - return size; - size += sizeof(*msg) + mex->inputdatalength; - - /* message header, cprbx and f&r */ - msg->hdr = static_type6_hdrX; - msg->hdr.ToCardLen1 = size - sizeof(msg->hdr); - msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr); - - msg->cprbx = static_cprbx; - msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid); - msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1; - - msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ? - static_pke_fnr_MCL2 : static_pke_fnr; - - msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx); - - ap_msg->length = size; - return 0; -} - -/** - * Convert a ICACRT message to a type6 CRT message. - * - * @zdev: crypto device pointer - * @ap_msg: pointer to AP message - * @crt: pointer to user input data - * - * Returns 0 on success or -EFAULT. - */ -static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_rsa_modexpo_crt *crt) -{ - static struct type6_hdr static_type6_hdrX = { - .type = 0x06, - .offset1 = 0x00000058, - .agent_id = {'C','A',}, - .function_code = {'P','D'}, - }; - static struct function_and_rules_block static_pkd_fnr = { - .function_code = {'P','D'}, - .ulen = 10, - .only_rule = {'Z','E','R','O','-','P','A','D'} - }; - - static struct function_and_rules_block static_pkd_fnr_MCL2 = { - .function_code = {'P','D'}, - .ulen = 10, - .only_rule = {'P','K','C','S','-','1','.','2'} - }; - struct { - struct type6_hdr hdr; - struct CPRBX cprbx; - struct function_and_rules_block fr; - unsigned short length; - char text[0]; - } __attribute__((packed)) *msg = ap_msg->message; - int size; - - /* VUD.ciphertext */ - msg->length = crt->inputdatalength + 2; - if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength)) - return -EFAULT; - - /* Set up key which is located after the variable length text. */ - size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1); - if (size < 0) - return size; - size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */ - - /* message header, cprbx and f&r */ - msg->hdr = static_type6_hdrX; - msg->hdr.ToCardLen1 = size - sizeof(msg->hdr); - msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr); - - msg->cprbx = static_cprbx; - msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid); - msg->cprbx.req_parml = msg->cprbx.rpl_msgbl = - size - sizeof(msg->hdr) - sizeof(msg->cprbx); - - msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ? - static_pkd_fnr_MCL2 : static_pkd_fnr; - - ap_msg->length = size; - return 0; -} - -/** - * Convert a XCRB message to a type6 CPRB message. - * - * @zdev: crypto device pointer - * @ap_msg: pointer to AP message - * @xcRB: pointer to user input data - * - * Returns 0 on success or -EFAULT. - */ -struct type86_fmt2_msg { - struct type86_hdr hdr; - struct type86_fmt2_ext fmt2; -} __attribute__((packed)); - -static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, - struct ap_message *ap_msg, - struct ica_xcRB *xcRB) -{ - static struct type6_hdr static_type6_hdrX = { - .type = 0x06, - .offset1 = 0x00000058, - }; - struct { - struct type6_hdr hdr; - struct ica_CPRBX cprbx; - } __attribute__((packed)) *msg = ap_msg->message; - - int rcblen = CEIL4(xcRB->request_control_blk_length); - int replylen; - char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen; - char *function_code; - - /* length checks */ - ap_msg->length = sizeof(struct type6_hdr) + - CEIL4(xcRB->request_control_blk_length) + - xcRB->request_data_length; - if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE) { - PRINTK("Combined message is too large (%ld/%d/%d).\n", - sizeof(struct type6_hdr), - xcRB->request_control_blk_length, - xcRB->request_data_length); - return -EFAULT; - } - if (CEIL4(xcRB->reply_control_blk_length) > - PCIXCC_MAX_XCRB_REPLY_SIZE) { - PDEBUG("Reply CPRB length is too large (%d).\n", - xcRB->request_control_blk_length); - return -EFAULT; - } - if (CEIL4(xcRB->reply_data_length) > PCIXCC_MAX_XCRB_DATA_SIZE) { - PDEBUG("Reply data block length is too large (%d).\n", - xcRB->reply_data_length); - return -EFAULT; - } - replylen = CEIL4(xcRB->reply_control_blk_length) + - CEIL4(xcRB->reply_data_length) + - sizeof(struct type86_fmt2_msg); - if (replylen > PCIXCC_MAX_XCRB_RESPONSE_SIZE) { - PDEBUG("Reply CPRB + data block > PCIXCC_MAX_XCRB_RESPONSE_SIZE" - " (%d/%d/%d).\n", - sizeof(struct type86_fmt2_msg), - xcRB->reply_control_blk_length, - xcRB->reply_data_length); - xcRB->reply_control_blk_length = PCIXCC_MAX_XCRB_RESPONSE_SIZE - - (sizeof(struct type86_fmt2_msg) + - CEIL4(xcRB->reply_data_length)); - PDEBUG("Capping Reply CPRB length at %d\n", - xcRB->reply_control_blk_length); - } - - /* prepare type6 header */ - msg->hdr = static_type6_hdrX; - memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID)); - msg->hdr.ToCardLen1 = xcRB->request_control_blk_length; - if (xcRB->request_data_length) { - msg->hdr.offset2 = msg->hdr.offset1 + rcblen; - msg->hdr.ToCardLen2 = xcRB->request_data_length; - } - msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length; - msg->hdr.FromCardLen2 = xcRB->reply_data_length; - - /* prepare CPRB */ - if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr, - xcRB->request_control_blk_length)) - return -EFAULT; - if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) > - xcRB->request_control_blk_length) { - PDEBUG("cprb_len too large (%d/%d)\n", msg->cprbx.cprb_len, - xcRB->request_control_blk_length); - return -EFAULT; - } - function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len; - memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code)); - - /* copy data block */ - if (xcRB->request_data_length && - copy_from_user(req_data, xcRB->request_data_address, - xcRB->request_data_length)) - return -EFAULT; - return 0; -} - -/** - * Copy results from a type 86 ICA reply message back to user space. - * - * @zdev: crypto device pointer - * @reply: reply AP message. - * @data: pointer to user output data - * @length: size of user output data - * - * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error. - */ -struct type86x_reply { - struct type86_hdr hdr; - struct type86_fmt2_ext fmt2; - struct CPRBX cprbx; - unsigned char pad[4]; /* 4 byte function code/rules block ? */ - unsigned short length; - char text[0]; -} __attribute__((packed)); - -static int convert_type86_ica(struct zcrypt_device *zdev, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) -{ - static unsigned char static_pad[] = { - 0x00,0x02, - 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD, - 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57, - 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B, - 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39, - 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5, - 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D, - 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB, - 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F, - 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9, - 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45, - 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9, - 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F, - 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD, - 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D, - 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD, - 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9, - 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B, - 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B, - 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B, - 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD, - 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7, - 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1, - 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3, - 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23, - 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55, - 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43, - 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F, - 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F, - 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5, - 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD, - 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41, - 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09 - }; - struct type86x_reply *msg = reply->message; - unsigned short service_rc, service_rs; - unsigned int reply_len, pad_len; - char *data; - - service_rc = msg->cprbx.ccp_rtcode; - if (unlikely(service_rc != 0)) { - service_rs = msg->cprbx.ccp_rscode; - if (service_rc == 8 && service_rs == 66) { - PDEBUG("Bad block format on PCIXCC/CEX2C\n"); - return -EINVAL; - } - if (service_rc == 8 && service_rs == 65) { - PDEBUG("Probably an even modulus on PCIXCC/CEX2C\n"); - return -EINVAL; - } - if (service_rc == 8 && service_rs == 770) { - PDEBUG("Invalid key length on PCIXCC/CEX2C\n"); - zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; - return -EAGAIN; - } - if (service_rc == 8 && service_rs == 783) { - PDEBUG("Extended bitlengths not enabled on PCIXCC/CEX2C\n"); - zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; - return -EAGAIN; - } - PRINTK("Unknown service rc/rs (PCIXCC/CEX2C): %d/%d\n", - service_rc, service_rs); - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } - data = msg->text; - reply_len = msg->length - 2; - if (reply_len > outputdatalength) - return -EINVAL; - /** - * For all encipher requests, the length of the ciphertext (reply_len) - * will always equal the modulus length. For MEX decipher requests - * the output needs to get padded. Minimum pad size is 10. - * - * Currently, the cases where padding will be added is for: - * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support - * ZERO-PAD and CRT is only supported for PKD requests) - * - PCICC, always - */ - pad_len = outputdatalength - reply_len; - if (pad_len > 0) { - if (pad_len < 10) - return -EINVAL; - /* 'restore' padding left in the PCICC/PCIXCC card. */ - if (copy_to_user(outputdata, static_pad, pad_len - 1)) - return -EFAULT; - if (put_user(0, outputdata + pad_len - 1)) - return -EFAULT; - } - /* Copy the crypto response to user space. */ - if (copy_to_user(outputdata + pad_len, data, reply_len)) - return -EFAULT; - return 0; -} - -/** - * Copy results from a type 86 XCRB reply message back to user space. - * - * @zdev: crypto device pointer - * @reply: reply AP message. - * @xcRB: pointer to XCRB - * - * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error. - */ -static int convert_type86_xcrb(struct zcrypt_device *zdev, - struct ap_message *reply, - struct ica_xcRB *xcRB) -{ - struct type86_fmt2_msg *msg = reply->message; - char *data = reply->message; - - /* Copy CPRB to user */ - if (copy_to_user(xcRB->reply_control_blk_addr, - data + msg->fmt2.offset1, msg->fmt2.count1)) - return -EFAULT; - xcRB->reply_control_blk_length = msg->fmt2.count1; - - /* Copy data buffer to user */ - if (msg->fmt2.count2) - if (copy_to_user(xcRB->reply_data_addr, - data + msg->fmt2.offset2, msg->fmt2.count2)) - return -EFAULT; - xcRB->reply_data_length = msg->fmt2.count2; - return 0; -} - -static int convert_response_ica(struct zcrypt_device *zdev, - struct ap_message *reply, - char __user *outputdata, - unsigned int outputdatalength) -{ - struct type86x_reply *msg = reply->message; - - /* Response type byte is the second byte in the response. */ - switch (((unsigned char *) reply->message)[1]) { - case TYPE82_RSP_CODE: - case TYPE88_RSP_CODE: - return convert_error(zdev, reply); - case TYPE86_RSP_CODE: - if (msg->hdr.reply_code) - return convert_error(zdev, reply); - if (msg->cprbx.cprb_ver_id == 0x02) - return convert_type86_ica(zdev, reply, - outputdata, outputdatalength); - /* no break, incorrect cprb version is an unknown response */ - default: /* Unknown response type, this should NEVER EVER happen */ - PRINTK("Unrecognized Message Header: %08x%08x\n", - *(unsigned int *) reply->message, - *(unsigned int *) (reply->message+4)); - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } -} - -static int convert_response_xcrb(struct zcrypt_device *zdev, - struct ap_message *reply, - struct ica_xcRB *xcRB) -{ - struct type86x_reply *msg = reply->message; - - /* Response type byte is the second byte in the response. */ - switch (((unsigned char *) reply->message)[1]) { - case TYPE82_RSP_CODE: - case TYPE88_RSP_CODE: - xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ - return convert_error(zdev, reply); - case TYPE86_RSP_CODE: - if (msg->hdr.reply_code) { - memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32)); - return convert_error(zdev, reply); - } - if (msg->cprbx.cprb_ver_id == 0x02) - return convert_type86_xcrb(zdev, reply, xcRB); - /* no break, incorrect cprb version is an unknown response */ - default: /* Unknown response type, this should NEVER EVER happen */ - PRINTK("Unrecognized Message Header: %08x%08x\n", - *(unsigned int *) reply->message, - *(unsigned int *) (reply->message+4)); - xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ - zdev->online = 0; - return -EAGAIN; /* repeat the request on a different device. */ - } -} - -/** - * This function is called from the AP bus code after a crypto request - * "msg" has finished with the reply message "reply". - * It is called from tasklet context. - * @ap_dev: pointer to the AP device - * @msg: pointer to the AP message - * @reply: pointer to the AP reply message - */ -static void zcrypt_pcixcc_receive(struct ap_device *ap_dev, - struct ap_message *msg, - struct ap_message *reply) -{ - static struct error_hdr error_reply = { - .type = TYPE82_RSP_CODE, - .reply_code = REP82_ERROR_MACHINE_FAILURE, - }; - struct response_type *resp_type = - (struct response_type *) msg->private; - struct type86x_reply *t86r = reply->message; - int length; - - /* Copy the reply message to the request message buffer. */ - if (IS_ERR(reply)) - memcpy(msg->message, &error_reply, sizeof(error_reply)); - else if (t86r->hdr.type == TYPE86_RSP_CODE && - t86r->cprbx.cprb_ver_id == 0x02) { - switch (resp_type->type) { - case PCIXCC_RESPONSE_TYPE_ICA: - length = sizeof(struct type86x_reply) - + t86r->length - 2; - length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length); - memcpy(msg->message, reply->message, length); - break; - case PCIXCC_RESPONSE_TYPE_XCRB: - length = t86r->fmt2.offset2 + t86r->fmt2.count2; - length = min(PCIXCC_MAX_XCRB_RESPONSE_SIZE, length); - memcpy(msg->message, reply->message, length); - break; - default: - PRINTK("Invalid internal response type: %i\n", - resp_type->type); - memcpy(msg->message, &error_reply, - sizeof error_reply); - } - } else - memcpy(msg->message, reply->message, sizeof error_reply); - complete(&(resp_type->work)); -} - -static atomic_t zcrypt_step = ATOMIC_INIT(0); - -/** - * The request distributor calls this function if it picked the PCIXCC/CEX2C - * device to handle a modexpo request. - * @zdev: pointer to zcrypt_device structure that identifies the - * PCIXCC/CEX2C device to the request distributor - * @mex: pointer to the modexpo request buffer - */ -static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev, - struct ica_rsa_modexpo *mex) -{ - struct ap_message ap_msg; - struct response_type resp_type = { - .type = PCIXCC_RESPONSE_TYPE_ICA, - }; - int rc; - - ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &resp_type; - rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex); - if (rc) - goto out_free; - init_completion(&resp_type.work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible_timeout( - &resp_type.work, PCIXCC_CLEANUP_TIME); - if (rc > 0) - rc = convert_response_ica(zdev, &ap_msg, mex->outputdata, - mex->outputdatalength); - else { - /* Signal pending or message timed out. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); - if (rc == 0) - /* Message timed out. */ - rc = -ETIME; - } -out_free: - free_page((unsigned long) ap_msg.message); - return rc; -} - -/** - * The request distributor calls this function if it picked the PCIXCC/CEX2C - * device to handle a modexpo_crt request. - * @zdev: pointer to zcrypt_device structure that identifies the - * PCIXCC/CEX2C device to the request distributor - * @crt: pointer to the modexpoc_crt request buffer - */ -static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev, - struct ica_rsa_modexpo_crt *crt) -{ - struct ap_message ap_msg; - struct response_type resp_type = { - .type = PCIXCC_RESPONSE_TYPE_ICA, - }; - int rc; - - ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &resp_type; - rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt); - if (rc) - goto out_free; - init_completion(&resp_type.work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible_timeout( - &resp_type.work, PCIXCC_CLEANUP_TIME); - if (rc > 0) - rc = convert_response_ica(zdev, &ap_msg, crt->outputdata, - crt->outputdatalength); - else { - /* Signal pending or message timed out. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); - if (rc == 0) - /* Message timed out. */ - rc = -ETIME; - } -out_free: - free_page((unsigned long) ap_msg.message); - return rc; -} - -/** - * The request distributor calls this function if it picked the PCIXCC/CEX2C - * device to handle a send_cprb request. - * @zdev: pointer to zcrypt_device structure that identifies the - * PCIXCC/CEX2C device to the request distributor - * @xcRB: pointer to the send_cprb request buffer - */ -long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, struct ica_xcRB *xcRB) -{ - struct ap_message ap_msg; - struct response_type resp_type = { - .type = PCIXCC_RESPONSE_TYPE_XCRB, - }; - int rc; - - ap_msg.message = (void *) kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL); - if (!ap_msg.message) - return -ENOMEM; - ap_msg.psmid = (((unsigned long long) current->pid) << 32) + - atomic_inc_return(&zcrypt_step); - ap_msg.private = &resp_type; - rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB); - if (rc) - goto out_free; - init_completion(&resp_type.work); - ap_queue_message(zdev->ap_dev, &ap_msg); - rc = wait_for_completion_interruptible_timeout( - &resp_type.work, PCIXCC_CLEANUP_TIME); - if (rc > 0) - rc = convert_response_xcrb(zdev, &ap_msg, xcRB); - else { - /* Signal pending or message timed out. */ - ap_cancel_message(zdev->ap_dev, &ap_msg); - if (rc == 0) - /* Message timed out. */ - rc = -ETIME; - } -out_free: - memset(ap_msg.message, 0x0, ap_msg.length); - kfree(ap_msg.message); - return rc; -} - -/** - * The crypto operations for a PCIXCC/CEX2C card. - */ -static struct zcrypt_ops zcrypt_pcixcc_ops = { - .rsa_modexpo = zcrypt_pcixcc_modexpo, - .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt, - .send_cprb = zcrypt_pcixcc_send_cprb, -}; - -/** - * Micro-code detection function. Its sends a message to a pcixcc card - * to find out the microcode level. - * @ap_dev: pointer to the AP device. - */ -static int zcrypt_pcixcc_mcl(struct ap_device *ap_dev) -{ - static unsigned char msg[] = { - 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00, - 0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8, - 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x0A, - 0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20, - 0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05, - 0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D, - 0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55, - 0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD, - 0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA, - 0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22, - 0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB, - 0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54, - 0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00, - 0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00, - 0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40, - 0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C, - 0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF, - 0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9, - 0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63, - 0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5, - 0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A, - 0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01, - 0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28, - 0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91, - 0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5, - 0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C, - 0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98, - 0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96, - 0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19, - 0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47, - 0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36, - 0xF1,0x3D,0x93,0x53 - }; - unsigned long long psmid; - struct CPRBX *cprbx; - char *reply; - int rc, i; - - reply = (void *) get_zeroed_page(GFP_KERNEL); - if (!reply) - return -ENOMEM; - - rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, msg, sizeof(msg)); - if (rc) - goto out_free; - - /* Wait for the test message to complete. */ - for (i = 0; i < 6; i++) { - mdelay(300); - rc = ap_recv(ap_dev->qid, &psmid, reply, 4096); - if (rc == 0 && psmid == 0x0102030405060708ULL) - break; - } - - if (i >= 6) { - /* Got no answer. */ - rc = -ENODEV; - goto out_free; - } - - cprbx = (struct CPRBX *) (reply + 48); - if (cprbx->ccp_rtcode == 8 && cprbx->ccp_rscode == 33) - rc = ZCRYPT_PCIXCC_MCL2; - else - rc = ZCRYPT_PCIXCC_MCL3; -out_free: - free_page((unsigned long) reply); - return rc; -} - -/** - * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device - * since the bus_match already checked the hardware type. The PCIXCC - * cards come in two flavours: micro code level 2 and micro code level 3. - * This is checked by sending a test message to the device. - * @ap_dev: pointer to the AP device. - */ -static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) -{ - struct zcrypt_device *zdev; - int rc; - - zdev = zcrypt_device_alloc(PCIXCC_MAX_RESPONSE_SIZE); - if (!zdev) - return -ENOMEM; - zdev->ap_dev = ap_dev; - zdev->ops = &zcrypt_pcixcc_ops; - zdev->online = 1; - if (ap_dev->device_type == AP_DEVICE_TYPE_PCIXCC) { - rc = zcrypt_pcixcc_mcl(ap_dev); - if (rc < 0) { - zcrypt_device_free(zdev); - return rc; - } - zdev->user_space_type = rc; - if (rc == ZCRYPT_PCIXCC_MCL2) { - zdev->type_string = "PCIXCC_MCL2"; - zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING; - zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; - zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE; - } else { - zdev->type_string = "PCIXCC_MCL3"; - zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING; - zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE; - zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE; - } - } else { - zdev->user_space_type = ZCRYPT_CEX2C; - zdev->type_string = "CEX2C"; - zdev->speed_rating = CEX2C_SPEED_RATING; - zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE; - zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE; - } - ap_dev->reply = &zdev->reply; - ap_dev->private = zdev; - rc = zcrypt_device_register(zdev); - if (rc) - goto out_free; - return 0; - - out_free: - ap_dev->private = NULL; - zcrypt_device_free(zdev); - return rc; -} - -/** - * This is called to remove the extended PCIXCC/CEX2C driver information - * if an AP device is removed. - */ -static void zcrypt_pcixcc_remove(struct ap_device *ap_dev) -{ - struct zcrypt_device *zdev = ap_dev->private; - - zcrypt_device_unregister(zdev); -} - -int __init zcrypt_pcixcc_init(void) -{ - return ap_driver_register(&zcrypt_pcixcc_driver, THIS_MODULE, "pcixcc"); -} - -void zcrypt_pcixcc_exit(void) -{ - ap_driver_unregister(&zcrypt_pcixcc_driver); -} - -#ifndef CONFIG_ZCRYPT_MONOLITHIC -module_init(zcrypt_pcixcc_init); -module_exit(zcrypt_pcixcc_exit); -#endif diff --git a/trunk/drivers/s390/crypto/zcrypt_pcixcc.h b/trunk/drivers/s390/crypto/zcrypt_pcixcc.h deleted file mode 100644 index a78ff307fd19..000000000000 --- a/trunk/drivers/s390/crypto/zcrypt_pcixcc.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * linux/drivers/s390/crypto/zcrypt_pcixcc.h - * - * zcrypt 2.1.0 - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * Major cleanup & driver split: Martin Schwidefsky - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _ZCRYPT_PCIXCC_H_ -#define _ZCRYPT_PCIXCC_H_ - -/** - * CPRBX - * Note that all shorts and ints are big-endian. - * All pointer fields are 16 bytes long, and mean nothing. - * - * A request CPRB is followed by a request_parameter_block. - * - * The request (or reply) parameter block is organized thus: - * function code - * VUD block - * key block - */ -struct CPRBX { - unsigned short cprb_len; /* CPRB length 220 */ - unsigned char cprb_ver_id; /* CPRB version id. 0x02 */ - unsigned char pad_000[3]; /* Alignment pad bytes */ - unsigned char func_id[2]; /* function id 0x5432 */ - unsigned char cprb_flags[4]; /* Flags */ - unsigned int req_parml; /* request parameter buffer len */ - unsigned int req_datal; /* request data buffer */ - unsigned int rpl_msgbl; /* reply message block length */ - unsigned int rpld_parml; /* replied parameter block len */ - unsigned int rpl_datal; /* reply data block len */ - unsigned int rpld_datal; /* replied data block len */ - unsigned int req_extbl; /* request extension block len */ - unsigned char pad_001[4]; /* reserved */ - unsigned int rpld_extbl; /* replied extension block len */ - unsigned char req_parmb[16]; /* request parm block 'address' */ - unsigned char req_datab[16]; /* request data block 'address' */ - unsigned char rpl_parmb[16]; /* reply parm block 'address' */ - unsigned char rpl_datab[16]; /* reply data block 'address' */ - unsigned char req_extb[16]; /* request extension block 'addr'*/ - unsigned char rpl_extb[16]; /* reply extension block 'addres'*/ - unsigned short ccp_rtcode; /* server return code */ - unsigned short ccp_rscode; /* server reason code */ - unsigned int mac_data_len; /* Mac Data Length */ - unsigned char logon_id[8]; /* Logon Identifier */ - unsigned char mac_value[8]; /* Mac Value */ - unsigned char mac_content_flgs;/* Mac content flag byte */ - unsigned char pad_002; /* Alignment */ - unsigned short domain; /* Domain */ - unsigned char pad_003[12]; /* Domain masks */ - unsigned char pad_004[36]; /* reserved */ -} __attribute__((packed)); - -int zcrypt_pcixcc_init(void); -void zcrypt_pcixcc_exit(void); - -#endif /* _ZCRYPT_PCIXCC_H_ */ diff --git a/trunk/drivers/s390/net/Kconfig b/trunk/drivers/s390/net/Kconfig index 1a93fa684e9f..548854754921 100644 --- a/trunk/drivers/s390/net/Kconfig +++ b/trunk/drivers/s390/net/Kconfig @@ -92,6 +92,15 @@ config QETH_VLAN If CONFIG_QETH is switched on, this option will include IEEE 802.1q VLAN support in the qeth device driver. +config QETH_PERF_STATS + bool "Performance statistics in /proc" + depends on QETH + help + When switched on, this option will add a file in the proc-fs + (/proc/qeth_perf_stats) containing performance statistics. It + may slightly impact performance, so this is only recommended for + internal tuning of the device driver. + config CCWGROUP tristate default (LCS || CTC || QETH) diff --git a/trunk/drivers/s390/net/Makefile b/trunk/drivers/s390/net/Makefile index 4777e36a922f..6775a837d646 100644 --- a/trunk/drivers/s390/net/Makefile +++ b/trunk/drivers/s390/net/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_SMSGIUCV) += smsgiucv.o obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o obj-$(CONFIG_LCS) += lcs.o cu3088.o obj-$(CONFIG_CLAW) += claw.o cu3088.o +obj-$(CONFIG_MPC) += ctcmpc.o fsm.o cu3088.o qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o qeth-$(CONFIG_PROC_FS) += qeth_proc.o obj-$(CONFIG_QETH) += qeth.o diff --git a/trunk/drivers/s390/net/ctcmain.c b/trunk/drivers/s390/net/ctcmain.c index 3257c22dd79c..8a4b58120146 100644 --- a/trunk/drivers/s390/net/ctcmain.c +++ b/trunk/drivers/s390/net/ctcmain.c @@ -1714,9 +1714,6 @@ add_channel(struct ccw_device *cdev, enum channel_types type) kfree(ch); return 0; } - - spin_lock_init(&ch->collect_lock); - fsm_settimer(ch->fsm, &ch->timer); skb_queue_head_init(&ch->io_queue); skb_queue_head_init(&ch->collect_queue); diff --git a/trunk/drivers/s390/net/iucv.c b/trunk/drivers/s390/net/iucv.c index 821dde86e240..0e863df4027a 100644 --- a/trunk/drivers/s390/net/iucv.c +++ b/trunk/drivers/s390/net/iucv.c @@ -335,8 +335,8 @@ do { \ #else -#define iucv_debug(lvl, fmt, args...) do { } while (0) -#define iucv_dumpit(title, buf, len) do { } while (0) +#define iucv_debug(lvl, fmt, args...) +#define iucv_dumpit(title, buf, len) #endif diff --git a/trunk/drivers/s390/net/lcs.c b/trunk/drivers/s390/net/lcs.c index 16ac68c27a27..2eded55ae88d 100644 --- a/trunk/drivers/s390/net/lcs.c +++ b/trunk/drivers/s390/net/lcs.c @@ -670,8 +670,9 @@ lcs_ready_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) int index, rc; LCS_DBF_TEXT(5, trace, "rdybuff"); - BUG_ON(buffer->state != BUF_STATE_LOCKED && - buffer->state != BUF_STATE_PROCESSED); + if (buffer->state != BUF_STATE_LOCKED && + buffer->state != BUF_STATE_PROCESSED) + BUG(); spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); buffer->state = BUF_STATE_READY; index = buffer - channel->iob; @@ -695,7 +696,8 @@ __lcs_processed_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) int index, prev, next; LCS_DBF_TEXT(5, trace, "prcsbuff"); - BUG_ON(buffer->state != BUF_STATE_READY); + if (buffer->state != BUF_STATE_READY) + BUG(); buffer->state = BUF_STATE_PROCESSED; index = buffer - channel->iob; prev = (index - 1) & (LCS_NUM_BUFFS - 1); @@ -727,8 +729,9 @@ lcs_release_buffer(struct lcs_channel *channel, struct lcs_buffer *buffer) unsigned long flags; LCS_DBF_TEXT(5, trace, "relbuff"); - BUG_ON(buffer->state != BUF_STATE_LOCKED && - buffer->state != BUF_STATE_PROCESSED); + if (buffer->state != BUF_STATE_LOCKED && + buffer->state != BUF_STATE_PROCESSED) + BUG(); spin_lock_irqsave(get_ccwdev_lock(channel->ccwdev), flags); buffer->state = BUF_STATE_EMPTY; spin_unlock_irqrestore(get_ccwdev_lock(channel->ccwdev), flags); diff --git a/trunk/drivers/s390/net/netiucv.c b/trunk/drivers/s390/net/netiucv.c index d7d1cc0a5c8e..5d6e6cbfa360 100644 --- a/trunk/drivers/s390/net/netiucv.c +++ b/trunk/drivers/s390/net/netiucv.c @@ -112,12 +112,7 @@ struct iucv_connection { /** * Linked list of all connection structs. */ -struct iucv_connection_struct { - struct iucv_connection *iucv_connections; - rwlock_t iucv_rwlock; -}; - -static struct iucv_connection_struct iucv_conns; +static struct iucv_connection *iucv_connections; /** * Representation of event-data for the @@ -1373,10 +1368,8 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf, struct net_device *ndev = priv->conn->netdev; char *p; char *tmp; - char username[9]; + char username[10]; int i; - struct iucv_connection **clist = &iucv_conns.iucv_connections; - unsigned long flags; IUCV_DBF_TEXT(trace, 3, __FUNCTION__); if (count>9) { @@ -1389,7 +1382,7 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf, tmp = strsep((char **) &buf, "\n"); for (i=0, p=tmp; i<8 && *p; i++, p++) { if (isalnum(*p) || (*p == '$')) - username[i]= toupper(*p); + username[i]= *p; else if (*p == '\n') { /* trailing lf, grr */ break; @@ -1402,11 +1395,11 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf, return -EINVAL; } } - while (i<8) + while (i<9) username[i++] = ' '; - username[8] = '\0'; + username[9] = '\0'; - if (memcmp(username, priv->conn->userid, 9)) { + if (memcmp(username, priv->conn->userid, 8)) { /* username changed */ if (ndev->flags & (IFF_UP | IFF_RUNNING)) { PRINT_WARN( @@ -1417,19 +1410,6 @@ user_write (struct device *dev, struct device_attribute *attr, const char *buf, return -EBUSY; } } - read_lock_irqsave(&iucv_conns.iucv_rwlock, flags); - while (*clist) { - if (!strncmp(username, (*clist)->userid, 9) || - ((*clist)->netdev != ndev)) - break; - clist = &((*clist)->next); - } - read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); - if (*clist) { - PRINT_WARN("netiucv: Connection to %s already exists\n", - username); - return -EEXIST; - } memcpy(priv->conn->userid, username, 9); return count; @@ -1801,15 +1781,13 @@ netiucv_unregister_device(struct device *dev) static struct iucv_connection * netiucv_new_connection(struct net_device *dev, char *username) { - unsigned long flags; - struct iucv_connection **clist = &iucv_conns.iucv_connections; + struct iucv_connection **clist = &iucv_connections; struct iucv_connection *conn = kzalloc(sizeof(struct iucv_connection), GFP_KERNEL); if (conn) { skb_queue_head_init(&conn->collect_queue); skb_queue_head_init(&conn->commit_queue); - spin_lock_init(&conn->collect_lock); conn->max_buffsize = NETIUCV_BUFSIZE_DEFAULT; conn->netdev = dev; @@ -1844,10 +1822,8 @@ netiucv_new_connection(struct net_device *dev, char *username) fsm_newstate(conn->fsm, CONN_STATE_STOPPED); } - write_lock_irqsave(&iucv_conns.iucv_rwlock, flags); conn->next = *clist; *clist = conn; - write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); } return conn; } @@ -1859,17 +1835,14 @@ netiucv_new_connection(struct net_device *dev, char *username) static void netiucv_remove_connection(struct iucv_connection *conn) { - struct iucv_connection **clist = &iucv_conns.iucv_connections; - unsigned long flags; + struct iucv_connection **clist = &iucv_connections; IUCV_DBF_TEXT(trace, 3, __FUNCTION__); if (conn == NULL) return; - write_lock_irqsave(&iucv_conns.iucv_rwlock, flags); while (*clist) { if (*clist == conn) { *clist = conn->next; - write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); if (conn->handle) { iucv_unregister_program(conn->handle); conn->handle = NULL; @@ -1882,7 +1855,6 @@ netiucv_remove_connection(struct iucv_connection *conn) } clist = &((*clist)->next); } - write_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); } /** @@ -1975,11 +1947,9 @@ static ssize_t conn_write(struct device_driver *drv, const char *buf, size_t count) { char *p; - char username[9]; + char username[10]; int i, ret; struct net_device *dev; - struct iucv_connection **clist = &iucv_conns.iucv_connections; - unsigned long flags; IUCV_DBF_TEXT(trace, 3, __FUNCTION__); if (count>9) { @@ -1990,7 +1960,7 @@ conn_write(struct device_driver *drv, const char *buf, size_t count) for (i=0, p=(char *)buf; i<8 && *p; i++, p++) { if (isalnum(*p) || (*p == '$')) - username[i]= toupper(*p); + username[i]= *p; else if (*p == '\n') { /* trailing lf, grr */ break; @@ -2001,22 +1971,9 @@ conn_write(struct device_driver *drv, const char *buf, size_t count) return -EINVAL; } } - while (i<8) + while (i<9) username[i++] = ' '; - username[8] = '\0'; - - read_lock_irqsave(&iucv_conns.iucv_rwlock, flags); - while (*clist) { - if (!strncmp(username, (*clist)->userid, 9)) - break; - clist = &((*clist)->next); - } - read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); - if (*clist) { - PRINT_WARN("netiucv: Connection to %s already exists\n", - username); - return -EEXIST; - } + username[9] = '\0'; dev = netiucv_init_netdevice(username); if (!dev) { PRINT_WARN( @@ -2058,8 +2015,7 @@ DRIVER_ATTR(connection, 0200, NULL, conn_write); static ssize_t remove_write (struct device_driver *drv, const char *buf, size_t count) { - struct iucv_connection **clist = &iucv_conns.iucv_connections; - unsigned long flags; + struct iucv_connection **clist = &iucv_connections; struct net_device *ndev; struct netiucv_priv *priv; struct device *dev; @@ -2070,7 +2026,7 @@ remove_write (struct device_driver *drv, const char *buf, size_t count) IUCV_DBF_TEXT(trace, 3, __FUNCTION__); if (count >= IFNAMSIZ) - count = IFNAMSIZ - 1;; + count = IFNAMSIZ-1; for (i=0, p=(char *)buf; inetdev; priv = (struct netiucv_priv*)ndev->priv; @@ -2092,7 +2047,6 @@ remove_write (struct device_driver *drv, const char *buf, size_t count) clist = &((*clist)->next); continue; } - read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); if (ndev->flags & (IFF_UP | IFF_RUNNING)) { PRINT_WARN( "netiucv: net device %s active with peer %s\n", @@ -2106,7 +2060,6 @@ remove_write (struct device_driver *drv, const char *buf, size_t count) netiucv_unregister_device(dev); return count; } - read_unlock_irqrestore(&iucv_conns.iucv_rwlock, flags); PRINT_WARN("netiucv: net device %s unknown\n", name); IUCV_DBF_TEXT(data, 2, "remove_write: unknown device\n"); return -EINVAL; @@ -2124,8 +2077,8 @@ static void __exit netiucv_exit(void) { IUCV_DBF_TEXT(trace, 3, __FUNCTION__); - while (iucv_conns.iucv_connections) { - struct net_device *ndev = iucv_conns.iucv_connections->netdev; + while (iucv_connections) { + struct net_device *ndev = iucv_connections->netdev; struct netiucv_priv *priv = (struct netiucv_priv*)ndev->priv; struct device *dev = priv->dev; @@ -2167,7 +2120,6 @@ netiucv_init(void) if (!ret) { ret = driver_create_file(&netiucv_driver, &driver_attr_remove); netiucv_banner(); - rwlock_init(&iucv_conns.iucv_rwlock); } else { PRINT_ERR("NETIUCV: failed to add driver attribute.\n"); IUCV_DBF_TEXT_(setup, 2, "ret %d from driver_create_file\n", ret); diff --git a/trunk/drivers/s390/net/qeth.h b/trunk/drivers/s390/net/qeth.h index 821383d8cbe7..619f4a0c7160 100644 --- a/trunk/drivers/s390/net/qeth.h +++ b/trunk/drivers/s390/net/qeth.h @@ -176,6 +176,7 @@ extern struct ccwgroup_driver qeth_ccwgroup_driver; /** * card stuff */ +#ifdef CONFIG_QETH_PERF_STATS struct qeth_perf_stats { unsigned int bufs_rec; unsigned int bufs_sent; @@ -210,10 +211,8 @@ struct qeth_perf_stats { unsigned int large_send_cnt; unsigned int sg_skbs_sent; unsigned int sg_frags_sent; - /* initial values when measuring starts */ - unsigned long initial_rx_packets; - unsigned long initial_tx_packets; }; +#endif /* CONFIG_QETH_PERF_STATS */ /* Routing stuff */ struct qeth_routing_info { @@ -463,7 +462,6 @@ enum qeth_qdio_info_states { QETH_QDIO_UNINITIALIZED, QETH_QDIO_ALLOCATED, QETH_QDIO_ESTABLISHED, - QETH_QDIO_CLEANING }; struct qeth_buffer_pool_entry { @@ -538,7 +536,7 @@ struct qeth_qdio_out_q { } __attribute__ ((aligned(256))); struct qeth_qdio_info { - atomic_t state; + volatile enum qeth_qdio_info_states state; /* input */ struct qeth_qdio_q *in_q; struct qeth_qdio_buffer_pool in_buf_pool; @@ -769,7 +767,6 @@ struct qeth_card_options { int fake_ll; int layer2; enum qeth_large_send_types large_send; - int performance_stats; }; /* @@ -822,7 +819,9 @@ struct qeth_card { struct list_head cmd_waiter_list; /* QDIO buffer handling */ struct qeth_qdio_info qdio; +#ifdef CONFIG_QETH_PERF_STATS struct qeth_perf_stats perf_stats; +#endif /* CONFIG_QETH_PERF_STATS */ int use_hard_stop; int (*orig_hard_header)(struct sk_buff *,struct net_device *, unsigned short,void *,void *,unsigned); @@ -860,18 +859,23 @@ qeth_get_ipa_adp_type(enum qeth_link_types link_type) } } -static inline struct sk_buff * -qeth_realloc_headroom(struct qeth_card *card, struct sk_buff *skb, int size) +static inline int +qeth_realloc_headroom(struct qeth_card *card, struct sk_buff **skb, int size) { - struct sk_buff *new_skb = skb; - - if (skb_headroom(skb) >= size) - return skb; - new_skb = skb_realloc_headroom(skb, size); - if (!new_skb) - PRINT_ERR("Could not realloc headroom for qeth_hdr " - "on interface %s", QETH_CARD_IFNAME(card)); - return new_skb; + struct sk_buff *new_skb = NULL; + + if (skb_headroom(*skb) < size){ + new_skb = skb_realloc_headroom(*skb, size); + if (!new_skb) { + PRINT_ERR("qeth_prepare_skb: could " + "not realloc headroom for qeth_hdr " + "on interface %s", QETH_CARD_IFNAME(card)); + return -ENOMEM; + } + kfree_skb(*skb); + *skb = new_skb; + } + return 0; } static inline struct sk_buff * @@ -881,15 +885,16 @@ qeth_pskb_unshare(struct sk_buff *skb, int pri) if (!skb_cloned(skb)) return skb; nskb = skb_copy(skb, pri); + kfree_skb(skb); /* free our shared copy */ return nskb; } static inline void * -qeth_push_skb(struct qeth_card *card, struct sk_buff *skb, int size) +qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size) { void *hdr; - hdr = (void *) skb_push(skb, size); + hdr = (void *) skb_push(*skb, size); /* * sanity check, the Linux memory allocation scheme should * never present us cases like this one (the qdio header size plus @@ -898,7 +903,8 @@ qeth_push_skb(struct qeth_card *card, struct sk_buff *skb, int size) if ((((unsigned long) hdr) & (~(PAGE_SIZE - 1))) != (((unsigned long) hdr + size + QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) { - PRINT_ERR("Misaligned packet on interface %s. Discarded.", + PRINT_ERR("qeth_prepare_skb: misaligned " + "packet on interface %s. Discarded.", QETH_CARD_IFNAME(card)); return NULL; } @@ -1050,11 +1056,13 @@ qeth_get_arphdr_type(int cardtype, int linktype) } } +#ifdef CONFIG_QETH_PERF_STATS static inline int qeth_get_micros(void) { return (int) (get_clock() >> 12); } +#endif static inline int qeth_get_qdio_q_format(struct qeth_card *card) @@ -1088,11 +1096,10 @@ qeth_string_to_ipaddr4(const char *buf, __u8 *addr) { int count = 0, rc = 0; int in[4]; - char c; - rc = sscanf(buf, "%u.%u.%u.%u%c", - &in[0], &in[1], &in[2], &in[3], &c); - if (rc != 4 && (rc != 5 || c != '\n')) + rc = sscanf(buf, "%d.%d.%d.%d%n", + &in[0], &in[1], &in[2], &in[3], &count); + if (rc != 4 || count<=0) return -EINVAL; for (count = 0; count < 4; count++) { if (in[count] > 255) @@ -1116,28 +1123,24 @@ qeth_ipaddr6_to_string(const __u8 *addr, char *buf) static inline int qeth_string_to_ipaddr6(const char *buf, __u8 *addr) { - const char *end, *end_tmp, *start; + char *end, *start; __u16 *in; char num[5]; int num2, cnt, out, found, save_cnt; unsigned short in_tmp[8] = {0, }; cnt = out = found = save_cnt = num2 = 0; - end = start = buf; + end = start = (char *) buf; in = (__u16 *) addr; memset(in, 0, 16); - while (*end) { - end = strchr(start,':'); + while (end) { + end = strchr(end,':'); if (end == NULL) { - end = buf + strlen(buf); - if ((end_tmp = strchr(start, '\n')) != NULL) - end = end_tmp; - out = 1; + end = (char *)buf + (strlen(buf)); + out = 1; } if ((end - start)) { memset(num, 0, 5); - if ((end - start) > 4) - return -EINVAL; memcpy(num, start, end - start); if (!qeth_isxdigit(num)) return -EINVAL; @@ -1155,8 +1158,6 @@ qeth_string_to_ipaddr6(const char *buf, __u8 *addr) } start = ++end; } - if (cnt + save_cnt > 8) - return -EINVAL; cnt = 7; while (save_cnt) in[cnt--] = in_tmp[--save_cnt]; diff --git a/trunk/drivers/s390/net/qeth_eddp.c b/trunk/drivers/s390/net/qeth_eddp.c index a363721cf28d..8491598f9149 100644 --- a/trunk/drivers/s390/net/qeth_eddp.c +++ b/trunk/drivers/s390/net/qeth_eddp.c @@ -179,8 +179,9 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue, flush_cnt++; } } else { - if (queue->card->options.performance_stats) - queue->card->perf_stats.skbs_sent_pack++; +#ifdef CONFIG_QETH_PERF_STATS + queue->card->perf_stats.skbs_sent_pack++; +#endif QETH_DBF_TEXT(trace, 6, "fillbfpa"); if (buf->next_element_to_fill >= QETH_MAX_BUFFER_ELEMENTS(queue->card)) { diff --git a/trunk/drivers/s390/net/qeth_main.c b/trunk/drivers/s390/net/qeth_main.c index 5613b4564fa2..5fff1f93973a 100644 --- a/trunk/drivers/s390/net/qeth_main.c +++ b/trunk/drivers/s390/net/qeth_main.c @@ -1073,7 +1073,6 @@ qeth_set_intial_options(struct qeth_card *card) card->options.layer2 = 1; else card->options.layer2 = 0; - card->options.performance_stats = 1; } /** @@ -1709,7 +1708,6 @@ qeth_check_ipa_data(struct qeth_card *card, struct qeth_cmd_buffer *iob) "IP address reset.\n", QETH_CARD_IFNAME(card), card->info.chpid); - netif_carrier_on(card->dev); qeth_schedule_recovery(card); return NULL; case IPA_CMD_MODCCID: @@ -2466,6 +2464,24 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, qeth_rebuild_skb_fake_ll_eth(card, skb, hdr); } +static inline void +qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb, + struct qeth_hdr *hdr) +{ +#ifdef CONFIG_QETH_VLAN + u16 *vlan_tag; + + if (hdr->hdr.l3.ext_flags & + (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { + vlan_tag = (u16 *) skb_push(skb, VLAN_HLEN); + *vlan_tag = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)? + hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); + *(vlan_tag + 1) = skb->protocol; + skb->protocol = __constant_htons(ETH_P_8021Q); + } +#endif /* CONFIG_QETH_VLAN */ +} + static inline __u16 qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr) @@ -2494,16 +2510,15 @@ qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, return vlan_id; } -static inline __u16 +static inline void qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, struct qeth_hdr *hdr) { - unsigned short vlan_id = 0; #ifdef CONFIG_QETH_IPV6 if (hdr->hdr.l3.flags & QETH_HDR_PASSTHRU) { skb->pkt_type = PACKET_HOST; skb->protocol = qeth_type_trans(skb, card->dev); - return 0; + return; } #endif /* CONFIG_QETH_IPV6 */ skb->protocol = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 : @@ -2525,13 +2540,7 @@ qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, default: skb->pkt_type = PACKET_HOST; } - - if (hdr->hdr.l3.ext_flags & - (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { - vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)? - hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); - } - + qeth_rebuild_skb_vlan(card, skb, hdr); if (card->options.fake_ll) qeth_rebuild_skb_fake_ll(card, skb, hdr); else @@ -2547,7 +2556,6 @@ qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, else skb->ip_summed = SW_CHECKSUMMING; } - return vlan_id; } static inline void @@ -2560,20 +2568,20 @@ qeth_process_inbound_buffer(struct qeth_card *card, int offset; int rxrc; __u16 vlan_tag = 0; - __u16 *vlan_addr; /* get first element of current buffer */ element = (struct qdio_buffer_element *)&buf->buffer->element[0]; offset = 0; - if (card->options.performance_stats) - card->perf_stats.bufs_rec++; +#ifdef CONFIG_QETH_PERF_STATS + card->perf_stats.bufs_rec++; +#endif while((skb = qeth_get_next_skb(card, buf->buffer, &element, &offset, &hdr))) { skb->dev = card->dev; if (hdr->hdr.l2.id == QETH_HEADER_TYPE_LAYER2) vlan_tag = qeth_layer2_rebuild_skb(card, skb, hdr); else if (hdr->hdr.l3.id == QETH_HEADER_TYPE_LAYER3) - vlan_tag = qeth_rebuild_skb(card, skb, hdr); + qeth_rebuild_skb(card, skb, hdr); else { /*in case of OSN*/ skb_push(skb, sizeof(struct qeth_hdr)); memcpy(skb->data, hdr, sizeof(struct qeth_hdr)); @@ -2583,19 +2591,14 @@ qeth_process_inbound_buffer(struct qeth_card *card, dev_kfree_skb_any(skb); continue; } - if (card->info.type == QETH_CARD_TYPE_OSN) - rxrc = card->osn_info.data_cb(skb); - else #ifdef CONFIG_QETH_VLAN if (vlan_tag) - if (card->vlangrp) - vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag); - else { - dev_kfree_skb_any(skb); - continue; - } + vlan_hwaccel_rx(skb, card->vlangrp, vlan_tag); else #endif + if (card->info.type == QETH_CARD_TYPE_OSN) + rxrc = card->osn_info.data_cb(skb); + else rxrc = netif_rx(skb); card->dev->last_rx = jiffies; card->stats.rx_packets++; @@ -2623,7 +2626,7 @@ qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf) { struct qeth_buffer_pool_entry *pool_entry; int i; - + pool_entry = qeth_get_buffer_pool_entry(card); /* * since the buffer is accessed only from the input_tasklet @@ -2697,18 +2700,17 @@ qeth_queue_input_buffer(struct qeth_card *card, int index) * 'index') un-requeued -> this buffer is the first buffer that * will be requeued the next time */ - if (card->options.performance_stats) { - card->perf_stats.inbound_do_qdio_cnt++; - card->perf_stats.inbound_do_qdio_start_time = - qeth_get_micros(); - } +#ifdef CONFIG_QETH_PERF_STATS + card->perf_stats.inbound_do_qdio_cnt++; + card->perf_stats.inbound_do_qdio_start_time = qeth_get_micros(); +#endif rc = do_QDIO(CARD_DDEV(card), QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT, 0, queue->next_buf_to_init, count, NULL); - if (card->options.performance_stats) - card->perf_stats.inbound_do_qdio_time += - qeth_get_micros() - - card->perf_stats.inbound_do_qdio_start_time; +#ifdef CONFIG_QETH_PERF_STATS + card->perf_stats.inbound_do_qdio_time += qeth_get_micros() - + card->perf_stats.inbound_do_qdio_start_time; +#endif if (rc){ PRINT_WARN("qeth_queue_input_buffer's do_QDIO " "return %i (device %s).\n", @@ -2744,10 +2746,10 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, QETH_DBF_TEXT(trace, 6, "qdinput"); card = (struct qeth_card *) card_ptr; net_dev = card->dev; - if (card->options.performance_stats) { - card->perf_stats.inbound_cnt++; - card->perf_stats.inbound_start_time = qeth_get_micros(); - } +#ifdef CONFIG_QETH_PERF_STATS + card->perf_stats.inbound_cnt++; + card->perf_stats.inbound_start_time = qeth_get_micros(); +#endif if (status & QDIO_STATUS_LOOK_FOR_ERROR) { if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ QETH_DBF_TEXT(trace, 1,"qdinchk"); @@ -2769,9 +2771,10 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, qeth_put_buffer_pool_entry(card, buffer->pool_entry); qeth_queue_input_buffer(card, index); } - if (card->options.performance_stats) - card->perf_stats.inbound_time += qeth_get_micros() - - card->perf_stats.inbound_start_time; +#ifdef CONFIG_QETH_PERF_STATS + card->perf_stats.inbound_time += qeth_get_micros() - + card->perf_stats.inbound_start_time; +#endif } static inline int @@ -2861,11 +2864,10 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, } queue->card->dev->trans_start = jiffies; - if (queue->card->options.performance_stats) { - queue->card->perf_stats.outbound_do_qdio_cnt++; - queue->card->perf_stats.outbound_do_qdio_start_time = - qeth_get_micros(); - } +#ifdef CONFIG_QETH_PERF_STATS + queue->card->perf_stats.outbound_do_qdio_cnt++; + queue->card->perf_stats.outbound_do_qdio_start_time = qeth_get_micros(); +#endif if (under_int) rc = do_QDIO(CARD_DDEV(queue->card), QDIO_FLAG_SYNC_OUTPUT | QDIO_FLAG_UNDER_INTERRUPT, @@ -2873,10 +2875,10 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, else rc = do_QDIO(CARD_DDEV(queue->card), QDIO_FLAG_SYNC_OUTPUT, queue->queue_no, index, count, NULL); - if (queue->card->options.performance_stats) - queue->card->perf_stats.outbound_do_qdio_time += - qeth_get_micros() - - queue->card->perf_stats.outbound_do_qdio_start_time; +#ifdef CONFIG_QETH_PERF_STATS + queue->card->perf_stats.outbound_do_qdio_time += qeth_get_micros() - + queue->card->perf_stats.outbound_do_qdio_start_time; +#endif if (rc){ QETH_DBF_TEXT(trace, 2, "flushbuf"); QETH_DBF_TEXT_(trace, 2, " err%d", rc); @@ -2888,8 +2890,9 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, return; } atomic_add(count, &queue->used_buffers); - if (queue->card->options.performance_stats) - queue->card->perf_stats.bufs_sent += count; +#ifdef CONFIG_QETH_PERF_STATS + queue->card->perf_stats.bufs_sent += count; +#endif } /* @@ -2904,8 +2907,9 @@ qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue) >= QETH_HIGH_WATERMARK_PACK){ /* switch non-PACKING -> PACKING */ QETH_DBF_TEXT(trace, 6, "np->pack"); - if (queue->card->options.performance_stats) - queue->card->perf_stats.sc_dp_p++; +#ifdef CONFIG_QETH_PERF_STATS + queue->card->perf_stats.sc_dp_p++; +#endif queue->do_pack = 1; } } @@ -2928,8 +2932,9 @@ qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) <= QETH_LOW_WATERMARK_PACK) { /* switch PACKING -> non-PACKING */ QETH_DBF_TEXT(trace, 6, "pack->np"); - if (queue->card->options.performance_stats) - queue->card->perf_stats.sc_p_dp++; +#ifdef CONFIG_QETH_PERF_STATS + queue->card->perf_stats.sc_p_dp++; +#endif queue->do_pack = 0; /* flush packing buffers */ buffer = &queue->bufs[queue->next_buf_to_fill]; @@ -2941,7 +2946,7 @@ qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q; - } + } } } return flush_count; @@ -2997,10 +3002,11 @@ qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) !atomic_read(&queue->set_pci_flags_count)) flush_cnt += qeth_flush_buffers_on_no_pci(queue); - if (queue->card->options.performance_stats && - q_was_packing) +#ifdef CONFIG_QETH_PERF_STATS + if (q_was_packing) queue->card->perf_stats.bufs_sent_pack += flush_cnt; +#endif if (flush_cnt) qeth_flush_buffers(queue, 1, index, flush_cnt); atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); @@ -3030,11 +3036,10 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, return; } } - if (card->options.performance_stats) { - card->perf_stats.outbound_handler_cnt++; - card->perf_stats.outbound_handler_start_time = - qeth_get_micros(); - } +#ifdef CONFIG_QETH_PERF_STATS + card->perf_stats.outbound_handler_cnt++; + card->perf_stats.outbound_handler_start_time = qeth_get_micros(); +#endif for(i = first_element; i < (first_element + count); ++i){ buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; /*we only handle the KICK_IT error by doing a recovery */ @@ -3053,9 +3058,10 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, qeth_check_outbound_queue(queue); netif_wake_queue(queue->card->dev); - if (card->options.performance_stats) - card->perf_stats.outbound_handler_time += qeth_get_micros() - - card->perf_stats.outbound_handler_start_time; +#ifdef CONFIG_QETH_PERF_STATS + card->perf_stats.outbound_handler_time += qeth_get_micros() - + card->perf_stats.outbound_handler_start_time; +#endif } static void @@ -3179,14 +3185,13 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) QETH_DBF_TEXT(setup, 2, "allcqdbf"); - if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED, - QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED) + if (card->qdio.state == QETH_QDIO_ALLOCATED) return 0; card->qdio.in_q = kmalloc(sizeof(struct qeth_qdio_q), GFP_KERNEL|GFP_DMA); if (!card->qdio.in_q) - goto out_nomem; + return - ENOMEM; QETH_DBF_TEXT(setup, 2, "inq"); QETH_DBF_HEX(setup, 2, &card->qdio.in_q, sizeof(void *)); memset(card->qdio.in_q, 0, sizeof(struct qeth_qdio_q)); @@ -3195,19 +3200,27 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) card->qdio.in_q->bufs[i].buffer = &card->qdio.in_q->qdio_bufs[i]; /* inbound buffer pool */ - if (qeth_alloc_buffer_pool(card)) - goto out_freeinq; + if (qeth_alloc_buffer_pool(card)){ + kfree(card->qdio.in_q); + return -ENOMEM; + } /* outbound */ card->qdio.out_qs = kmalloc(card->qdio.no_out_queues * sizeof(struct qeth_qdio_out_q *), GFP_KERNEL); - if (!card->qdio.out_qs) - goto out_freepool; - for (i = 0; i < card->qdio.no_out_queues; ++i) { + if (!card->qdio.out_qs){ + qeth_free_buffer_pool(card); + return -ENOMEM; + } + for (i = 0; i < card->qdio.no_out_queues; ++i){ card->qdio.out_qs[i] = kmalloc(sizeof(struct qeth_qdio_out_q), GFP_KERNEL|GFP_DMA); - if (!card->qdio.out_qs[i]) - goto out_freeoutq; + if (!card->qdio.out_qs[i]){ + while (i > 0) + kfree(card->qdio.out_qs[--i]); + kfree(card->qdio.out_qs); + return -ENOMEM; + } QETH_DBF_TEXT_(setup, 2, "outq %i", i); QETH_DBF_HEX(setup, 2, &card->qdio.out_qs[i], sizeof(void *)); memset(card->qdio.out_qs[i], 0, sizeof(struct qeth_qdio_out_q)); @@ -3224,19 +3237,8 @@ qeth_alloc_qdio_buffers(struct qeth_card *card) INIT_LIST_HEAD(&card->qdio.out_qs[i]->bufs[j].ctx_list); } } + card->qdio.state = QETH_QDIO_ALLOCATED; return 0; - -out_freeoutq: - while (i > 0) - kfree(card->qdio.out_qs[--i]); - kfree(card->qdio.out_qs); -out_freepool: - qeth_free_buffer_pool(card); -out_freeinq: - kfree(card->qdio.in_q); -out_nomem: - atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED); - return -ENOMEM; } static void @@ -3245,8 +3247,7 @@ qeth_free_qdio_buffers(struct qeth_card *card) int i, j; QETH_DBF_TEXT(trace, 2, "freeqdbf"); - if (atomic_swap(&card->qdio.state, QETH_QDIO_UNINITIALIZED) == - QETH_QDIO_UNINITIALIZED) + if (card->qdio.state == QETH_QDIO_UNINITIALIZED) return; kfree(card->qdio.in_q); /* inbound buffer pool */ @@ -3259,6 +3260,7 @@ qeth_free_qdio_buffers(struct qeth_card *card) kfree(card->qdio.out_qs[i]); } kfree(card->qdio.out_qs); + card->qdio.state = QETH_QDIO_UNINITIALIZED; } static void @@ -3280,7 +3282,7 @@ static void qeth_init_qdio_info(struct qeth_card *card) { QETH_DBF_TEXT(setup, 4, "intqdinf"); - atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED); + card->qdio.state = QETH_QDIO_UNINITIALIZED; /* inbound */ card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT; card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT; @@ -3343,7 +3345,7 @@ qeth_qdio_establish(struct qeth_card *card) struct qdio_buffer **in_sbal_ptrs; struct qdio_buffer **out_sbal_ptrs; int i, j, k; - int rc = 0; + int rc; QETH_DBF_TEXT(setup, 2, "qdioest"); @@ -3402,10 +3404,8 @@ qeth_qdio_establish(struct qeth_card *card) init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; init_data.output_sbal_addr_array = (void **) out_sbal_ptrs; - if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED, - QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) - if ((rc = qdio_initialize(&init_data))) - atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); + if (!(rc = qdio_initialize(&init_data))) + card->qdio.state = QETH_QDIO_ESTABLISHED; kfree(out_sbal_ptrs); kfree(in_sbal_ptrs); @@ -3521,20 +3521,13 @@ qeth_qdio_clear_card(struct qeth_card *card, int use_halt) int rc = 0; QETH_DBF_TEXT(trace,3,"qdioclr"); - switch (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ESTABLISHED, - QETH_QDIO_CLEANING)) { - case QETH_QDIO_ESTABLISHED: + if (card->qdio.state == QETH_QDIO_ESTABLISHED){ if ((rc = qdio_cleanup(CARD_DDEV(card), - (card->info.type == QETH_CARD_TYPE_IQD) ? - QDIO_FLAG_CLEANUP_USING_HALT : - QDIO_FLAG_CLEANUP_USING_CLEAR))) + (card->info.type == QETH_CARD_TYPE_IQD) ? + QDIO_FLAG_CLEANUP_USING_HALT : + QDIO_FLAG_CLEANUP_USING_CLEAR))) QETH_DBF_TEXT_(trace, 3, "1err%d", rc); - atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); - break; - case QETH_QDIO_CLEANING: - return rc; - default: - break; + card->qdio.state = QETH_QDIO_ALLOCATED; } if ((rc = qeth_clear_halt_card(card, use_halt))) QETH_DBF_TEXT_(trace, 3, "2err%d", rc); @@ -3694,10 +3687,10 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) /* return OK; otherwise ksoftirqd goes to 100% */ return NETDEV_TX_OK; } - if (card->options.performance_stats) { - card->perf_stats.outbound_cnt++; - card->perf_stats.outbound_start_time = qeth_get_micros(); - } +#ifdef CONFIG_QETH_PERF_STATS + card->perf_stats.outbound_cnt++; + card->perf_stats.outbound_start_time = qeth_get_micros(); +#endif netif_stop_queue(dev); if ((rc = qeth_send_packet(card, skb))) { if (rc == -EBUSY) { @@ -3711,9 +3704,10 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } } netif_wake_queue(dev); - if (card->options.performance_stats) - card->perf_stats.outbound_time += qeth_get_micros() - - card->perf_stats.outbound_start_time; +#ifdef CONFIG_QETH_PERF_STATS + card->perf_stats.outbound_time += qeth_get_micros() - + card->perf_stats.outbound_start_time; +#endif return rc; } @@ -3928,59 +3922,49 @@ qeth_get_ip_version(struct sk_buff *skb) } } -static inline struct qeth_hdr * -__qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv) +static inline int +qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, + struct qeth_hdr **hdr, int ipv) { + int rc = 0; #ifdef CONFIG_QETH_VLAN u16 *tag; - if (card->vlangrp && vlan_tx_tag_present(skb) && +#endif + + QETH_DBF_TEXT(trace, 6, "prepskb"); + if (card->info.type == QETH_CARD_TYPE_OSN) { + *hdr = (struct qeth_hdr *)(*skb)->data; + return rc; + } + rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); + if (rc) + return rc; +#ifdef CONFIG_QETH_VLAN + if (card->vlangrp && vlan_tx_tag_present(*skb) && ((ipv == 6) || card->options.layer2) ) { /* * Move the mac addresses (6 bytes src, 6 bytes dest) * to the beginning of the new header. We are using three * memcpys instead of one memmove to save cycles. */ - skb_push(skb, VLAN_HLEN); - memcpy(skb->data, skb->data + 4, 4); - memcpy(skb->data + 4, skb->data + 8, 4); - memcpy(skb->data + 8, skb->data + 12, 4); - tag = (u16 *)(skb->data + 12); + skb_push(*skb, VLAN_HLEN); + memcpy((*skb)->data, (*skb)->data + 4, 4); + memcpy((*skb)->data + 4, (*skb)->data + 8, 4); + memcpy((*skb)->data + 8, (*skb)->data + 12, 4); + tag = (u16 *)((*skb)->data + 12); /* * first two bytes = ETH_P_8021Q (0x8100) * second two bytes = VLANID */ *tag = __constant_htons(ETH_P_8021Q); - *(tag + 1) = htons(vlan_tx_tag_get(skb)); + *(tag + 1) = htons(vlan_tx_tag_get(*skb)); } #endif - return ((struct qeth_hdr *) - qeth_push_skb(card, skb, sizeof(struct qeth_hdr))); -} - -static inline void -__qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb) -{ - if (orig_skb != new_skb) - dev_kfree_skb_any(new_skb); -} - -static inline struct sk_buff * -qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, - struct qeth_hdr **hdr, int ipv) -{ - struct sk_buff *new_skb; - - QETH_DBF_TEXT(trace, 6, "prepskb"); - - new_skb = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); - if (new_skb == NULL) - return NULL; - *hdr = __qeth_prepare_skb(card, new_skb, ipv); - if (*hdr == NULL) { - __qeth_free_new_skb(skb, new_skb); - return NULL; - } - return new_skb; + *hdr = (struct qeth_hdr *) + qeth_push_skb(card, skb, sizeof(struct qeth_hdr)); + if (*hdr == NULL) + return -EINVAL; + return 0; } static inline u8 @@ -4222,8 +4206,9 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue, flush_cnt = 1; } else { QETH_DBF_TEXT(trace, 6, "fillbfpa"); - if (queue->card->options.performance_stats) - queue->card->perf_stats.skbs_sent_pack++; +#ifdef CONFIG_QETH_PERF_STATS + queue->card->perf_stats.skbs_sent_pack++; +#endif if (buf->next_element_to_fill >= QETH_MAX_BUFFER_ELEMENTS(queue->card)) { /* @@ -4260,15 +4245,21 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, * check if buffer is empty to make sure that we do not 'overtake' * ourselves and try to fill a buffer that is already primed */ - if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) - goto out; + if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) { + card->stats.tx_dropped++; + atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); + return -EBUSY; + } if (ctx == NULL) queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q; else { buffers_needed = qeth_eddp_check_buffers_for_context(queue,ctx); - if (buffers_needed < 0) - goto out; + if (buffers_needed < 0) { + card->stats.tx_dropped++; + atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); + return -EBUSY; + } queue->next_buf_to_fill = (queue->next_buf_to_fill + buffers_needed) % QDIO_MAX_BUFFERS_PER_Q; @@ -4283,9 +4274,6 @@ qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, qeth_flush_buffers(queue, 0, index, flush_cnt); } return 0; -out: - atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); - return -EBUSY; } static inline int @@ -4311,7 +4299,8 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, * check if buffer is empty to make sure that we do not 'overtake' * ourselves and try to fill a buffer that is already primed */ - if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) { + if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){ + card->stats.tx_dropped++; atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); return -EBUSY; } @@ -4334,6 +4323,7 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, * again */ if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){ + card->stats.tx_dropped++; qeth_flush_buffers(queue, 0, start_index, flush_count); atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); return -EBUSY; @@ -4344,6 +4334,7 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, * free buffers) to handle eddp context */ if (qeth_eddp_check_buffers_for_context(queue,ctx) < 0){ printk("eddp tx_dropped 1\n"); + card->stats.tx_dropped++; rc = -EBUSY; goto out; } @@ -4355,6 +4346,7 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, tmp = qeth_eddp_fill_buffer(queue,ctx,queue->next_buf_to_fill); if (tmp < 0) { printk("eddp tx_dropped 2\n"); + card->stats.tx_dropped++; rc = - EBUSY; goto out; } @@ -4388,8 +4380,10 @@ qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, qeth_flush_buffers(queue, 0, start_index, flush_count); } /* at this point the queue is UNLOCKED again */ - if (queue->card->options.performance_stats && do_pack) +#ifdef CONFIG_QETH_PERF_STATS + if (do_pack) queue->card->perf_stats.bufs_sent_pack += flush_count; +#endif /* CONFIG_QETH_PERF_STATS */ return rc; } @@ -4400,21 +4394,21 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, { int elements_needed = 0; - if (skb_shinfo(skb)->nr_frags > 0) + if (skb_shinfo(skb)->nr_frags > 0) { elements_needed = (skb_shinfo(skb)->nr_frags + 1); - if (elements_needed == 0) + } + if (elements_needed == 0 ) elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) + skb->len) >> PAGE_SHIFT); if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){ - PRINT_ERR("Invalid size of IP packet " - "(Number=%d / Length=%d). Discarded.\n", + PRINT_ERR("qeth_do_send_packet: invalid size of " + "IP packet (Number=%d / Length=%d). Discarded.\n", (elements_needed+elems), skb->len); return 0; } return elements_needed; } - static inline int qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) { @@ -4426,112 +4420,112 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; struct qeth_eddp_context *ctx = NULL; int tx_bytes = skb->len; +#ifdef CONFIG_QETH_PERF_STATS unsigned short nr_frags = skb_shinfo(skb)->nr_frags; unsigned short tso_size = skb_shinfo(skb)->gso_size; - struct sk_buff *new_skb, *new_skb2; +#endif int rc; QETH_DBF_TEXT(trace, 6, "sendpkt"); - new_skb = skb; - if ((card->info.type == QETH_CARD_TYPE_OSN) && - (skb->protocol == htons(ETH_P_IPV6))) - return -EPERM; - cast_type = qeth_get_cast_type(card, skb); - if ((cast_type == RTN_BROADCAST) && - (card->info.broadcast_capable == 0)) - return -EPERM; - queue = card->qdio.out_qs - [qeth_get_priority_queue(card, skb, ipv, cast_type)]; if (!card->options.layer2) { ipv = qeth_get_ip_version(skb); if ((card->dev->hard_header == qeth_fake_header) && ipv) { - new_skb = qeth_pskb_unshare(skb, GFP_ATOMIC); - if (!new_skb) - return -ENOMEM; + if ((skb = qeth_pskb_unshare(skb,GFP_ATOMIC)) == NULL) { + card->stats.tx_dropped++; + dev_kfree_skb_irq(skb); + return 0; + } if(card->dev->type == ARPHRD_IEEE802_TR){ - skb_pull(new_skb, QETH_FAKE_LL_LEN_TR); + skb_pull(skb, QETH_FAKE_LL_LEN_TR); } else { - skb_pull(new_skb, QETH_FAKE_LL_LEN_ETH); + skb_pull(skb, QETH_FAKE_LL_LEN_ETH); } } } + if ((card->info.type == QETH_CARD_TYPE_OSN) && + (skb->protocol == htons(ETH_P_IPV6))) { + dev_kfree_skb_any(skb); + return 0; + } + cast_type = qeth_get_cast_type(card, skb); + if ((cast_type == RTN_BROADCAST) && + (card->info.broadcast_capable == 0)){ + card->stats.tx_dropped++; + card->stats.tx_errors++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + queue = card->qdio.out_qs + [qeth_get_priority_queue(card, skb, ipv, cast_type)]; + if (skb_is_gso(skb)) large_send = card->options.large_send; - /* check on OSN device*/ - if (card->info.type == QETH_CARD_TYPE_OSN) - hdr = (struct qeth_hdr *)new_skb->data; - /*are we able to do TSO ? */ + + /*are we able to do TSO ? If so ,prepare and send it from here */ if ((large_send == QETH_LARGE_SEND_TSO) && (cast_type == RTN_UNSPEC)) { - rc = qeth_tso_prepare_packet(card, new_skb, ipv, cast_type); + rc = qeth_tso_prepare_packet(card, skb, ipv, cast_type); if (rc) { - __qeth_free_new_skb(skb, new_skb); - return rc; + card->stats.tx_dropped++; + card->stats.tx_errors++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; } elements_needed++; - } else if (card->info.type != QETH_CARD_TYPE_OSN) { - new_skb2 = qeth_prepare_skb(card, new_skb, &hdr, ipv); - if (!new_skb2) { - __qeth_free_new_skb(skb, new_skb); - return -EINVAL; + } else { + if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))) { + QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc); + return rc; } - if (new_skb != skb) - __qeth_free_new_skb(new_skb2, new_skb); - new_skb = new_skb2; - qeth_fill_header(card, hdr, new_skb, ipv, cast_type); + if (card->info.type != QETH_CARD_TYPE_OSN) + qeth_fill_header(card, hdr, skb, ipv, cast_type); } + if (large_send == QETH_LARGE_SEND_EDDP) { - ctx = qeth_eddp_create_context(card, new_skb, hdr); + ctx = qeth_eddp_create_context(card, skb, hdr); if (ctx == NULL) { - __qeth_free_new_skb(skb, new_skb); PRINT_WARN("could not create eddp context\n"); return -EINVAL; } } else { - int elems = qeth_get_elements_no(card,(void*) hdr, new_skb, + int elems = qeth_get_elements_no(card,(void*) hdr, skb, elements_needed); - if (!elems) { - __qeth_free_new_skb(skb, new_skb); + if (!elems) return -EINVAL; - } elements_needed += elems; } if (card->info.type != QETH_CARD_TYPE_IQD) - rc = qeth_do_send_packet(card, queue, new_skb, hdr, + rc = qeth_do_send_packet(card, queue, skb, hdr, elements_needed, ctx); else - rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr, + rc = qeth_do_send_packet_fast(card, queue, skb, hdr, elements_needed, ctx); - if (!rc) { + if (!rc){ card->stats.tx_packets++; card->stats.tx_bytes += tx_bytes; - if (new_skb != skb) - dev_kfree_skb_any(skb); - if (card->options.performance_stats) { - if (tso_size && - !(large_send == QETH_LARGE_SEND_NO)) { - card->perf_stats.large_send_bytes += tx_bytes; - card->perf_stats.large_send_cnt++; - } - if (nr_frags > 0) { - card->perf_stats.sg_skbs_sent++; - /* nr_frags + skb->data */ - card->perf_stats.sg_frags_sent += - nr_frags + 1; - } +#ifdef CONFIG_QETH_PERF_STATS + if (tso_size && + !(large_send == QETH_LARGE_SEND_NO)) { + card->perf_stats.large_send_bytes += tx_bytes; + card->perf_stats.large_send_cnt++; } - } else { - card->stats.tx_dropped++; - __qeth_free_new_skb(skb, new_skb); + if (nr_frags > 0){ + card->perf_stats.sg_skbs_sent++; + /* nr_frags + skb->data */ + card->perf_stats.sg_frags_sent += + nr_frags + 1; + } +#endif /* CONFIG_QETH_PERF_STATS */ } if (ctx != NULL) { /* drop creator's reference */ qeth_eddp_put_context(ctx); /* free skb; it's not referenced by a buffer */ - if (!rc) - dev_kfree_skb_any(new_skb); + if (rc == 0) + dev_kfree_skb_any(skb); + } return rc; } @@ -7344,8 +7338,6 @@ qeth_setrouting_v6(struct qeth_card *card) QETH_DBF_TEXT(trace,3,"setrtg6"); #ifdef CONFIG_QETH_IPV6 - if (!qeth_is_supported(card, IPA_IPV6)) - return 0; qeth_correct_routing_type(card, &card->options.route6.type, QETH_PROT_IPV6); @@ -7884,12 +7876,12 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode) QETH_DBF_TEXT_(setup, 2, "5err%d", rc); goto out_remove; } + card->state = CARD_STATE_SOFTSETUP; if ((rc = qeth_init_qdio_queues(card))){ QETH_DBF_TEXT_(setup, 2, "6err%d", rc); goto out_remove; } - card->state = CARD_STATE_SOFTSETUP; netif_carrier_on(card->dev); qeth_set_allowed_threads(card, 0xffffffff, 0); @@ -8518,9 +8510,9 @@ static int qeth_ipv6_init(void) { qeth_old_arp_constructor = arp_tbl.constructor; - write_lock_bh(&arp_tbl.lock); + write_lock(&arp_tbl.lock); arp_tbl.constructor = qeth_arp_constructor; - write_unlock_bh(&arp_tbl.lock); + write_unlock(&arp_tbl.lock); arp_direct_ops = (struct neigh_ops*) kmalloc(sizeof(struct neigh_ops), GFP_KERNEL); @@ -8536,9 +8528,9 @@ qeth_ipv6_init(void) static void qeth_ipv6_uninit(void) { - write_lock_bh(&arp_tbl.lock); + write_lock(&arp_tbl.lock); arp_tbl.constructor = qeth_old_arp_constructor; - write_unlock_bh(&arp_tbl.lock); + write_unlock(&arp_tbl.lock); kfree(arp_direct_ops); } #endif /* CONFIG_QETH_IPV6 */ @@ -8546,44 +8538,34 @@ qeth_ipv6_uninit(void) static void qeth_sysfs_unregister(void) { - s390_root_dev_unregister(qeth_root_dev); qeth_remove_driver_attributes(); ccw_driver_unregister(&qeth_ccw_driver); ccwgroup_driver_unregister(&qeth_ccwgroup_driver); + s390_root_dev_unregister(qeth_root_dev); } - /** * register qeth at sysfs */ static int qeth_sysfs_register(void) { - int rc; + int rc=0; rc = ccwgroup_driver_register(&qeth_ccwgroup_driver); if (rc) - goto out; - + return rc; rc = ccw_driver_register(&qeth_ccw_driver); if (rc) - goto out_ccw_driver; - + return rc; rc = qeth_create_driver_attributes(); if (rc) - goto out_qeth_attr; - + return rc; qeth_root_dev = s390_root_dev_register("qeth"); - rc = IS_ERR(qeth_root_dev) ? PTR_ERR(qeth_root_dev) : 0; - if (!rc) - goto out; - - qeth_remove_driver_attributes(); -out_qeth_attr: - ccw_driver_unregister(&qeth_ccw_driver); -out_ccw_driver: - ccwgroup_driver_unregister(&qeth_ccwgroup_driver); -out: - return rc; + if (IS_ERR(qeth_root_dev)) { + rc = PTR_ERR(qeth_root_dev); + return rc; + } + return 0; } /*** @@ -8592,7 +8574,7 @@ qeth_sysfs_register(void) static int __init qeth_init(void) { - int rc; + int rc=0; PRINT_INFO("loading %s\n", version); @@ -8601,26 +8583,20 @@ qeth_init(void) spin_lock_init(&qeth_notify_lock); rwlock_init(&qeth_card_list.rwlock); - rc = qeth_register_dbf_views(); - if (rc) + if (qeth_register_dbf_views()) goto out_err; - - rc = qeth_sysfs_register(); - if (rc) - goto out_dbf; + if (qeth_sysfs_register()) + goto out_sysfs; #ifdef CONFIG_QETH_IPV6 - rc = qeth_ipv6_init(); - if (rc) { - PRINT_ERR("Out of memory during ipv6 init code = %d\n", rc); + if (qeth_ipv6_init()) { + PRINT_ERR("Out of memory during ipv6 init.\n"); goto out_sysfs; } #endif /* QETH_IPV6 */ - rc = qeth_register_notifiers(); - if (rc) + if (qeth_register_notifiers()) goto out_ipv6; - rc = qeth_create_procfs_entries(); - if (rc) + if (qeth_create_procfs_entries()) goto out_notifiers; return rc; @@ -8630,13 +8606,12 @@ qeth_init(void) out_ipv6: #ifdef CONFIG_QETH_IPV6 qeth_ipv6_uninit(); -out_sysfs: #endif /* QETH_IPV6 */ +out_sysfs: qeth_sysfs_unregister(); -out_dbf: qeth_unregister_dbf_views(); out_err: - PRINT_ERR("Initialization failed with code %d\n", rc); + PRINT_ERR("Initialization failed"); return rc; } diff --git a/trunk/drivers/s390/net/qeth_proc.c b/trunk/drivers/s390/net/qeth_proc.c index faa768e59257..66f2da14e6e3 100644 --- a/trunk/drivers/s390/net/qeth_proc.c +++ b/trunk/drivers/s390/net/qeth_proc.c @@ -173,6 +173,7 @@ static struct file_operations qeth_procfile_fops = { #define QETH_PERF_PROCFILE_NAME "qeth_perf" static struct proc_dir_entry *qeth_perf_procfile; +#ifdef CONFIG_QETH_PERF_STATS static int qeth_perf_procfile_seq_show(struct seq_file *s, void *it) { @@ -191,21 +192,14 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it) CARD_DDEV_ID(card), QETH_CARD_IFNAME(card) ); - if (!card->options.performance_stats) - seq_printf(s, "Performance statistics are deactivated.\n"); seq_printf(s, " Skb's/buffers received : %lu/%u\n" " Skb's/buffers sent : %lu/%u\n\n", - card->stats.rx_packets - - card->perf_stats.initial_rx_packets, - card->perf_stats.bufs_rec, - card->stats.tx_packets - - card->perf_stats.initial_tx_packets, - card->perf_stats.bufs_sent + card->stats.rx_packets, card->perf_stats.bufs_rec, + card->stats.tx_packets, card->perf_stats.bufs_sent ); seq_printf(s, " Skb's/buffers sent without packing : %lu/%u\n" " Skb's/buffers sent with packing : %u/%u\n\n", - card->stats.tx_packets - card->perf_stats.initial_tx_packets - - card->perf_stats.skbs_sent_pack, + card->stats.tx_packets - card->perf_stats.skbs_sent_pack, card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack, card->perf_stats.skbs_sent_pack, card->perf_stats.bufs_sent_pack @@ -281,6 +275,11 @@ static struct file_operations qeth_perf_procfile_fops = { .release = seq_release, }; +#define qeth_perf_procfile_created qeth_perf_procfile +#else +#define qeth_perf_procfile_created 1 +#endif /* CONFIG_QETH_PERF_STATS */ + int __init qeth_create_procfs_entries(void) { @@ -289,13 +288,15 @@ qeth_create_procfs_entries(void) if (qeth_procfile) qeth_procfile->proc_fops = &qeth_procfile_fops; +#ifdef CONFIG_QETH_PERF_STATS qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME, S_IFREG | 0444, NULL); if (qeth_perf_procfile) qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops; +#endif /* CONFIG_QETH_PERF_STATS */ if (qeth_procfile && - qeth_perf_procfile) + qeth_perf_procfile_created) return 0; else return -ENOMEM; diff --git a/trunk/drivers/s390/net/qeth_sys.c b/trunk/drivers/s390/net/qeth_sys.c index 5836737ac58f..001497bbea16 100644 --- a/trunk/drivers/s390/net/qeth_sys.c +++ b/trunk/drivers/s390/net/qeth_sys.c @@ -742,47 +742,6 @@ qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const c static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show, qeth_dev_layer2_store); -static ssize_t -qeth_dev_performance_stats_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct qeth_card *card = dev->driver_data; - - if (!card) - return -EINVAL; - - return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0); -} - -static ssize_t -qeth_dev_performance_stats_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct qeth_card *card = dev->driver_data; - char *tmp; - int i; - - if (!card) - return -EINVAL; - - i = simple_strtoul(buf, &tmp, 16); - if ((i == 0) || (i == 1)) { - if (i == card->options.performance_stats) - return count; - card->options.performance_stats = i; - if (i == 0) - memset(&card->perf_stats, 0, - sizeof(struct qeth_perf_stats)); - card->perf_stats.initial_rx_packets = card->stats.rx_packets; - card->perf_stats.initial_tx_packets = card->stats.tx_packets; - } else { - PRINT_WARN("performance_stats: write 0 or 1 to this file!\n"); - return -EINVAL; - } - return count; -} - -static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show, - qeth_dev_performance_stats_store); - static ssize_t qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -969,7 +928,6 @@ static struct device_attribute * qeth_device_attrs[] = { &dev_attr_canonical_macaddr, &dev_attr_layer2, &dev_attr_large_send, - &dev_attr_performance_stats, NULL, }; @@ -1152,12 +1110,12 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, { const char *start, *end; char *tmp; - char buffer[40] = {0, }; + char buffer[49] = {0, }; start = buf; /* get address string */ end = strchr(start, '/'); - if (!end || (end - start >= 40)){ + if (!end || (end-start >= 49)){ PRINT_WARN("Invalid format for ipato_addx/delx. " "Use /\n"); return -EINVAL; @@ -1169,12 +1127,7 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, } start = end + 1; *mask_bits = simple_strtoul(start, &tmp, 10); - if (!strlen(start) || - (tmp == start) || - (*mask_bits > ((proto == QETH_PROT_IPV4) ? 32 : 128))) { - PRINT_WARN("Invalid mask bits for ipato_addx/delx !\n"); - return -EINVAL; - } + return 0; } @@ -1745,16 +1698,11 @@ qeth_create_device_attributes(struct device *dev) sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group); sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group); - return ret; } - if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group))){ - sysfs_remove_group(&dev->kobj, &qeth_device_attr_group); - sysfs_remove_group(&dev->kobj, &qeth_device_ipato_group); - sysfs_remove_group(&dev->kobj, &qeth_device_vipa_group); - sysfs_remove_group(&dev->kobj, &qeth_device_rxip_group); + if ((ret = sysfs_create_group(&dev->kobj, &qeth_device_blkt_group))) return ret; - } - return 0; + + return ret; } void diff --git a/trunk/drivers/s390/net/qeth_tso.h b/trunk/drivers/s390/net/qeth_tso.h index 14504afb044e..593f298142c1 100644 --- a/trunk/drivers/s390/net/qeth_tso.h +++ b/trunk/drivers/s390/net/qeth_tso.h @@ -24,7 +24,7 @@ static inline struct qeth_hdr_tso * qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb) { QETH_DBF_TEXT(trace, 5, "tsoprsk"); - return qeth_push_skb(card, *skb, sizeof(struct qeth_hdr_tso)); + return qeth_push_skb(card, skb, sizeof(struct qeth_hdr_tso)); } /** diff --git a/trunk/drivers/s390/s390mach.c b/trunk/drivers/s390/s390mach.c index a914129a4da9..5399c5d99b81 100644 --- a/trunk/drivers/s390/s390mach.c +++ b/trunk/drivers/s390/s390mach.c @@ -19,6 +19,9 @@ #include "s390mach.h" +#define DBG printk +// #define DBG(args,...) do {} while (0); + static struct semaphore m_sem; extern int css_process_crw(int, int); @@ -80,11 +83,11 @@ s390_collect_crw_info(void *param) ccode = stcrw(&crw[chain]); if (ccode != 0) break; - printk(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, " - "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", - crw[chain].slct, crw[chain].oflw, crw[chain].chn, - crw[chain].rsc, crw[chain].anc, crw[chain].erc, - crw[chain].rsid); + DBG(KERN_DEBUG "crw_info : CRW reports slct=%d, oflw=%d, " + "chn=%d, rsc=%X, anc=%d, erc=%X, rsid=%X\n", + crw[chain].slct, crw[chain].oflw, crw[chain].chn, + crw[chain].rsc, crw[chain].anc, crw[chain].erc, + crw[chain].rsid); /* Check for overflows. */ if (crw[chain].oflw) { pr_debug("%s: crw overflow detected!\n", __FUNCTION__); @@ -114,8 +117,8 @@ s390_collect_crw_info(void *param) * reported to the common I/O layer. */ if (crw[chain].slct) { - pr_debug("solicited machine check for " - "channel path %02X\n", crw[0].rsid); + DBG(KERN_INFO"solicited machine check for " + "channel path %02X\n", crw[0].rsid); break; } switch (crw[0].erc) { diff --git a/trunk/drivers/s390/scsi/zfcp_aux.c b/trunk/drivers/s390/scsi/zfcp_aux.c index adc9d8f2c28f..9cd789b8acd4 100644 --- a/trunk/drivers/s390/scsi/zfcp_aux.c +++ b/trunk/drivers/s390/scsi/zfcp_aux.c @@ -112,105 +112,6 @@ _zfcp_hex_dump(char *addr, int count) printk("\n"); } - -/****************************************************************/ -/****** Functions to handle the request ID hash table ********/ -/****************************************************************/ - -#define ZFCP_LOG_AREA ZFCP_LOG_AREA_FSF - -static int zfcp_reqlist_init(struct zfcp_adapter *adapter) -{ - int i; - - adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head), - GFP_KERNEL); - - if (!adapter->req_list) - return -ENOMEM; - - for (i=0; ireq_list[i]); - - return 0; -} - -static void zfcp_reqlist_free(struct zfcp_adapter *adapter) -{ - struct zfcp_fsf_req *request, *tmp; - unsigned int i; - - for (i=0; ireq_list[i])) - continue; - - list_for_each_entry_safe(request, tmp, - &adapter->req_list[i], list) - list_del(&request->list); - } - - kfree(adapter->req_list); -} - -void zfcp_reqlist_add(struct zfcp_adapter *adapter, - struct zfcp_fsf_req *fsf_req) -{ - unsigned int i; - - i = fsf_req->req_id % REQUEST_LIST_SIZE; - list_add_tail(&fsf_req->list, &adapter->req_list[i]); -} - -void zfcp_reqlist_remove(struct zfcp_adapter *adapter, unsigned long req_id) -{ - struct zfcp_fsf_req *request, *tmp; - unsigned int i, counter; - u64 dbg_tmp[2]; - - i = req_id % REQUEST_LIST_SIZE; - BUG_ON(list_empty(&adapter->req_list[i])); - - counter = 0; - list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list) { - if (request->req_id == req_id) { - dbg_tmp[0] = (u64) atomic_read(&adapter->reqs_active); - dbg_tmp[1] = (u64) counter; - debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16); - list_del(&request->list); - break; - } - counter++; - } -} - -struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *adapter, - unsigned long req_id) -{ - struct zfcp_fsf_req *request, *tmp; - unsigned int i; - - i = req_id % REQUEST_LIST_SIZE; - - list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list) - if (request->req_id == req_id) - return request; - - return NULL; -} - -int zfcp_reqlist_isempty(struct zfcp_adapter *adapter) -{ - unsigned int i; - - for (i=0; ireq_list[i])) - return 0; - - return 1; -} - -#undef ZFCP_LOG_AREA - /****************************************************************/ /************** Uncategorised Functions *************************/ /****************************************************************/ @@ -1060,12 +961,8 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) INIT_LIST_HEAD(&adapter->port_remove_lh); /* initialize list of fsf requests */ - spin_lock_init(&adapter->req_list_lock); - retval = zfcp_reqlist_init(adapter); - if (retval) { - ZFCP_LOG_INFO("request list initialization failed\n"); - goto failed_low_mem_buffers; - } + spin_lock_init(&adapter->fsf_req_list_lock); + INIT_LIST_HEAD(&adapter->fsf_req_list_head); /* initialize debug locks */ @@ -1144,6 +1041,8 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) * !0 - struct zfcp_adapter data structure could not be removed * (e.g. still used) * locks: adapter list write lock is assumed to be held by caller + * adapter->fsf_req_list_lock is taken and released within this + * function and must not be held on entry */ void zfcp_adapter_dequeue(struct zfcp_adapter *adapter) @@ -1155,14 +1054,14 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); dev_set_drvdata(&adapter->ccw_device->dev, NULL); /* sanity check: no pending FSF requests */ - spin_lock_irqsave(&adapter->req_list_lock, flags); - retval = zfcp_reqlist_isempty(adapter); - spin_unlock_irqrestore(&adapter->req_list_lock, flags); - if (!retval) { + spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); + retval = !list_empty(&adapter->fsf_req_list_head); + spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); + if (retval) { ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, " "%i requests outstanding\n", zfcp_get_busid_by_adapter(adapter), adapter, - atomic_read(&adapter->reqs_active)); + atomic_read(&adapter->fsf_reqs_active)); retval = -EBUSY; goto out; } @@ -1188,7 +1087,6 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) zfcp_free_low_mem_buffers(adapter); /* free memory of adapter data structure and queues */ zfcp_qdio_free_queues(adapter); - zfcp_reqlist_free(adapter); kfree(adapter->fc_stats); kfree(adapter->stats_reset_data); ZFCP_LOG_TRACE("freeing adapter structure\n"); diff --git a/trunk/drivers/s390/scsi/zfcp_ccw.c b/trunk/drivers/s390/scsi/zfcp_ccw.c index fdabadeaa9ee..57d8e4bfb8d9 100644 --- a/trunk/drivers/s390/scsi/zfcp_ccw.c +++ b/trunk/drivers/s390/scsi/zfcp_ccw.c @@ -164,11 +164,6 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device) retval = zfcp_adapter_scsi_register(adapter); if (retval) goto out_scsi_register; - - /* initialize request counter */ - BUG_ON(!zfcp_reqlist_isempty(adapter)); - adapter->req_no = 0; - zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED); diff --git a/trunk/drivers/s390/scsi/zfcp_def.h b/trunk/drivers/s390/scsi/zfcp_def.h index 7c84b3d4bd94..2df512a18e2c 100644 --- a/trunk/drivers/s390/scsi/zfcp_def.h +++ b/trunk/drivers/s390/scsi/zfcp_def.h @@ -52,7 +52,7 @@ /********************* GENERAL DEFINES *********************************/ /* zfcp version number, it consists of major, minor, and patch-level number */ -#define ZFCP_VERSION "4.8.0" +#define ZFCP_VERSION "4.7.0" /** * zfcp_sg_to_address - determine kernel address from struct scatterlist @@ -80,7 +80,7 @@ zfcp_address_to_sg(void *address, struct scatterlist *list) #define REQUEST_LIST_SIZE 128 /********************* SCSI SPECIFIC DEFINES *********************************/ -#define ZFCP_SCSI_ER_TIMEOUT (10*HZ) +#define ZFCP_SCSI_ER_TIMEOUT (100*HZ) /********************* CIO/QDIO SPECIFIC DEFINES *****************************/ @@ -543,7 +543,7 @@ do { \ } while (0) #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_NORMAL -# define ZFCP_LOG_NORMAL(fmt, args...) do { } while (0) +# define ZFCP_LOG_NORMAL(fmt, args...) #else # define ZFCP_LOG_NORMAL(fmt, args...) \ do { \ @@ -553,7 +553,7 @@ do { \ #endif #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_INFO -# define ZFCP_LOG_INFO(fmt, args...) do { } while (0) +# define ZFCP_LOG_INFO(fmt, args...) #else # define ZFCP_LOG_INFO(fmt, args...) \ do { \ @@ -563,14 +563,14 @@ do { \ #endif #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_DEBUG -# define ZFCP_LOG_DEBUG(fmt, args...) do { } while (0) +# define ZFCP_LOG_DEBUG(fmt, args...) #else # define ZFCP_LOG_DEBUG(fmt, args...) \ ZFCP_LOG(ZFCP_LOG_LEVEL_DEBUG, fmt , ##args) #endif #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_TRACE -# define ZFCP_LOG_TRACE(fmt, args...) do { } while (0) +# define ZFCP_LOG_TRACE(fmt, args...) #else # define ZFCP_LOG_TRACE(fmt, args...) \ ZFCP_LOG(ZFCP_LOG_LEVEL_TRACE, fmt , ##args) @@ -886,11 +886,11 @@ struct zfcp_adapter { struct list_head port_remove_lh; /* head of ports to be removed */ u32 ports; /* number of remote ports */ - struct timer_list scsi_er_timer; /* SCSI err recovery watch */ - atomic_t reqs_active; /* # active FSF reqs */ - unsigned long req_no; /* unique FSF req number */ - struct list_head *req_list; /* list of pending reqs */ - spinlock_t req_list_lock; /* request list lock */ + struct timer_list scsi_er_timer; /* SCSI err recovery watch */ + struct list_head fsf_req_list_head; /* head of FSF req list */ + spinlock_t fsf_req_list_lock; /* lock for ops on list of + FSF requests */ + atomic_t fsf_reqs_active; /* # active FSF reqs */ struct zfcp_qdio_queue request_queue; /* request queue */ u32 fsf_req_seq_no; /* FSF cmnd seq number */ wait_queue_head_t request_wq; /* can be used to wait for @@ -986,7 +986,6 @@ struct zfcp_unit { /* FSF request */ struct zfcp_fsf_req { struct list_head list; /* list of FSF requests */ - unsigned long req_id; /* unique request ID */ struct zfcp_adapter *adapter; /* adapter request belongs to */ u8 sbal_number; /* nr of SBALs free for use */ u8 sbal_first; /* first SBAL for this request */ diff --git a/trunk/drivers/s390/scsi/zfcp_erp.c b/trunk/drivers/s390/scsi/zfcp_erp.c index 7f60b6fdf724..8ec8da0beaa8 100644 --- a/trunk/drivers/s390/scsi/zfcp_erp.c +++ b/trunk/drivers/s390/scsi/zfcp_erp.c @@ -64,8 +64,8 @@ static int zfcp_erp_strategy_check_action(struct zfcp_erp_action *, int); static int zfcp_erp_adapter_strategy(struct zfcp_erp_action *); static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *, int); static int zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *); -static void zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *); -static void zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *); +static int zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *); +static int zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *); static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *); static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *); static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *); @@ -93,9 +93,10 @@ static int zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *); static int zfcp_erp_unit_strategy_close(struct zfcp_erp_action *); static int zfcp_erp_unit_strategy_open(struct zfcp_erp_action *); -static void zfcp_erp_action_dismiss_port(struct zfcp_port *); -static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *); -static void zfcp_erp_action_dismiss(struct zfcp_erp_action *); +static int zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *); +static int zfcp_erp_action_dismiss_port(struct zfcp_port *); +static int zfcp_erp_action_dismiss_unit(struct zfcp_unit *); +static int zfcp_erp_action_dismiss(struct zfcp_erp_action *); static int zfcp_erp_action_enqueue(int, struct zfcp_adapter *, struct zfcp_port *, struct zfcp_unit *); @@ -134,39 +135,29 @@ zfcp_fsf_request_timeout_handler(unsigned long data) zfcp_erp_adapter_reopen(adapter, 0); } -/** - * zfcp_fsf_scsi_er_timeout_handler - timeout handler for scsi eh tasks - * - * This function needs to be called whenever a SCSI error recovery - * action (abort/reset) does not return. Re-opening the adapter means - * that the abort/reset command can be returned by zfcp. It won't complete - * via the adapter anymore (because qdio queues are closed). If ERP is - * already running on this adapter it will be stopped. +/* + * function: zfcp_fsf_scsi_er_timeout_handler + * + * purpose: This function needs to be called whenever a SCSI error recovery + * action (abort/reset) does not return. + * Re-opening the adapter means that the command can be returned + * by zfcp (it is guarranteed that it does not return via the + * adapter anymore). The buffer can then be used again. + * + * returns: sod all */ -void zfcp_fsf_scsi_er_timeout_handler(unsigned long data) +void +zfcp_fsf_scsi_er_timeout_handler(unsigned long data) { struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; - unsigned long flags; ZFCP_LOG_NORMAL("warning: SCSI error recovery timed out. " "Restarting all operations on the adapter %s\n", zfcp_get_busid_by_adapter(adapter)); debug_text_event(adapter->erp_dbf, 1, "eh_lmem_tout"); - - write_lock_irqsave(&adapter->erp_lock, flags); - if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, - &adapter->status)) { - zfcp_erp_modify_adapter_status(adapter, - ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN, - ZFCP_CLEAR); - zfcp_erp_action_dismiss_adapter(adapter); - write_unlock_irqrestore(&adapter->erp_lock, flags); - /* dismiss all pending requests including requests for ERP */ - zfcp_fsf_req_dismiss_all(adapter); - adapter->fsf_req_seq_no = 0; - } else - write_unlock_irqrestore(&adapter->erp_lock, flags); zfcp_erp_adapter_reopen(adapter, 0); + + return; } /* @@ -679,10 +670,17 @@ zfcp_erp_unit_reopen(struct zfcp_unit *unit, int clear_mask) return retval; } -/** - * zfcp_erp_adapter_block - mark adapter as blocked, block scsi requests +/* + * function: + * + * purpose: disable I/O, + * return any open requests and clean them up, + * aim: no pending and incoming I/O + * + * returns: */ -static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask) +static void +zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask) { debug_text_event(adapter->erp_dbf, 6, "a_bl"); zfcp_erp_modify_adapter_status(adapter, @@ -690,10 +688,15 @@ static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int clear_mask) clear_mask, ZFCP_CLEAR); } -/** - * zfcp_erp_adapter_unblock - mark adapter as unblocked, allow scsi requests +/* + * function: + * + * purpose: enable I/O + * + * returns: */ -static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) +static void +zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) { debug_text_event(adapter->erp_dbf, 6, "a_ubl"); atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status); @@ -845,16 +848,18 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) struct zfcp_adapter *adapter = erp_action->adapter; if (erp_action->fsf_req) { - /* take lock to ensure that request is not deleted meanwhile */ - spin_lock(&adapter->req_list_lock); - if ((!zfcp_reqlist_ismember(adapter, - erp_action->fsf_req->req_id)) && - (fsf_req->erp_action == erp_action)) { + /* take lock to ensure that request is not being deleted meanwhile */ + spin_lock(&adapter->fsf_req_list_lock); + /* check whether fsf req does still exist */ + list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list) + if (fsf_req == erp_action->fsf_req) + break; + if (fsf_req && (fsf_req->erp_action == erp_action)) { /* fsf_req still exists */ debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); debug_event(adapter->erp_dbf, 3, &fsf_req, sizeof (unsigned long)); - /* dismiss fsf_req of timed out/dismissed erp_action */ + /* dismiss fsf_req of timed out or dismissed erp_action */ if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED | ZFCP_STATUS_ERP_TIMEDOUT)) { debug_text_event(adapter->erp_dbf, 3, @@ -887,22 +892,30 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) */ erp_action->fsf_req = NULL; } - spin_unlock(&adapter->req_list_lock); + spin_unlock(&adapter->fsf_req_list_lock); } else debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq"); return retval; } -/** - * zfcp_erp_async_handler_nolock - complete erp_action +/* + * purpose: generic handler for asynchronous events related to erp_action events + * (normal completion, time-out, dismissing, retry after + * low memory condition) + * + * note: deletion of timer is not required (e.g. in case of a time-out), + * but a second try does no harm, + * we leave it in here to allow for greater simplification * - * Used for normal completion, time-out, dismissal and failure after - * low memory condition. + * returns: 0 - there was an action to handle + * !0 - otherwise */ -static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action, - unsigned long set_mask) +static int +zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action, + unsigned long set_mask) { + int retval; struct zfcp_adapter *adapter = erp_action->adapter; if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) { @@ -913,26 +926,43 @@ static void zfcp_erp_async_handler_nolock(struct zfcp_erp_action *erp_action, del_timer(&erp_action->timer); erp_action->status |= set_mask; zfcp_erp_action_ready(erp_action); + retval = 0; } else { /* action is ready or gone - nothing to do */ debug_text_event(adapter->erp_dbf, 3, "a_asyh_gone"); debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int)); + retval = 1; } + + return retval; } -/** - * zfcp_erp_async_handler - wrapper for erp_async_handler_nolock w/ locking +/* + * purpose: generic handler for asynchronous events related to erp_action + * events (normal completion, time-out, dismissing, retry after + * low memory condition) + * + * note: deletion of timer is not required (e.g. in case of a time-out), + * but a second try does no harm, + * we leave it in here to allow for greater simplification + * + * returns: 0 - there was an action to handle + * !0 - otherwise */ -void zfcp_erp_async_handler(struct zfcp_erp_action *erp_action, - unsigned long set_mask) +int +zfcp_erp_async_handler(struct zfcp_erp_action *erp_action, + unsigned long set_mask) { struct zfcp_adapter *adapter = erp_action->adapter; unsigned long flags; + int retval; write_lock_irqsave(&adapter->erp_lock, flags); - zfcp_erp_async_handler_nolock(erp_action, set_mask); + retval = zfcp_erp_async_handler_nolock(erp_action, set_mask); write_unlock_irqrestore(&adapter->erp_lock, flags); + + return retval; } /* @@ -969,15 +999,17 @@ zfcp_erp_timeout_handler(unsigned long data) zfcp_erp_async_handler(erp_action, ZFCP_STATUS_ERP_TIMEDOUT); } -/** - * zfcp_erp_action_dismiss - dismiss an erp_action +/* + * purpose: is called for an erp_action which needs to be ended + * though not being done, + * this is usually required if an higher is generated, + * action gets an appropriate flag and will be processed + * accordingly * - * adapter->erp_lock must be held - * - * Dismissal of an erp_action is usually required if an erp_action of - * higher priority is generated. + * locks: erp_lock held (thus we need to call another handler variant) */ -static void zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action) +static int +zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action) { struct zfcp_adapter *adapter = erp_action->adapter; @@ -985,6 +1017,8 @@ static void zfcp_erp_action_dismiss(struct zfcp_erp_action *erp_action) debug_event(adapter->erp_dbf, 2, &erp_action->action, sizeof (int)); zfcp_erp_async_handler_nolock(erp_action, ZFCP_STATUS_ERP_DISMISSED); + + return 0; } int @@ -2040,12 +2074,18 @@ zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) return retval; } -/** - * zfcp_erp_adapter_strategy_close_qdio - close qdio queues for an adapter +/* + * function: zfcp_qdio_cleanup + * + * purpose: cleans up QDIO operation for the specified adapter + * + * returns: 0 - successful cleanup + * !0 - failed cleanup */ -static void +int zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) { + int retval = ZFCP_ERP_SUCCEEDED; int first_used; int used_count; struct zfcp_adapter *adapter = erp_action->adapter; @@ -2054,13 +2094,15 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) ZFCP_LOG_DEBUG("error: attempt to shut down inactive QDIO " "queues on adapter %s\n", zfcp_get_busid_by_adapter(adapter)); - return; + retval = ZFCP_ERP_FAILED; + goto out; } /* * Get queue_lock and clear QDIOUP flag. Thus it's guaranteed that * do_QDIO won't be called while qdio_shutdown is in progress. */ + write_lock_irq(&adapter->request_queue.queue_lock); atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status); write_unlock_irq(&adapter->request_queue.queue_lock); @@ -2092,6 +2134,8 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) adapter->request_queue.free_index = 0; atomic_set(&adapter->request_queue.free_count, 0); adapter->request_queue.distance_from_int = 0; + out: + return retval; } static int @@ -2214,11 +2258,11 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) "%s)\n", zfcp_get_busid_by_adapter(adapter)); ret = ZFCP_ERP_FAILED; } - - /* don't treat as error for the sake of compatibility */ - if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) - ZFCP_LOG_INFO("warning: exchange port data failed (adapter " + if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status)) { + ZFCP_LOG_INFO("error: exchange port data failed (adapter " "%s\n", zfcp_get_busid_by_adapter(adapter)); + ret = ZFCP_ERP_FAILED; + } return ret; } @@ -2248,12 +2292,18 @@ zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action return retval; } -/** - * zfcp_erp_adapter_strategy_close_fsf - stop FSF operations for an adapter +/* + * function: zfcp_fsf_cleanup + * + * purpose: cleanup FSF operation for specified adapter + * + * returns: 0 - FSF operation successfully cleaned up + * !0 - failed to cleanup FSF operation for this adapter */ -static void +static int zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *erp_action) { + int retval = ZFCP_ERP_SUCCEEDED; struct zfcp_adapter *adapter = erp_action->adapter; /* @@ -2267,6 +2317,8 @@ zfcp_erp_adapter_strategy_close_fsf(struct zfcp_erp_action *erp_action) /* all ports and units are closed */ zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR); + + return retval; } /* @@ -3241,8 +3293,10 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, } -void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) +static int +zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) { + int retval = 0; struct zfcp_port *port; debug_text_event(adapter->erp_dbf, 5, "a_actab"); @@ -3251,10 +3305,14 @@ void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) else list_for_each_entry(port, &adapter->port_list_head, list) zfcp_erp_action_dismiss_port(port); + + return retval; } -static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) +static int +zfcp_erp_action_dismiss_port(struct zfcp_port *port) { + int retval = 0; struct zfcp_unit *unit; struct zfcp_adapter *adapter = port->adapter; @@ -3265,16 +3323,22 @@ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) else list_for_each_entry(unit, &port->unit_list_head, list) zfcp_erp_action_dismiss_unit(unit); + + return retval; } -static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) +static int +zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) { + int retval = 0; struct zfcp_adapter *adapter = unit->port->adapter; debug_text_event(adapter->erp_dbf, 5, "u_actab"); debug_event(adapter->erp_dbf, 5, &unit->fcp_lun, sizeof (fcp_lun_t)); if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) zfcp_erp_action_dismiss(&unit->erp_action); + + return retval; } static inline void diff --git a/trunk/drivers/s390/scsi/zfcp_ext.h b/trunk/drivers/s390/scsi/zfcp_ext.h index 146d7a2b4c4a..d02366004cdd 100644 --- a/trunk/drivers/s390/scsi/zfcp_ext.h +++ b/trunk/drivers/s390/scsi/zfcp_ext.h @@ -63,6 +63,7 @@ extern int zfcp_qdio_allocate_queues(struct zfcp_adapter *); extern void zfcp_qdio_free_queues(struct zfcp_adapter *); extern int zfcp_qdio_determine_pci(struct zfcp_qdio_queue *, struct zfcp_fsf_req *); +extern int zfcp_qdio_reqid_check(struct zfcp_adapter *, void *); extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req (struct zfcp_fsf_req *, int, int); @@ -139,7 +140,6 @@ extern void zfcp_erp_modify_adapter_status(struct zfcp_adapter *, u32, int); extern int zfcp_erp_adapter_reopen(struct zfcp_adapter *, int); extern int zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int); extern void zfcp_erp_adapter_failed(struct zfcp_adapter *); -extern void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *); extern void zfcp_erp_modify_port_status(struct zfcp_port *, u32, int); extern int zfcp_erp_port_reopen(struct zfcp_port *, int); @@ -156,7 +156,7 @@ extern void zfcp_erp_unit_failed(struct zfcp_unit *); extern int zfcp_erp_thread_setup(struct zfcp_adapter *); extern int zfcp_erp_thread_kill(struct zfcp_adapter *); extern int zfcp_erp_wait(struct zfcp_adapter *); -extern void zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long); +extern int zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long); extern int zfcp_test_link(struct zfcp_port *); @@ -190,10 +190,5 @@ extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *, struct zfcp_fsf_req *); extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, struct scsi_cmnd *); -extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *); -extern void zfcp_reqlist_remove(struct zfcp_adapter *, unsigned long); -extern struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *, - unsigned long); -extern int zfcp_reqlist_isempty(struct zfcp_adapter *); #endif /* ZFCP_EXT_H */ diff --git a/trunk/drivers/s390/scsi/zfcp_fsf.c b/trunk/drivers/s390/scsi/zfcp_fsf.c index ff2eacf5ec8c..31db2b06faba 100644 --- a/trunk/drivers/s390/scsi/zfcp_fsf.c +++ b/trunk/drivers/s390/scsi/zfcp_fsf.c @@ -49,6 +49,7 @@ static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *, struct fsf_link_down_info *); static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); +static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *); /* association between FSF command and FSF QTCB type */ static u32 fsf_qtcb_type[] = { @@ -145,50 +146,49 @@ zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req) kfree(fsf_req); } -/** - * zfcp_fsf_req_dismiss - dismiss a single fsf request +/* + * function: + * + * purpose: + * + * returns: + * + * note: qdio queues shall be down (no ongoing inbound processing) */ -static void zfcp_fsf_req_dismiss(struct zfcp_adapter *adapter, - struct zfcp_fsf_req *fsf_req, - unsigned int counter) +int +zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) { - u64 dbg_tmp[2]; + struct zfcp_fsf_req *fsf_req, *tmp; + unsigned long flags; + LIST_HEAD(remove_queue); - dbg_tmp[0] = (u64) atomic_read(&adapter->reqs_active); - dbg_tmp[1] = (u64) counter; - debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16); - list_del(&fsf_req->list); - fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; - zfcp_fsf_req_complete(fsf_req); -} + spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); + list_splice_init(&adapter->fsf_req_list_head, &remove_queue); + atomic_set(&adapter->fsf_reqs_active, 0); + spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); -/** - * zfcp_fsf_req_dismiss_all - dismiss all remaining fsf requests - */ -int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) -{ - struct zfcp_fsf_req *request, *tmp; - unsigned long flags; - unsigned int i, counter; - - spin_lock_irqsave(&adapter->req_list_lock, flags); - atomic_set(&adapter->reqs_active, 0); - for (i=0; ireq_list[i])) - continue; - - counter = 0; - list_for_each_entry_safe(request, tmp, - &adapter->req_list[i], list) { - zfcp_fsf_req_dismiss(adapter, request, counter); - counter++; - } + list_for_each_entry_safe(fsf_req, tmp, &remove_queue, list) { + list_del(&fsf_req->list); + zfcp_fsf_req_dismiss(fsf_req); } - spin_unlock_irqrestore(&adapter->req_list_lock, flags); return 0; } +/* + * function: + * + * purpose: + * + * returns: + */ +static void +zfcp_fsf_req_dismiss(struct zfcp_fsf_req *fsf_req) +{ + fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; + zfcp_fsf_req_complete(fsf_req); +} + /* * function: zfcp_fsf_req_complete * @@ -4592,14 +4592,12 @@ static inline void zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req) { if (likely(fsf_req->qtcb != NULL)) { - fsf_req->qtcb->prefix.req_seq_no = - fsf_req->adapter->fsf_req_seq_no; - fsf_req->qtcb->prefix.req_id = fsf_req->req_id; + fsf_req->qtcb->prefix.req_seq_no = fsf_req->adapter->fsf_req_seq_no; + fsf_req->qtcb->prefix.req_id = (unsigned long)fsf_req; fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION; - fsf_req->qtcb->prefix.qtcb_type = - fsf_qtcb_type[fsf_req->fsf_command]; + fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_req->fsf_command]; fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION; - fsf_req->qtcb->header.req_handle = fsf_req->req_id; + fsf_req->qtcb->header.req_handle = (unsigned long)fsf_req; fsf_req->qtcb->header.fsf_command = fsf_req->fsf_command; } } @@ -4656,7 +4654,6 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, { volatile struct qdio_buffer_element *sbale; struct zfcp_fsf_req *fsf_req = NULL; - unsigned long flags; int ret = 0; struct zfcp_qdio_queue *req_queue = &adapter->request_queue; @@ -4671,12 +4668,6 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, fsf_req->adapter = adapter; fsf_req->fsf_command = fsf_cmd; - INIT_LIST_HEAD(&fsf_req->list); - - /* unique request id */ - spin_lock_irqsave(&adapter->req_list_lock, flags); - fsf_req->req_id = adapter->req_no++; - spin_unlock_irqrestore(&adapter->req_list_lock, flags); zfcp_fsf_req_qtcb_init(fsf_req); @@ -4716,7 +4707,7 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); /* setup common SBALE fields */ - sbale[0].addr = (void *) fsf_req->req_id; + sbale[0].addr = fsf_req; sbale[0].flags |= SBAL_FLAGS0_COMMAND; if (likely(fsf_req->qtcb != NULL)) { sbale[1].addr = (void *) fsf_req->qtcb; @@ -4756,7 +4747,7 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) volatile struct qdio_buffer_element *sbale; int inc_seq_no; int new_distance_from_int; - u64 dbg_tmp[2]; + unsigned long flags; int retval = 0; adapter = fsf_req->adapter; @@ -4770,10 +4761,10 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr, sbale[1].length); - /* put allocated FSF request into hash table */ - spin_lock(&adapter->req_list_lock); - zfcp_reqlist_add(adapter, fsf_req); - spin_unlock(&adapter->req_list_lock); + /* put allocated FSF request at list tail */ + spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); + list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head); + spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); inc_seq_no = (fsf_req->qtcb != NULL); @@ -4812,10 +4803,6 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) QDIO_FLAG_SYNC_OUTPUT, 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL); - dbg_tmp[0] = (unsigned long) sbale[0].addr; - dbg_tmp[1] = (u64) retval; - debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16); - if (unlikely(retval)) { /* Queues are down..... */ retval = -EIO; @@ -4825,17 +4812,22 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) */ if (timer) del_timer(timer); - spin_lock(&adapter->req_list_lock); - zfcp_reqlist_remove(adapter, fsf_req->req_id); - spin_unlock(&adapter->req_list_lock); - /* undo changes in request queue made for this request */ + spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); + list_del(&fsf_req->list); + spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); + /* + * adjust the number of free SBALs in request queue as well as + * position of first one + */ zfcp_qdio_zero_sbals(req_queue->buffer, fsf_req->sbal_first, fsf_req->sbal_number); atomic_add(fsf_req->sbal_number, &req_queue->free_count); - req_queue->free_index -= fsf_req->sbal_number; + req_queue->free_index -= fsf_req->sbal_number; /* increase */ req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q; req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */ - zfcp_erp_adapter_reopen(adapter, 0); + ZFCP_LOG_DEBUG + ("error: do_QDIO failed. Buffers could not be enqueued " + "to request queue.\n"); } else { req_queue->distance_from_int = new_distance_from_int; /* @@ -4851,7 +4843,7 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) adapter->fsf_req_seq_no++; /* count FSF requests pending */ - atomic_inc(&adapter->reqs_active); + atomic_inc(&adapter->fsf_reqs_active); } return retval; } diff --git a/trunk/drivers/s390/scsi/zfcp_qdio.c b/trunk/drivers/s390/scsi/zfcp_qdio.c index dbd9f48e863e..49ea5add4abc 100644 --- a/trunk/drivers/s390/scsi/zfcp_qdio.c +++ b/trunk/drivers/s390/scsi/zfcp_qdio.c @@ -282,37 +282,6 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device, return; } -/** - * zfcp_qdio_reqid_check - checks for valid reqids or unsolicited status - */ -static int zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, - unsigned long req_id) -{ - struct zfcp_fsf_req *fsf_req; - unsigned long flags; - - debug_long_event(adapter->erp_dbf, 4, req_id); - - spin_lock_irqsave(&adapter->req_list_lock, flags); - fsf_req = zfcp_reqlist_ismember(adapter, req_id); - - if (!fsf_req) { - spin_unlock_irqrestore(&adapter->req_list_lock, flags); - ZFCP_LOG_NORMAL("error: unknown request id (%ld).\n", req_id); - zfcp_erp_adapter_reopen(adapter, 0); - return -EINVAL; - } - - zfcp_reqlist_remove(adapter, req_id); - atomic_dec(&adapter->reqs_active); - spin_unlock_irqrestore(&adapter->req_list_lock, flags); - - /* finish the FSF request */ - zfcp_fsf_req_complete(fsf_req); - - return 0; -} - /* * function: zfcp_qdio_response_handler * @@ -375,7 +344,7 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device, /* look for QDIO request identifiers in SB */ buffere = &buffer->element[buffere_index]; retval = zfcp_qdio_reqid_check(adapter, - (unsigned long) buffere->addr); + (void *) buffere->addr); if (retval) { ZFCP_LOG_NORMAL("bug: unexpected inbound " @@ -446,6 +415,52 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device, return; } +/* + * function: zfcp_qdio_reqid_check + * + * purpose: checks for valid reqids or unsolicited status + * + * returns: 0 - valid request id or unsolicited status + * !0 - otherwise + */ +int +zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr) +{ + struct zfcp_fsf_req *fsf_req; + unsigned long flags; + + /* invalid (per convention used in this driver) */ + if (unlikely(!sbale_addr)) { + ZFCP_LOG_NORMAL("bug: invalid reqid\n"); + return -EINVAL; + } + + /* valid request id and thus (hopefully :) valid fsf_req address */ + fsf_req = (struct zfcp_fsf_req *) sbale_addr; + + /* serialize with zfcp_fsf_req_dismiss_all */ + spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); + if (list_empty(&adapter->fsf_req_list_head)) { + spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); + return 0; + } + list_del(&fsf_req->list); + atomic_dec(&adapter->fsf_reqs_active); + spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); + + if (unlikely(adapter != fsf_req->adapter)) { + ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, " + "fsf_req->adapter=%p, adapter=%p)\n", + fsf_req, fsf_req->adapter, adapter); + return -EINVAL; + } + + /* finish the FSF request */ + zfcp_fsf_req_complete(fsf_req); + + return 0; +} + /** * zfcp_qdio_sbale_get - return pointer to SBALE of qdio_queue * @queue: queue from which SBALE should be returned diff --git a/trunk/drivers/s390/scsi/zfcp_scsi.c b/trunk/drivers/s390/scsi/zfcp_scsi.c index 1bb55086db9f..671f4a6a5d18 100644 --- a/trunk/drivers/s390/scsi/zfcp_scsi.c +++ b/trunk/drivers/s390/scsi/zfcp_scsi.c @@ -30,6 +30,7 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *, void (*done) (struct scsi_cmnd *)); static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); +static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *); static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); static int zfcp_task_management_function(struct zfcp_unit *, u8, struct scsi_cmnd *); @@ -45,22 +46,30 @@ struct zfcp_data zfcp_data = { .scsi_host_template = { .name = ZFCP_NAME, .proc_name = "zfcp", + .proc_info = NULL, + .detect = NULL, .slave_alloc = zfcp_scsi_slave_alloc, .slave_configure = zfcp_scsi_slave_configure, .slave_destroy = zfcp_scsi_slave_destroy, .queuecommand = zfcp_scsi_queuecommand, .eh_abort_handler = zfcp_scsi_eh_abort_handler, .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, - .eh_bus_reset_handler = zfcp_scsi_eh_host_reset_handler, + .eh_bus_reset_handler = zfcp_scsi_eh_bus_reset_handler, .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, .can_queue = 4096, .this_id = -1, + /* + * FIXME: + * one less? can zfcp_create_sbale cope with it? + */ .sg_tablesize = ZFCP_MAX_SBALES_PER_REQ, .cmd_per_lun = 1, + .unchecked_isa_dma = 0, .use_clustering = 1, .sdev_attrs = zfcp_sysfs_sdev_attrs, }, .driver_version = ZFCP_VERSION, + /* rest initialised with zeros */ }; /* Find start of Response Information in FCP response unit*/ @@ -167,14 +176,8 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp) return retval; } -/** - * zfcp_scsi_slave_destroy - called when scsi device is removed - * - * Remove reference to associated scsi device for an zfcp_unit. - * Mark zfcp_unit as failed. The scsi device might be deleted via sysfs - * or a scan for this device might have failed. - */ -static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) +static void +zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) { struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; @@ -182,7 +185,6 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); sdpnt->hostdata = NULL; unit->device = NULL; - zfcp_erp_unit_failed(unit); zfcp_unit_put(unit); } else { ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at " @@ -547,38 +549,35 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags, } /** - * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset - * - * If ERP is already running it will be stopped. + * zfcp_scsi_eh_bus_reset_handler - reset bus (reopen adapter) */ -int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) +int +zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt) { - struct zfcp_unit *unit; - struct zfcp_adapter *adapter; - unsigned long flags; - - unit = (struct zfcp_unit*) scpnt->device->hostdata; - adapter = unit->port->adapter; + struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; + struct zfcp_adapter *adapter = unit->port->adapter; - ZFCP_LOG_NORMAL("host/bus reset because of problems with " + ZFCP_LOG_NORMAL("bus reset because of problems with " "unit 0x%016Lx\n", unit->fcp_lun); + zfcp_erp_adapter_reopen(adapter, 0); + zfcp_erp_wait(adapter); - write_lock_irqsave(&adapter->erp_lock, flags); - if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, - &adapter->status)) { - zfcp_erp_modify_adapter_status(adapter, - ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN, - ZFCP_CLEAR); - zfcp_erp_action_dismiss_adapter(adapter); - write_unlock_irqrestore(&adapter->erp_lock, flags); - zfcp_fsf_req_dismiss_all(adapter); - adapter->fsf_req_seq_no = 0; - zfcp_erp_adapter_reopen(adapter, 0); - } else { - write_unlock_irqrestore(&adapter->erp_lock, flags); - zfcp_erp_adapter_reopen(adapter, 0); - zfcp_erp_wait(adapter); - } + return SUCCESS; +} + +/** + * zfcp_scsi_eh_host_reset_handler - reset host (reopen adapter) + */ +int +zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) +{ + struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; + struct zfcp_adapter *adapter = unit->port->adapter; + + ZFCP_LOG_NORMAL("host reset because of problems with " + "unit 0x%016Lx\n", unit->fcp_lun); + zfcp_erp_adapter_reopen(adapter, 0); + zfcp_erp_wait(adapter); return SUCCESS; } diff --git a/trunk/drivers/s390/sysinfo.c b/trunk/drivers/s390/sysinfo.c index 1e788e815ce7..d1c1e75bfd60 100644 --- a/trunk/drivers/s390/sysinfo.c +++ b/trunk/drivers/s390/sysinfo.c @@ -11,18 +11,19 @@ #include #include -struct sysinfo_1_1_1 { +struct sysinfo_1_1_1 +{ char reserved_0[32]; char manufacturer[16]; char type[4]; char reserved_1[12]; - char model_capacity[16]; + char model[16]; char sequence[16]; char plant[4]; - char model[16]; }; -struct sysinfo_1_2_1 { +struct sysinfo_1_2_1 +{ char reserved_0[80]; char sequence[16]; char plant[4]; @@ -30,12 +31,9 @@ struct sysinfo_1_2_1 { unsigned short cpu_address; }; -struct sysinfo_1_2_2 { - char format; - char reserved_0[1]; - unsigned short acc_offset; - char reserved_1[24]; - unsigned int secondary_capability; +struct sysinfo_1_2_2 +{ + char reserved_0[32]; unsigned int capability; unsigned short cpus_total; unsigned short cpus_configured; @@ -44,12 +42,8 @@ struct sysinfo_1_2_2 { unsigned short adjustment[0]; }; -struct sysinfo_1_2_2_extension { - unsigned int alt_capability; - unsigned short alt_adjustment[0]; -}; - -struct sysinfo_2_2_1 { +struct sysinfo_2_2_1 +{ char reserved_0[80]; char sequence[16]; char plant[4]; @@ -57,11 +51,15 @@ struct sysinfo_2_2_1 { unsigned short cpu_address; }; -struct sysinfo_2_2_2 { +struct sysinfo_2_2_2 +{ char reserved_0[32]; unsigned short lpar_number; char reserved_1; unsigned char characteristics; + #define LPAR_CHAR_DEDICATED (1 << 7) + #define LPAR_CHAR_SHARED (1 << 6) + #define LPAR_CHAR_LIMITED (1 << 5) unsigned short cpus_total; unsigned short cpus_configured; unsigned short cpus_standby; @@ -73,14 +71,12 @@ struct sysinfo_2_2_2 { unsigned short cpus_shared; }; -#define LPAR_CHAR_DEDICATED (1 << 7) -#define LPAR_CHAR_SHARED (1 << 6) -#define LPAR_CHAR_LIMITED (1 << 5) - -struct sysinfo_3_2_2 { +struct sysinfo_3_2_2 +{ char reserved_0[31]; unsigned char count; - struct { + struct + { char reserved_0[4]; unsigned short cpus_total; unsigned short cpus_configured; @@ -94,223 +90,136 @@ struct sysinfo_3_2_2 { } vm[8]; }; -static inline int stsi(void *sysinfo, int fc, int sel1, int sel2) +union s390_sysinfo { - register int r0 asm("0") = (fc << 28) | sel1; - register int r1 asm("1") = sel2; - - asm volatile( - " stsi 0(%2)\n" - "0: jz 2f\n" - "1: lhi %0,%3\n" - "2:\n" - EX_TABLE(0b,1b) - : "+d" (r0) : "d" (r1), "a" (sysinfo), "K" (-ENOSYS) - : "cc", "memory" ); - return r0; -} + struct sysinfo_1_1_1 sysinfo_1_1_1; + struct sysinfo_1_2_1 sysinfo_1_2_1; + struct sysinfo_1_2_2 sysinfo_1_2_2; + struct sysinfo_2_2_1 sysinfo_2_2_1; + struct sysinfo_2_2_2 sysinfo_2_2_2; + struct sysinfo_3_2_2 sysinfo_3_2_2; +}; -static inline int stsi_0(void) +static inline int stsi (void *sysinfo, + int fc, int sel1, int sel2) { - int rc = stsi (NULL, 0, 0, 0); - return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); + int cc, retv; + +#ifndef CONFIG_64BIT + __asm__ __volatile__ ( "lr\t0,%2\n" + "\tlr\t1,%3\n" + "\tstsi\t0(%4)\n" + "0:\tipm\t%0\n" + "\tsrl\t%0,28\n" + "1:lr\t%1,0\n" + ".section .fixup,\"ax\"\n" + "2:\tlhi\t%0,3\n" + "\tbras\t1,3f\n" + "\t.long 1b\n" + "3:\tl\t1,0(1)\n" + "\tbr\t1\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + "\t.align 4\n" + "\t.long 0b,2b\n" + ".previous\n" + : "=d" (cc), "=d" (retv) + : "d" ((fc << 28) | sel1), "d" (sel2), "a" (sysinfo) + : "cc", "memory", "0", "1" ); +#else + __asm__ __volatile__ ( "lr\t0,%2\n" + "lr\t1,%3\n" + "\tstsi\t0(%4)\n" + "0:\tipm\t%0\n" + "\tsrl\t%0,28\n" + "1:lr\t%1,0\n" + ".section .fixup,\"ax\"\n" + "2:\tlhi\t%0,3\n" + "\tjg\t1b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + "\t.align 8\n" + "\t.quad 0b,2b\n" + ".previous\n" + : "=d" (cc), "=d" (retv) + : "d" ((fc << 28) | sel1), "d" (sel2), "a" (sysinfo) + : "cc", "memory", "0", "1" ); +#endif + + return cc? -1 : retv; } -static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len) +static inline int stsi_0 (void) { - if (stsi(info, 1, 1, 1) == -ENOSYS) - return len; - - EBCASC(info->manufacturer, sizeof(info->manufacturer)); - EBCASC(info->type, sizeof(info->type)); - EBCASC(info->model, sizeof(info->model)); - EBCASC(info->sequence, sizeof(info->sequence)); - EBCASC(info->plant, sizeof(info->plant)); - EBCASC(info->model_capacity, sizeof(info->model_capacity)); - len += sprintf(page + len, "Manufacturer: %-16.16s\n", - info->manufacturer); - len += sprintf(page + len, "Type: %-4.4s\n", - info->type); - if (info->model[0] != '\0') - /* - * Sigh: the model field has been renamed with System z9 - * to model_capacity and a new model field has been added - * after the plant field. To avoid confusing older programs - * the "Model:" prints "model_capacity model" or just - * "model_capacity" if the model string is empty . - */ - len += sprintf(page + len, - "Model: %-16.16s %-16.16s\n", - info->model_capacity, info->model); - else - len += sprintf(page + len, "Model: %-16.16s\n", - info->model_capacity); - len += sprintf(page + len, "Sequence Code: %-16.16s\n", - info->sequence); - len += sprintf(page + len, "Plant: %-4.4s\n", - info->plant); - len += sprintf(page + len, "Model Capacity: %-16.16s\n", - info->model_capacity); - return len; + int rc = stsi (NULL, 0, 0, 0); + return rc == -1 ? rc : (((unsigned int)rc) >> 28); } -#if 0 /* Currently unused */ -static int stsi_1_2_1(struct sysinfo_1_2_1 *info, char *page, int len) +static inline int stsi_1_1_1 (struct sysinfo_1_1_1 *info) { - if (stsi(info, 1, 2, 1) == -ENOSYS) - return len; - - len += sprintf(page + len, "\n"); - EBCASC(info->sequence, sizeof(info->sequence)); - EBCASC(info->plant, sizeof(info->plant)); - len += sprintf(page + len, "Sequence Code of CPU: %-16.16s\n", - info->sequence); - len += sprintf(page + len, "Plant of CPU: %-16.16s\n", - info->plant); - return len; + int rc = stsi (info, 1, 1, 1); + if (rc != -1) + { + EBCASC (info->manufacturer, sizeof(info->manufacturer)); + EBCASC (info->type, sizeof(info->type)); + EBCASC (info->model, sizeof(info->model)); + EBCASC (info->sequence, sizeof(info->sequence)); + EBCASC (info->plant, sizeof(info->plant)); + } + return rc == -1 ? rc : 0; } -#endif -static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) +static inline int stsi_1_2_1 (struct sysinfo_1_2_1 *info) { - struct sysinfo_1_2_2_extension *ext; - int i; - - if (stsi(info, 1, 2, 2) == -ENOSYS) - return len; - ext = (struct sysinfo_1_2_2_extension *) - ((unsigned long) info + info->acc_offset); - - len += sprintf(page + len, "\n"); - len += sprintf(page + len, "CPUs Total: %d\n", - info->cpus_total); - len += sprintf(page + len, "CPUs Configured: %d\n", - info->cpus_configured); - len += sprintf(page + len, "CPUs Standby: %d\n", - info->cpus_standby); - len += sprintf(page + len, "CPUs Reserved: %d\n", - info->cpus_reserved); - - if (info->format == 1) { - /* - * Sigh 2. According to the specification the alternate - * capability field is a 32 bit floating point number - * if the higher order 8 bits are not zero. Printing - * a floating point number in the kernel is a no-no, - * always print the number as 32 bit unsigned integer. - * The user-space needs to know about the stange - * encoding of the alternate cpu capability. - */ - len += sprintf(page + len, "Capability: %u %u\n", - info->capability, ext->alt_capability); - for (i = 2; i <= info->cpus_total; i++) - len += sprintf(page + len, - "Adjustment %02d-way: %u %u\n", - i, info->adjustment[i-2], - ext->alt_adjustment[i-2]); - - } else { - len += sprintf(page + len, "Capability: %u\n", - info->capability); - for (i = 2; i <= info->cpus_total; i++) - len += sprintf(page + len, - "Adjustment %02d-way: %u\n", - i, info->adjustment[i-2]); + int rc = stsi (info, 1, 2, 1); + if (rc != -1) + { + EBCASC (info->sequence, sizeof(info->sequence)); + EBCASC (info->plant, sizeof(info->plant)); } - - if (info->secondary_capability != 0) - len += sprintf(page + len, "Secondary Capability: %d\n", - info->secondary_capability); - - return len; + return rc == -1 ? rc : 0; } -#if 0 /* Currently unused */ -static int stsi_2_2_1(struct sysinfo_2_2_1 *info, char *page, int len) +static inline int stsi_1_2_2 (struct sysinfo_1_2_2 *info) { - if (stsi(info, 2, 2, 1) == -ENOSYS) - return len; - - len += sprintf(page + len, "\n"); - EBCASC (info->sequence, sizeof(info->sequence)); - EBCASC (info->plant, sizeof(info->plant)); - len += sprintf(page + len, "Sequence Code of logical CPU: %-16.16s\n", - info->sequence); - len += sprintf(page + len, "Plant of logical CPU: %-16.16s\n", - info->plant); - return len; + int rc = stsi (info, 1, 2, 2); + return rc == -1 ? rc : 0; } -#endif -static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len) +static inline int stsi_2_2_1 (struct sysinfo_2_2_1 *info) { - if (stsi(info, 2, 2, 2) == -ENOSYS) - return len; - - EBCASC (info->name, sizeof(info->name)); - - len += sprintf(page + len, "\n"); - len += sprintf(page + len, "LPAR Number: %d\n", - info->lpar_number); - - len += sprintf(page + len, "LPAR Characteristics: "); - if (info->characteristics & LPAR_CHAR_DEDICATED) - len += sprintf(page + len, "Dedicated "); - if (info->characteristics & LPAR_CHAR_SHARED) - len += sprintf(page + len, "Shared "); - if (info->characteristics & LPAR_CHAR_LIMITED) - len += sprintf(page + len, "Limited "); - len += sprintf(page + len, "\n"); - - len += sprintf(page + len, "LPAR Name: %-8.8s\n", - info->name); - - len += sprintf(page + len, "LPAR Adjustment: %d\n", - info->caf); - - len += sprintf(page + len, "LPAR CPUs Total: %d\n", - info->cpus_total); - len += sprintf(page + len, "LPAR CPUs Configured: %d\n", - info->cpus_configured); - len += sprintf(page + len, "LPAR CPUs Standby: %d\n", - info->cpus_standby); - len += sprintf(page + len, "LPAR CPUs Reserved: %d\n", - info->cpus_reserved); - len += sprintf(page + len, "LPAR CPUs Dedicated: %d\n", - info->cpus_dedicated); - len += sprintf(page + len, "LPAR CPUs Shared: %d\n", - info->cpus_shared); - return len; + int rc = stsi (info, 2, 2, 1); + if (rc != -1) + { + EBCASC (info->sequence, sizeof(info->sequence)); + EBCASC (info->plant, sizeof(info->plant)); + } + return rc == -1 ? rc : 0; } -static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len) +static inline int stsi_2_2_2 (struct sysinfo_2_2_2 *info) { - int i; + int rc = stsi (info, 2, 2, 2); + if (rc != -1) + { + EBCASC (info->name, sizeof(info->name)); + } + return rc == -1 ? rc : 0; +} - if (stsi(info, 3, 2, 2) == -ENOSYS) - return len; - for (i = 0; i < info->count; i++) { - EBCASC (info->vm[i].name, sizeof(info->vm[i].name)); - EBCASC (info->vm[i].cpi, sizeof(info->vm[i].cpi)); - len += sprintf(page + len, "\n"); - len += sprintf(page + len, "VM%02d Name: %-8.8s\n", - i, info->vm[i].name); - len += sprintf(page + len, "VM%02d Control Program: %-16.16s\n", - i, info->vm[i].cpi); - - len += sprintf(page + len, "VM%02d Adjustment: %d\n", - i, info->vm[i].caf); - - len += sprintf(page + len, "VM%02d CPUs Total: %d\n", - i, info->vm[i].cpus_total); - len += sprintf(page + len, "VM%02d CPUs Configured: %d\n", - i, info->vm[i].cpus_configured); - len += sprintf(page + len, "VM%02d CPUs Standby: %d\n", - i, info->vm[i].cpus_standby); - len += sprintf(page + len, "VM%02d CPUs Reserved: %d\n", - i, info->vm[i].cpus_reserved); +static inline int stsi_3_2_2 (struct sysinfo_3_2_2 *info) +{ + int rc = stsi (info, 3, 2, 2); + if (rc != -1) + { + int i; + for (i = 0; i < info->count; i++) + { + EBCASC (info->vm[i].name, sizeof(info->vm[i].name)); + EBCASC (info->vm[i].cpi, sizeof(info->vm[i].cpi)); + } } - return len; + return rc == -1 ? rc : 0; } @@ -318,34 +227,118 @@ static int proc_read_sysinfo(char *page, char **start, off_t off, int count, int *eof, void *data) { - unsigned long info = get_zeroed_page (GFP_KERNEL); - int level, len; + unsigned long info_page = get_zeroed_page (GFP_KERNEL); + union s390_sysinfo *info = (union s390_sysinfo *) info_page; + int len = 0; + int level; + int i; if (!info) return 0; - len = 0; - level = stsi_0(); - if (level >= 1) - len = stsi_1_1_1((struct sysinfo_1_1_1 *) info, page, len); + level = stsi_0 (); + + if (level >= 1 && stsi_1_1_1 (&info->sysinfo_1_1_1) == 0) + { + len += sprintf (page+len, "Manufacturer: %-16.16s\n", + info->sysinfo_1_1_1.manufacturer); + len += sprintf (page+len, "Type: %-4.4s\n", + info->sysinfo_1_1_1.type); + len += sprintf (page+len, "Model: %-16.16s\n", + info->sysinfo_1_1_1.model); + len += sprintf (page+len, "Sequence Code: %-16.16s\n", + info->sysinfo_1_1_1.sequence); + len += sprintf (page+len, "Plant: %-4.4s\n", + info->sysinfo_1_1_1.plant); + } + + if (level >= 1 && stsi_1_2_2 (&info->sysinfo_1_2_2) == 0) + { + len += sprintf (page+len, "\n"); + len += sprintf (page+len, "CPUs Total: %d\n", + info->sysinfo_1_2_2.cpus_total); + len += sprintf (page+len, "CPUs Configured: %d\n", + info->sysinfo_1_2_2.cpus_configured); + len += sprintf (page+len, "CPUs Standby: %d\n", + info->sysinfo_1_2_2.cpus_standby); + len += sprintf (page+len, "CPUs Reserved: %d\n", + info->sysinfo_1_2_2.cpus_reserved); + + len += sprintf (page+len, "Capability: %d\n", + info->sysinfo_1_2_2.capability); - if (level >= 1) - len = stsi_1_2_2((struct sysinfo_1_2_2 *) info, page, len); + for (i = 2; i <= info->sysinfo_1_2_2.cpus_total; i++) + len += sprintf (page+len, "Adjustment %02d-way: %d\n", + i, info->sysinfo_1_2_2.adjustment[i-2]); + } - if (level >= 2) - len = stsi_2_2_2((struct sysinfo_2_2_2 *) info, page, len); + if (level >= 2 && stsi_2_2_2 (&info->sysinfo_2_2_2) == 0) + { + len += sprintf (page+len, "\n"); + len += sprintf (page+len, "LPAR Number: %d\n", + info->sysinfo_2_2_2.lpar_number); + + len += sprintf (page+len, "LPAR Characteristics: "); + if (info->sysinfo_2_2_2.characteristics & LPAR_CHAR_DEDICATED) + len += sprintf (page+len, "Dedicated "); + if (info->sysinfo_2_2_2.characteristics & LPAR_CHAR_SHARED) + len += sprintf (page+len, "Shared "); + if (info->sysinfo_2_2_2.characteristics & LPAR_CHAR_LIMITED) + len += sprintf (page+len, "Limited "); + len += sprintf (page+len, "\n"); + + len += sprintf (page+len, "LPAR Name: %-8.8s\n", + info->sysinfo_2_2_2.name); + + len += sprintf (page+len, "LPAR Adjustment: %d\n", + info->sysinfo_2_2_2.caf); + + len += sprintf (page+len, "LPAR CPUs Total: %d\n", + info->sysinfo_2_2_2.cpus_total); + len += sprintf (page+len, "LPAR CPUs Configured: %d\n", + info->sysinfo_2_2_2.cpus_configured); + len += sprintf (page+len, "LPAR CPUs Standby: %d\n", + info->sysinfo_2_2_2.cpus_standby); + len += sprintf (page+len, "LPAR CPUs Reserved: %d\n", + info->sysinfo_2_2_2.cpus_reserved); + len += sprintf (page+len, "LPAR CPUs Dedicated: %d\n", + info->sysinfo_2_2_2.cpus_dedicated); + len += sprintf (page+len, "LPAR CPUs Shared: %d\n", + info->sysinfo_2_2_2.cpus_shared); + } - if (level >= 3) - len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len); + if (level >= 3 && stsi_3_2_2 (&info->sysinfo_3_2_2) == 0) + { + for (i = 0; i < info->sysinfo_3_2_2.count; i++) + { + len += sprintf (page+len, "\n"); + len += sprintf (page+len, "VM%02d Name: %-8.8s\n", + i, info->sysinfo_3_2_2.vm[i].name); + len += sprintf (page+len, "VM%02d Control Program: %-16.16s\n", + i, info->sysinfo_3_2_2.vm[i].cpi); + + len += sprintf (page+len, "VM%02d Adjustment: %d\n", + i, info->sysinfo_3_2_2.vm[i].caf); + + len += sprintf (page+len, "VM%02d CPUs Total: %d\n", + i, info->sysinfo_3_2_2.vm[i].cpus_total); + len += sprintf (page+len, "VM%02d CPUs Configured: %d\n", + i, info->sysinfo_3_2_2.vm[i].cpus_configured); + len += sprintf (page+len, "VM%02d CPUs Standby: %d\n", + i, info->sysinfo_3_2_2.vm[i].cpus_standby); + len += sprintf (page+len, "VM%02d CPUs Reserved: %d\n", + i, info->sysinfo_3_2_2.vm[i].cpus_reserved); + } + } - free_page (info); + free_page (info_page); return len; } static __init int create_proc_sysinfo(void) { - create_proc_read_entry("sysinfo", 0444, NULL, - proc_read_sysinfo, NULL); + create_proc_read_entry ("sysinfo", 0444, NULL, + proc_read_sysinfo, NULL); return 0; } diff --git a/trunk/drivers/sbus/char/openprom.c b/trunk/drivers/sbus/char/openprom.c index 2f698763ba5d..293bb2fdb1d5 100644 --- a/trunk/drivers/sbus/char/openprom.c +++ b/trunk/drivers/sbus/char/openprom.c @@ -145,9 +145,8 @@ static int opromgetprop(void __user *argp, struct device_node *dp, struct openpr void *pval; int len; - if (!dp || - !(pval = of_get_property(dp, op->oprom_array, &len)) || - len <= 0 || len > bufsize) + pval = of_get_property(dp, op->oprom_array, &len); + if (!pval || len <= 0 || len > bufsize) return copyout(argp, op, sizeof(int)); memcpy(op->oprom_array, pval, len); @@ -162,8 +161,6 @@ static int opromnxtprop(void __user *argp, struct device_node *dp, struct openpr struct property *prop; int len; - if (!dp) - return copyout(argp, op, sizeof(int)); if (op->oprom_array[0] == '\0') { prop = dp->properties; if (!prop) @@ -269,13 +266,9 @@ static int oprompci2node(void __user *argp, struct device_node *dp, struct openp static int oprompath2node(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data) { - phandle ph = 0; - dp = of_find_node_by_path(op->oprom_array); - if (dp) - ph = dp->node; data->current_node = dp; - *((int *)op->oprom_array) = ph; + *((int *)op->oprom_array) = dp->node; op->oprom_size = sizeof(int); return copyout(argp, op, bufsize + sizeof(int)); diff --git a/trunk/drivers/scsi/ahci.c b/trunk/drivers/scsi/ahci.c index 904c25fb4ba4..77e7202a0eba 100644 --- a/trunk/drivers/scsi/ahci.c +++ b/trunk/drivers/scsi/ahci.c @@ -940,8 +940,14 @@ static void ahci_host_intr(struct ata_port *ap) return; /* ignore interim PIO setup fis interrupts */ - if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS)) - return; + if (ata_tag_valid(ap->active_tag)) { + struct ata_queued_cmd *qc = + ata_qc_from_tag(ap, ap->active_tag); + + if (qc && qc->tf.protocol == ATA_PROT_PIO && + (status & PORT_IRQ_PIOS_FIS)) + return; + } if (ata_ratelimit()) ata_port_printk(ap, KERN_INFO, "spurious interrupt " diff --git a/trunk/drivers/scsi/aic7xxx/aicasm/Makefile b/trunk/drivers/scsi/aic7xxx/aicasm/Makefile index b98c5c1056c3..8c91fda6482c 100644 --- a/trunk/drivers/scsi/aic7xxx/aicasm/Makefile +++ b/trunk/drivers/scsi/aic7xxx/aicasm/Makefile @@ -14,8 +14,6 @@ LIBS= -ldb clean-files:= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output) $(PROG) # Override default kernel CFLAGS. This is a userland app. AICASM_CFLAGS:= -I/usr/include -I. -LEX= flex -YACC= bison YFLAGS= -d NOMAN= noman diff --git a/trunk/drivers/scsi/arm/Kconfig b/trunk/drivers/scsi/arm/Kconfig index d006a8cb4a74..06d7601cdf56 100644 --- a/trunk/drivers/scsi/arm/Kconfig +++ b/trunk/drivers/scsi/arm/Kconfig @@ -69,7 +69,6 @@ comment "The following drivers are not fully supported" config SCSI_CUMANA_1 tristate "CumanaSCSI I support (EXPERIMENTAL)" depends on ARCH_ACORN && EXPERIMENTAL && SCSI - select SCSI_SPI_ATTRS help This enables support for the Cumana SCSI I card. If you have an Acorn system with one of these, say Y. If unsure, say N. @@ -77,7 +76,6 @@ config SCSI_CUMANA_1 config SCSI_ECOSCSI tristate "EcoScsi support (EXPERIMENTAL)" depends on ARCH_ACORN && EXPERIMENTAL && (ARCH_ARC || ARCH_A5K) && SCSI - select SCSI_SPI_ATTRS help This enables support for the EcoSCSI card -- a small card that sits in the Econet socket. If you have an Acorn system with one of these, @@ -86,7 +84,6 @@ config SCSI_ECOSCSI config SCSI_OAK1 tristate "Oak SCSI support (EXPERIMENTAL)" depends on ARCH_ACORN && EXPERIMENTAL && SCSI - select SCSI_SPI_ATTRS help This enables support for the Oak SCSI card. If you have an Acorn system with one of these, say Y. If unsure, say N. diff --git a/trunk/drivers/scsi/arm/scsi.h b/trunk/drivers/scsi/arm/scsi.h index 8c2600ffc6af..6dd544a5eb56 100644 --- a/trunk/drivers/scsi/arm/scsi.h +++ b/trunk/drivers/scsi/arm/scsi.h @@ -74,7 +74,7 @@ static inline void init_SCp(Scsi_Cmnd *SCpnt) unsigned long len = 0; int buf; - SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; + SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer; SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; SCpnt->SCp.ptr = (char *) (page_address(SCpnt->SCp.buffer->page) + diff --git a/trunk/drivers/scsi/ata_piix.c b/trunk/drivers/scsi/ata_piix.c index a9bb3cb7e89b..19745a31072b 100644 --- a/trunk/drivers/scsi/ata_piix.c +++ b/trunk/drivers/scsi/ata_piix.c @@ -123,8 +123,7 @@ enum { ich6_sata = 4, ich6_sata_ahci = 5, ich6m_sata_ahci = 6, - ich7m_sata_ahci = 7, - ich8_sata_ahci = 8, + ich8_sata_ahci = 7, /* constants for mapping table */ P0 = 0, /* port 0 */ @@ -189,7 +188,7 @@ static const struct pci_device_id piix_pci_tbl[] = { /* 82801GB/GR/GH (ICH7, identical to ICH6) */ { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, /* 2801GBM/GHM (ICH7M, identical to ICH6M) */ - { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7m_sata_ahci }, + { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci }, /* Enterprise Southbridge 2 (where's the datasheet?) */ { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, /* SATA Controller 1 IDE (ICH8, no datasheet yet) */ @@ -337,24 +336,6 @@ static const struct piix_map_db ich6m_map_db = { }, }; -static const struct piix_map_db ich7m_map_db = { - .mask = 0x3, - .port_enable = 0x5, - .present_shift = 4, - - /* Map 01b isn't specified in the doc but some notebooks use - * it anyway. ATM, the only case spotted carries subsystem ID - * 1025:0107. This is the only difference from ich6m. - */ - .map = { - /* PM PS SM SS MAP */ - { P0, P2, RV, RV }, /* 00b */ - { IDE, IDE, P1, P3 }, /* 01b */ - { P0, P2, IDE, IDE }, /* 10b */ - { RV, RV, RV, RV }, - }, -}; - static const struct piix_map_db ich8_map_db = { .mask = 0x3, .port_enable = 0x3, @@ -374,7 +355,6 @@ static const struct piix_map_db *piix_map_db_table[] = { [ich6_sata] = &ich6_map_db, [ich6_sata_ahci] = &ich6_map_db, [ich6m_sata_ahci] = &ich6m_map_db, - [ich7m_sata_ahci] = &ich7m_map_db, [ich8_sata_ahci] = &ich8_map_db, }; @@ -410,8 +390,7 @@ static struct ata_port_info piix_port_info[] = { /* ich5_sata */ { .sht = &piix_sht, - .host_flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR | - PIIX_FLAG_IGNORE_PCS, + .host_flags = ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 */ @@ -464,18 +443,6 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich7m_sata_ahci */ - { - .sht = &piix_sht, - .host_flags = ATA_FLAG_SATA | - PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | - PIIX_FLAG_AHCI, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = 0x7f, /* udma0-6 */ - .port_ops = &piix_sata_ops, - }, - /* ich8_sata_ahci */ { .sht = &piix_sht, @@ -500,11 +467,6 @@ MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, piix_pci_tbl); MODULE_VERSION(DRV_VERSION); -static int force_pcs = 0; -module_param(force_pcs, int, 0444); -MODULE_PARM_DESC(force_pcs, "force honoring or ignoring PCS to work around " - "device mis-detection (0=default, 1=ignore PCS, 2=honor PCS)"); - /** * piix_pata_cbl_detect - Probe host controller cable detect info * @ap: Port for which cable detect info is desired @@ -569,25 +531,27 @@ static void piix_pata_error_handler(struct ata_port *ap) } /** - * piix_sata_present_mask - determine present mask for SATA host controller + * piix_sata_prereset - prereset for SATA host controller * @ap: Target port * - * Reads SATA PCI device's PCI config register Port Configuration - * and Status (PCS) to determine port and device availability. + * Reads and configures SATA PCI device's PCI config register + * Port Configuration and Status (PCS) to determine port and + * device availability. Return -ENODEV to skip reset if no + * device is present. * * LOCKING: * None (inherited from caller). * * RETURNS: - * determined present_mask + * 0 if device is present, -ENODEV otherwise. */ -static unsigned int piix_sata_present_mask(struct ata_port *ap) +static int piix_sata_prereset(struct ata_port *ap) { struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); struct piix_host_priv *hpriv = ap->host_set->private_data; const unsigned int *map = hpriv->map; int base = 2 * ap->hard_port_no; - unsigned int present_mask = 0; + unsigned int present = 0; int port, i; u16 pcs; @@ -600,52 +564,24 @@ static unsigned int piix_sata_present_mask(struct ata_port *ap) continue; if ((ap->flags & PIIX_FLAG_IGNORE_PCS) || (pcs & 1 << (hpriv->map_db->present_shift + port))) - present_mask |= 1 << i; + present = 1; } DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n", ap->id, pcs, present_mask); - return present_mask; -} - -/** - * piix_sata_softreset - reset SATA host port via ATA SRST - * @ap: port to reset - * @classes: resulting classes of attached devices - * - * Reset SATA host port via ATA SRST. On controllers with - * reliable PCS present bits, the bits are used to determine - * device presence. - * - * LOCKING: - * Kernel thread context (may sleep) - * - * RETURNS: - * 0 on success, -errno otherwise. - */ -static int piix_sata_softreset(struct ata_port *ap, unsigned int *classes) -{ - unsigned int present_mask; - int i, rc; - - present_mask = piix_sata_present_mask(ap); - - rc = ata_std_softreset(ap, classes); - if (rc) - return rc; - - for (i = 0; i < ATA_MAX_DEVICES; i++) { - if (!(present_mask & (1 << i))) - classes[i] = ATA_DEV_NONE; + if (!present) { + ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n"); + ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; + return 0; } - return 0; + return ata_std_prereset(ap); } static void piix_sata_error_handler(struct ata_port *ap) { - ata_bmdma_drive_eh(ap, ata_std_prereset, piix_sata_softreset, NULL, + ata_bmdma_drive_eh(ap, piix_sata_prereset, ata_std_softreset, NULL, ata_std_postreset); } @@ -849,7 +785,6 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev) } static void __devinit piix_init_pcs(struct pci_dev *pdev, - struct ata_port_info *pinfo, const struct piix_map_db *map_db) { u16 pcs, new_pcs; @@ -863,18 +798,6 @@ static void __devinit piix_init_pcs(struct pci_dev *pdev, pci_write_config_word(pdev, ICH5_PCS, new_pcs); msleep(150); } - - if (force_pcs == 1) { - dev_printk(KERN_INFO, &pdev->dev, - "force ignoring PCS (0x%x)\n", new_pcs); - pinfo[0].host_flags |= PIIX_FLAG_IGNORE_PCS; - pinfo[1].host_flags |= PIIX_FLAG_IGNORE_PCS; - } else if (force_pcs == 2) { - dev_printk(KERN_INFO, &pdev->dev, - "force honoring PCS (0x%x)\n", new_pcs); - pinfo[0].host_flags &= ~PIIX_FLAG_IGNORE_PCS; - pinfo[1].host_flags &= ~PIIX_FLAG_IGNORE_PCS; - } } static void __devinit piix_init_sata_map(struct pci_dev *pdev, @@ -905,7 +828,6 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev, case IDE: WARN_ON((i & 1) || map[i + 1] != IDE); pinfo[i / 2] = piix_port_info[ich5_pata]; - pinfo[i / 2].private_data = hpriv; i++; printk(" IDE IDE"); break; @@ -983,8 +905,7 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (host_flags & ATA_FLAG_SATA) { piix_init_sata_map(pdev, port_info, piix_map_db_table[ent->driver_data]); - piix_init_pcs(pdev, port_info, - piix_map_db_table[ent->driver_data]); + piix_init_pcs(pdev, piix_map_db_table[ent->driver_data]); } /* On ICH5, some BIOSen disable the interrupt using the diff --git a/trunk/drivers/scsi/esp.c b/trunk/drivers/scsi/esp.c index 5630868c1b25..98bd22714d0d 100644 --- a/trunk/drivers/scsi/esp.c +++ b/trunk/drivers/scsi/esp.c @@ -1146,7 +1146,7 @@ static struct sbus_dev sun4_esp_dev; static int __init esp_sun4_probe(struct scsi_host_template *tpnt) { if (sun4_esp_physaddr) { - memset(&sun4_esp_dev, 0, sizeof(sun4_esp_dev)); + memset(&sun4_esp_dev, 0, sizeof(esp_dev)); sun4_esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr; sun4_esp_dev.irqs[0] = 4; sun4_esp_dev.resource[0].start = sun4_esp_physaddr; @@ -1162,7 +1162,6 @@ static int __init esp_sun4_probe(struct scsi_host_template *tpnt) static int __devexit esp_sun4_remove(void) { - struct of_device *dev = &sun4_esp_dev.ofdev; struct esp *esp = dev_get_drvdata(&dev->dev); return esp_remove_common(esp); diff --git a/trunk/drivers/scsi/hptiop.c b/trunk/drivers/scsi/hptiop.c index bcb3444f1dcf..ab2f8b267908 100644 --- a/trunk/drivers/scsi/hptiop.c +++ b/trunk/drivers/scsi/hptiop.c @@ -45,6 +45,10 @@ static char driver_name[] = "hptiop"; static const char driver_name_long[] = "RocketRAID 3xxx SATA Controller driver"; static const char driver_ver[] = "v1.0 (060426)"; +static DEFINE_SPINLOCK(hptiop_hba_list_lock); +static LIST_HEAD(hptiop_hba_list); +static int hptiop_cdev_major = -1; + static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag); static void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag); static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg); @@ -573,7 +577,7 @@ static int hptiop_reset_hba(struct hptiop_hba *hba) if (atomic_xchg(&hba->resetting, 1) == 0) { atomic_inc(&hba->reset_count); writel(IOPMU_INBOUND_MSG0_RESET, - &hba->iop->inbound_msgaddr0); + &hba->iop->outbound_msgaddr0); hptiop_pci_posting_flush(hba->iop); } @@ -616,11 +620,532 @@ static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev, return queue_depth; } +struct hptiop_getinfo { + char __user *buffer; + loff_t buflength; + loff_t bufoffset; + loff_t buffillen; + loff_t filpos; +}; + +static void hptiop_copy_mem_info(struct hptiop_getinfo *pinfo, + char *data, int datalen) +{ + if (pinfo->filpos < pinfo->bufoffset) { + if (pinfo->filpos + datalen <= pinfo->bufoffset) { + pinfo->filpos += datalen; + return; + } else { + data += (pinfo->bufoffset - pinfo->filpos); + datalen -= (pinfo->bufoffset - pinfo->filpos); + pinfo->filpos = pinfo->bufoffset; + } + } + + pinfo->filpos += datalen; + if (pinfo->buffillen == pinfo->buflength) + return; + + if (pinfo->buflength - pinfo->buffillen < datalen) + datalen = pinfo->buflength - pinfo->buffillen; + + if (copy_to_user(pinfo->buffer + pinfo->buffillen, data, datalen)) + return; + + pinfo->buffillen += datalen; +} + +static int hptiop_copy_info(struct hptiop_getinfo *pinfo, char *fmt, ...) +{ + va_list args; + char buf[128]; + int len; + + va_start(args, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + hptiop_copy_mem_info(pinfo, buf, len); + return len; +} + +static void hptiop_ioctl_done(struct hpt_ioctl_k *arg) +{ + arg->done = NULL; + wake_up(&arg->hba->ioctl_wq); +} + +static void hptiop_do_ioctl(struct hpt_ioctl_k *arg) +{ + struct hptiop_hba *hba = arg->hba; + u32 val; + struct hpt_iop_request_ioctl_command __iomem *req; + int ioctl_retry = 0; + + dprintk("scsi%d: hptiop_do_ioctl\n", hba->host->host_no); + + /* + * check (in + out) buff size from application. + * outbuf must be dword aligned. + */ + if (((arg->inbuf_size + 3) & ~3) + arg->outbuf_size > + hba->max_request_size + - sizeof(struct hpt_iop_request_header) + - 4 * sizeof(u32)) { + dprintk("scsi%d: ioctl buf size (%d/%d) is too large\n", + hba->host->host_no, + arg->inbuf_size, arg->outbuf_size); + arg->result = HPT_IOCTL_RESULT_FAILED; + return; + } + +retry: + spin_lock_irq(hba->host->host_lock); + + val = readl(&hba->iop->inbound_queue); + if (val == IOPMU_QUEUE_EMPTY) { + spin_unlock_irq(hba->host->host_lock); + dprintk("scsi%d: no free req for ioctl\n", hba->host->host_no); + arg->result = -1; + return; + } + + req = (struct hpt_iop_request_ioctl_command __iomem *) + ((unsigned long)hba->iop + val); + + writel(HPT_CTL_CODE_LINUX_TO_IOP(arg->ioctl_code), + &req->ioctl_code); + writel(arg->inbuf_size, &req->inbuf_size); + writel(arg->outbuf_size, &req->outbuf_size); + + /* + * use the buffer on the IOP local memory first, then copy it + * back to host. + * the caller's request buffer shoudl be little-endian. + */ + if (arg->inbuf_size) + memcpy_toio(req->buf, arg->inbuf, arg->inbuf_size); + + /* correct the controller ID for IOP */ + if ((arg->ioctl_code == HPT_IOCTL_GET_CHANNEL_INFO || + arg->ioctl_code == HPT_IOCTL_GET_CONTROLLER_INFO_V2 || + arg->ioctl_code == HPT_IOCTL_GET_CONTROLLER_INFO) + && arg->inbuf_size >= sizeof(u32)) + writel(0, req->buf); + + writel(IOP_REQUEST_TYPE_IOCTL_COMMAND, &req->header.type); + writel(0, &req->header.flags); + writel(offsetof(struct hpt_iop_request_ioctl_command, buf) + + arg->inbuf_size, &req->header.size); + writel((u32)(unsigned long)arg, &req->header.context); + writel(BITS_PER_LONG > 32 ? (u32)((unsigned long)arg>>32) : 0, + &req->header.context_hi32); + writel(IOP_RESULT_PENDING, &req->header.result); + + arg->result = HPT_IOCTL_RESULT_FAILED; + arg->done = hptiop_ioctl_done; + + writel(val, &hba->iop->inbound_queue); + hptiop_pci_posting_flush(hba->iop); + + spin_unlock_irq(hba->host->host_lock); + + wait_event_timeout(hba->ioctl_wq, arg->done == NULL, 60 * HZ); + + if (arg->done != NULL) { + hptiop_reset_hba(hba); + if (ioctl_retry++ < 3) + goto retry; + } + + dprintk("hpt_iop_ioctl %x result %d\n", + arg->ioctl_code, arg->result); +} + +static int __hpt_do_ioctl(struct hptiop_hba *hba, u32 code, void *inbuf, + u32 insize, void *outbuf, u32 outsize) +{ + struct hpt_ioctl_k arg; + arg.hba = hba; + arg.ioctl_code = code; + arg.inbuf = inbuf; + arg.outbuf = outbuf; + arg.inbuf_size = insize; + arg.outbuf_size = outsize; + arg.bytes_returned = NULL; + hptiop_do_ioctl(&arg); + return arg.result; +} + +static inline int hpt_id_valid(__le32 id) +{ + return id != 0 && id != cpu_to_le32(0xffffffff); +} + +static int hptiop_get_controller_info(struct hptiop_hba *hba, + struct hpt_controller_info *pinfo) +{ + int id = 0; + + return __hpt_do_ioctl(hba, HPT_IOCTL_GET_CONTROLLER_INFO, + &id, sizeof(int), pinfo, sizeof(*pinfo)); +} + + +static int hptiop_get_channel_info(struct hptiop_hba *hba, int bus, + struct hpt_channel_info *pinfo) +{ + u32 ids[2]; + + ids[0] = 0; + ids[1] = bus; + return __hpt_do_ioctl(hba, HPT_IOCTL_GET_CHANNEL_INFO, + ids, sizeof(ids), pinfo, sizeof(*pinfo)); + +} + +static int hptiop_get_logical_devices(struct hptiop_hba *hba, + __le32 *pids, int maxcount) +{ + int i; + u32 count = maxcount - 1; + + if (__hpt_do_ioctl(hba, HPT_IOCTL_GET_LOGICAL_DEVICES, + &count, sizeof(u32), + pids, sizeof(u32) * maxcount)) + return -1; + + maxcount = le32_to_cpu(pids[0]); + for (i = 0; i < maxcount; i++) + pids[i] = pids[i+1]; + + return maxcount; +} + +static int hptiop_get_device_info_v3(struct hptiop_hba *hba, __le32 id, + struct hpt_logical_device_info_v3 *pinfo) +{ + return __hpt_do_ioctl(hba, HPT_IOCTL_GET_DEVICE_INFO_V3, + &id, sizeof(u32), + pinfo, sizeof(*pinfo)); +} + +static const char *get_array_status(struct hpt_logical_device_info_v3 *devinfo) +{ + static char s[64]; + u32 flags = le32_to_cpu(devinfo->u.array.flags); + u32 trans_prog = le32_to_cpu(devinfo->u.array.transforming_progress); + u32 reb_prog = le32_to_cpu(devinfo->u.array.rebuilding_progress); + + if (flags & ARRAY_FLAG_DISABLED) + return "Disabled"; + else if (flags & ARRAY_FLAG_TRANSFORMING) + sprintf(s, "Expanding/Migrating %d.%d%%%s%s", + trans_prog / 100, + trans_prog % 100, + (flags & (ARRAY_FLAG_NEEDBUILDING|ARRAY_FLAG_BROKEN))? + ", Critical" : "", + ((flags & ARRAY_FLAG_NEEDINITIALIZING) && + !(flags & ARRAY_FLAG_REBUILDING) && + !(flags & ARRAY_FLAG_INITIALIZING))? + ", Unintialized" : ""); + else if ((flags & ARRAY_FLAG_BROKEN) && + devinfo->u.array.array_type != AT_RAID6) + return "Critical"; + else if (flags & ARRAY_FLAG_REBUILDING) + sprintf(s, + (flags & ARRAY_FLAG_NEEDINITIALIZING)? + "%sBackground initializing %d.%d%%" : + "%sRebuilding %d.%d%%", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : "", + reb_prog / 100, + reb_prog % 100); + else if (flags & ARRAY_FLAG_VERIFYING) + sprintf(s, "%sVerifying %d.%d%%", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : "", + reb_prog / 100, + reb_prog % 100); + else if (flags & ARRAY_FLAG_INITIALIZING) + sprintf(s, "%sForground initializing %d.%d%%", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : "", + reb_prog / 100, + reb_prog % 100); + else if (flags & ARRAY_FLAG_NEEDTRANSFORM) + sprintf(s,"%s%s%s", "Need Expanding/Migrating", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : "", + ((flags & ARRAY_FLAG_NEEDINITIALIZING) && + !(flags & ARRAY_FLAG_REBUILDING) && + !(flags & ARRAY_FLAG_INITIALIZING))? + ", Unintialized" : ""); + else if (flags & ARRAY_FLAG_NEEDINITIALIZING && + !(flags & ARRAY_FLAG_REBUILDING) && + !(flags & ARRAY_FLAG_INITIALIZING)) + sprintf(s,"%sUninitialized", + (flags & ARRAY_FLAG_BROKEN)? "Critical, " : ""); + else if ((flags & ARRAY_FLAG_NEEDBUILDING) || + (flags & ARRAY_FLAG_BROKEN)) + return "Critical"; + else + return "Normal"; + return s; +} + +static void hptiop_dump_devinfo(struct hptiop_hba *hba, + struct hptiop_getinfo *pinfo, __le32 id, int indent) +{ + struct hpt_logical_device_info_v3 devinfo; + int i; + u64 capacity; + + for (i = 0; i < indent; i++) + hptiop_copy_info(pinfo, "\t"); + + if (hptiop_get_device_info_v3(hba, id, &devinfo)) { + hptiop_copy_info(pinfo, "unknown\n"); + return; + } + + switch (devinfo.type) { + + case LDT_DEVICE: { + struct hd_driveid *driveid; + u32 flags = le32_to_cpu(devinfo.u.device.flags); + + driveid = (struct hd_driveid *)devinfo.u.device.ident; + /* model[] is 40 chars long, but we just want 20 chars here */ + driveid->model[20] = 0; + + if (indent) + if (flags & DEVICE_FLAG_DISABLED) + hptiop_copy_info(pinfo,"Missing\n"); + else + hptiop_copy_info(pinfo, "CH%d %s\n", + devinfo.u.device.path_id + 1, + driveid->model); + else { + capacity = le64_to_cpu(devinfo.capacity) * 512; + do_div(capacity, 1000000); + hptiop_copy_info(pinfo, + "CH%d %s, %lluMB, %s %s%s%s%s\n", + devinfo.u.device.path_id + 1, + driveid->model, + capacity, + (flags & DEVICE_FLAG_DISABLED)? + "Disabled" : "Normal", + devinfo.u.device.read_ahead_enabled? + "[RA]" : "", + devinfo.u.device.write_cache_enabled? + "[WC]" : "", + devinfo.u.device.TCQ_enabled? + "[TCQ]" : "", + devinfo.u.device.NCQ_enabled? + "[NCQ]" : "" + ); + } + break; + } + + case LDT_ARRAY: + if (devinfo.target_id != INVALID_TARGET_ID) + hptiop_copy_info(pinfo, "[DISK %d_%d] ", + devinfo.vbus_id, devinfo.target_id); + + capacity = le64_to_cpu(devinfo.capacity) * 512; + do_div(capacity, 1000000); + hptiop_copy_info(pinfo, "%s (%s), %lluMB, %s\n", + devinfo.u.array.name, + devinfo.u.array.array_type==AT_RAID0? "RAID0" : + devinfo.u.array.array_type==AT_RAID1? "RAID1" : + devinfo.u.array.array_type==AT_RAID5? "RAID5" : + devinfo.u.array.array_type==AT_RAID6? "RAID6" : + devinfo.u.array.array_type==AT_JBOD? "JBOD" : + "unknown", + capacity, + get_array_status(&devinfo)); + for (i = 0; i < devinfo.u.array.ndisk; i++) { + if (hpt_id_valid(devinfo.u.array.members[i])) { + if (cpu_to_le16(1<private_data; + struct hptiop_getinfo info; + int i, j, ndev; + struct hpt_controller_info con_info; + struct hpt_channel_info chan_info; + __le32 ids[32]; + + info.buffer = buf; + info.buflength = count; + info.bufoffset = ppos ? *ppos : 0; + info.filpos = 0; + info.buffillen = 0; + + if (hptiop_get_controller_info(hba, &con_info)) + return -EIO; + + for (i = 0; i < con_info.num_buses; i++) { + if (hptiop_get_channel_info(hba, i, &chan_info) == 0) { + if (hpt_id_valid(chan_info.devices[0])) + hptiop_dump_devinfo(hba, &info, + chan_info.devices[0], 0); + if (hpt_id_valid(chan_info.devices[1])) + hptiop_dump_devinfo(hba, &info, + chan_info.devices[1], 0); + } + } + + ndev = hptiop_get_logical_devices(hba, ids, + sizeof(ids) / sizeof(ids[0])); + + /* + * if hptiop_get_logical_devices fails, ndev==-1 and it just + * output nothing here + */ + for (j = 0; j < ndev; j++) + hptiop_dump_devinfo(hba, &info, ids[j], 0); + + if (ppos) + *ppos += info.buffillen; + + return info.buffillen; +} + +static int hptiop_cdev_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct hptiop_hba *hba = file->private_data; + struct hpt_ioctl_u ioctl_u; + struct hpt_ioctl_k ioctl_k; + u32 bytes_returned; + int err = -EINVAL; + + if (copy_from_user(&ioctl_u, + (void __user *)arg, sizeof(struct hpt_ioctl_u))) + return -EINVAL; + + if (ioctl_u.magic != HPT_IOCTL_MAGIC) + return -EINVAL; + + ioctl_k.ioctl_code = ioctl_u.ioctl_code; + ioctl_k.inbuf = NULL; + ioctl_k.inbuf_size = ioctl_u.inbuf_size; + ioctl_k.outbuf = NULL; + ioctl_k.outbuf_size = ioctl_u.outbuf_size; + ioctl_k.hba = hba; + ioctl_k.bytes_returned = &bytes_returned; + + /* verify user buffer */ + if ((ioctl_k.inbuf_size && !access_ok(VERIFY_READ, + ioctl_u.inbuf, ioctl_k.inbuf_size)) || + (ioctl_k.outbuf_size && !access_ok(VERIFY_WRITE, + ioctl_u.outbuf, ioctl_k.outbuf_size)) || + (ioctl_u.bytes_returned && !access_ok(VERIFY_WRITE, + ioctl_u.bytes_returned, sizeof(u32))) || + ioctl_k.inbuf_size + ioctl_k.outbuf_size > 0x10000) { + + dprintk("scsi%d: got bad user address\n", hba->host->host_no); + return -EINVAL; + } + + /* map buffer to kernel. */ + if (ioctl_k.inbuf_size) { + ioctl_k.inbuf = kmalloc(ioctl_k.inbuf_size, GFP_KERNEL); + if (!ioctl_k.inbuf) { + dprintk("scsi%d: fail to alloc inbuf\n", + hba->host->host_no); + err = -ENOMEM; + goto err_exit; + } + + if (copy_from_user(ioctl_k.inbuf, + ioctl_u.inbuf, ioctl_k.inbuf_size)) { + goto err_exit; + } + } + + if (ioctl_k.outbuf_size) { + ioctl_k.outbuf = kmalloc(ioctl_k.outbuf_size, GFP_KERNEL); + if (!ioctl_k.outbuf) { + dprintk("scsi%d: fail to alloc outbuf\n", + hba->host->host_no); + err = -ENOMEM; + goto err_exit; + } + } + + hptiop_do_ioctl(&ioctl_k); + + if (ioctl_k.result == HPT_IOCTL_RESULT_OK) { + if (ioctl_k.outbuf_size && + copy_to_user(ioctl_u.outbuf, + ioctl_k.outbuf, ioctl_k.outbuf_size)) + goto err_exit; + + if (ioctl_u.bytes_returned && + copy_to_user(ioctl_u.bytes_returned, + &bytes_returned, sizeof(u32))) + goto err_exit; + + err = 0; + } + +err_exit: + kfree(ioctl_k.inbuf); + kfree(ioctl_k.outbuf); + + return err; +} + +static int hptiop_cdev_open(struct inode *inode, struct file *file) +{ + struct hptiop_hba *hba; + unsigned i = 0, minor = iminor(inode); + int ret = -ENODEV; + + spin_lock(&hptiop_hba_list_lock); + list_for_each_entry(hba, &hptiop_hba_list, link) { + if (i == minor) { + file->private_data = hba; + ret = 0; + goto out; + } + i++; + } + +out: + spin_unlock(&hptiop_hba_list_lock); + return ret; +} + +static struct file_operations hptiop_cdev_fops = { + .owner = THIS_MODULE, + .read = hptiop_cdev_read, + .ioctl = hptiop_cdev_ioctl, + .open = hptiop_cdev_open, +}; + static ssize_t hptiop_show_fw_version(struct class_device *class_dev, char *buf) { struct Scsi_Host *host = class_to_shost(class_dev); @@ -771,13 +1296,19 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, goto unmap_pci_bar; } + if (scsi_add_host(host, &pcidev->dev)) { + printk(KERN_ERR "scsi%d: scsi_add_host failed\n", + hba->host->host_no); + goto unmap_pci_bar; + } + pci_set_drvdata(pcidev, host); if (request_irq(pcidev->irq, hptiop_intr, IRQF_SHARED, driver_name, hba)) { printk(KERN_ERR "scsi%d: request irq %d failed\n", hba->host->host_no, pcidev->irq); - goto unmap_pci_bar; + goto remove_scsi_host; } /* Allocate request mem */ @@ -824,12 +1355,9 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, if (hptiop_initialize_iop(hba)) goto free_request_mem; - if (scsi_add_host(host, &pcidev->dev)) { - printk(KERN_ERR "scsi%d: scsi_add_host failed\n", - hba->host->host_no); - goto free_request_mem; - } - + spin_lock(&hptiop_hba_list_lock); + list_add_tail(&hba->link, &hptiop_hba_list); + spin_unlock(&hptiop_hba_list_lock); scsi_scan_host(host); @@ -844,6 +1372,9 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, free_request_irq: free_irq(hba->pcidev->irq, hba); +remove_scsi_host: + scsi_remove_host(host); + unmap_pci_bar: iounmap(hba->iop); @@ -891,6 +1422,10 @@ static void hptiop_remove(struct pci_dev *pcidev) scsi_remove_host(host); + spin_lock(&hptiop_hba_list_lock); + list_del_init(&hba->link); + spin_unlock(&hptiop_hba_list_lock); + hptiop_shutdown(pcidev); free_irq(hba->pcidev->irq, hba); @@ -927,12 +1462,27 @@ static struct pci_driver hptiop_pci_driver = { static int __init hptiop_module_init(void) { + int error; + printk(KERN_INFO "%s %s\n", driver_name_long, driver_ver); - return pci_register_driver(&hptiop_pci_driver); + + error = pci_register_driver(&hptiop_pci_driver); + if (error < 0) + return error; + + hptiop_cdev_major = register_chrdev(0, "hptiop", &hptiop_cdev_fops); + if (hptiop_cdev_major < 0) { + printk(KERN_WARNING "unable to register hptiop device.\n"); + return hptiop_cdev_major; + } + + return 0; } static void __exit hptiop_module_exit(void) { + dprintk("hptiop_module_exit\n"); + unregister_chrdev(hptiop_cdev_major, "hptiop"); pci_unregister_driver(&hptiop_pci_driver); } diff --git a/trunk/drivers/scsi/ibmvscsi/rpa_vscsi.c b/trunk/drivers/scsi/ibmvscsi/rpa_vscsi.c index 01b8ac641eb8..ed22b96580c6 100644 --- a/trunk/drivers/scsi/ibmvscsi/rpa_vscsi.c +++ b/trunk/drivers/scsi/ibmvscsi/rpa_vscsi.c @@ -156,8 +156,8 @@ static void gather_partition_info(void) { struct device_node *rootdn; - const char *ppartition_name; - const unsigned int *p_number_ptr; + char *ppartition_name; + unsigned int *p_number_ptr; /* Retrieve information about this partition */ rootdn = find_path_device("/"); @@ -165,11 +165,14 @@ static void gather_partition_info(void) return; } - ppartition_name = get_property(rootdn, "ibm,partition-name", NULL); + ppartition_name = + get_property(rootdn, "ibm,partition-name", NULL); if (ppartition_name) strncpy(partition_name, ppartition_name, sizeof(partition_name)); - p_number_ptr = get_property(rootdn, "ibm,partition-no", NULL); + p_number_ptr = + (unsigned int *)get_property(rootdn, "ibm,partition-no", + NULL); if (p_number_ptr) partition_number = *p_number_ptr; } diff --git a/trunk/drivers/scsi/ide-scsi.c b/trunk/drivers/scsi/ide-scsi.c index 94d1de55607f..f7b5d7372d26 100644 --- a/trunk/drivers/scsi/ide-scsi.c +++ b/trunk/drivers/scsi/ide-scsi.c @@ -517,7 +517,7 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) /* No more interrupts */ if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred); - local_irq_enable_in_hardirq(); + local_irq_enable(); if (status.b.check) rq->errors++; idescsi_end_request (drive, 1, 0); diff --git a/trunk/drivers/scsi/iscsi_tcp.c b/trunk/drivers/scsi/iscsi_tcp.c index 66a1ae1d6982..848fb2aa4ca3 100644 --- a/trunk/drivers/scsi/iscsi_tcp.c +++ b/trunk/drivers/scsi/iscsi_tcp.c @@ -26,7 +26,6 @@ * Zhenyu Wang */ -#include #include #include #include @@ -44,10 +43,13 @@ #include "iscsi_tcp.h" +#define ISCSI_TCP_VERSION "1.0-595" + MODULE_AUTHOR("Dmitry Yusupov , " "Alex Aizman "); MODULE_DESCRIPTION("iSCSI/TCP data-path"); MODULE_LICENSE("GPL"); +MODULE_VERSION(ISCSI_TCP_VERSION); /* #define DEBUG_TCP */ #define DEBUG_ASSERT @@ -108,11 +110,8 @@ iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf, u8* crc) { struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - struct hash_desc desc; - desc.tfm = tcp_conn->tx_tfm; - desc.flags = 0; - crypto_hash_digest(&desc, &buf->sg, buf->sg.length, crc); + crypto_digest_digest(tcp_conn->tx_tfm, &buf->sg, 1, crc); buf->sg.length += sizeof(uint32_t); } @@ -186,19 +185,11 @@ iscsi_hdr_extract(struct iscsi_tcp_conn *tcp_conn) * must be called with session lock */ static void -iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +__iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) { struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - struct iscsi_r2t_info *r2t; struct scsi_cmnd *sc; - /* flush ctask's r2t queues */ - while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) { - __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, - sizeof(void*)); - debug_scsi("iscsi_tcp_cleanup_ctask pending r2t dropped\n"); - } - sc = ctask->sc; if (unlikely(!sc)) return; @@ -383,7 +374,6 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) spin_unlock(&session->lock); return 0; } - rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); BUG_ON(!rc); @@ -409,7 +399,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) tcp_ctask->exp_r2tsn = r2tsn + 1; tcp_ctask->xmstate |= XMSTATE_SOL_HDR; __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); - list_move_tail(&ctask->running, &conn->xmitqueue); + __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); scsi_queue_work(session->host, &conn->xmitwork); conn->r2t_pdus_cnt++; @@ -456,14 +446,11 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn) } if (conn->hdrdgst_en) { - struct hash_desc desc; struct scatterlist sg; sg_init_one(&sg, (u8 *)hdr, sizeof(struct iscsi_hdr) + ahslen); - desc.tfm = tcp_conn->rx_tfm; - desc.flags = 0; - crypto_hash_digest(&desc, &sg, sg.length, (u8 *)&cdgst); + crypto_digest_digest(tcp_conn->rx_tfm, &sg, 1, (u8 *)&cdgst); rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) + ahslen); if (cdgst != rdgst) { @@ -490,8 +477,6 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn) case ISCSI_OP_SCSI_DATA_IN: tcp_conn->in.ctask = session->cmds[itt]; rc = iscsi_data_rsp(conn, tcp_conn->in.ctask); - if (rc) - return rc; /* fall through */ case ISCSI_OP_SCSI_CMD_RSP: tcp_conn->in.ctask = session->cmds[itt]; @@ -499,7 +484,7 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn) goto copy_hdr; spin_lock(&session->lock); - iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask); + __iscsi_ctask_cleanup(conn, tcp_conn->in.ctask); rc = __iscsi_complete_pdu(conn, hdr, NULL, 0); spin_unlock(&session->lock); break; @@ -515,28 +500,13 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn) break; case ISCSI_OP_LOGIN_RSP: case ISCSI_OP_TEXT_RSP: + case ISCSI_OP_LOGOUT_RSP: + case ISCSI_OP_NOOP_IN: case ISCSI_OP_REJECT: case ISCSI_OP_ASYNC_EVENT: - /* - * It is possible that we could get a PDU with a buffer larger - * than 8K, but there are no targets that currently do this. - * For now we fail until we find a vendor that needs it - */ - if (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH < - tcp_conn->in.datalen) { - printk(KERN_ERR "iscsi_tcp: received buffer of len %u " - "but conn buffer is only %u (opcode %0x)\n", - tcp_conn->in.datalen, - DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, opcode); - rc = ISCSI_ERR_PROTO; - break; - } - if (tcp_conn->in.datalen) goto copy_hdr; /* fall through */ - case ISCSI_OP_LOGOUT_RSP: - case ISCSI_OP_NOOP_IN: case ISCSI_OP_SCSI_TMFUNC_RSP: rc = iscsi_complete_pdu(conn, hdr, NULL, 0); break; @@ -553,7 +523,7 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn) * skbs to complete the command then we have to copy the header * for later use */ - if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy <= + if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy < (tcp_conn->in.datalen + tcp_conn->in.padding + (conn->datadgst_en ? 4 : 0))) { debug_tcp("Copying header for later use. in.copy %d in.datalen" @@ -644,9 +614,9 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask, * byte counters. **/ static inline int -iscsi_tcp_copy(struct iscsi_conn *conn) +iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn) { - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + void *buf = tcp_conn->data; int buf_size = tcp_conn->in.datalen; int buf_left = buf_size - tcp_conn->data_copied; int size = min(tcp_conn->in.copy, buf_left); @@ -657,7 +627,7 @@ iscsi_tcp_copy(struct iscsi_conn *conn) BUG_ON(size <= 0); rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, - (char*)conn->data + tcp_conn->data_copied, size); + (char*)buf + tcp_conn->data_copied, size); BUG_ON(rc); tcp_conn->in.offset += size; @@ -680,7 +650,7 @@ partial_sg_digest_update(struct iscsi_tcp_conn *tcp_conn, memcpy(&temp, sg, sizeof(struct scatterlist)); temp.offset = offset; temp.length = length; - crypto_hash_update(&tcp_conn->data_rx_hash, &temp, length); + crypto_digest_update(tcp_conn->data_rx_tfm, &temp, 1); } static void @@ -689,7 +659,7 @@ iscsi_recv_digest_update(struct iscsi_tcp_conn *tcp_conn, char* buf, int len) struct scatterlist tmp; sg_init_one(&tmp, buf, len); - crypto_hash_update(&tcp_conn->data_rx_hash, &tmp, len); + crypto_digest_update(tcp_conn->data_rx_tfm, &tmp, 1); } static int iscsi_scsi_data_in(struct iscsi_conn *conn) @@ -743,9 +713,9 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) if (!rc) { if (conn->datadgst_en) { if (!offset) - crypto_hash_update( - &tcp_conn->data_rx_hash, - &sg[i], sg[i].length); + crypto_digest_update( + tcp_conn->data_rx_tfm, + &sg[i], 1); else partial_sg_digest_update(tcp_conn, &sg[i], @@ -775,11 +745,10 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) done: /* check for non-exceptional status */ if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) { - debug_scsi("done [sc %lx res %d itt 0x%x flags 0x%x]\n", - (long)sc, sc->result, ctask->itt, - tcp_conn->in.hdr->flags); + debug_scsi("done [sc %lx res %d itt 0x%x]\n", + (long)sc, sc->result, ctask->itt); spin_lock(&conn->session->lock); - iscsi_tcp_cleanup_ctask(conn, ctask); + __iscsi_ctask_cleanup(conn, ctask); __iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0); spin_unlock(&conn->session->lock); } @@ -800,25 +769,26 @@ iscsi_data_recv(struct iscsi_conn *conn) break; case ISCSI_OP_SCSI_CMD_RSP: spin_lock(&conn->session->lock); - iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask); + __iscsi_ctask_cleanup(conn, tcp_conn->in.ctask); spin_unlock(&conn->session->lock); case ISCSI_OP_TEXT_RSP: case ISCSI_OP_LOGIN_RSP: + case ISCSI_OP_NOOP_IN: case ISCSI_OP_ASYNC_EVENT: case ISCSI_OP_REJECT: /* * Collect data segment to the connection's data * placeholder */ - if (iscsi_tcp_copy(conn)) { + if (iscsi_tcp_copy(tcp_conn)) { rc = -EAGAIN; goto exit; } - rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, conn->data, + rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, tcp_conn->data, tcp_conn->in.datalen); if (!rc && conn->datadgst_en && opcode != ISCSI_OP_LOGIN_RSP) - iscsi_recv_digest_update(tcp_conn, conn->data, + iscsi_recv_digest_update(tcp_conn, tcp_conn->data, tcp_conn->in.datalen); break; default: @@ -873,7 +843,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, if (rc == -EAGAIN) goto nomore; else { - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + iscsi_conn_failure(conn, rc); return 0; } } @@ -884,7 +854,8 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, rc = iscsi_tcp_hdr_recv(conn); if (!rc && tcp_conn->in.datalen) { if (conn->datadgst_en) { - crypto_hash_init(&tcp_conn->data_rx_hash); + BUG_ON(!tcp_conn->data_rx_tfm); + crypto_digest_init(tcp_conn->data_rx_tfm); } tcp_conn->in_progress = IN_PROGRESS_DATA_RECV; } else if (rc) { @@ -926,7 +897,7 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, if (rc) { if (rc == -EAGAIN) goto again; - iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + iscsi_conn_failure(conn, rc); return 0; } tcp_conn->in.copy -= tcp_conn->in.padding; @@ -937,11 +908,11 @@ iscsi_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, tcp_conn->in.padding); memset(pad, 0, tcp_conn->in.padding); sg_init_one(&sg, pad, tcp_conn->in.padding); - crypto_hash_update(&tcp_conn->data_rx_hash, - &sg, sg.length); + crypto_digest_update(tcp_conn->data_rx_tfm, + &sg, 1); } - crypto_hash_final(&tcp_conn->data_rx_hash, - (u8 *)&tcp_conn->in.datadgst); + crypto_digest_final(tcp_conn->data_rx_tfm, + (u8 *) & tcp_conn->in.datadgst); debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst); tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV; } else @@ -1057,8 +1028,9 @@ iscsi_conn_set_callbacks(struct iscsi_conn *conn) } static void -iscsi_conn_restore_callbacks(struct iscsi_tcp_conn *tcp_conn) +iscsi_conn_restore_callbacks(struct iscsi_conn *conn) { + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct sock *sk = tcp_conn->sock->sk; /* restore socket callbacks, see also: iscsi_conn_set_callbacks() */ @@ -1187,7 +1159,8 @@ iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn, { struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; - crypto_hash_init(&tcp_conn->data_tx_hash); + BUG_ON(!tcp_conn->data_tx_tfm); + crypto_digest_init(tcp_conn->data_tx_tfm); tcp_ctask->digest_count = 4; } @@ -1201,7 +1174,7 @@ iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, int sent = 0; if (final) - crypto_hash_final(&tcp_conn->data_tx_hash, (u8 *)digest); + crypto_digest_final(tcp_conn->data_tx_tfm, (u8*)digest); iscsi_buf_init_iov(buf, (char*)digest, 4); rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); @@ -1335,7 +1308,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) ctask->imm_count - ctask->unsol_count; - debug_scsi("cmd [itt 0x%x total %d imm %d imm_data %d " + debug_scsi("cmd [itt %x total %d imm %d imm_data %d " "r2t_data %d]\n", ctask->itt, ctask->total_length, ctask->imm_count, ctask->unsol_count, tcp_ctask->r2t_data_count); @@ -1496,17 +1469,16 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) if (rc) { tcp_ctask->xmstate |= XMSTATE_IMM_DATA; if (conn->datadgst_en) { - crypto_hash_final(&tcp_conn->data_tx_hash, - (u8 *)&tcp_ctask->immdigest); + crypto_digest_final(tcp_conn->data_tx_tfm, + (u8*)&tcp_ctask->immdigest); debug_tcp("tx imm sendpage fail 0x%x\n", tcp_ctask->datadigest); } return rc; } if (conn->datadgst_en) - crypto_hash_update(&tcp_conn->data_tx_hash, - &tcp_ctask->sendbuf.sg, - tcp_ctask->sendbuf.sg.length); + crypto_digest_update(tcp_conn->data_tx_tfm, + &tcp_ctask->sendbuf.sg, 1); if (!ctask->imm_count) break; @@ -1583,8 +1555,8 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) tcp_ctask->xmstate |= XMSTATE_UNS_DATA; /* will continue with this ctask later.. */ if (conn->datadgst_en) { - crypto_hash_final(&tcp_conn->data_tx_hash, - (u8 *)&dtask->digest); + crypto_digest_final(tcp_conn->data_tx_tfm, + (u8 *)&dtask->digest); debug_tcp("tx uns data fail 0x%x\n", dtask->digest); } @@ -1599,9 +1571,8 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) * so pass it */ if (conn->datadgst_en && tcp_ctask->sent - start > 0) - crypto_hash_update(&tcp_conn->data_tx_hash, - &tcp_ctask->sendbuf.sg, - tcp_ctask->sendbuf.sg.length); + crypto_digest_update(tcp_conn->data_tx_tfm, + &tcp_ctask->sendbuf.sg, 1); if (!ctask->data_count) break; @@ -1665,7 +1636,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } solicit_again: /* - * send Data-Out within this R2T sequence. + * send Data-Out whitnin this R2T sequence. */ if (!r2t->data_count) goto data_out_done; @@ -1675,7 +1646,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) tcp_ctask->xmstate |= XMSTATE_SOL_DATA; /* will continue with this ctask later.. */ if (conn->datadgst_en) { - crypto_hash_final(&tcp_conn->data_tx_hash, + crypto_digest_final(tcp_conn->data_tx_tfm, (u8 *)&dtask->digest); debug_tcp("r2t data send fail 0x%x\n", dtask->digest); } @@ -1684,8 +1655,8 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) BUG_ON(r2t->data_count < 0); if (conn->datadgst_en) - crypto_hash_update(&tcp_conn->data_tx_hash, &r2t->sendbuf.sg, - r2t->sendbuf.sg.length); + crypto_digest_update(tcp_conn->data_tx_tfm, &r2t->sendbuf.sg, + 1); if (r2t->data_count) { BUG_ON(ctask->sc->use_sg == 0); @@ -1760,7 +1731,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct iscsi_data_task *dtask = tcp_ctask->dtask; - int sent = 0, rc; + int sent, rc; tcp_ctask->xmstate &= ~XMSTATE_W_PAD; iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, @@ -1773,9 +1744,8 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) } if (conn->datadgst_en) { - crypto_hash_update(&tcp_conn->data_tx_hash, - &tcp_ctask->sendbuf.sg, - tcp_ctask->sendbuf.sg.length); + crypto_digest_update(tcp_conn->data_tx_tfm, + &tcp_ctask->sendbuf.sg, 1); /* imm data? */ if (!dtask) { rc = iscsi_digest_final_send(conn, ctask, @@ -1930,31 +1900,26 @@ iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; /* initial operational parameters */ tcp_conn->hdr_size = sizeof(struct iscsi_hdr); + tcp_conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; + + /* allocate initial PDU receive place holder */ + if (tcp_conn->data_size <= PAGE_SIZE) + tcp_conn->data = kmalloc(tcp_conn->data_size, GFP_KERNEL); + else + tcp_conn->data = (void*)__get_free_pages(GFP_KERNEL, + get_order(tcp_conn->data_size)); + if (!tcp_conn->data) + goto max_recv_dlenght_alloc_fail; return cls_conn; +max_recv_dlenght_alloc_fail: + kfree(tcp_conn); tcp_conn_alloc_fail: iscsi_conn_teardown(cls_conn); return NULL; } -static void -iscsi_tcp_release_conn(struct iscsi_conn *conn) -{ - struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - - if (!tcp_conn->sock) - return; - - sock_hold(tcp_conn->sock->sk); - iscsi_conn_restore_callbacks(tcp_conn); - sock_put(tcp_conn->sock->sk); - - sock_release(tcp_conn->sock); - tcp_conn->sock = NULL; - conn->recv_lock = NULL; -} - static void iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) { @@ -1965,33 +1930,29 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) if (conn->hdrdgst_en || conn->datadgst_en) digest = 1; - iscsi_tcp_release_conn(conn); iscsi_conn_teardown(cls_conn); /* now free tcp_conn */ if (digest) { if (tcp_conn->tx_tfm) - crypto_free_hash(tcp_conn->tx_tfm); + crypto_free_tfm(tcp_conn->tx_tfm); if (tcp_conn->rx_tfm) - crypto_free_hash(tcp_conn->rx_tfm); - if (tcp_conn->data_tx_hash.tfm) - crypto_free_hash(tcp_conn->data_tx_hash.tfm); - if (tcp_conn->data_rx_hash.tfm) - crypto_free_hash(tcp_conn->data_rx_hash.tfm); + crypto_free_tfm(tcp_conn->rx_tfm); + if (tcp_conn->data_tx_tfm) + crypto_free_tfm(tcp_conn->data_tx_tfm); + if (tcp_conn->data_rx_tfm) + crypto_free_tfm(tcp_conn->data_rx_tfm); } + /* free conn->data, size = MaxRecvDataSegmentLength */ + if (tcp_conn->data_size <= PAGE_SIZE) + kfree(tcp_conn->data); + else + free_pages((unsigned long)tcp_conn->data, + get_order(tcp_conn->data_size)); kfree(tcp_conn); } -static void -iscsi_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) -{ - struct iscsi_conn *conn = cls_conn->dd_data; - - iscsi_conn_stop(cls_conn, flag); - iscsi_tcp_release_conn(conn); -} - static int iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, @@ -2040,6 +2001,52 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, return 0; } +static void +iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +{ + struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; + struct iscsi_r2t_info *r2t; + + /* flush ctask's r2t queues */ + while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) + __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, + sizeof(void*)); + + __iscsi_ctask_cleanup(conn, ctask); +} + +static void +iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn) +{ + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + struct sock *sk; + + if (!tcp_conn->sock) + return; + + sk = tcp_conn->sock->sk; + write_lock_bh(&sk->sk_callback_lock); + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); + write_unlock_bh(&sk->sk_callback_lock); +} + +static void +iscsi_tcp_terminate_conn(struct iscsi_conn *conn) +{ + struct iscsi_tcp_conn *tcp_conn = conn->dd_data; + + if (!tcp_conn->sock) + return; + + sock_hold(tcp_conn->sock->sk); + iscsi_conn_restore_callbacks(conn); + sock_put(tcp_conn->sock->sk); + + sock_release(tcp_conn->sock); + tcp_conn->sock = NULL; + conn->recv_lock = NULL; +} + /* called with host lock */ static void iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, @@ -2050,7 +2057,6 @@ iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, sizeof(struct iscsi_hdr)); tcp_mtask->xmstate = XMSTATE_IMM_HDR; - tcp_mtask->sent = 0; if (mtask->data_count) iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data, @@ -2132,54 +2138,83 @@ iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, int value; switch(param) { + case ISCSI_PARAM_MAX_RECV_DLENGTH: { + char *saveptr = tcp_conn->data; + gfp_t flags = GFP_KERNEL; + + sscanf(buf, "%d", &value); + if (tcp_conn->data_size >= value) { + iscsi_set_param(cls_conn, param, buf, buflen); + break; + } + + spin_lock_bh(&session->lock); + if (conn->stop_stage == STOP_CONN_RECOVER) + flags = GFP_ATOMIC; + spin_unlock_bh(&session->lock); + + if (value <= PAGE_SIZE) + tcp_conn->data = kmalloc(value, flags); + else + tcp_conn->data = (void*)__get_free_pages(flags, + get_order(value)); + if (tcp_conn->data == NULL) { + tcp_conn->data = saveptr; + return -ENOMEM; + } + if (tcp_conn->data_size <= PAGE_SIZE) + kfree(saveptr); + else + free_pages((unsigned long)saveptr, + get_order(tcp_conn->data_size)); + iscsi_set_param(cls_conn, param, buf, buflen); + tcp_conn->data_size = value; + break; + } case ISCSI_PARAM_HDRDGST_EN: iscsi_set_param(cls_conn, param, buf, buflen); tcp_conn->hdr_size = sizeof(struct iscsi_hdr); if (conn->hdrdgst_en) { tcp_conn->hdr_size += sizeof(__u32); if (!tcp_conn->tx_tfm) - tcp_conn->tx_tfm = - crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(tcp_conn->tx_tfm)) - return PTR_ERR(tcp_conn->tx_tfm); + tcp_conn->tx_tfm = crypto_alloc_tfm("crc32c", + 0); + if (!tcp_conn->tx_tfm) + return -ENOMEM; if (!tcp_conn->rx_tfm) - tcp_conn->rx_tfm = - crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(tcp_conn->rx_tfm)) { - crypto_free_hash(tcp_conn->tx_tfm); - return PTR_ERR(tcp_conn->rx_tfm); + tcp_conn->rx_tfm = crypto_alloc_tfm("crc32c", + 0); + if (!tcp_conn->rx_tfm) { + crypto_free_tfm(tcp_conn->tx_tfm); + return -ENOMEM; } } else { if (tcp_conn->tx_tfm) - crypto_free_hash(tcp_conn->tx_tfm); + crypto_free_tfm(tcp_conn->tx_tfm); if (tcp_conn->rx_tfm) - crypto_free_hash(tcp_conn->rx_tfm); + crypto_free_tfm(tcp_conn->rx_tfm); } break; case ISCSI_PARAM_DATADGST_EN: iscsi_set_param(cls_conn, param, buf, buflen); if (conn->datadgst_en) { - if (!tcp_conn->data_tx_hash.tfm) - tcp_conn->data_tx_hash.tfm = - crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(tcp_conn->data_tx_hash.tfm)) - return PTR_ERR(tcp_conn->data_tx_hash.tfm); - if (!tcp_conn->data_rx_hash.tfm) - tcp_conn->data_rx_hash.tfm = - crypto_alloc_hash("crc32c", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(tcp_conn->data_rx_hash.tfm)) { - crypto_free_hash(tcp_conn->data_tx_hash.tfm); - return PTR_ERR(tcp_conn->data_rx_hash.tfm); + if (!tcp_conn->data_tx_tfm) + tcp_conn->data_tx_tfm = + crypto_alloc_tfm("crc32c", 0); + if (!tcp_conn->data_tx_tfm) + return -ENOMEM; + if (!tcp_conn->data_rx_tfm) + tcp_conn->data_rx_tfm = + crypto_alloc_tfm("crc32c", 0); + if (!tcp_conn->data_rx_tfm) { + crypto_free_tfm(tcp_conn->data_tx_tfm); + return -ENOMEM; } } else { - if (tcp_conn->data_tx_hash.tfm) - crypto_free_hash(tcp_conn->data_tx_hash.tfm); - if (tcp_conn->data_rx_hash.tfm) - crypto_free_hash(tcp_conn->data_rx_hash.tfm); + if (tcp_conn->data_tx_tfm) + crypto_free_tfm(tcp_conn->data_tx_tfm); + if (tcp_conn->data_rx_tfm) + crypto_free_tfm(tcp_conn->data_rx_tfm); } tcp_conn->sendpage = conn->datadgst_en ? sock_no_sendpage : tcp_conn->sock->ops->sendpage; @@ -2326,7 +2361,8 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) } static struct scsi_host_template iscsi_sht = { - .name = "iSCSI Initiator over TCP/IP", + .name = "iSCSI Initiator over TCP/IP, v" + ISCSI_TCP_VERSION, .queuecommand = iscsi_queuecommand, .change_queue_depth = iscsi_change_queue_depth, .can_queue = ISCSI_XMIT_CMDS_MAX - 1, @@ -2378,7 +2414,10 @@ static struct iscsi_transport iscsi_tcp_transport = { .get_conn_param = iscsi_tcp_conn_get_param, .get_session_param = iscsi_session_get_param, .start_conn = iscsi_conn_start, - .stop_conn = iscsi_tcp_conn_stop, + .stop_conn = iscsi_conn_stop, + /* these are called as part of conn recovery */ + .suspend_conn_recv = iscsi_tcp_suspend_conn_rx, + .terminate_conn = iscsi_tcp_terminate_conn, /* IO */ .send_pdu = iscsi_conn_send_pdu, .get_stats = iscsi_conn_get_stats, diff --git a/trunk/drivers/scsi/iscsi_tcp.h b/trunk/drivers/scsi/iscsi_tcp.h index e35701305fc9..808302832e68 100644 --- a/trunk/drivers/scsi/iscsi_tcp.h +++ b/trunk/drivers/scsi/iscsi_tcp.h @@ -51,7 +51,6 @@ #define ISCSI_SG_TABLESIZE SG_ALL #define ISCSI_TCP_MAX_CMD_LEN 16 -struct crypto_hash; struct socket; /* Socket connection recieve helper */ @@ -79,14 +78,16 @@ struct iscsi_tcp_conn { char hdrext[4*sizeof(__u16) + sizeof(__u32)]; int data_copied; + char *data; /* data placeholder */ + int data_size; /* actual recv_dlength */ int stop_stage; /* conn_stop() flag: * * stop to recover, * * stop to terminate */ /* iSCSI connection-wide sequencing */ int hdr_size; /* PDU header size */ - struct crypto_hash *rx_tfm; /* CRC32C (Rx) */ - struct hash_desc data_rx_hash; /* CRC32C (Rx) for data */ + struct crypto_tfm *rx_tfm; /* CRC32C (Rx) */ + struct crypto_tfm *data_rx_tfm; /* CRC32C (Rx) for data */ /* control data */ struct iscsi_tcp_recv in; /* TCP receive context */ @@ -98,8 +99,8 @@ struct iscsi_tcp_conn { void (*old_write_space)(struct sock *); /* xmit */ - struct crypto_hash *tx_tfm; /* CRC32C (Tx) */ - struct hash_desc data_tx_hash; /* CRC32C (Tx) for data */ + struct crypto_tfm *tx_tfm; /* CRC32C (Tx) */ + struct crypto_tfm *data_tx_tfm; /* CRC32C (Tx) for data */ /* MIB custom statistics */ uint32_t sendpage_failures_cnt; diff --git a/trunk/drivers/scsi/libata-core.c b/trunk/drivers/scsi/libata-core.c index 427b73a3886a..386e5f21e191 100644 --- a/trunk/drivers/scsi/libata-core.c +++ b/trunk/drivers/scsi/libata-core.c @@ -1256,15 +1256,10 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, swap_buf_le16(id, ATA_ID_WORDS); /* sanity check */ - rc = -EINVAL; - reason = "device reports illegal type"; - - if (class == ATA_DEV_ATA) { - if (!ata_id_is_ata(id) && !ata_id_is_cfa(id)) - goto err_out; - } else { - if (ata_id_is_ata(id)) - goto err_out; + if ((class == ATA_DEV_ATA) != (ata_id_is_ata(id) | ata_id_is_cfa(id))) { + rc = -EINVAL; + reason = "device reports illegal type"; + goto err_out; } if (post_reset && class == ATA_DEV_ATA) { @@ -2751,7 +2746,7 @@ int sata_std_hardreset(struct ata_port *ap, unsigned int *class) if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol))) return rc; - scontrol = (scontrol & 0x0f0) | 0x304; + scontrol = (scontrol & 0x0f0) | 0x302; if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol))) return rc; @@ -5190,6 +5185,28 @@ void ata_host_stop (struct ata_host_set *host_set) iounmap(host_set->mmio_base); } + +/** + * ata_host_remove - Unregister SCSI host structure with upper layers + * @ap: Port to unregister + * @do_unregister: 1 if we fully unregister, 0 to just stop the port + * + * LOCKING: + * Inherited from caller. + */ + +static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister) +{ + struct Scsi_Host *sh = ap->host; + + DPRINTK("ENTER\n"); + + if (do_unregister) + scsi_remove_host(sh); + + ap->ops->port_stop(ap); +} + /** * ata_dev_init - Initialize an ata_device structure * @dev: Device structure to initialize @@ -5515,11 +5532,8 @@ int ata_device_add(const struct ata_probe_ent *ent) err_out: for (i = 0; i < count; i++) { - struct ata_port *ap = host_set->ports[i]; - if (ap) { - ap->ops->port_stop(ap); - scsi_host_put(ap->host); - } + ata_host_remove(host_set->ports[i], 1); + scsi_host_put(host_set->ports[i]->host); } err_free_ret: kfree(host_set); @@ -5544,7 +5558,7 @@ void ata_port_detach(struct ata_port *ap) int i; if (!ap->ops->error_handler) - goto skip_eh; + return; /* tell EH we're leaving & flush EH */ spin_lock_irqsave(ap->lock, flags); @@ -5580,7 +5594,6 @@ void ata_port_detach(struct ata_port *ap) cancel_delayed_work(&ap->hotplug_task); flush_workqueue(ata_aux_wq); - skip_eh: /* remove the associated SCSI host */ scsi_remove_host(ap->host); } @@ -5649,7 +5662,7 @@ int ata_scsi_release(struct Scsi_Host *host) DPRINTK("ENTER\n"); ap->ops->port_disable(ap); - ap->ops->port_stop(ap); + ata_host_remove(ap, 0); DPRINTK("EXIT\n"); return 1; diff --git a/trunk/drivers/scsi/libata-eh.c b/trunk/drivers/scsi/libata-eh.c index 29f59345305d..4b6aa30f4d68 100644 --- a/trunk/drivers/scsi/libata-eh.c +++ b/trunk/drivers/scsi/libata-eh.c @@ -764,27 +764,12 @@ static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev, unsigned int action) { unsigned long flags; - struct ata_eh_info *ehi = &ap->eh_info; - struct ata_eh_context *ehc = &ap->eh_context; spin_lock_irqsave(ap->lock, flags); - /* Reset is represented by combination of actions and EHI - * flags. Suck in all related bits before clearing eh_info to - * avoid losing requested action. - */ - if (action & ATA_EH_RESET_MASK) { - ehc->i.action |= ehi->action & ATA_EH_RESET_MASK; - ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK; - - /* make sure all reset actions are cleared & clear EHI flags */ - action |= ATA_EH_RESET_MASK; - ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK; - } - - ata_eh_clear_action(dev, ehi, action); + ata_eh_clear_action(dev, &ap->eh_info, action); - if (!(ehc->i.flags & ATA_EHI_QUIET)) + if (!(ap->eh_context.i.flags & ATA_EHI_QUIET)) ap->pflags |= ATA_PFLAG_RECOVERED; spin_unlock_irqrestore(ap->lock, flags); @@ -805,12 +790,6 @@ static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev, static void ata_eh_done(struct ata_port *ap, struct ata_device *dev, unsigned int action) { - /* if reset is complete, clear all reset actions & reset modifier */ - if (action & ATA_EH_RESET_MASK) { - action |= ATA_EH_RESET_MASK; - ap->eh_context.i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK; - } - ata_eh_clear_action(dev, &ap->eh_context.i, action); } @@ -1297,6 +1276,8 @@ static int ata_eh_speed_down(struct ata_device *dev, int is_io, static void ata_eh_autopsy(struct ata_port *ap) { struct ata_eh_context *ehc = &ap->eh_context; + unsigned int action = ehc->i.action; + struct ata_device *failed_dev = NULL; unsigned int all_err_mask = 0; int tag, is_io = 0; u32 serror; @@ -1313,7 +1294,7 @@ static void ata_eh_autopsy(struct ata_port *ap) ehc->i.serror |= serror; ata_eh_analyze_serror(ap); } else if (rc != -EOPNOTSUPP) - ehc->i.action |= ATA_EH_HARDRESET; + action |= ATA_EH_HARDRESET; /* analyze NCQ failure */ ata_eh_analyze_ncq_error(ap); @@ -1334,7 +1315,7 @@ static void ata_eh_autopsy(struct ata_port *ap) qc->err_mask |= ehc->i.err_mask; /* analyze TF */ - ehc->i.action |= ata_eh_analyze_tf(qc, &qc->result_tf); + action |= ata_eh_analyze_tf(qc, &qc->result_tf); /* DEV errors are probably spurious in case of ATA_BUS error */ if (qc->err_mask & AC_ERR_ATA_BUS) @@ -1348,11 +1329,11 @@ static void ata_eh_autopsy(struct ata_port *ap) /* SENSE_VALID trumps dev/unknown error and revalidation */ if (qc->flags & ATA_QCFLAG_SENSE_VALID) { qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); - ehc->i.action &= ~ATA_EH_REVALIDATE; + action &= ~ATA_EH_REVALIDATE; } /* accumulate error info */ - ehc->i.dev = qc->dev; + failed_dev = qc->dev; all_err_mask |= qc->err_mask; if (qc->flags & ATA_QCFLAG_IO) is_io = 1; @@ -1361,22 +1342,25 @@ static void ata_eh_autopsy(struct ata_port *ap) /* enforce default EH actions */ if (ap->pflags & ATA_PFLAG_FROZEN || all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)) - ehc->i.action |= ATA_EH_SOFTRESET; + action |= ATA_EH_SOFTRESET; else if (all_err_mask) - ehc->i.action |= ATA_EH_REVALIDATE; + action |= ATA_EH_REVALIDATE; /* if we have offending qcs and the associated failed device */ - if (ehc->i.dev) { + if (failed_dev) { /* speed down */ - ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io, - all_err_mask); + action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask); /* perform per-dev EH action only on the offending device */ - ehc->i.dev_action[ehc->i.dev->devno] |= - ehc->i.action & ATA_EH_PERDEV_MASK; - ehc->i.action &= ~ATA_EH_PERDEV_MASK; + ehc->i.dev_action[failed_dev->devno] |= + action & ATA_EH_PERDEV_MASK; + action &= ~ATA_EH_PERDEV_MASK; } + /* record autopsy result */ + ehc->i.dev = failed_dev; + ehc->i.action |= action; + DPRINTK("EXIT\n"); } @@ -1499,9 +1483,6 @@ static int ata_eh_reset(struct ata_port *ap, int classify, ata_reset_fn_t reset; int i, did_followup_srst, rc; - /* about to reset */ - ata_eh_about_to_do(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK); - /* Determine which reset to use and record in ehc->i.action. * prereset() may examine and modify it. */ @@ -1550,7 +1531,8 @@ static int ata_eh_reset(struct ata_port *ap, int classify, ata_port_printk(ap, KERN_INFO, "%s resetting port\n", reset == softreset ? "soft" : "hard"); - /* mark that this EH session started with reset */ + /* reset */ + ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK); ehc->i.flags |= ATA_EHI_DID_RESET; rc = ata_do_reset(ap, reset, classes); @@ -1613,7 +1595,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify, postreset(ap, classes); /* reset successful, schedule revalidation */ - ata_eh_done(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK); + ata_eh_done(ap, NULL, ATA_EH_RESET_MASK); ehc->i.action |= ATA_EH_REVALIDATE; } @@ -1866,16 +1848,15 @@ static int ata_eh_skip_recovery(struct ata_port *ap) for (i = 0; i < ata_port_max_devices(ap); i++) { struct ata_device *dev = &ap->device[i]; - if (!(dev->flags & ATA_DFLAG_SUSPENDED)) + if (ata_dev_absent(dev) || ata_dev_ready(dev)) break; } if (i == ata_port_max_devices(ap)) return 1; - /* thaw frozen port, resume link and recover failed devices */ - if ((ap->pflags & ATA_PFLAG_FROZEN) || - (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_port_nr_enabled(ap)) + /* always thaw frozen port and recover failed devices */ + if (ap->pflags & ATA_PFLAG_FROZEN || ata_port_nr_enabled(ap)) return 0; /* skip if class codes for all vacant slots are ATA_DEV_NONE */ diff --git a/trunk/drivers/scsi/libata-scsi.c b/trunk/drivers/scsi/libata-scsi.c index e92c31d698ff..7ced41ecde86 100644 --- a/trunk/drivers/scsi/libata-scsi.c +++ b/trunk/drivers/scsi/libata-scsi.c @@ -2353,19 +2353,6 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) ata_gen_ata_desc_sense(qc); } - /* SCSI EH automatically locks door if sdev->locked is - * set. Sometimes door lock request continues to - * fail, for example, when no media is present. This - * creates a loop - SCSI EH issues door lock which - * fails and gets invoked again to acquire sense data - * for the failed command. - * - * If door lock fails, always clear sdev->locked to - * avoid this infinite loop. - */ - if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL) - qc->dev->sdev->locked = 0; - qc->scsicmd->result = SAM_STAT_CHECK_CONDITION; qc->scsidone(cmd); ata_qc_free(qc); diff --git a/trunk/drivers/scsi/libiscsi.c b/trunk/drivers/scsi/libiscsi.c index 5884cd26d53a..7e6e031cc41b 100644 --- a/trunk/drivers/scsi/libiscsi.c +++ b/trunk/drivers/scsi/libiscsi.c @@ -189,7 +189,6 @@ static void iscsi_complete_command(struct iscsi_session *session, { struct scsi_cmnd *sc = ctask->sc; - ctask->state = ISCSI_TASK_COMPLETED; ctask->sc = NULL; list_del_init(&ctask->running); __kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); @@ -276,25 +275,6 @@ static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, return rc; } -static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) -{ - struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr; - - conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; - conn->tmfrsp_pdus_cnt++; - - if (conn->tmabort_state != TMABORT_INITIAL) - return; - - if (tmf->response == ISCSI_TMF_RSP_COMPLETE) - conn->tmabort_state = TMABORT_SUCCESS; - else if (tmf->response == ISCSI_TMF_RSP_NO_TASK) - conn->tmabort_state = TMABORT_NOT_FOUND; - else - conn->tmabort_state = TMABORT_FAILED; - wake_up(&conn->ehwait); -} - /** * __iscsi_complete_pdu - complete pdu * @conn: iscsi conn @@ -360,10 +340,6 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, switch(opcode) { case ISCSI_OP_LOGOUT_RSP: - if (datalen) { - rc = ISCSI_ERR_PROTO; - break; - } conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; /* fall through */ case ISCSI_OP_LOGIN_RSP: @@ -372,8 +348,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, * login related PDU's exp_statsn is handled in * userspace */ - if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) - rc = ISCSI_ERR_CONN_FAILED; + rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen); list_del(&mtask->running); if (conn->login_mtask != mtask) __kfifo_put(session->mgmtpool.queue, @@ -385,17 +360,25 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, break; } - iscsi_tmf_rsp(conn, hdr); + conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; + conn->tmfrsp_pdus_cnt++; + if (conn->tmabort_state == TMABORT_INITIAL) { + conn->tmabort_state = + ((struct iscsi_tm_rsp *)hdr)-> + response == ISCSI_TMF_RSP_COMPLETE ? + TMABORT_SUCCESS:TMABORT_FAILED; + /* unblock eh_abort() */ + wake_up(&conn->ehwait); + } break; case ISCSI_OP_NOOP_IN: - if (hdr->ttt != ISCSI_RESERVED_TAG || datalen) { + if (hdr->ttt != ISCSI_RESERVED_TAG) { rc = ISCSI_ERR_PROTO; break; } conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; - if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) - rc = ISCSI_ERR_CONN_FAILED; + rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen); list_del(&mtask->running); if (conn->login_mtask != mtask) __kfifo_put(session->mgmtpool.queue, @@ -408,21 +391,14 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, } else if (itt == ISCSI_RESERVED_TAG) { switch(opcode) { case ISCSI_OP_NOOP_IN: - if (datalen) { - rc = ISCSI_ERR_PROTO; - break; - } - - rc = iscsi_check_assign_cmdsn(session, + if (!datalen) { + rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)hdr); - if (rc) - break; - - if (hdr->ttt == ISCSI_RESERVED_TAG) - break; - - if (iscsi_recv_pdu(conn->cls_conn, hdr, NULL, 0)) - rc = ISCSI_ERR_CONN_FAILED; + if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) + rc = iscsi_recv_pdu(conn->cls_conn, + hdr, NULL, 0); + } else + rc = ISCSI_ERR_PROTO; break; case ISCSI_OP_REJECT: /* we need sth like iscsi_reject_rsp()*/ @@ -592,24 +568,20 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) } /* process command queue */ - spin_lock_bh(&conn->session->lock); - while (!list_empty(&conn->xmitqueue)) { + while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask, + sizeof(void*))) { /* * iscsi tcp may readd the task to the xmitqueue to send * write data */ - conn->ctask = list_entry(conn->xmitqueue.next, - struct iscsi_cmd_task, running); - conn->ctask->state = ISCSI_TASK_RUNNING; - list_move_tail(conn->xmitqueue.next, &conn->run_list); + spin_lock_bh(&conn->session->lock); + if (list_empty(&conn->ctask->running)) + list_add_tail(&conn->ctask->running, &conn->run_list); spin_unlock_bh(&conn->session->lock); - rc = tt->xmit_cmd_task(conn, conn->ctask); if (rc) goto again; - spin_lock_bh(&conn->session->lock); } - spin_unlock_bh(&conn->session->lock); /* done with this ctask */ conn->ctask = NULL; @@ -719,7 +691,6 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) sc->SCp.phase = session->age; sc->SCp.ptr = (char *)ctask; - ctask->state = ISCSI_TASK_PENDING; ctask->mtask = NULL; ctask->conn = conn; ctask->sc = sc; @@ -729,7 +700,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) session->tt->init_cmd_task(ctask); - list_add_tail(&ctask->running, &conn->xmitqueue); + __kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*)); debug_scsi( "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n", sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", @@ -1006,28 +977,32 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, /* * xmit mutex and session lock must be held */ -static struct iscsi_mgmt_task * -iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt) -{ - int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); - struct iscsi_mgmt_task *task; - - debug_scsi("searching %d tasks\n", nr_tasks); - - for (i = 0; i < nr_tasks; i++) { - __kfifo_get(fifo, (void*)&task, sizeof(void*)); - debug_scsi("check task %u\n", task->itt); - - if (task->itt == itt) { - debug_scsi("matched task\n"); - return task; - } - - __kfifo_put(fifo, (void*)&task, sizeof(void*)); - } - return NULL; +#define iscsi_remove_task(tasktype) \ +static struct iscsi_##tasktype * \ +iscsi_remove_##tasktype(struct kfifo *fifo, uint32_t itt) \ +{ \ + int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); \ + struct iscsi_##tasktype *task; \ + \ + debug_scsi("searching %d tasks\n", nr_tasks); \ + \ + for (i = 0; i < nr_tasks; i++) { \ + __kfifo_get(fifo, (void*)&task, sizeof(void*)); \ + debug_scsi("check task %u\n", task->itt); \ + \ + if (task->itt == itt) { \ + debug_scsi("matched task\n"); \ + return task; \ + } \ + \ + __kfifo_put(fifo, (void*)&task, sizeof(void*)); \ + } \ + return NULL; \ } +iscsi_remove_task(mgmt_task); +iscsi_remove_task(cmd_task); + static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) { struct iscsi_conn *conn = ctask->conn; @@ -1052,13 +1027,12 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, { struct scsi_cmnd *sc; - sc = ctask->sc; - if (!sc) - return; - conn->session->tt->cleanup_cmd_task(conn, ctask); iscsi_ctask_mtask_cleanup(ctask); + sc = ctask->sc; + if (!sc) + return; sc->result = err; sc->resid = sc->request_bufflen; iscsi_complete_command(conn->session, ctask); @@ -1069,6 +1043,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; struct iscsi_conn *conn = ctask->conn; struct iscsi_session *session = conn->session; + struct iscsi_cmd_task *pending_ctask; int rc; conn->eh_abort_cnt++; @@ -1086,11 +1061,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) goto failed; /* ctask completed before time out */ - if (!ctask->sc) { - spin_unlock_bh(&session->lock); - debug_scsi("sc completed while abort in progress\n"); - goto success_rel_mutex; - } + if (!ctask->sc) + goto success; /* what should we do here ? */ if (conn->ctask == ctask) { @@ -1099,8 +1071,17 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) goto failed; } - if (ctask->state == ISCSI_TASK_PENDING) - goto success_cleanup; + /* check for the easy pending cmd abort */ + pending_ctask = iscsi_remove_cmd_task(conn->xmitqueue, ctask->itt); + if (pending_ctask) { + /* iscsi_tcp queues write transfers on the xmitqueue */ + if (list_empty(&pending_ctask->running)) { + debug_scsi("found pending task\n"); + goto success; + } else + __kfifo_put(conn->xmitqueue, (void*)&pending_ctask, + sizeof(void*)); + } conn->tmabort_state = TMABORT_INITIAL; @@ -1108,31 +1089,25 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) rc = iscsi_exec_abort_task(sc, ctask); spin_lock_bh(&session->lock); + iscsi_ctask_mtask_cleanup(ctask); if (rc || sc->SCp.phase != session->age || session->state != ISCSI_STATE_LOGGED_IN) goto failed; - iscsi_ctask_mtask_cleanup(ctask); - switch (conn->tmabort_state) { - case TMABORT_SUCCESS: - goto success_cleanup; - case TMABORT_NOT_FOUND: - if (!ctask->sc) { - /* ctask completed before tmf abort response */ - spin_unlock_bh(&session->lock); - debug_scsi("sc completed while abort in progress\n"); - goto success_rel_mutex; - } - /* fall through */ - default: - /* timedout or failed */ + /* ctask completed before tmf abort response */ + if (!ctask->sc) { + debug_scsi("sc completed while abort in progress\n"); + goto success; + } + + if (conn->tmabort_state != TMABORT_SUCCESS) { spin_unlock_bh(&session->lock); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); spin_lock_bh(&session->lock); goto failed; } -success_cleanup: +success: debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); spin_unlock_bh(&session->lock); @@ -1146,7 +1121,6 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) spin_unlock(&session->lock); write_unlock_bh(conn->recv_lock); -success_rel_mutex: mutex_unlock(&conn->xmitmutex); return SUCCESS; @@ -1289,7 +1263,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit, if (cmd_task_size) ctask->dd_data = &ctask[1]; ctask->itt = cmd_i; - INIT_LIST_HEAD(&ctask->running); } spin_lock_init(&session->lock); @@ -1309,7 +1282,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit, if (mgmt_task_size) mtask->dd_data = &mtask[1]; mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i; - INIT_LIST_HEAD(&mtask->running); } if (scsi_add_host(shost, NULL)) @@ -1350,18 +1322,15 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) { struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); struct iscsi_session *session = iscsi_hostdata(shost->hostdata); - struct module *owner = cls_session->transport->owner; scsi_remove_host(shost); iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); iscsi_pool_free(&session->cmdpool, (void**)session->cmds); - kfree(session->targetname); - iscsi_destroy_session(cls_session); scsi_host_put(shost); - module_put(owner); + module_put(cls_session->transport->owner); } EXPORT_SYMBOL_GPL(iscsi_session_teardown); @@ -1392,7 +1361,12 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) conn->tmabort_state = TMABORT_INITIAL; INIT_LIST_HEAD(&conn->run_list); INIT_LIST_HEAD(&conn->mgmt_run_list); - INIT_LIST_HEAD(&conn->xmitqueue); + + /* initialize general xmit PDU commands queue */ + conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*), + GFP_KERNEL, NULL); + if (conn->xmitqueue == ERR_PTR(-ENOMEM)) + goto xmitqueue_alloc_fail; /* initialize general immediate & non-immediate PDU commands queue */ conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), @@ -1420,7 +1394,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL); if (!data) goto login_mtask_data_alloc_fail; - conn->login_mtask->data = conn->data = data; + conn->login_mtask->data = data; init_timer(&conn->tmabort_timer); mutex_init(&conn->xmitmutex); @@ -1436,6 +1410,8 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx) mgmtqueue_alloc_fail: kfifo_free(conn->immqueue); immqueue_alloc_fail: + kfifo_free(conn->xmitqueue); +xmitqueue_alloc_fail: iscsi_destroy_conn(cls_conn); return NULL; } @@ -1456,6 +1432,12 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); mutex_lock(&conn->xmitmutex); + if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) { + if (session->tt->suspend_conn_recv) + session->tt->suspend_conn_recv(conn); + + session->tt->terminate_conn(conn); + } spin_lock_bh(&session->lock); conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; @@ -1492,8 +1474,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) } spin_lock_bh(&session->lock); - kfree(conn->data); - kfree(conn->persistent_address); + kfree(conn->login_mtask->data); __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, sizeof(void*)); list_del(&conn->item); @@ -1508,6 +1489,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; spin_unlock_bh(&session->lock); + kfifo_free(conn->xmitqueue); kfifo_free(conn->immqueue); kfifo_free(conn->mgmtqueue); @@ -1590,7 +1572,7 @@ static void fail_all_commands(struct iscsi_conn *conn) struct iscsi_cmd_task *ctask, *tmp; /* flush pending */ - list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) { + while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) { debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, ctask->itt); fail_command(conn, ctask, DID_BUS_BUSY << 16); @@ -1633,9 +1615,8 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); spin_unlock_bh(&session->lock); - write_lock_bh(conn->recv_lock); - set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); - write_unlock_bh(conn->recv_lock); + if (session->tt->suspend_conn_recv) + session->tt->suspend_conn_recv(conn); mutex_lock(&conn->xmitmutex); /* @@ -1654,6 +1635,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, } } + session->tt->terminate_conn(conn); /* * flush queues. */ diff --git a/trunk/drivers/scsi/lpfc/lpfc_attr.c b/trunk/drivers/scsi/lpfc/lpfc_attr.c index d384c16f4a87..5c68cdd8736f 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_attr.c +++ b/trunk/drivers/scsi/lpfc/lpfc_attr.c @@ -222,7 +222,7 @@ lpfc_issue_lip(struct Scsi_Host *host) pmboxq->mb.mbxCommand = MBX_DOWN_LINK; pmboxq->mb.mbxOwner = OWN_HOST; - mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, LPFC_MBOX_TMO * 2); + mbxstatus = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); if ((mbxstatus == MBX_SUCCESS) && (pmboxq->mb.mbxStatus == 0)) { memset((void *)pmboxq, 0, sizeof (LPFC_MBOXQ_t)); @@ -884,7 +884,7 @@ sysfs_mbox_write(struct kobject *kobj, char *buf, loff_t off, size_t count) phba->sysfs_mbox.mbox == NULL ) { sysfs_mbox_idle(phba); spin_unlock_irq(host->host_lock); - return -EAGAIN; + return -EINVAL; } } @@ -1000,15 +1000,14 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count) spin_unlock_irq(phba->host->host_lock); rc = lpfc_sli_issue_mbox_wait (phba, phba->sysfs_mbox.mbox, - lpfc_mbox_tmo_val(phba, - phba->sysfs_mbox.mbox->mb.mbxCommand) * HZ); + phba->fc_ratov * 2); spin_lock_irq(phba->host->host_lock); } if (rc != MBX_SUCCESS) { sysfs_mbox_idle(phba); spin_unlock_irq(host->host_lock); - return (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV; + return -ENODEV; } phba->sysfs_mbox.state = SMBOX_READING; } @@ -1017,7 +1016,7 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count) printk(KERN_WARNING "mbox_read: Bad State\n"); sysfs_mbox_idle(phba); spin_unlock_irq(host->host_lock); - return -EAGAIN; + return -EINVAL; } memcpy(buf, (uint8_t *) & phba->sysfs_mbox.mbox->mb + off, count); @@ -1211,10 +1210,8 @@ lpfc_get_stats(struct Scsi_Host *shost) struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; struct lpfc_sli *psli = &phba->sli; struct fc_host_statistics *hs = &phba->link_stats; - struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets; LPFC_MBOXQ_t *pmboxq; MAILBOX_t *pmb; - unsigned long seconds; int rc = 0; pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); @@ -1275,103 +1272,22 @@ lpfc_get_stats(struct Scsi_Host *shost) hs->invalid_crc_count = pmb->un.varRdLnk.crcCnt; hs->error_frames = pmb->un.varRdLnk.crcCnt; - hs->link_failure_count -= lso->link_failure_count; - hs->loss_of_sync_count -= lso->loss_of_sync_count; - hs->loss_of_signal_count -= lso->loss_of_signal_count; - hs->prim_seq_protocol_err_count -= lso->prim_seq_protocol_err_count; - hs->invalid_tx_word_count -= lso->invalid_tx_word_count; - hs->invalid_crc_count -= lso->invalid_crc_count; - hs->error_frames -= lso->error_frames; - if (phba->fc_topology == TOPOLOGY_LOOP) { hs->lip_count = (phba->fc_eventTag >> 1); - hs->lip_count -= lso->link_events; hs->nos_count = -1; } else { hs->lip_count = -1; hs->nos_count = (phba->fc_eventTag >> 1); - hs->nos_count -= lso->link_events; } hs->dumped_frames = -1; - seconds = get_seconds(); - if (seconds < psli->stats_start) - hs->seconds_since_last_reset = seconds + - ((unsigned long)-1 - psli->stats_start); - else - hs->seconds_since_last_reset = seconds - psli->stats_start; +/* FIX ME */ + /*hs->SecondsSinceLastReset = (jiffies - lpfc_loadtime) / HZ;*/ return hs; } -static void -lpfc_reset_stats(struct Scsi_Host *shost) -{ - struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata; - struct lpfc_sli *psli = &phba->sli; - struct lpfc_lnk_stat * lso = &psli->lnk_stat_offsets; - LPFC_MBOXQ_t *pmboxq; - MAILBOX_t *pmb; - int rc = 0; - - pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); - if (!pmboxq) - return; - memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); - - pmb = &pmboxq->mb; - pmb->mbxCommand = MBX_READ_STATUS; - pmb->mbxOwner = OWN_HOST; - pmb->un.varWords[0] = 0x1; /* reset request */ - pmboxq->context1 = NULL; - - if ((phba->fc_flag & FC_OFFLINE_MODE) || - (!(psli->sli_flag & LPFC_SLI2_ACTIVE))) - rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL); - else - rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); - - if (rc != MBX_SUCCESS) { - if (rc == MBX_TIMEOUT) - pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - else - mempool_free(pmboxq, phba->mbox_mem_pool); - return; - } - - memset(pmboxq, 0, sizeof(LPFC_MBOXQ_t)); - pmb->mbxCommand = MBX_READ_LNK_STAT; - pmb->mbxOwner = OWN_HOST; - pmboxq->context1 = NULL; - - if ((phba->fc_flag & FC_OFFLINE_MODE) || - (!(psli->sli_flag & LPFC_SLI2_ACTIVE))) - rc = lpfc_sli_issue_mbox(phba, pmboxq, MBX_POLL); - else - rc = lpfc_sli_issue_mbox_wait(phba, pmboxq, phba->fc_ratov * 2); - - if (rc != MBX_SUCCESS) { - if (rc == MBX_TIMEOUT) - pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; - else - mempool_free( pmboxq, phba->mbox_mem_pool); - return; - } - - lso->link_failure_count = pmb->un.varRdLnk.linkFailureCnt; - lso->loss_of_sync_count = pmb->un.varRdLnk.lossSyncCnt; - lso->loss_of_signal_count = pmb->un.varRdLnk.lossSignalCnt; - lso->prim_seq_protocol_err_count = pmb->un.varRdLnk.primSeqErrCnt; - lso->invalid_tx_word_count = pmb->un.varRdLnk.invalidXmitWord; - lso->invalid_crc_count = pmb->un.varRdLnk.crcCnt; - lso->error_frames = pmb->un.varRdLnk.crcCnt; - lso->link_events = (phba->fc_eventTag >> 1); - - psli->stats_start = get_seconds(); - - return; -} /* * The LPFC driver treats linkdown handling as target loss events so there @@ -1515,7 +1431,8 @@ struct fc_function_template lpfc_transport_functions = { */ .get_fc_host_stats = lpfc_get_stats, - .reset_fc_host_stats = lpfc_reset_stats, + + /* the LPFC driver doesn't support resetting stats yet */ .dd_fcrport_size = sizeof(struct lpfc_rport_data), .show_rport_maxframe_size = 1, diff --git a/trunk/drivers/scsi/lpfc/lpfc_crtn.h b/trunk/drivers/scsi/lpfc/lpfc_crtn.h index 2a176467f71b..517e9e4dd461 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_crtn.h +++ b/trunk/drivers/scsi/lpfc/lpfc_crtn.h @@ -127,7 +127,6 @@ void lpfc_config_port(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_kill_board(struct lpfc_hba *, LPFC_MBOXQ_t *); void lpfc_mbox_put(struct lpfc_hba *, LPFC_MBOXQ_t *); LPFC_MBOXQ_t *lpfc_mbox_get(struct lpfc_hba *); -int lpfc_mbox_tmo_val(struct lpfc_hba *, int); int lpfc_mem_alloc(struct lpfc_hba *); void lpfc_mem_free(struct lpfc_hba *); diff --git a/trunk/drivers/scsi/lpfc/lpfc_ct.c b/trunk/drivers/scsi/lpfc/lpfc_ct.c index bbb7310210b0..b65ee57af53e 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_ct.c +++ b/trunk/drivers/scsi/lpfc/lpfc_ct.c @@ -131,7 +131,6 @@ lpfc_ct_unsol_event(struct lpfc_hba * phba, } ct_unsol_event_exit_piocbq: - list_del(&head); if (pmbuf) { list_for_each_entry_safe(matp, next_matp, &pmbuf->list, list) { lpfc_mbuf_free(phba, matp->virt, matp->phys); @@ -482,7 +481,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, if (CTrsp->CommandResponse.bits.CmdRsp == be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) { lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d:0208 NameServer Rsp " + "%d:0239 NameServer Rsp " "Data: x%x\n", phba->brd_no, phba->fc_flag); @@ -589,9 +588,13 @@ lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp) lpfc_decode_firmware_rev(phba, fwrev, 0); - sprintf(symbp, "Emulex %s FV%s DV%s", phba->ModelName, - fwrev, lpfc_release_version); - return; + if (phba->Port[0]) { + sprintf(symbp, "Emulex %s Port %s FV%s DV%s", phba->ModelName, + phba->Port, fwrev, lpfc_release_version); + } else { + sprintf(symbp, "Emulex %s FV%s DV%s", phba->ModelName, + fwrev, lpfc_release_version); + } } /* diff --git a/trunk/drivers/scsi/lpfc/lpfc_els.c b/trunk/drivers/scsi/lpfc/lpfc_els.c index 3567de613162..b89f6cb641e6 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_els.c +++ b/trunk/drivers/scsi/lpfc/lpfc_els.c @@ -1848,12 +1848,9 @@ static void lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb) { - IOCB_t *irsp; struct lpfc_nodelist *ndlp; LPFC_MBOXQ_t *mbox = NULL; - irsp = &rspiocb->iocb; - ndlp = (struct lpfc_nodelist *) cmdiocb->context1; if (cmdiocb->context_un.mbox) mbox = cmdiocb->context_un.mbox; @@ -1896,15 +1893,9 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, mempool_free( mbox, phba->mbox_mem_pool); } else { mempool_free( mbox, phba->mbox_mem_pool); - /* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */ - if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && - ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) || - (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) || - (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) { - if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) { - lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); - ndlp = NULL; - } + if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) { + lpfc_nlp_list(phba, ndlp, NLP_NO_LIST); + ndlp = NULL; } } } @@ -2848,7 +2839,7 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb) /* Xmit ELS RPS ACC response tag */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d:0118 Xmit ELS RPS ACC response tag x%x " + "%d:0128 Xmit ELS RPS ACC response tag x%x " "Data: x%x x%x x%x x%x x%x\n", phba->brd_no, elsiocb->iocb.ulpIoTag, @@ -2957,7 +2948,7 @@ lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize, /* Xmit ELS RPL ACC response tag */ lpfc_printf_log(phba, KERN_INFO, LOG_ELS, - "%d:0120 Xmit ELS RPL ACC response tag x%x " + "%d:0128 Xmit ELS RPL ACC response tag x%x " "Data: x%x x%x x%x x%x x%x\n", phba->brd_no, elsiocb->iocb.ulpIoTag, @@ -3118,7 +3109,7 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist *ndlp, *next_ndlp; /* FAN received */ - lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n", + lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:265 FAN received\n", phba->brd_no); icmd = &cmdiocb->iocb; diff --git a/trunk/drivers/scsi/lpfc/lpfc_hbadisc.c b/trunk/drivers/scsi/lpfc/lpfc_hbadisc.c index b2f1552f1848..4d6cf990c4fc 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/trunk/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -1557,8 +1557,6 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl; } } - - spin_lock_irq(phba->host->host_lock); list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) { if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) && (ndlp == (struct lpfc_nodelist *) mb->context2)) { @@ -1571,7 +1569,6 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp) mempool_free(mb, phba->mbox_mem_pool); } } - spin_unlock_irq(phba->host->host_lock); lpfc_els_abort(phba,ndlp,0); spin_lock_irq(phba->host->host_lock); @@ -1785,7 +1782,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) /* LOG change to REGLOGIN */ /* FIND node DID reglogin */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0901 FIND node DID reglogin" + "%d:0931 FIND node DID reglogin" " Data: x%p x%x x%x x%x\n", phba->brd_no, ndlp, ndlp->nlp_DID, @@ -1808,7 +1805,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) /* LOG change to PRLI */ /* FIND node DID prli */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0902 FIND node DID prli " + "%d:0931 FIND node DID prli " "Data: x%p x%x x%x x%x\n", phba->brd_no, ndlp, ndlp->nlp_DID, @@ -1831,7 +1828,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) /* LOG change to NPR */ /* FIND node DID npr */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0903 FIND node DID npr " + "%d:0931 FIND node DID npr " "Data: x%p x%x x%x x%x\n", phba->brd_no, ndlp, ndlp->nlp_DID, @@ -1854,7 +1851,7 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did) /* LOG change to UNUSED */ /* FIND node DID unused */ lpfc_printf_log(phba, KERN_INFO, LOG_NODE, - "%d:0905 FIND node DID unused " + "%d:0931 FIND node DID unused " "Data: x%p x%x x%x x%x\n", phba->brd_no, ndlp, ndlp->nlp_DID, @@ -2338,7 +2335,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) initlinkmbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (!initlinkmbox) { lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d:0206 Device Discovery " + "%d:0226 Device Discovery " "completion error\n", phba->brd_no); phba->hba_state = LPFC_HBA_ERROR; @@ -2368,7 +2365,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba) if (!clearlambox) { clrlaerr = 1; lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, - "%d:0207 Device Discovery " + "%d:0226 Device Discovery " "completion error\n", phba->brd_no); phba->hba_state = LPFC_HBA_ERROR; diff --git a/trunk/drivers/scsi/lpfc/lpfc_init.c b/trunk/drivers/scsi/lpfc/lpfc_init.c index f6948ffe689a..ef47b824cbed 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_init.c +++ b/trunk/drivers/scsi/lpfc/lpfc_init.c @@ -1379,7 +1379,6 @@ lpfc_offline(struct lpfc_hba * phba) /* stop all timers associated with this hba */ lpfc_stop_timer(phba); phba->work_hba_events = 0; - phba->work_ha = 0; lpfc_printf_log(phba, KERN_WARNING, @@ -1617,11 +1616,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_free_iocbq; } - /* - * Set initial can_queue value since 0 is no longer supported and - * scsi_add_host will fail. This will be adjusted later based on the - * max xri value determined in hba setup. - */ + /* We can rely on a queue depth attribute only after SLI HBA setup */ host->can_queue = phba->cfg_hba_queue_depth - 10; /* Tell the midlayer we support 16 byte commands */ @@ -1661,12 +1656,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) goto out_free_irq; } - /* - * hba setup may have changed the hba_queue_depth so we need to adjust - * the value of can_queue. - */ - host->can_queue = phba->cfg_hba_queue_depth - 10; - lpfc_discovery_wait(phba); if (phba->cfg_poll & DISABLE_FCP_RING_INT) { diff --git a/trunk/drivers/scsi/lpfc/lpfc_mbox.c b/trunk/drivers/scsi/lpfc/lpfc_mbox.c index 4d016c2a1b26..e42f22aaf71b 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_mbox.c +++ b/trunk/drivers/scsi/lpfc/lpfc_mbox.c @@ -651,19 +651,3 @@ lpfc_mbox_get(struct lpfc_hba * phba) return mbq; } - -int -lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd) -{ - switch (cmd) { - case MBX_WRITE_NV: /* 0x03 */ - case MBX_UPDATE_CFG: /* 0x1B */ - case MBX_DOWN_LOAD: /* 0x1C */ - case MBX_DEL_LD_ENTRY: /* 0x1D */ - case MBX_LOAD_AREA: /* 0x81 */ - case MBX_FLASH_WR_ULA: /* 0x98 */ - case MBX_LOAD_EXP_ROM: /* 0x9C */ - return LPFC_MBOX_TMO_FLASH_CMD; - } - return LPFC_MBOX_TMO; -} diff --git a/trunk/drivers/scsi/lpfc/lpfc_nportdisc.c b/trunk/drivers/scsi/lpfc/lpfc_nportdisc.c index 20449a8dd53d..bd0b0e293d63 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/trunk/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -179,7 +179,7 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, /* Abort outstanding I/O on NPort */ lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, - "%d:0205 Abort outstanding I/O on NPort x%x " + "%d:0201 Abort outstanding I/O on NPort x%x " "Data: x%x x%x x%x\n", phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi); @@ -393,20 +393,6 @@ lpfc_rcv_plogi(struct lpfc_hba * phba, mbox->context2 = ndlp; ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI); - /* - * If there is an outstanding PLOGI issued, abort it before - * sending ACC rsp for received PLOGI. If pending plogi - * is not canceled here, the plogi will be rejected by - * remote port and will be retried. On a configuration with - * single discovery thread, this will cause a huge delay in - * discovery. Also this will cause multiple state machines - * running in parallel for this node. - */ - if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) { - /* software abort outstanding PLOGI */ - lpfc_els_abort(phba, ndlp, 1); - } - lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0); return 1; @@ -1615,13 +1601,7 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba, lpfc_rcv_padisc(phba, ndlp, cmdiocb); - /* - * Do not start discovery if discovery is about to start - * or discovery in progress for this node. Starting discovery - * here will affect the counting of discovery threads. - */ - if ((!(ndlp->nlp_flag & NLP_DELAY_TMO)) && - (ndlp->nlp_flag & NLP_NPR_2B_DISC)){ + if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { if (ndlp->nlp_flag & NLP_NPR_ADISC) { ndlp->nlp_prev_state = NLP_STE_NPR_NODE; ndlp->nlp_state = NLP_STE_ADISC_ISSUE; diff --git a/trunk/drivers/scsi/lpfc/lpfc_scsi.c b/trunk/drivers/scsi/lpfc/lpfc_scsi.c index a8816a8738f8..a760a44173df 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_scsi.c +++ b/trunk/drivers/scsi/lpfc/lpfc_scsi.c @@ -21,7 +21,6 @@ #include #include -#include #include #include @@ -842,21 +841,6 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) return 0; } -static void -lpfc_block_error_handler(struct scsi_cmnd *cmnd) -{ - struct Scsi_Host *shost = cmnd->device->host; - struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); - - spin_lock_irq(shost->host_lock); - while (rport->port_state == FC_PORTSTATE_BLOCKED) { - spin_unlock_irq(shost->host_lock); - msleep(1000); - spin_lock_irq(shost->host_lock); - } - spin_unlock_irq(shost->host_lock); - return; -} static int lpfc_abort_handler(struct scsi_cmnd *cmnd) @@ -871,7 +855,6 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) unsigned int loop_count = 0; int ret = SUCCESS; - lpfc_block_error_handler(cmnd); spin_lock_irq(shost->host_lock); lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble; @@ -974,7 +957,6 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd) int ret = FAILED; int cnt, loopcnt; - lpfc_block_error_handler(cmnd); spin_lock_irq(shost->host_lock); /* * If target is not in a MAPPED state, delay the reset until @@ -1091,7 +1073,6 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) int cnt, loopcnt; struct lpfc_scsi_buf * lpfc_cmd; - lpfc_block_error_handler(cmnd); spin_lock_irq(shost->host_lock); lpfc_cmd = lpfc_get_scsi_buf(phba); @@ -1123,7 +1104,7 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd) ndlp->rport->dd_data); if (ret != SUCCESS) { lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "%d:0700 Bus Reset on target %d failed\n", + "%d:0713 Bus Reset on target %d failed\n", phba->brd_no, i); err_count++; } diff --git a/trunk/drivers/scsi/lpfc/lpfc_sli.c b/trunk/drivers/scsi/lpfc/lpfc_sli.c index 70f4d5a1348e..350a625fa224 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_sli.c +++ b/trunk/drivers/scsi/lpfc/lpfc_sli.c @@ -320,8 +320,7 @@ lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocbq) kfree(old_arr); return iotag; } - } else - spin_unlock_irq(phba->host->host_lock); + } lpfc_printf_log(phba, KERN_ERR,LOG_SLI, "%d:0318 Failed to allocate IOTAG.last IOTAG is %d\n", @@ -970,11 +969,9 @@ void lpfc_sli_poll_fcp_ring(struct lpfc_hba * phba) * resources need to be recovered. */ if (unlikely(irsp->ulpCommand == CMD_XRI_ABORTED_CX)) { - lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "%d:0314 IOCB cmd 0x%x" - " processed. Skipping" - " completion", phba->brd_no, - irsp->ulpCommand); + printk(KERN_INFO "%s: IOCB cmd 0x%x processed." + " Skipping completion\n", __FUNCTION__, + irsp->ulpCommand); break; } @@ -1107,7 +1104,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba, if (unlikely(irsp->ulpStatus)) { /* Rsp ring error: IOCB */ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, - "%d:0336 Rsp Ring %d error: IOCB Data: " + "%d:0326 Rsp Ring %d error: IOCB Data: " "x%x x%x x%x x%x x%x x%x x%x x%x\n", phba->brd_no, pring->ringno, irsp->un.ulpWord[0], irsp->un.ulpWord[1], @@ -1125,11 +1122,9 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba, * resources need to be recovered. */ if (unlikely(irsp->ulpCommand == CMD_XRI_ABORTED_CX)) { - lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "%d:0333 IOCB cmd 0x%x" - " processed. Skipping" - " completion\n", phba->brd_no, - irsp->ulpCommand); + printk(KERN_INFO "%s: IOCB cmd 0x%x processed. " + "Skipping completion\n", __FUNCTION__, + irsp->ulpCommand); break; } @@ -1160,7 +1155,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba, } else { /* Unknown IOCB command */ lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0334 Unknown IOCB command " + "%d:0321 Unknown IOCB command " "Data: x%x, x%x x%x x%x x%x\n", phba->brd_no, type, irsp->ulpCommand, irsp->ulpStatus, irsp->ulpIoTag, @@ -1243,7 +1238,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba, lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0303 Ring %d handler: portRspPut %d " + "%d:0312 Ring %d handler: portRspPut %d " "is bigger then rsp ring %d\n", phba->brd_no, pring->ringno, portRspPut, portRspMax); @@ -1388,7 +1383,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba, lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0335 Unknown IOCB command " + "%d:0321 Unknown IOCB command " "Data: x%x x%x x%x x%x\n", phba->brd_no, irsp->ulpCommand, @@ -1404,11 +1399,11 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba, next_iocb, &saveq->list, list) { - list_del(&rspiocbp->list); lpfc_sli_release_iocbq(phba, rspiocbp); } } + lpfc_sli_release_iocbq(phba, saveq); } } @@ -1716,13 +1711,15 @@ lpfc_sli_brdreset(struct lpfc_hba * phba) phba->fc_myDID = 0; phba->fc_prevDID = 0; + psli->sli_flag = 0; + /* Turn off parity checking and serr during the physical reset */ pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value); pci_write_config_word(phba->pcidev, PCI_COMMAND, (cfg_value & ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR))); - psli->sli_flag &= ~(LPFC_SLI2_ACTIVE | LPFC_PROCESS_LA); + psli->sli_flag &= ~LPFC_SLI2_ACTIVE; /* Now toggle INITFF bit in the Host Control Register */ writel(HC_INITFF, phba->HCregaddr); mdelay(1); @@ -1763,7 +1760,7 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba) /* Restart HBA */ lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "%d:0337 Restart HBA Data: x%x x%x\n", phba->brd_no, + "%d:0328 Restart HBA Data: x%x x%x\n", phba->brd_no, phba->hba_state, psli->sli_flag); word0 = 0; @@ -1795,9 +1792,6 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba) spin_unlock_irq(phba->host->host_lock); - memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets)); - psli->stats_start = get_seconds(); - if (skip_post) mdelay(100); else @@ -1908,9 +1902,6 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba) } while (resetcount < 2 && !done) { - spin_lock_irq(phba->host->host_lock); - phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE; - spin_unlock_irq(phba->host->host_lock); phba->hba_state = LPFC_STATE_UNKNOWN; lpfc_sli_brdrestart(phba); msleep(2500); @@ -1918,9 +1909,6 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba) if (rc) break; - spin_lock_irq(phba->host->host_lock); - phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; - spin_unlock_irq(phba->host->host_lock); resetcount++; /* Call pre CONFIG_PORT mailbox command initialization. A value of 0 @@ -2206,8 +2194,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag) return (MBX_NOT_FINISHED); } /* timeout active mbox command */ - mod_timer(&psli->mbox_tmo, (jiffies + - (HZ * lpfc_mbox_tmo_val(phba, mb->mbxCommand)))); + mod_timer(&psli->mbox_tmo, jiffies + HZ * LPFC_MBOX_TMO); } /* Mailbox cmd issue */ @@ -2267,6 +2254,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag) break; case MBX_POLL: + i = 0; psli->mbox_active = NULL; if (psli->sli_flag & LPFC_SLI2_ACTIVE) { /* First read mbox status word */ @@ -2280,14 +2268,11 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag) /* Read the HBA Host Attention Register */ ha_copy = readl(phba->HAregaddr); - i = lpfc_mbox_tmo_val(phba, mb->mbxCommand); - i *= 1000; /* Convert to ms */ - /* Wait for command to complete */ while (((word0 & OWN_CHIP) == OWN_CHIP) || (!(ha_copy & HA_MBATT) && (phba->hba_state > LPFC_WARM_START))) { - if (i-- <= 0) { + if (i++ >= 100) { psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; spin_unlock_irqrestore(phba->host->host_lock, drvr_flag); @@ -2305,7 +2290,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag) /* Can be in interrupt context, do not sleep */ /* (or might be called with interrupts disabled) */ - mdelay(1); + mdelay(i); spin_lock_irqsave(phba->host->host_lock, drvr_flag); @@ -3020,7 +3005,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba, if (timeleft == 0) { lpfc_printf_log(phba, KERN_ERR, LOG_SLI, - "%d:0338 IOCB wait timeout error - no " + "%d:0329 IOCB wait timeout error - no " "wake response Data x%x\n", phba->brd_no, timeout); retval = IOCB_TIMEDOUT; diff --git a/trunk/drivers/scsi/lpfc/lpfc_sli.h b/trunk/drivers/scsi/lpfc/lpfc_sli.h index e26de6809358..d8ef0d2894d4 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_sli.h +++ b/trunk/drivers/scsi/lpfc/lpfc_sli.h @@ -172,18 +172,6 @@ struct lpfc_sli_stat { uint32_t mbox_busy; /* Mailbox cmd busy */ }; -/* Structure to store link status values when port stats are reset */ -struct lpfc_lnk_stat { - uint32_t link_failure_count; - uint32_t loss_of_sync_count; - uint32_t loss_of_signal_count; - uint32_t prim_seq_protocol_err_count; - uint32_t invalid_tx_word_count; - uint32_t invalid_crc_count; - uint32_t error_frames; - uint32_t link_events; -}; - /* Structure used to hold SLI information */ struct lpfc_sli { uint32_t num_rings; @@ -213,8 +201,6 @@ struct lpfc_sli { struct lpfc_iocbq ** iocbq_lookup; /* array to lookup IOCB by IOTAG */ size_t iocbq_lookup_len; /* current lengs of the array */ uint16_t last_iotag; /* last allocated IOTAG */ - unsigned long stats_start; /* in seconds */ - struct lpfc_lnk_stat lnk_stat_offsets; }; /* Given a pointer to the start of the ring, and the slot number of @@ -225,9 +211,3 @@ struct lpfc_sli { #define LPFC_MBOX_TMO 30 /* Sec tmo for outstanding mbox command */ -#define LPFC_MBOX_TMO_FLASH_CMD 300 /* Sec tmo for outstanding FLASH write - * or erase cmds. This is especially - * long because of the potential of - * multiple flash erases that can be - * spawned. - */ diff --git a/trunk/drivers/scsi/lpfc/lpfc_version.h b/trunk/drivers/scsi/lpfc/lpfc_version.h index c7091ea29f3f..10e89c6ae823 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_version.h +++ b/trunk/drivers/scsi/lpfc/lpfc_version.h @@ -18,7 +18,7 @@ * included with this package. * *******************************************************************/ -#define LPFC_DRIVER_VERSION "8.1.9" +#define LPFC_DRIVER_VERSION "8.1.7" #define LPFC_DRIVER_NAME "lpfc" diff --git a/trunk/drivers/scsi/mac53c94.c b/trunk/drivers/scsi/mac53c94.c index 6422de72bf43..89ef34df5a1d 100644 --- a/trunk/drivers/scsi/mac53c94.c +++ b/trunk/drivers/scsi/mac53c94.c @@ -431,7 +431,7 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat struct fsc_state *state; struct Scsi_Host *host; void *dma_cmd_space; - const unsigned char *clkprop; + unsigned char *clkprop; int proplen, rc = -ENODEV; if (macio_resource_count(mdev) != 2 || macio_irq_count(mdev) != 2) { diff --git a/trunk/drivers/scsi/megaraid/mega_common.h b/trunk/drivers/scsi/megaraid/mega_common.h index 8cd0bd1d0f7c..4675343228ad 100644 --- a/trunk/drivers/scsi/megaraid/mega_common.h +++ b/trunk/drivers/scsi/megaraid/mega_common.h @@ -37,12 +37,6 @@ #define LSI_MAX_CHANNELS 16 #define LSI_MAX_LOGICAL_DRIVES_64LD (64+1) -#define HBA_SIGNATURE_64_BIT 0x299 -#define PCI_CONF_AMISIG64 0xa4 - -#define MEGA_SCSI_INQ_EVPD 1 -#define MEGA_INVALID_FIELD_IN_CDB 0x24 - /** * scb_t - scsi command control block diff --git a/trunk/drivers/scsi/megaraid/megaraid_ioctl.h b/trunk/drivers/scsi/megaraid/megaraid_ioctl.h index b8aa34202ec3..bdaee144a1c3 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_ioctl.h +++ b/trunk/drivers/scsi/megaraid/megaraid_ioctl.h @@ -132,10 +132,6 @@ typedef struct uioc { /* Driver Data: */ void __user * user_data; uint32_t user_data_len; - - /* 64bit alignment */ - uint32_t pad_for_64bit_align; - mraid_passthru_t __user *user_pthru; mraid_passthru_t *pthru32; diff --git a/trunk/drivers/scsi/megaraid/megaraid_mbox.c b/trunk/drivers/scsi/megaraid/megaraid_mbox.c index cd982c877da0..7ae580f17e64 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_mbox.c +++ b/trunk/drivers/scsi/megaraid/megaraid_mbox.c @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. * * FILE : megaraid_mbox.c - * Version : v2.20.4.9 (Jul 16 2006) + * Version : v2.20.4.8 (Apr 11 2006) * * Authors: * Atul Mukker @@ -330,6 +330,21 @@ static struct device_attribute *megaraid_sdev_attrs[] = { NULL, }; +/** + * megaraid_change_queue_depth - Change the device's queue depth + * @sdev: scsi device struct + * @qdepth: depth to set + * + * Return value: + * actual depth set + **/ +static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth) +{ + if (qdepth > MBOX_MAX_SCSI_CMDS) + qdepth = MBOX_MAX_SCSI_CMDS; + scsi_adjust_queue_depth(sdev, 0, qdepth); + return sdev->queue_depth; +} /* * Scsi host template for megaraid unified driver @@ -343,6 +358,7 @@ static struct scsi_host_template megaraid_template_g = { .eh_device_reset_handler = megaraid_reset_handler, .eh_bus_reset_handler = megaraid_reset_handler, .eh_host_reset_handler = megaraid_reset_handler, + .change_queue_depth = megaraid_change_queue_depth, .use_clustering = ENABLE_CLUSTERING, .sdev_attrs = megaraid_sdev_attrs, .shost_attrs = megaraid_shost_attrs, @@ -720,7 +736,6 @@ megaraid_init_mbox(adapter_t *adapter) struct pci_dev *pdev; mraid_device_t *raid_dev; int i; - uint32_t magic64; adapter->ito = MBOX_TIMEOUT; @@ -864,33 +879,12 @@ megaraid_init_mbox(adapter_t *adapter) // Set the DMA mask to 64-bit. All supported controllers as capable of // DMA in this range - pci_read_config_dword(adapter->pdev, PCI_CONF_AMISIG64, &magic64); - - if (((magic64 == HBA_SIGNATURE_64_BIT) && - ((adapter->pdev->subsystem_device != - PCI_SUBSYS_ID_MEGARAID_SATA_150_6) || - (adapter->pdev->subsystem_device != - PCI_SUBSYS_ID_MEGARAID_SATA_150_4))) || - (adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC && - adapter->pdev->device == PCI_DEVICE_ID_VERDE) || - (adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC && - adapter->pdev->device == PCI_DEVICE_ID_DOBSON) || - (adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC && - adapter->pdev->device == PCI_DEVICE_ID_LINDSAY) || - (adapter->pdev->vendor == PCI_VENDOR_ID_DELL && - adapter->pdev->device == PCI_DEVICE_ID_PERC4_DI_EVERGLADES) || - (adapter->pdev->vendor == PCI_VENDOR_ID_DELL && - adapter->pdev->device == PCI_DEVICE_ID_PERC4E_DI_KOBUK)) { - if (pci_set_dma_mask(adapter->pdev, DMA_64BIT_MASK)) { - con_log(CL_ANN, (KERN_WARNING - "megaraid: DMA mask for 64-bit failed\n")); + if (pci_set_dma_mask(adapter->pdev, DMA_64BIT_MASK) != 0) { - if (pci_set_dma_mask (adapter->pdev, DMA_32BIT_MASK)) { - con_log(CL_ANN, (KERN_WARNING - "megaraid: 32-bit DMA mask failed\n")); - goto out_free_sysfs_res; - } - } + con_log(CL_ANN, (KERN_WARNING + "megaraid: could not set DMA mask for 64-bit.\n")); + + goto out_free_sysfs_res; } // setup tasklet for DPC @@ -1644,14 +1638,6 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) rdev->last_disp |= (1L << SCP2CHANNEL(scp)); } - if (scp->cmnd[1] & MEGA_SCSI_INQ_EVPD) { - scp->sense_buffer[0] = 0x70; - scp->sense_buffer[2] = ILLEGAL_REQUEST; - scp->sense_buffer[12] = MEGA_INVALID_FIELD_IN_CDB; - scp->result = CHECK_CONDITION << 1; - return NULL; - } - /* Fall through */ case READ_CAPACITY: diff --git a/trunk/drivers/scsi/megaraid/megaraid_mbox.h b/trunk/drivers/scsi/megaraid/megaraid_mbox.h index 2b5a3285f799..868fb0ec93e7 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_mbox.h +++ b/trunk/drivers/scsi/megaraid/megaraid_mbox.h @@ -21,8 +21,8 @@ #include "megaraid_ioctl.h" -#define MEGARAID_VERSION "2.20.4.9" -#define MEGARAID_EXT_VERSION "(Release Date: Sun Jul 16 12:27:22 EST 2006)" +#define MEGARAID_VERSION "2.20.4.8" +#define MEGARAID_EXT_VERSION "(Release Date: Mon Apr 11 12:27:22 EST 2006)" /* diff --git a/trunk/drivers/scsi/megaraid/megaraid_mm.c b/trunk/drivers/scsi/megaraid/megaraid_mm.c index d85b9a8f1b8d..e8f534fb336b 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_mm.c +++ b/trunk/drivers/scsi/megaraid/megaraid_mm.c @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. * * FILE : megaraid_mm.c - * Version : v2.20.2.7 (Jul 16 2006) + * Version : v2.20.2.6 (Mar 7 2005) * * Common management module */ diff --git a/trunk/drivers/scsi/megaraid/megaraid_mm.h b/trunk/drivers/scsi/megaraid/megaraid_mm.h index c8762b2b8ed1..3d9e67d6849d 100644 --- a/trunk/drivers/scsi/megaraid/megaraid_mm.h +++ b/trunk/drivers/scsi/megaraid/megaraid_mm.h @@ -27,9 +27,9 @@ #include "megaraid_ioctl.h" -#define LSI_COMMON_MOD_VERSION "2.20.2.7" +#define LSI_COMMON_MOD_VERSION "2.20.2.6" #define LSI_COMMON_MOD_EXT_VERSION \ - "(Release Date: Sun Jul 16 00:01:03 EST 2006)" + "(Release Date: Mon Mar 7 00:01:03 EST 2005)" #define LSI_DBGLVL dbglevel diff --git a/trunk/drivers/scsi/mesh.c b/trunk/drivers/scsi/mesh.c index 592b52afe658..5572981a9f92 100644 --- a/trunk/drivers/scsi/mesh.c +++ b/trunk/drivers/scsi/mesh.c @@ -1850,8 +1850,7 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match) { struct device_node *mesh = macio_get_of_node(mdev); struct pci_dev* pdev = macio_get_pci_dev(mdev); - int tgt, minper; - const int *cfp; + int tgt, *cfp, minper; struct mesh_state *ms; struct Scsi_Host *mesh_host; void *dma_cmd_space; @@ -1940,7 +1939,7 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match) ms->tgts[tgt].current_req = NULL; } - if ((cfp = get_property(mesh, "clock-frequency", NULL))) + if ((cfp = (int *) get_property(mesh, "clock-frequency", NULL))) ms->clk_freq = *cfp; else { printk(KERN_INFO "mesh: assuming 50MHz clock frequency\n"); diff --git a/trunk/drivers/scsi/pdc_adma.c b/trunk/drivers/scsi/pdc_adma.c index efc8fff1d250..d1f38c32aa15 100644 --- a/trunk/drivers/scsi/pdc_adma.c +++ b/trunk/drivers/scsi/pdc_adma.c @@ -183,8 +183,7 @@ static struct ata_port_info adma_port_info[] = { { .sht = &adma_ata_sht, .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | - ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | - ATA_FLAG_PIO_POLLING, + ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO, .pio_mask = 0x10, /* pio4 */ .udma_mask = 0x1f, /* udma0-4 */ .port_ops = &adma_ata_ops, diff --git a/trunk/drivers/scsi/qla2xxx/qla_def.h b/trunk/drivers/scsi/qla2xxx/qla_def.h index 0930260aec2c..139ea0e27fd7 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_def.h +++ b/trunk/drivers/scsi/qla2xxx/qla_def.h @@ -487,7 +487,6 @@ typedef struct { #define MBA_IP_RCV_BUFFER_EMPTY 0x8026 /* IP receive buffer queue empty. */ #define MBA_IP_HDR_DATA_SPLIT 0x8027 /* IP header/data splitting feature */ /* used. */ -#define MBA_TRACE_NOTIFICATION 0x8028 /* Trace/Diagnostic notification. */ #define MBA_POINT_TO_POINT 0x8030 /* Point to point mode. */ #define MBA_CMPLT_1_16BIT 0x8031 /* Completion 1 16bit IOSB. */ #define MBA_CMPLT_2_16BIT 0x8032 /* Completion 2 16bit IOSB. */ diff --git a/trunk/drivers/scsi/qla2xxx/qla_init.c b/trunk/drivers/scsi/qla2xxx/qla_init.c index 859649160caa..9758dba95542 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_init.c +++ b/trunk/drivers/scsi/qla2xxx/qla_init.c @@ -3063,7 +3063,6 @@ qla2x00_update_fcports(scsi_qla_host_t *ha) int qla2x00_abort_isp(scsi_qla_host_t *ha) { - int rval; unsigned long flags = 0; uint16_t cnt; srb_t *sp; @@ -3120,16 +3119,6 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) ha->isp_abort_cnt = 0; clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); - - if (ha->eft) { - rval = qla2x00_trace_control(ha, TC_ENABLE, - ha->eft_dma, EFT_NUM_BUFFERS); - if (rval) { - qla_printk(KERN_WARNING, ha, - "Unable to reinitialize EFT " - "(%d).\n", rval); - } - } } else { /* failed the ISP abort */ ha->flags.online = 1; if (test_bit(ISP_ABORT_RETRY, &ha->dpc_flags)) { diff --git a/trunk/drivers/scsi/qla2xxx/qla_iocb.c b/trunk/drivers/scsi/qla2xxx/qla_iocb.c index c5b3c610a32a..2b60a27eff0b 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_iocb.c +++ b/trunk/drivers/scsi/qla2xxx/qla_iocb.c @@ -471,7 +471,6 @@ __qla2x00_marker(scsi_qla_host_t *ha, uint16_t loop_id, uint16_t lun, mrk24->nport_handle = cpu_to_le16(loop_id); mrk24->lun[1] = LSB(lun); mrk24->lun[2] = MSB(lun); - host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); } else { SET_TARGET_ID(ha, mrk->target, loop_id); mrk->lun = cpu_to_le16(lun); diff --git a/trunk/drivers/scsi/qla2xxx/qla_isr.c b/trunk/drivers/scsi/qla2xxx/qla_isr.c index de0613135f70..795bf15b1b8f 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_isr.c +++ b/trunk/drivers/scsi/qla2xxx/qla_isr.c @@ -587,11 +587,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) DEBUG2(printk("scsi(%ld): Discard RND Frame -- %04x %04x " "%04x.\n", ha->host_no, mb[1], mb[2], mb[3])); break; - - case MBA_TRACE_NOTIFICATION: - DEBUG2(printk("scsi(%ld): Trace Notification -- %04x %04x.\n", - ha->host_no, mb[1], mb[2])); - break; } } diff --git a/trunk/drivers/scsi/qla2xxx/qla_os.c b/trunk/drivers/scsi/qla2xxx/qla_os.c index 65cbe2f5eea2..ec7ebb6037e6 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_os.c +++ b/trunk/drivers/scsi/qla2xxx/qla_os.c @@ -744,6 +744,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; + srb_t *sp; int ret; unsigned int id, lun; unsigned long serial; @@ -754,7 +755,8 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) lun = cmd->device->lun; serial = cmd->serial_number; - if (!fcport) + sp = (srb_t *) CMD_SP(cmd); + if (!sp || !fcport) return ret; qla_printk(KERN_INFO, ha, @@ -873,6 +875,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; + srb_t *sp; int ret; unsigned int id, lun; unsigned long serial; @@ -883,7 +886,8 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) lun = cmd->device->lun; serial = cmd->serial_number; - if (!fcport) + sp = (srb_t *) CMD_SP(cmd); + if (!sp || !fcport) return ret; qla_printk(KERN_INFO, ha, @@ -932,6 +936,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; + srb_t *sp; int ret; unsigned int id, lun; unsigned long serial; @@ -942,7 +947,8 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) lun = cmd->device->lun; serial = cmd->serial_number; - if (!fcport) + sp = (srb_t *) CMD_SP(cmd); + if (!sp || !fcport) return ret; qla_printk(KERN_INFO, ha, @@ -2238,6 +2244,9 @@ qla2x00_do_dpc(void *data) next_loopid = 0; list_for_each_entry(fcport, &ha->fcports, list) { + if (fcport->port_type != FCT_TARGET) + continue; + /* * If the port is not ONLINE then try to login * to it if we haven't run out of retries. diff --git a/trunk/drivers/scsi/qla2xxx/qla_version.h b/trunk/drivers/scsi/qla2xxx/qla_version.h index 971259032ef7..d2d683440659 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_version.h +++ b/trunk/drivers/scsi/qla2xxx/qla_version.h @@ -7,9 +7,9 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.01.07-k1" +#define QLA2XXX_VERSION "8.01.05-k3" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 1 -#define QLA_DRIVER_PATCH_VER 7 +#define QLA_DRIVER_PATCH_VER 5 #define QLA_DRIVER_BETA_VER 0 diff --git a/trunk/drivers/scsi/sata_mv.c b/trunk/drivers/scsi/sata_mv.c index fa38a413d16b..1053c7c76b7d 100644 --- a/trunk/drivers/scsi/sata_mv.c +++ b/trunk/drivers/scsi/sata_mv.c @@ -1961,7 +1961,8 @@ static void __mv_phy_reset(struct ata_port *ap, int can_sleep) timeout = jiffies + msecs_to_jiffies(200); do { sata_scr_read(ap, SCR_STATUS, &sstatus); - if (((sstatus & 0x3) == 3) || ((sstatus & 0x3) == 0)) + sstatus &= 0x3; + if ((sstatus == 3) || (sstatus == 0)) break; __msleep(1, can_sleep); diff --git a/trunk/drivers/scsi/sata_promise.c b/trunk/drivers/scsi/sata_promise.c index 4776f4e55839..64631bd38952 100644 --- a/trunk/drivers/scsi/sata_promise.c +++ b/trunk/drivers/scsi/sata_promise.c @@ -269,15 +269,8 @@ static const struct pci_device_id pdc_ata_pci_tbl[] = { { PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20619 }, -/* TODO: remove all associated board_20771 code, as it completely - * duplicates board_2037x code, unless reason for separation can be - * divined. - */ -#if 0 { PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20771 }, -#endif - { } /* terminate list */ }; diff --git a/trunk/drivers/scsi/sata_sil24.c b/trunk/drivers/scsi/sata_sil24.c index 3f368c7d3ef9..2e0f4a4076af 100644 --- a/trunk/drivers/scsi/sata_sil24.c +++ b/trunk/drivers/scsi/sata_sil24.c @@ -1106,6 +1106,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) probe_ent->irq = pdev->irq; probe_ent->irq_flags = IRQF_SHARED; + probe_ent->mmio_base = port_base; probe_ent->private_data = hpriv; hpriv->host_base = host_base; diff --git a/trunk/drivers/scsi/sata_svw.c b/trunk/drivers/scsi/sata_svw.c index 6b70c3c76dfd..7d0858095e1f 100644 --- a/trunk/drivers/scsi/sata_svw.c +++ b/trunk/drivers/scsi/sata_svw.c @@ -268,7 +268,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start, /* Match it to a port node */ index = (ap == ap->host_set->ports[0]) ? 0 : 1; for (np = np->child; np != NULL; np = np->sibling) { - const u32 *reg = get_property(np, "reg", NULL); + u32 *reg = (u32 *)get_property(np, "reg", NULL); if (!reg) continue; if (index == *reg) diff --git a/trunk/drivers/scsi/sata_via.c b/trunk/drivers/scsi/sata_via.c index a3727af8b9c1..03baec2191bf 100644 --- a/trunk/drivers/scsi/sata_via.c +++ b/trunk/drivers/scsi/sata_via.c @@ -74,10 +74,8 @@ enum { static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg); static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); -static void vt6420_error_handler(struct ata_port *ap); static const struct pci_device_id svia_pci_tbl[] = { - { 0x1106, 0x0591, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 }, { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 }, { 0x1106, 0x3249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6421 }, @@ -109,38 +107,7 @@ static struct scsi_host_template svia_sht = { .bios_param = ata_std_bios_param, }; -static const struct ata_port_operations vt6420_sata_ops = { - .port_disable = ata_port_disable, - - .tf_load = ata_tf_load, - .tf_read = ata_tf_read, - .check_status = ata_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - - .bmdma_setup = ata_bmdma_setup, - .bmdma_start = ata_bmdma_start, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_pio_data_xfer, - - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = vt6420_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_host_stop, -}; - -static const struct ata_port_operations vt6421_sata_ops = { +static const struct ata_port_operations svia_sata_ops = { .port_disable = ata_port_disable, .tf_load = ata_tf_load, @@ -174,13 +141,13 @@ static const struct ata_port_operations vt6421_sata_ops = { .host_stop = ata_host_stop, }; -static struct ata_port_info vt6420_port_info = { +static struct ata_port_info svia_port_info = { .sht = &svia_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, .pio_mask = 0x1f, .mwdma_mask = 0x07, .udma_mask = 0x7f, - .port_ops = &vt6420_sata_ops, + .port_ops = &svia_sata_ops, }; MODULE_AUTHOR("Jeff Garzik"); @@ -203,81 +170,6 @@ static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) outl(val, ap->ioaddr.scr_addr + (4 * sc_reg)); } -/** - * vt6420_prereset - prereset for vt6420 - * @ap: target ATA port - * - * SCR registers on vt6420 are pieces of shit and may hang the - * whole machine completely if accessed with the wrong timing. - * To avoid such catastrophe, vt6420 doesn't provide generic SCR - * access operations, but uses SStatus and SControl only during - * boot probing in controlled way. - * - * As the old (pre EH update) probing code is proven to work, we - * strictly follow the access pattern. - * - * LOCKING: - * Kernel thread context (may sleep) - * - * RETURNS: - * 0 on success, -errno otherwise. - */ -static int vt6420_prereset(struct ata_port *ap) -{ - struct ata_eh_context *ehc = &ap->eh_context; - unsigned long timeout = jiffies + (HZ * 5); - u32 sstatus, scontrol; - int online; - - /* don't do any SCR stuff if we're not loading */ - if (!ATA_PFLAG_LOADING) - goto skip_scr; - - /* Resume phy. This is the old resume sequence from - * __sata_phy_reset(). - */ - svia_scr_write(ap, SCR_CONTROL, 0x300); - svia_scr_read(ap, SCR_CONTROL); /* flush */ - - /* wait for phy to become ready, if necessary */ - do { - msleep(200); - if ((svia_scr_read(ap, SCR_STATUS) & 0xf) != 1) - break; - } while (time_before(jiffies, timeout)); - - /* open code sata_print_link_status() */ - sstatus = svia_scr_read(ap, SCR_STATUS); - scontrol = svia_scr_read(ap, SCR_CONTROL); - - online = (sstatus & 0xf) == 0x3; - - ata_port_printk(ap, KERN_INFO, - "SATA link %s 1.5 Gbps (SStatus %X SControl %X)\n", - online ? "up" : "down", sstatus, scontrol); - - /* SStatus is read one more time */ - svia_scr_read(ap, SCR_STATUS); - - if (!online) { - /* tell EH to bail */ - ehc->i.action &= ~ATA_EH_RESET_MASK; - return 0; - } - - skip_scr: - /* wait for !BSY */ - ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); - - return 0; -} - -static void vt6420_error_handler(struct ata_port *ap) -{ - return ata_bmdma_drive_eh(ap, vt6420_prereset, ata_std_softreset, - NULL, ata_std_postreset); -} - static const unsigned int svia_bar_sizes[] = { 8, 4, 8, 4, 16, 256 }; @@ -318,7 +210,7 @@ static void vt6421_init_addrs(struct ata_probe_ent *probe_ent, static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev) { struct ata_probe_ent *probe_ent; - struct ata_port_info *ppi = &vt6420_port_info; + struct ata_port_info *ppi = &svia_port_info; probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); if (!probe_ent) @@ -347,7 +239,7 @@ static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev) probe_ent->sht = &svia_sht; probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY; - probe_ent->port_ops = &vt6421_sata_ops; + probe_ent->port_ops = &svia_sata_ops; probe_ent->n_ports = N_PORTS; probe_ent->irq = pdev->irq; probe_ent->irq_flags = IRQF_SHARED; diff --git a/trunk/drivers/scsi/scsi_error.c b/trunk/drivers/scsi/scsi_error.c index 3d355d054612..6a5b731bd5ba 100644 --- a/trunk/drivers/scsi/scsi_error.c +++ b/trunk/drivers/scsi/scsi_error.c @@ -460,13 +460,12 @@ static void scsi_eh_done(struct scsi_cmnd *scmd) * Return value: * SUCCESS or FAILED or NEEDS_RETRY **/ -static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, - int cmnd_size, int timeout, int copy_sense) +static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout, int copy_sense) { struct scsi_device *sdev = scmd->device; struct Scsi_Host *shost = sdev->host; int old_result = scmd->result; - DECLARE_COMPLETION_ONSTACK(done); + DECLARE_COMPLETION(done); unsigned long timeleft; unsigned long flags; unsigned char old_cmnd[MAX_COMMAND_SIZE]; @@ -491,9 +490,6 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, old_cmd_len = scmd->cmd_len; old_use_sg = scmd->use_sg; - memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); - memcpy(scmd->cmnd, cmnd, cmnd_size); - if (copy_sense) { int gfp_mask = GFP_ATOMIC; @@ -614,7 +610,8 @@ static int scsi_request_sense(struct scsi_cmnd *scmd) static unsigned char generic_sense[6] = {REQUEST_SENSE, 0, 0, 0, 252, 0}; - return scsi_send_eh_cmnd(scmd, generic_sense, 6, SENSE_TIMEOUT, 1); + memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense)); + return scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 1); } /** @@ -739,7 +736,10 @@ static int scsi_eh_tur(struct scsi_cmnd *scmd) int retry_cnt = 1, rtn; retry_tur: - rtn = scsi_send_eh_cmnd(scmd, tur_command, 6, SENSE_TIMEOUT, 0); + memcpy(scmd->cmnd, tur_command, sizeof(tur_command)); + + + rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT, 0); SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n", __FUNCTION__, scmd, rtn)); @@ -839,8 +839,8 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd) if (scmd->device->allow_restart) { int rtn; - rtn = scsi_send_eh_cmnd(scmd, stu_command, 6, - START_UNIT_TIMEOUT, 0); + memcpy(scmd->cmnd, stu_command, sizeof(stu_command)); + rtn = scsi_send_eh_cmnd(scmd, START_UNIT_TIMEOUT, 0); if (rtn == SUCCESS) return 0; } diff --git a/trunk/drivers/scsi/scsi_ioctl.c b/trunk/drivers/scsi/scsi_ioctl.c index 32293f451669..a89c4115cfba 100644 --- a/trunk/drivers/scsi/scsi_ioctl.c +++ b/trunk/drivers/scsi/scsi_ioctl.c @@ -110,8 +110,11 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, sshdr.asc, sshdr.ascq); break; case NOT_READY: /* This happens if there is no disc in drive */ - if (sdev->removable) + if (sdev->removable && (cmd[0] != TEST_UNIT_READY)) { + printk(KERN_INFO "Device not ready. Make sure" + " there is a disc in the drive.\n"); break; + } case UNIT_ATTENTION: if (sdev->removable) { sdev->changed = 1; diff --git a/trunk/drivers/scsi/scsi_transport_iscsi.c b/trunk/drivers/scsi/scsi_transport_iscsi.c index 2ecd14188574..7b9e8fa1a4e0 100644 --- a/trunk/drivers/scsi/scsi_transport_iscsi.c +++ b/trunk/drivers/scsi/scsi_transport_iscsi.c @@ -34,7 +34,6 @@ #define ISCSI_SESSION_ATTRS 11 #define ISCSI_CONN_ATTRS 11 #define ISCSI_HOST_ATTRS 0 -#define ISCSI_TRANSPORT_VERSION "1.1-646" struct iscsi_internal { int daemon_pid; @@ -635,13 +634,13 @@ mempool_zone_get_skb(struct mempool_zone *zone) } static int -iscsi_broadcast_skb(struct mempool_zone *zone, struct sk_buff *skb, gfp_t gfp) +iscsi_broadcast_skb(struct mempool_zone *zone, struct sk_buff *skb) { unsigned long flags; int rc; skb_get(skb); - rc = netlink_broadcast(nls, skb, 0, 1, gfp); + rc = netlink_broadcast(nls, skb, 0, 1, GFP_KERNEL); if (rc < 0) { mempool_free(skb, zone->pool); printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc); @@ -750,7 +749,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) ev->r.connerror.cid = conn->cid; ev->r.connerror.sid = iscsi_conn_get_sid(conn); - iscsi_broadcast_skb(conn->z_error, skb, GFP_ATOMIC); + iscsi_broadcast_skb(conn->z_error, skb); dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n", error); @@ -896,7 +895,7 @@ int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn) * this will occur if the daemon is not up, so we just warn * the user and when the daemon is restarted it will handle it */ - rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL); + rc = iscsi_broadcast_skb(conn->z_pdu, skb); if (rc < 0) dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of " "session destruction event. Check iscsi daemon\n"); @@ -959,7 +958,7 @@ int iscsi_if_create_session_done(struct iscsi_cls_conn *conn) * this will occur if the daemon is not up, so we just warn * the user and when the daemon is restarted it will handle it */ - rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL); + rc = iscsi_broadcast_skb(conn->z_pdu, skb); if (rc < 0) dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of " "session creation event. Check iscsi daemon\n"); @@ -1614,9 +1613,6 @@ static __init int iscsi_transport_init(void) { int err; - printk(KERN_INFO "Loading iSCSI transport class v%s.", - ISCSI_TRANSPORT_VERSION); - err = class_register(&iscsi_transport_class); if (err) return err; @@ -1682,4 +1678,3 @@ MODULE_AUTHOR("Mike Christie , " "Alex Aizman "); MODULE_DESCRIPTION("iSCSI Transport Interface"); MODULE_LICENSE("GPL"); -MODULE_VERSION(ISCSI_TRANSPORT_VERSION); diff --git a/trunk/drivers/scsi/sg.c b/trunk/drivers/scsi/sg.c index 34f9343ed0af..65eef33846bb 100644 --- a/trunk/drivers/scsi/sg.c +++ b/trunk/drivers/scsi/sg.c @@ -18,8 +18,8 @@ * */ -static int sg_version_num = 30534; /* 2 digits for each component */ -#define SG_VERSION_STR "3.5.34" +static int sg_version_num = 30533; /* 2 digits for each component */ +#define SG_VERSION_STR "3.5.33" /* * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: @@ -60,7 +60,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */ #ifdef CONFIG_SCSI_PROC_FS #include -static char *sg_version_date = "20060818"; +static char *sg_version_date = "20050908"; static int sg_proc_init(void); static void sg_proc_cleanup(void); @@ -1164,7 +1164,7 @@ sg_vma_nopage(struct vm_area_struct *vma, unsigned long addr, int *type) len = vma->vm_end - sa; len = (len < sg->length) ? len : sg->length; if (offset < len) { - page = virt_to_page(page_address(sg->page) + offset); + page = sg->page; get_page(page); /* increment page count */ break; } diff --git a/trunk/drivers/scsi/sym53c8xx_2/sym_glue.c b/trunk/drivers/scsi/sym53c8xx_2/sym_glue.c index 739d3ef46a40..8c505076c0eb 100644 --- a/trunk/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/trunk/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -2084,7 +2084,7 @@ static struct pci_device_id sym2_id_table[] __devinitdata = { { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C860, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1510, - PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_SCSI<<8, 0xffff00, 0UL }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C896, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_NCR_53C895, diff --git a/trunk/drivers/serial/8250_pci.c b/trunk/drivers/serial/8250_pci.c index 851e4839d6d9..a1d322f8a16c 100644 --- a/trunk/drivers/serial/8250_pci.c +++ b/trunk/drivers/serial/8250_pci.c @@ -458,11 +458,11 @@ static int pci_siig_setup(struct serial_private *priv, * growing *huge*, we use this function to collapse some 70 entries * in the PCI table into one, for sanity's and compactness's sake. */ -static const unsigned short timedia_single_port[] = { +static unsigned short timedia_single_port[] = { 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 }; -static const unsigned short timedia_dual_port[] = { +static unsigned short timedia_dual_port[] = { 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085, 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079, 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079, @@ -470,34 +470,35 @@ static const unsigned short timedia_dual_port[] = { 0xD079, 0 }; -static const unsigned short timedia_quad_port[] = { +static unsigned short timedia_quad_port[] = { 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157, 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159, 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056, 0xB157, 0 }; -static const unsigned short timedia_eight_port[] = { +static unsigned short timedia_eight_port[] = { 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166, 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 }; static const struct timedia_struct { int num; - const unsigned short *ids; + unsigned short *ids; } timedia_data[] = { { 1, timedia_single_port }, { 2, timedia_dual_port }, { 4, timedia_quad_port }, - { 8, timedia_eight_port } + { 8, timedia_eight_port }, + { 0, NULL } }; static int pci_timedia_init(struct pci_dev *dev) { - const unsigned short *ids; + unsigned short *ids; int i, j; - for (i = 0; i < ARRAY_SIZE(timedia_data); i++) { + for (i = 0; timedia_data[i].num; i++) { ids = timedia_data[i].ids; for (j = 0; ids[j]; j++) if (dev->subsystem_device == ids[j]) @@ -935,7 +936,6 @@ enum pci_board_num_t { pbn_b1_8_1382400, pbn_b2_1_115200, - pbn_b2_2_115200, pbn_b2_8_115200, pbn_b2_1_460800, @@ -1243,12 +1243,6 @@ static struct pciserial_board pci_boards[] __devinitdata = { .base_baud = 115200, .uart_offset = 8, }, - [pbn_b2_2_115200] = { - .flags = FL_BASE2, - .num_ports = 2, - .base_baud = 115200, - .uart_offset = 8, - }, [pbn_b2_8_115200] = { .flags = FL_BASE2, .num_ports = 8, @@ -2345,13 +2339,6 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_1_115200 }, - /* - * IntaShield IS-200 - */ - { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS200, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0811 */ - pbn_b2_2_115200 }, - /* * These entries match devices with class COMMUNICATION_SERIAL, * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL diff --git a/trunk/drivers/serial/pmac_zilog.c b/trunk/drivers/serial/pmac_zilog.c index a3b99caf80e6..bfd2a22759eb 100644 --- a/trunk/drivers/serial/pmac_zilog.c +++ b/trunk/drivers/serial/pmac_zilog.c @@ -1400,8 +1400,8 @@ static struct uart_ops pmz_pops = { static int __init pmz_init_port(struct uart_pmac_port *uap) { struct device_node *np = uap->node; - const char *conn; - const struct slot_names_prop { + char *conn; + struct slot_names_prop { int count; char name[1]; } *slots; @@ -1458,7 +1458,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap) uap->flags |= PMACZILOG_FLAG_IS_IRDA; uap->port_type = PMAC_SCC_ASYNC; /* 1999 Powerbook G3 has slot-names property instead */ - slots = get_property(np, "slot-names", &len); + slots = (struct slot_names_prop *)get_property(np, "slot-names", &len); if (slots && slots->count > 0) { if (strcmp(slots->name, "IrDA") == 0) uap->flags |= PMACZILOG_FLAG_IS_IRDA; @@ -1470,8 +1470,7 @@ static int __init pmz_init_port(struct uart_pmac_port *uap) if (ZS_IS_INTMODEM(uap)) { struct device_node* i2c_modem = find_devices("i2c-modem"); if (i2c_modem) { - const char* mid = - get_property(i2c_modem, "modem-id", NULL); + char* mid = get_property(i2c_modem, "modem-id", NULL); if (mid) switch(*mid) { case 0x04 : case 0x05 : diff --git a/trunk/drivers/serial/s3c2410.c b/trunk/drivers/serial/s3c2410.c index 95738a19cde7..392bffcf96e8 100644 --- a/trunk/drivers/serial/s3c2410.c +++ b/trunk/drivers/serial/s3c2410.c @@ -1621,7 +1621,7 @@ static struct s3c24xx_uart_info s3c2412_uart_inf = { static int s3c2412_serial_probe(struct platform_device *dev) { dbg("s3c2440_serial_probe: dev=%p\n", dev); - return s3c24xx_serial_probe(dev, &s3c2412_uart_inf); + return s3c24xx_serial_probe(dev, &s3c2440_uart_inf); } static struct platform_driver s3c2412_serial_drv = { diff --git a/trunk/drivers/serial/serial_core.c b/trunk/drivers/serial/serial_core.c index 372e47f7d596..80ef7d482756 100644 --- a/trunk/drivers/serial/serial_core.c +++ b/trunk/drivers/serial/serial_core.c @@ -2377,9 +2377,6 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2) return (port1->iobase == port2->iobase) && (port1->hub6 == port2->hub6); case UPIO_MEM: - case UPIO_MEM32: - case UPIO_AU: - case UPIO_TSI: return (port1->mapbase == port2->mapbase); } return 0; diff --git a/trunk/drivers/serial/sh-sci.c b/trunk/drivers/serial/sh-sci.c index cbede06cac27..301573373c30 100644 --- a/trunk/drivers/serial/sh-sci.c +++ b/trunk/drivers/serial/sh-sci.c @@ -1579,7 +1579,7 @@ static int __init serial_console_setup(struct console *co, char *options) h8300_sci_enable(port, sci_enable); #endif #elif defined(CONFIG_SUPERH64) - port->uartclk = current_cpu_data.module_clock * 16; + port->uartclk = current_cpu_info.module_clock * 16; #else { struct clk *clk = clk_get("module_clk"); @@ -1720,7 +1720,7 @@ static int __init sci_init(void) #if defined(__H8300H__) || defined(__H8300S__) sciport->port.uartclk = CONFIG_CPU_CLOCK; #elif defined(CONFIG_SUPERH64) - sciport->port.uartclk = current_cpu_data.module_clock * 16; + sciport->port.uartclk = current_cpu_info.module_clock * 16; #else struct clk *clk = clk_get("module_clk"); sciport->port.uartclk = clk_get_rate(clk) * 16; diff --git a/trunk/drivers/serial/sunsab.c b/trunk/drivers/serial/sunsab.c index cfe20f730436..dc673e1b6fd9 100644 --- a/trunk/drivers/serial/sunsab.c +++ b/trunk/drivers/serial/sunsab.c @@ -886,15 +886,6 @@ static int sunsab_console_setup(struct console *con, char *options) unsigned long flags; unsigned int baud, quot; - /* - * The console framework calls us for each and every port - * registered. Defer the console setup until the requested - * port has been properly discovered. A bit of a hack, - * though... - */ - if (up->port.type != PORT_SUNSAB) - return -1; - printk("Console: ttyS%d (SAB82532)\n", (sunsab_reg.minor - 64) + con->index); diff --git a/trunk/drivers/serial/sunzilog.c b/trunk/drivers/serial/sunzilog.c index d34f336d53d8..47bc3d57e019 100644 --- a/trunk/drivers/serial/sunzilog.c +++ b/trunk/drivers/serial/sunzilog.c @@ -1146,9 +1146,6 @@ static int __init sunzilog_console_setup(struct console *con, char *options) unsigned long flags; int baud, brg; - if (up->port.type != PORT_SUNZILOG) - return -1; - printk(KERN_INFO "Console: ttyS%d (SunZilog zs%d)\n", (sunzilog_reg.minor - 64) + con->index, con->index); diff --git a/trunk/drivers/usb/Kconfig b/trunk/drivers/usb/Kconfig index 005043197527..2ee742d40c43 100644 --- a/trunk/drivers/usb/Kconfig +++ b/trunk/drivers/usb/Kconfig @@ -24,7 +24,7 @@ config USB_ARCH_HAS_OHCI default y if ARCH_S3C2410 default y if PXA27x default y if ARCH_EP93XX - default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261) + default y if ARCH_AT91RM9200 # PPC: default y if STB03xxx default y if PPC_MPC52xx diff --git a/trunk/drivers/usb/core/devio.c b/trunk/drivers/usb/core/devio.c index 218621b9958e..f7bdd94b3aa8 100644 --- a/trunk/drivers/usb/core/devio.c +++ b/trunk/drivers/usb/core/devio.c @@ -517,19 +517,19 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig static struct usb_device *usbdev_lookup_minor(int minor) { - struct class_device *class_dev; - struct usb_device *dev = NULL; + struct device *device; + struct usb_device *udev = NULL; down(&usb_device_class->sem); - list_for_each_entry(class_dev, &usb_device_class->children, node) { - if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { - dev = class_dev->class_data; + list_for_each_entry(device, &usb_device_class->devices, node) { + if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { + udev = device->platform_data; break; } } up(&usb_device_class->sem); - return dev; + return udev; }; /* @@ -1580,16 +1580,16 @@ static void usbdev_add(struct usb_device *dev) { int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); - dev->class_dev = class_device_create(usb_device_class, NULL, - MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev, + dev->usbfs_dev = device_create(usb_device_class, &dev->dev, + MKDEV(USB_DEVICE_MAJOR, minor), "usbdev%d.%d", dev->bus->busnum, dev->devnum); - dev->class_dev->class_data = dev; + dev->usbfs_dev->platform_data = dev; } static void usbdev_remove(struct usb_device *dev) { - class_device_unregister(dev->class_dev); + device_unregister(dev->usbfs_dev); } static int usbdev_notify(struct notifier_block *self, unsigned long action, diff --git a/trunk/drivers/usb/core/file.c b/trunk/drivers/usb/core/file.c index 8de4f8c99d61..abee0f5b6a66 100644 --- a/trunk/drivers/usb/core/file.c +++ b/trunk/drivers/usb/core/file.c @@ -194,14 +194,13 @@ int usb_register_dev(struct usb_interface *intf, ++temp; else temp = name; - intf->class_dev = class_device_create(usb_class->class, NULL, - MKDEV(USB_MAJOR, minor), - &intf->dev, "%s", temp); - if (IS_ERR(intf->class_dev)) { + intf->usb_dev = device_create(usb_class->class, &intf->dev, + MKDEV(USB_MAJOR, minor), "%s", temp); + if (IS_ERR(intf->usb_dev)) { spin_lock (&minor_lock); usb_minors[intf->minor] = NULL; spin_unlock (&minor_lock); - retval = PTR_ERR(intf->class_dev); + retval = PTR_ERR(intf->usb_dev); } exit: return retval; @@ -242,8 +241,8 @@ void usb_deregister_dev(struct usb_interface *intf, spin_unlock (&minor_lock); snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); - class_device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); - intf->class_dev = NULL; + device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); + intf->usb_dev = NULL; intf->minor = -1; destroy_usb_class(); } diff --git a/trunk/drivers/usb/gadget/Kconfig b/trunk/drivers/usb/gadget/Kconfig index 1a32d96774b4..363b2ad74ae6 100644 --- a/trunk/drivers/usb/gadget/Kconfig +++ b/trunk/drivers/usb/gadget/Kconfig @@ -207,7 +207,7 @@ config USB_AT91 config USB_GADGET_DUMMY_HCD boolean "Dummy HCD (DEVELOPMENT)" - depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL + depends on USB && EXPERIMENTAL select USB_GADGET_DUALSPEED help This host controller driver emulates USB, looping all data transfer diff --git a/trunk/drivers/usb/gadget/at91_udc.c b/trunk/drivers/usb/gadget/at91_udc.c index cfebca05ead5..1c459ff037ce 100644 --- a/trunk/drivers/usb/gadget/at91_udc.c +++ b/trunk/drivers/usb/gadget/at91_udc.c @@ -57,23 +57,19 @@ /* * This controller is simple and PIO-only. It's used in many AT91-series - * full speed USB controllers, including the at91rm9200 (arm920T, with MMU), - * at91sam926x (arm926ejs, with MMU), and several no-mmu versions. + * ARMv4T controllers, including the at91rm9200 (arm920T, with MMU), + * at91sam9261 (arm926ejs, with MMU), and several no-mmu versions. * * This driver expects the board has been wired with two GPIOs suppporting * a VBUS sensing IRQ, and a D+ pullup. (They may be omitted, but the - * testing hasn't covered such cases.) - * - * The pullup is most important (so it's integrated on sam926x parts). It + * testing hasn't covered such cases.) The pullup is most important; it * provides software control over whether the host enumerates the device. - * * The VBUS sensing helps during enumeration, and allows both USB clocks * (and the transceiver) to stay gated off until they're necessary, saving - * power. During USB suspend, the 48 MHz clock is gated off in hardware; - * it may also be gated off by software during some Linux sleep states. + * power. During USB suspend, the 48 MHz clock is gated off. */ -#define DRIVER_VERSION "3 May 2006" +#define DRIVER_VERSION "8 March 2005" static const char driver_name [] = "at91_udc"; static const char ep0name[] = "ep0"; @@ -320,15 +316,9 @@ static void done(struct at91_ep *ep, struct at91_request *req, int status) * * There are also state bits like FORCESTALL, EPEDS, DIR, and EPTYPE * that shouldn't normally be changed. - * - * NOTE at91sam9260 docs mention synch between UDPCK and MCK clock domains, - * implying a need to wait for one write to complete (test relevant bits) - * before starting the next write. This shouldn't be an issue given how - * infrequently we write, except maybe for write-then-read idioms. */ #define SET_FX (AT91_UDP_TXPKTRDY) -#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP \ - | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP) +#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP) /* pull OUT packet data from the endpoint's fifo */ static int read_fifo (struct at91_ep *ep, struct at91_request *req) @@ -482,8 +472,7 @@ static void nuke(struct at91_ep *ep, int status) /*-------------------------------------------------------------------------*/ -static int at91_ep_enable(struct usb_ep *_ep, - const struct usb_endpoint_descriptor *desc) +static int at91_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) { struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); struct at91_udc *dev = ep->udc; @@ -593,12 +582,11 @@ static int at91_ep_disable (struct usb_ep * _ep) * interesting for request or buffer allocation. */ -static struct usb_request * -at91_ep_alloc_request(struct usb_ep *_ep, unsigned int gfp_flags) +static struct usb_request *at91_ep_alloc_request (struct usb_ep *_ep, unsigned int gfp_flags) { struct at91_request *req; - req = kcalloc(1, sizeof (struct at91_request), gfp_flags); + req = kcalloc(1, sizeof (struct at91_request), SLAB_KERNEL); if (!req) return NULL; @@ -874,7 +862,6 @@ static void stop_activity(struct at91_udc *udc) if (udc->gadget.speed == USB_SPEED_UNKNOWN) driver = NULL; udc->gadget.speed = USB_SPEED_UNKNOWN; - udc->suspended = 0; for (i = 0; i < NUM_ENDPOINTS; i++) { struct at91_ep *ep = &udc->ep[i]; @@ -902,8 +889,8 @@ static void clk_off(struct at91_udc *udc) return; udc->clocked = 0; udc->gadget.speed = USB_SPEED_UNKNOWN; - clk_disable(udc->fclk); clk_disable(udc->iclk); + clk_disable(udc->fclk); } /* @@ -924,6 +911,9 @@ static void pullup(struct at91_udc *udc, int is_on) at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); at91_set_gpio_value(udc->board.pullup_pin, 0); clk_off(udc); + + // REVISIT: with transceiver disabled, will D- float + // so that a host would falsely detect a device? } } @@ -1300,8 +1290,7 @@ static void handle_ep0(struct at91_udc *udc) if (udc->wait_for_addr_ack) { u32 tmp; - at91_udp_write(AT91_UDP_FADDR, - AT91_UDP_FEN | udc->addr); + at91_udp_write(AT91_UDP_FADDR, AT91_UDP_FEN | udc->addr); tmp = at91_udp_read(AT91_UDP_GLB_STAT); tmp &= ~AT91_UDP_FADDEN; if (udc->addr) @@ -1372,10 +1361,9 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r) u32 rescans = 5; while (rescans--) { - u32 status; + u32 status = at91_udp_read(AT91_UDP_ISR); - status = at91_udp_read(AT91_UDP_ISR) - & at91_udp_read(AT91_UDP_IMR); + status &= at91_udp_read(AT91_UDP_IMR); if (!status) break; @@ -1391,17 +1379,18 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r) stop_activity(udc); /* enable ep0 */ - at91_udp_write(AT91_UDP_CSR(0), - AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL); + at91_udp_write(AT91_UDP_CSR(0), AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL); udc->gadget.speed = USB_SPEED_FULL; udc->suspended = 0; at91_udp_write(AT91_UDP_IER, AT91_UDP_EP(0)); /* * NOTE: this driver keeps clocks off unless the - * USB host is present. That saves power, but for - * boards that don't support VBUS detection, both - * clocks need to be active most of the time. + * USB host is present. That saves power, and also + * eliminates IRQs (reset, resume, suspend) that can + * otherwise flood from the controller. If your + * board doesn't support VBUS detection, suspend and + * resume irq logic may need more attention... */ /* host initiated suspend (3+ms bus idle) */ @@ -1463,19 +1452,13 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc, struct pt_regs *r) /*-------------------------------------------------------------------------*/ -static void nop_release(struct device *dev) -{ - /* nothing to free */ -} - static struct at91_udc controller = { .gadget = { - .ops = &at91_udc_ops, - .ep0 = &controller.ep[0].ep, - .name = driver_name, - .dev = { - .bus_id = "gadget", - .release = nop_release, + .ops = &at91_udc_ops, + .ep0 = &controller.ep[0].ep, + .name = driver_name, + .dev = { + .bus_id = "gadget" } }, .ep[0] = { @@ -1485,8 +1468,7 @@ static struct at91_udc controller = { }, .udc = &controller, .maxpacket = 8, - .creg = (void __iomem *)(AT91_VA_BASE_UDP - + AT91_UDP_CSR(0)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(0)), .int_mask = 1 << 0, }, .ep[1] = { @@ -1497,8 +1479,7 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 64, - .creg = (void __iomem *)(AT91_VA_BASE_UDP - + AT91_UDP_CSR(1)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(1)), .int_mask = 1 << 1, }, .ep[2] = { @@ -1509,8 +1490,7 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 64, - .creg = (void __iomem *)(AT91_VA_BASE_UDP - + AT91_UDP_CSR(2)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(2)), .int_mask = 1 << 2, }, .ep[3] = { @@ -1521,8 +1501,7 @@ static struct at91_udc controller = { }, .udc = &controller, .maxpacket = 8, - .creg = (void __iomem *)(AT91_VA_BASE_UDP - + AT91_UDP_CSR(3)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(3)), .int_mask = 1 << 3, }, .ep[4] = { @@ -1533,8 +1512,7 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 256, - .creg = (void __iomem *)(AT91_VA_BASE_UDP - + AT91_UDP_CSR(4)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(4)), .int_mask = 1 << 4, }, .ep[5] = { @@ -1545,11 +1523,10 @@ static struct at91_udc controller = { .udc = &controller, .is_pingpong = 1, .maxpacket = 256, - .creg = (void __iomem *)(AT91_VA_BASE_UDP - + AT91_UDP_CSR(5)), + .creg = (void __iomem *)(AT91_VA_BASE_UDP + AT91_UDP_CSR(5)), .int_mask = 1 << 5, }, - /* ep6 and ep7 are also reserved (custom silicon might use them) */ + /* ep6 and ep7 are also reserved */ }; static irqreturn_t at91_vbus_irq(int irq, void *_udc, struct pt_regs *r) @@ -1616,7 +1593,6 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) local_irq_disable(); udc->enabled = 0; - at91_udp_write(AT91_UDP_IDR, ~0); pullup(udc, 0); local_irq_enable(); @@ -1648,16 +1624,6 @@ static int __devinit at91udc_probe(struct platform_device *pdev) return -ENODEV; } - if (pdev->num_resources != 2) { - DBG("invalid num_resources"); - return -ENODEV; - } - if ((pdev->resource[0].flags != IORESOURCE_MEM) - || (pdev->resource[1].flags != IORESOURCE_IRQ)) { - DBG("invalid resource type"); - return -ENODEV; - } - if (!request_mem_region(AT91_BASE_UDP, SZ_16K, driver_name)) { DBG("someone's using UDC memory\n"); return -EBUSY; @@ -1683,26 +1649,19 @@ static int __devinit at91udc_probe(struct platform_device *pdev) if (retval < 0) goto fail0; - /* don't do anything until we have both gadget driver and VBUS */ - clk_enable(udc->iclk); - at91_udp_write(AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); - at91_udp_write(AT91_UDP_IDR, 0xffffffff); - clk_disable(udc->iclk); + /* disable everything until there's a gadget driver and vbus */ + pullup(udc, 0); /* request UDC and maybe VBUS irqs */ - udc->udp_irq = platform_get_irq(pdev, 0); - if (request_irq(udc->udp_irq, at91_udc_irq, - IRQF_DISABLED, driver_name, udc)) { - DBG("request irq %d failed\n", udc->udp_irq); + if (request_irq(AT91_ID_UDP, at91_udc_irq, IRQF_DISABLED, driver_name, udc)) { + DBG("request irq %d failed\n", AT91_ID_UDP); retval = -EBUSY; goto fail1; } if (udc->board.vbus_pin > 0) { - if (request_irq(udc->board.vbus_pin, at91_vbus_irq, - IRQF_DISABLED, driver_name, udc)) { - DBG("request vbus irq %d failed\n", - udc->board.vbus_pin); - free_irq(udc->udp_irq, udc); + if (request_irq(udc->board.vbus_pin, at91_vbus_irq, IRQF_DISABLED, driver_name, udc)) { + DBG("request vbus irq %d failed\n", udc->board.vbus_pin); + free_irq(AT91_ID_UDP, udc); retval = -EBUSY; goto fail1; } @@ -1711,7 +1670,6 @@ static int __devinit at91udc_probe(struct platform_device *pdev) udc->vbus = 1; } dev_set_drvdata(dev, udc); - device_init_wakeup(dev, 1); create_debug_file(udc); INFO("%s version %s\n", driver_name, DRIVER_VERSION); @@ -1720,14 +1678,14 @@ static int __devinit at91udc_probe(struct platform_device *pdev) fail1: device_unregister(&udc->gadget.dev); fail0: - release_mem_region(AT91_BASE_UDP, SZ_16K); + release_mem_region(AT91_VA_BASE_UDP, SZ_16K); DBG("%s probe failed, %d\n", driver_name, retval); return retval; } -static int __devexit at91udc_remove(struct platform_device *pdev) +static int __devexit at91udc_remove(struct platform_device *dev) { - struct at91_udc *udc = platform_get_drvdata(pdev); + struct at91_udc *udc = platform_get_drvdata(dev); DBG("remove\n"); @@ -1736,11 +1694,10 @@ static int __devexit at91udc_remove(struct platform_device *pdev) if (udc->driver != 0) usb_gadget_unregister_driver(udc->driver); - device_init_wakeup(&pdev->dev, 0); remove_debug_file(udc); if (udc->board.vbus_pin > 0) free_irq(udc->board.vbus_pin, udc); - free_irq(udc->udp_irq, udc); + free_irq(AT91_ID_UDP, udc); device_unregister(&udc->gadget.dev); release_mem_region(AT91_BASE_UDP, SZ_16K); @@ -1751,36 +1708,31 @@ static int __devexit at91udc_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int at91udc_suspend(struct platform_device *pdev, pm_message_t mesg) +static int at91udc_suspend(struct platform_device *dev, pm_message_t mesg) { - struct at91_udc *udc = platform_get_drvdata(pdev); - int wake = udc->driver && device_may_wakeup(&pdev->dev); + struct at91_udc *udc = platform_get_drvdata(dev); - /* Unless we can act normally to the host (letting it wake us up - * whenever it has work for us) force disconnect. Wakeup requires - * PLLB for USB events (signaling for reset, wakeup, or incoming - * tokens) and VBUS irqs (on systems which support them). + /* + * The "safe" suspend transitions are opportunistic ... e.g. when + * the USB link is suspended (48MHz clock autogated off), or when + * it's disconnected (programmatically gated off, elsewhere). + * Then we can suspend, and the chip can enter slow clock mode. + * + * The problem case is some component (user mode?) suspending this + * device while it's active, with the 48 MHz clock in use. There + * are two basic approaches: (a) veto suspend levels involving slow + * clock mode, (b) disconnect, so 48 MHz will no longer be in use + * and we can enter slow clock mode. This uses (b) for now, since + * it's simplest until AT91 PM exists and supports the other option. */ - if ((!udc->suspended && udc->addr) - || !wake - || at91_suspend_entering_slow_clock()) { + if (udc->vbus && !udc->suspended) pullup(udc, 0); - disable_irq_wake(udc->udp_irq); - } else - enable_irq_wake(udc->udp_irq); - - if (udc->board.vbus_pin > 0) { - if (wake) - enable_irq_wake(udc->board.vbus_pin); - else - disable_irq_wake(udc->board.vbus_pin); - } return 0; } -static int at91udc_resume(struct platform_device *pdev) +static int at91udc_resume(struct platform_device *dev) { - struct at91_udc *udc = platform_get_drvdata(pdev); + struct at91_udc *udc = platform_get_drvdata(dev); /* maybe reconnect to host; if so, clocks on */ pullup(udc, 1); @@ -1796,7 +1748,7 @@ static struct platform_driver at91_udc = { .remove = __devexit_p(at91udc_remove), .shutdown = at91udc_shutdown, .suspend = at91udc_suspend, - .resume = at91udc_resume, + .resume = at91udc_resume, .driver = { .name = (char *) driver_name, .owner = THIS_MODULE, @@ -1815,6 +1767,6 @@ static void __devexit udc_exit_module(void) } module_exit(udc_exit_module); -MODULE_DESCRIPTION("AT91 udc driver"); +MODULE_DESCRIPTION("AT91RM9200 udc driver"); MODULE_AUTHOR("Thomas Rathbone, David Brownell"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/usb/gadget/at91_udc.h b/trunk/drivers/usb/gadget/at91_udc.h index 882af42e86cc..5a4799cedd19 100644 --- a/trunk/drivers/usb/gadget/at91_udc.h +++ b/trunk/drivers/usb/gadget/at91_udc.h @@ -141,7 +141,6 @@ struct at91_udc { struct clk *iclk, *fclk; struct platform_device *pdev; struct proc_dir_entry *pde; - int udp_irq; }; static inline struct at91_udc *to_udc(struct usb_gadget *g) diff --git a/trunk/drivers/usb/gadget/dummy_hcd.c b/trunk/drivers/usb/gadget/dummy_hcd.c index 7d1c22c34957..4be47195bd38 100644 --- a/trunk/drivers/usb/gadget/dummy_hcd.c +++ b/trunk/drivers/usb/gadget/dummy_hcd.c @@ -609,8 +609,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) if (!dum->driver) return -ESHUTDOWN; - local_irq_save (flags); - spin_lock (&dum->lock); + spin_lock_irqsave (&dum->lock, flags); list_for_each_entry (req, &ep->queue, queue) { if (&req->req == _req) { list_del_init (&req->queue); @@ -619,7 +618,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) break; } } - spin_unlock (&dum->lock); + spin_unlock_irqrestore (&dum->lock, flags); if (retval == 0) { dev_dbg (udc_dev(dum), @@ -627,7 +626,6 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req) req, _ep->name, _req->length, _req->buf); _req->complete (_ep, _req); } - local_irq_restore (flags); return retval; } diff --git a/trunk/drivers/usb/gadget/ether.c b/trunk/drivers/usb/gadget/ether.c index 30299c620d97..4fe1bec1c255 100644 --- a/trunk/drivers/usb/gadget/ether.c +++ b/trunk/drivers/usb/gadget/ether.c @@ -117,8 +117,6 @@ struct eth_dev { struct usb_ep *in_ep, *out_ep, *status_ep; const struct usb_endpoint_descriptor *in, *out, *status; - - spinlock_t req_lock; struct list_head tx_reqs, rx_reqs; struct net_device *net; @@ -1068,31 +1066,21 @@ static void eth_reset_config (struct eth_dev *dev) */ if (dev->in) { usb_ep_disable (dev->in_ep); - spin_lock(&dev->req_lock); while (likely (!list_empty (&dev->tx_reqs))) { req = container_of (dev->tx_reqs.next, struct usb_request, list); list_del (&req->list); - - spin_unlock(&dev->req_lock); usb_ep_free_request (dev->in_ep, req); - spin_lock(&dev->req_lock); } - spin_unlock(&dev->req_lock); } if (dev->out) { usb_ep_disable (dev->out_ep); - spin_lock(&dev->req_lock); while (likely (!list_empty (&dev->rx_reqs))) { req = container_of (dev->rx_reqs.next, struct usb_request, list); list_del (&req->list); - - spin_unlock(&dev->req_lock); usb_ep_free_request (dev->out_ep, req); - spin_lock(&dev->req_lock); } - spin_unlock(&dev->req_lock); } if (dev->status) { @@ -1671,9 +1659,9 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) if (retval) { DEBUG (dev, "rx submit --> %d\n", retval); dev_kfree_skb_any (skb); - spin_lock(&dev->req_lock); + spin_lock (&dev->lock); list_add (&req->list, &dev->rx_reqs); - spin_unlock(&dev->req_lock); + spin_unlock (&dev->lock); } return retval; } @@ -1742,9 +1730,8 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req) dev_kfree_skb_any (skb); if (!netif_running (dev->net)) { clean: - spin_lock(&dev->req_lock); + /* nobody reading rx_reqs, so no dev->lock */ list_add (&req->list, &dev->rx_reqs); - spin_unlock(&dev->req_lock); req = NULL; } if (req) @@ -1795,18 +1782,15 @@ static int alloc_requests (struct eth_dev *dev, unsigned n, gfp_t gfp_flags) { int status; - spin_lock(&dev->req_lock); status = prealloc (&dev->tx_reqs, dev->in_ep, n, gfp_flags); if (status < 0) goto fail; status = prealloc (&dev->rx_reqs, dev->out_ep, n, gfp_flags); if (status < 0) goto fail; - goto done; + return 0; fail: DEBUG (dev, "can't alloc requests\n"); -done: - spin_unlock(&dev->req_lock); return status; } @@ -1816,21 +1800,21 @@ static void rx_fill (struct eth_dev *dev, gfp_t gfp_flags) unsigned long flags; /* fill unused rxq slots with some skb */ - spin_lock_irqsave(&dev->req_lock, flags); + spin_lock_irqsave (&dev->lock, flags); while (!list_empty (&dev->rx_reqs)) { req = container_of (dev->rx_reqs.next, struct usb_request, list); list_del_init (&req->list); - spin_unlock_irqrestore(&dev->req_lock, flags); + spin_unlock_irqrestore (&dev->lock, flags); if (rx_submit (dev, req, gfp_flags) < 0) { defer_kevent (dev, WORK_RX_MEMORY); return; } - spin_lock_irqsave(&dev->req_lock, flags); + spin_lock_irqsave (&dev->lock, flags); } - spin_unlock_irqrestore(&dev->req_lock, flags); + spin_unlock_irqrestore (&dev->lock, flags); } static void eth_work (void *_dev) @@ -1864,9 +1848,9 @@ static void tx_complete (struct usb_ep *ep, struct usb_request *req) } dev->stats.tx_packets++; - spin_lock(&dev->req_lock); + spin_lock (&dev->lock); list_add (&req->list, &dev->tx_reqs); - spin_unlock(&dev->req_lock); + spin_unlock (&dev->lock); dev_kfree_skb_any (skb); atomic_dec (&dev->tx_qlen); @@ -1912,12 +1896,12 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) /* ignores USB_CDC_PACKET_TYPE_DIRECTED */ } - spin_lock_irqsave(&dev->req_lock, flags); + spin_lock_irqsave (&dev->lock, flags); req = container_of (dev->tx_reqs.next, struct usb_request, list); list_del (&req->list); if (list_empty (&dev->tx_reqs)) netif_stop_queue (net); - spin_unlock_irqrestore(&dev->req_lock, flags); + spin_unlock_irqrestore (&dev->lock, flags); /* no buffer copies needed, unless the network stack did it * or the hardware can't use skb buffers. @@ -1971,11 +1955,11 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) drop: dev->stats.tx_dropped++; dev_kfree_skb_any (skb); - spin_lock_irqsave(&dev->req_lock, flags); + spin_lock_irqsave (&dev->lock, flags); if (list_empty (&dev->tx_reqs)) netif_start_queue (net); list_add (&req->list, &dev->tx_reqs); - spin_unlock_irqrestore(&dev->req_lock, flags); + spin_unlock_irqrestore (&dev->lock, flags); } return 0; } @@ -2394,7 +2378,6 @@ eth_bind (struct usb_gadget *gadget) return status; dev = netdev_priv(net); spin_lock_init (&dev->lock); - spin_lock_init (&dev->req_lock); INIT_WORK (&dev->work, eth_work, dev); INIT_LIST_HEAD (&dev->tx_reqs); INIT_LIST_HEAD (&dev->rx_reqs); diff --git a/trunk/drivers/usb/host/ehci-hcd.c b/trunk/drivers/usb/host/ehci-hcd.c index d63177a8eaea..85b0b4ad4c16 100644 --- a/trunk/drivers/usb/host/ehci-hcd.c +++ b/trunk/drivers/usb/host/ehci-hcd.c @@ -892,7 +892,7 @@ MODULE_LICENSE ("GPL"); #define PCI_DRIVER ehci_pci_driver #endif -#ifdef CONFIG_MPC834x +#ifdef CONFIG_PPC_83xx #include "ehci-fsl.c" #define PLATFORM_DRIVER ehci_fsl_driver #endif diff --git a/trunk/drivers/usb/host/ohci-at91.c b/trunk/drivers/usb/host/ohci-at91.c index 85cc059705a6..cdbafb710000 100644 --- a/trunk/drivers/usb/host/ohci-at91.c +++ b/trunk/drivers/usb/host/ohci-at91.c @@ -4,7 +4,7 @@ * Copyright (C) 2004 SAN People (Pty) Ltd. * Copyright (C) 2005 Thibaut VARENE * - * AT91 Bus Glue + * AT91RM9200 Bus Glue * * Based on fragments of 2.4 driver by Rick Bronson. * Based on ohci-omap.c @@ -19,13 +19,12 @@ #include #include -#ifndef CONFIG_ARCH_AT91 -#error "CONFIG_ARCH_AT91 must be defined." +#ifndef CONFIG_ARCH_AT91RM9200 +#error "CONFIG_ARCH_AT91RM9200 must be defined." #endif /* interface and function clocks */ static struct clk *iclk, *fclk; -static int clocked; extern int usb_disabled(void); @@ -36,14 +35,13 @@ static void at91_start_hc(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_regs __iomem *regs = hcd->regs; - dev_dbg(&pdev->dev, "start\n"); + dev_dbg(&pdev->dev, "starting AT91RM9200 OHCI USB Controller\n"); /* * Start the USB clocks. */ clk_enable(iclk); clk_enable(fclk); - clocked = 1; /* * The USB host controller must remain in reset. @@ -56,7 +54,7 @@ static void at91_stop_hc(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_regs __iomem *regs = hcd->regs; - dev_dbg(&pdev->dev, "stop\n"); + dev_dbg(&pdev->dev, "stopping AT91RM9200 OHCI USB Controller\n"); /* * Put the USB host controller into reset. @@ -68,7 +66,6 @@ static void at91_stop_hc(struct platform_device *pdev) */ clk_disable(fclk); clk_disable(iclk); - clocked = 0; } @@ -81,15 +78,14 @@ static int usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); /** - * usb_hcd_at91_probe - initialize AT91-based HCDs + * usb_hcd_at91_probe - initialize AT91RM9200-based HCDs * Context: !in_interrupt() * * Allocates basic resources for this USB host controller, and * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. */ -static int usb_hcd_at91_probe(const struct hc_driver *driver, - struct platform_device *pdev) +int usb_hcd_at91_probe (const struct hc_driver *driver, struct platform_device *pdev) { int retval; struct usb_hcd *hcd = NULL; @@ -99,13 +95,12 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, return -ENODEV; } - if ((pdev->resource[0].flags != IORESOURCE_MEM) - || (pdev->resource[1].flags != IORESOURCE_IRQ)) { + if ((pdev->resource[0].flags != IORESOURCE_MEM) || (pdev->resource[1].flags != IORESOURCE_IRQ)) { pr_debug("hcd probe: invalid resource type\n"); return -ENODEV; } - hcd = usb_create_hcd(driver, &pdev->dev, "at91"); + hcd = usb_create_hcd(driver, &pdev->dev, "at91rm9200"); if (!hcd) return -ENOMEM; hcd->rsrc_start = pdev->resource[0].start; @@ -154,23 +149,21 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, /* may be called with controller, bus, and devices active */ /** - * usb_hcd_at91_remove - shutdown processing for AT91-based HCDs + * usb_hcd_at91_remove - shutdown processing for AT91RM9200-based HCDs * @dev: USB Host Controller being removed * Context: !in_interrupt() * * Reverses the effect of usb_hcd_at91_probe(), first invoking * the HCD's stop() method. It is always called from a thread - * context, "rmmod" or something similar. + * context, normally "rmmod", "apmd", or something similar. * */ -static int usb_hcd_at91_remove(struct usb_hcd *hcd, - struct platform_device *pdev) +static int usb_hcd_at91_remove (struct usb_hcd *hcd, struct platform_device *pdev) { usb_remove_hcd(hcd); at91_stop_hc(pdev); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - disable_irq_wake(hcd->irq); clk_put(fclk); clk_put(iclk); @@ -185,21 +178,19 @@ static int usb_hcd_at91_remove(struct usb_hcd *hcd, static int __devinit ohci_at91_start (struct usb_hcd *hcd) { - struct at91_usbh_data *board = hcd->self.controller->platform_data; +// struct at91_ohci_data *board = hcd->self.controller->platform_data; struct ohci_hcd *ohci = hcd_to_ohci (hcd); - struct usb_device *root = hcd->self.root_hub; int ret; if ((ret = ohci_init(ohci)) < 0) return ret; - root->maxchild = board->ports; - if ((ret = ohci_run(ohci)) < 0) { err("can't start %s", hcd->self.bus_name); ohci_stop(hcd); return ret; } +// hcd->self.root_hub->maxchild = board->ports; return 0; } @@ -207,7 +198,7 @@ ohci_at91_start (struct usb_hcd *hcd) static const struct hc_driver ohci_at91_hc_driver = { .description = hcd_name, - .product_desc = "AT91 OHCI", + .product_desc = "AT91RM9200 OHCI", .hcd_priv_size = sizeof(struct ohci_hcd), /* @@ -249,54 +240,33 @@ static const struct hc_driver ohci_at91_hc_driver = { /*-------------------------------------------------------------------------*/ -static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) +static int ohci_hcd_at91_drv_probe(struct platform_device *dev) { - device_init_wakeup(&pdev->dev, 1); - return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev); + return usb_hcd_at91_probe(&ohci_at91_hc_driver, dev); } -static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) +static int ohci_hcd_at91_drv_remove(struct platform_device *dev) { - device_init_wakeup(&pdev->dev, 0); - return usb_hcd_at91_remove(platform_get_drvdata(pdev), pdev); + return usb_hcd_at91_remove(platform_get_drvdata(dev), dev); } #ifdef CONFIG_PM +/* REVISIT suspend/resume look "too" simple here */ + static int -ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) +ohci_hcd_at91_drv_suspend(struct platform_device *dev, pm_message_t mesg) { - struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - - if (device_may_wakeup(&pdev->dev)) - enable_irq_wake(hcd->irq); - else - disable_irq_wake(hcd->irq); - - /* - * The integrated transceivers seem unable to notice disconnect, - * reconnect, or wakeup without the 48 MHz clock active. so for - * correctness, always discard connection state (using reset). - * - * REVISIT: some boards will be able to turn VBUS off... - */ - if (at91_suspend_entering_slow_clock()) { - ohci_usb_reset (ohci); - clk_disable(fclk); - clk_disable(iclk); - clocked = 0; - } + clk_disable(fclk); + clk_disable(iclk); return 0; } -static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) +static int ohci_hcd_at91_drv_resume(struct platform_device *dev) { - if (!clocked) { - clk_enable(iclk); - clk_enable(fclk); - } + clk_enable(iclk); + clk_enable(fclk); return 0; } @@ -305,7 +275,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) #define ohci_hcd_at91_drv_resume NULL #endif -MODULE_ALIAS("at91_ohci"); +MODULE_ALIAS("at91rm9200-ohci"); static struct platform_driver ohci_hcd_at91_driver = { .probe = ohci_hcd_at91_drv_probe, @@ -313,7 +283,7 @@ static struct platform_driver ohci_hcd_at91_driver = { .suspend = ohci_hcd_at91_drv_suspend, .resume = ohci_hcd_at91_drv_resume, .driver = { - .name = "at91_ohci", + .name = "at91rm9200-ohci", .owner = THIS_MODULE, }, }; diff --git a/trunk/drivers/usb/host/ohci-au1xxx.c b/trunk/drivers/usb/host/ohci-au1xxx.c index f7a975d5db09..822914e2f43b 100644 --- a/trunk/drivers/usb/host/ohci-au1xxx.c +++ b/trunk/drivers/usb/host/ohci-au1xxx.c @@ -110,6 +110,7 @@ static void au1xxx_start_ohc(struct platform_device *dev) printk(KERN_DEBUG __FILE__ ": Clock to USB host has been enabled \n"); +#endif } static void au1xxx_stop_ohc(struct platform_device *dev) diff --git a/trunk/drivers/usb/host/ohci-hcd.c b/trunk/drivers/usb/host/ohci-hcd.c index 94d8cf4b36c1..afef5ac35b4a 100644 --- a/trunk/drivers/usb/host/ohci-hcd.c +++ b/trunk/drivers/usb/host/ohci-hcd.c @@ -913,7 +913,7 @@ MODULE_LICENSE ("GPL"); #include "ohci-ppc-soc.c" #endif -#if defined(CONFIG_ARCH_AT91RM9200) || defined(CONFIG_ARCH_AT91SAM9261) +#ifdef CONFIG_ARCH_AT91RM9200 #include "ohci-at91.c" #endif @@ -927,7 +927,6 @@ MODULE_LICENSE ("GPL"); || defined (CONFIG_SOC_AU1X00) \ || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ || defined (CONFIG_ARCH_AT91RM9200) \ - || defined (CONFIG_ARCH_AT91SAM9261) \ ) #error "missing bus glue for ohci-hcd" #endif diff --git a/trunk/drivers/usb/host/uhci-q.c b/trunk/drivers/usb/host/uhci-q.c index 431e8f31f1a9..c9d72ac0a1d7 100644 --- a/trunk/drivers/usb/host/uhci-q.c +++ b/trunk/drivers/usb/host/uhci-q.c @@ -372,7 +372,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first) * need to change any toggles in this URB */ td = list_entry(urbp->td_list.next, struct uhci_td, list); if (toggle > 1 || uhci_toggle(td_token(td)) == toggle) { - td = list_entry(urbp->td_list.prev, struct uhci_td, + td = list_entry(urbp->td_list.next, struct uhci_td, list); toggle = uhci_toggle(td_token(td)) ^ 1; @@ -943,9 +943,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) /* We received a short packet */ if (urb->transfer_flags & URB_SHORT_NOT_OK) ret = -EREMOTEIO; - - /* Fixup needed only if this isn't the URB's last TD */ - else if (&td->list != urbp->td_list.prev) + else if (ctrlstat & TD_CTRL_SPD) ret = 1; } @@ -1348,7 +1346,7 @@ static void uhci_scan_qh(struct uhci_hcd *uhci, struct uhci_qh *qh, } uhci_giveback_urb(uhci, qh, urb, regs); - if (status < 0 && qh->type != USB_ENDPOINT_XFER_ISOC) + if (status < 0) break; } diff --git a/trunk/drivers/usb/input/appletouch.c b/trunk/drivers/usb/input/appletouch.c index 044faa07e297..9e3f13903371 100644 --- a/trunk/drivers/usb/input/appletouch.c +++ b/trunk/drivers/usb/input/appletouch.c @@ -597,9 +597,9 @@ static void atp_disconnect(struct usb_interface *iface) if (dev) { usb_kill_urb(dev->urb); input_unregister_device(dev->input); + usb_free_urb(dev->urb); usb_buffer_free(dev->udev, dev->datalen, dev->data, dev->urb->transfer_dma); - usb_free_urb(dev->urb); kfree(dev); } printk(KERN_INFO "input: appletouch disconnected\n"); diff --git a/trunk/drivers/usb/input/ati_remote.c b/trunk/drivers/usb/input/ati_remote.c index 3719fcb04b8f..05d2d6012eb2 100644 --- a/trunk/drivers/usb/input/ati_remote.c +++ b/trunk/drivers/usb/input/ati_remote.c @@ -111,28 +111,14 @@ #define NAME_BUFSIZE 80 /* size of product name, path buffers */ #define DATA_BUFSIZE 63 /* size of URB data buffers */ -/* - * Duplicate event filtering time. - * Sequential, identical KIND_FILTERED inputs with less than - * FILTER_TIME milliseconds between them are considered as repeat - * events. The hardware generates 5 events for the first keypress - * and we have to take this into account for an accurate repeat - * behaviour. - */ -#define FILTER_TIME 60 /* msec */ - static unsigned long channel_mask; -module_param(channel_mask, ulong, 0644); +module_param(channel_mask, ulong, 0444); MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); static int debug; -module_param(debug, int, 0644); +module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); -static int repeat_filter = FILTER_TIME; -module_param(repeat_filter, int, 0644); -MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec"); - #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) #undef err #define err(format, arg...) printk(KERN_ERR format , ## arg) @@ -157,6 +143,19 @@ MODULE_DEVICE_TABLE(usb, ati_remote_table); static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; +/* Acceleration curve for directional control pad */ +static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; + +/* Duplicate event filtering time. + * Sequential, identical KIND_FILTERED inputs with less than + * FILTER_TIME jiffies between them are considered as repeat + * events. The hardware generates 5 events for the first keypress + * and we have to take this into account for an accurate repeat + * behaviour. + * (HZ / 20) == 50 ms and works well for me. + */ +#define FILTER_TIME (HZ / 20) + struct ati_remote { struct input_dev *idev; struct usb_device *udev; @@ -413,43 +412,6 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) return -1; } -/* - * ati_remote_compute_accel - * - * Implements acceleration curve for directional control pad - * If elapsed time since last event is > 1/4 second, user "stopped", - * so reset acceleration. Otherwise, user is probably holding the control - * pad down, so we increase acceleration, ramping up over two seconds to - * a maximum speed. - */ -static int ati_remote_compute_accel(struct ati_remote *ati_remote) -{ - static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; - unsigned long now = jiffies; - int acc; - - if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) { - acc = 1; - ati_remote->acc_jiffies = now; - } - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125))) - acc = accel[0]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250))) - acc = accel[1]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500))) - acc = accel[2]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000))) - acc = accel[3]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500))) - acc = accel[4]; - else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000))) - acc = accel[5]; - else - acc = accel[6]; - - return acc; -} - /* * ati_remote_report_input */ @@ -503,9 +465,9 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) if (ati_remote_tbl[index].kind == KIND_FILTERED) { /* Filter duplicate events which happen "too close" together. */ - if (ati_remote->old_data[0] == data[1] && - ati_remote->old_data[1] == data[2] && - time_before(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(repeat_filter))) { + if ((ati_remote->old_data[0] == data[1]) && + (ati_remote->old_data[1] == data[2]) && + time_before(jiffies, ati_remote->old_jiffies + FILTER_TIME)) { ati_remote->repeat_count++; } else { ati_remote->repeat_count = 0; @@ -515,61 +477,75 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) ati_remote->old_data[1] = data[2]; ati_remote->old_jiffies = jiffies; - if (ati_remote->repeat_count > 0 && - ati_remote->repeat_count < 5) + if ((ati_remote->repeat_count > 0) + && (ati_remote->repeat_count < 5)) return; input_regs(dev, regs); input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, 1); - input_sync(dev); input_event(dev, ati_remote_tbl[index].type, ati_remote_tbl[index].code, 0); input_sync(dev); - } else { - - /* - * Other event kinds are from the directional control pad, and have an - * acceleration factor applied to them. Without this acceleration, the - * control pad is mostly unusable. - */ - acc = ati_remote_compute_accel(ati_remote); - - input_regs(dev, regs); - switch (ati_remote_tbl[index].kind) { - case KIND_ACCEL: - input_event(dev, ati_remote_tbl[index].type, - ati_remote_tbl[index].code, - ati_remote_tbl[index].value * acc); - break; - case KIND_LU: - input_report_rel(dev, REL_X, -acc); - input_report_rel(dev, REL_Y, -acc); - break; - case KIND_RU: - input_report_rel(dev, REL_X, acc); - input_report_rel(dev, REL_Y, -acc); - break; - case KIND_LD: - input_report_rel(dev, REL_X, -acc); - input_report_rel(dev, REL_Y, acc); - break; - case KIND_RD: - input_report_rel(dev, REL_X, acc); - input_report_rel(dev, REL_Y, acc); - break; - default: - dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", - ati_remote_tbl[index].kind); - } - input_sync(dev); + return; + } - ati_remote->old_jiffies = jiffies; - ati_remote->old_data[0] = data[1]; - ati_remote->old_data[1] = data[2]; + /* + * Other event kinds are from the directional control pad, and have an + * acceleration factor applied to them. Without this acceleration, the + * control pad is mostly unusable. + * + * If elapsed time since last event is > 1/4 second, user "stopped", + * so reset acceleration. Otherwise, user is probably holding the control + * pad down, so we increase acceleration, ramping up over two seconds to + * a maximum speed. The acceleration curve is #defined above. + */ + if (time_after(jiffies, ati_remote->old_jiffies + (HZ >> 2))) { + acc = 1; + ati_remote->acc_jiffies = jiffies; + } + else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 3))) acc = accel[0]; + else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 2))) acc = accel[1]; + else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 1))) acc = accel[2]; + else if (time_before(jiffies, ati_remote->acc_jiffies + HZ)) acc = accel[3]; + else if (time_before(jiffies, ati_remote->acc_jiffies + HZ+(HZ>>1))) acc = accel[4]; + else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ << 1))) acc = accel[5]; + else acc = accel[6]; + + input_regs(dev, regs); + switch (ati_remote_tbl[index].kind) { + case KIND_ACCEL: + input_event(dev, ati_remote_tbl[index].type, + ati_remote_tbl[index].code, + ati_remote_tbl[index].value * acc); + break; + case KIND_LU: + input_report_rel(dev, REL_X, -acc); + input_report_rel(dev, REL_Y, -acc); + break; + case KIND_RU: + input_report_rel(dev, REL_X, acc); + input_report_rel(dev, REL_Y, -acc); + break; + case KIND_LD: + input_report_rel(dev, REL_X, -acc); + input_report_rel(dev, REL_Y, acc); + break; + case KIND_RD: + input_report_rel(dev, REL_X, acc); + input_report_rel(dev, REL_Y, acc); + break; + default: + dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", + ati_remote_tbl[index].kind); } + input_sync(dev); + + ati_remote->old_jiffies = jiffies; + ati_remote->old_data[0] = data[1]; + ati_remote->old_data[1] = data[2]; } /* diff --git a/trunk/drivers/usb/input/hid-core.c b/trunk/drivers/usb/input/hid-core.c index 3305fb6079eb..8ea9c915fbf9 100644 --- a/trunk/drivers/usb/input/hid-core.c +++ b/trunk/drivers/usb/input/hid-core.c @@ -1411,54 +1411,17 @@ void hid_init_reports(struct hid_device *hid) warn("timeout initializing reports"); } -#define USB_VENDOR_ID_GTCO 0x078c -#define USB_DEVICE_ID_GTCO_90 0x0090 -#define USB_DEVICE_ID_GTCO_100 0x0100 -#define USB_DEVICE_ID_GTCO_101 0x0101 -#define USB_DEVICE_ID_GTCO_103 0x0103 -#define USB_DEVICE_ID_GTCO_104 0x0104 -#define USB_DEVICE_ID_GTCO_105 0x0105 -#define USB_DEVICE_ID_GTCO_106 0x0106 -#define USB_DEVICE_ID_GTCO_107 0x0107 -#define USB_DEVICE_ID_GTCO_108 0x0108 -#define USB_DEVICE_ID_GTCO_200 0x0200 -#define USB_DEVICE_ID_GTCO_201 0x0201 -#define USB_DEVICE_ID_GTCO_202 0x0202 -#define USB_DEVICE_ID_GTCO_203 0x0203 -#define USB_DEVICE_ID_GTCO_204 0x0204 -#define USB_DEVICE_ID_GTCO_205 0x0205 -#define USB_DEVICE_ID_GTCO_206 0x0206 -#define USB_DEVICE_ID_GTCO_207 0x0207 -#define USB_DEVICE_ID_GTCO_300 0x0300 -#define USB_DEVICE_ID_GTCO_301 0x0301 -#define USB_DEVICE_ID_GTCO_302 0x0302 -#define USB_DEVICE_ID_GTCO_303 0x0303 -#define USB_DEVICE_ID_GTCO_304 0x0304 -#define USB_DEVICE_ID_GTCO_305 0x0305 -#define USB_DEVICE_ID_GTCO_306 0x0306 -#define USB_DEVICE_ID_GTCO_307 0x0307 -#define USB_DEVICE_ID_GTCO_308 0x0308 -#define USB_DEVICE_ID_GTCO_309 0x0309 -#define USB_DEVICE_ID_GTCO_400 0x0400 -#define USB_DEVICE_ID_GTCO_401 0x0401 -#define USB_DEVICE_ID_GTCO_402 0x0402 -#define USB_DEVICE_ID_GTCO_403 0x0403 -#define USB_DEVICE_ID_GTCO_404 0x0404 -#define USB_DEVICE_ID_GTCO_405 0x0405 -#define USB_DEVICE_ID_GTCO_500 0x0500 -#define USB_DEVICE_ID_GTCO_501 0x0501 -#define USB_DEVICE_ID_GTCO_502 0x0502 -#define USB_DEVICE_ID_GTCO_503 0x0503 -#define USB_DEVICE_ID_GTCO_504 0x0504 -#define USB_DEVICE_ID_GTCO_1000 0x1000 -#define USB_DEVICE_ID_GTCO_1001 0x1001 -#define USB_DEVICE_ID_GTCO_1002 0x1002 -#define USB_DEVICE_ID_GTCO_1003 0x1003 -#define USB_DEVICE_ID_GTCO_1004 0x1004 -#define USB_DEVICE_ID_GTCO_1005 0x1005 -#define USB_DEVICE_ID_GTCO_1006 0x1006 - #define USB_VENDOR_ID_WACOM 0x056a +#define USB_DEVICE_ID_WACOM_PENPARTNER 0x0000 +#define USB_DEVICE_ID_WACOM_GRAPHIRE 0x0010 +#define USB_DEVICE_ID_WACOM_INTUOS 0x0020 +#define USB_DEVICE_ID_WACOM_PL 0x0030 +#define USB_DEVICE_ID_WACOM_INTUOS2 0x0040 +#define USB_DEVICE_ID_WACOM_VOLITO 0x0060 +#define USB_DEVICE_ID_WACOM_PTU 0x0003 +#define USB_DEVICE_ID_WACOM_INTUOS3 0x00B0 +#define USB_DEVICE_ID_WACOM_CINTIQ 0x003F +#define USB_DEVICE_ID_WACOM_DTF 0x00C0 #define USB_VENDOR_ID_ACECAD 0x0460 #define USB_DEVICE_ID_ACECAD_FLAIR 0x0004 @@ -1625,51 +1588,6 @@ static const struct hid_blacklist { { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_100, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_101, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_103, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_104, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_105, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_106, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_107, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_108, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_200, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_201, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_202, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_203, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_204, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_205, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_206, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_207, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_300, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_301, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_302, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_303, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_304, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_305, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_306, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_307, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_308, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_309, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_400, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_401, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_402, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_403, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_404, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_405, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_500, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_501, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_502, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_503, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_504, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1000, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1001, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1002, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1003, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1004, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1005, HID_QUIRK_IGNORE }, - { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY, HID_QUIRK_IGNORE }, @@ -1699,6 +1617,49 @@ static const struct hid_blacklist { { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 2, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 3, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 4, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 1, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 2, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 3, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS + 4, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 1, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 2, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 3, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 4, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 5, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 7, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 8, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PL + 9, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 1, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 2, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 3, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 4, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 5, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 1, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 2, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 3, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO + 4, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 5, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 6, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 1, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 2, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 3, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 4, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 5, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_CINTIQ, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF + 3, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE }, @@ -1817,10 +1778,6 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) char *rdesc; int n, len, insize = 0; - /* Ignore all Wacom devices */ - if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_WACOM) - return NULL; - for (n = 0; hid_blacklist[n].idVendor; n++) if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) && (hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct))) diff --git a/trunk/drivers/usb/input/hid-input.c b/trunk/drivers/usb/input/hid-input.c index 7208839f2dbf..028e1ad89f5d 100644 --- a/trunk/drivers/usb/input/hid-input.c +++ b/trunk/drivers/usb/input/hid-input.c @@ -607,8 +607,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel } - if (usage->type == EV_ABS && - (usage->hat_min < usage->hat_max || usage->hat_dir)) { + if (usage->hat_min < usage->hat_max || usage->hat_dir) { int i; for (i = usage->code; i < usage->code + 2 && i <= max; i++) { input_set_abs_params(input, i, -1, 1, 0, 0); diff --git a/trunk/drivers/usb/input/hiddev.c b/trunk/drivers/usb/input/hiddev.c index f6b839c257a7..70477f02cc29 100644 --- a/trunk/drivers/usb/input/hiddev.c +++ b/trunk/drivers/usb/input/hiddev.c @@ -49,7 +49,7 @@ struct hiddev { int open; wait_queue_head_t wait; struct hid_device *hid; - struct list_head list; + struct hiddev_list *list; }; struct hiddev_list { @@ -59,7 +59,7 @@ struct hiddev_list { unsigned flags; struct fasync_struct *fasync; struct hiddev *hiddev; - struct list_head node; + struct hiddev_list *next; }; static struct hiddev *hiddev_table[HIDDEV_MINORS]; @@ -73,15 +73,12 @@ static struct hiddev *hiddev_table[HIDDEV_MINORS]; static struct hid_report * hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) { - unsigned int flags = rinfo->report_id & ~HID_REPORT_ID_MASK; - unsigned int rid = rinfo->report_id & HID_REPORT_ID_MASK; + unsigned flags = rinfo->report_id & ~HID_REPORT_ID_MASK; struct hid_report_enum *report_enum; - struct hid_report *report; struct list_head *list; if (rinfo->report_type < HID_REPORT_TYPE_MIN || - rinfo->report_type > HID_REPORT_TYPE_MAX) - return NULL; + rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL; report_enum = hid->report_enum + (rinfo->report_type - HID_REPORT_TYPE_MIN); @@ -91,25 +88,21 @@ hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) break; case HID_REPORT_ID_FIRST: - if (list_empty(&report_enum->report_list)) - return NULL; - list = report_enum->report_list.next; - report = list_entry(list, struct hid_report, list); - rinfo->report_id = report->id; + if (list == &report_enum->report_list) + return NULL; + rinfo->report_id = ((struct hid_report *) list)->id; break; case HID_REPORT_ID_NEXT: - report = report_enum->report_id_hash[rid]; - if (!report) + list = (struct list_head *) + report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK]; + if (list == NULL) return NULL; - - list = report->list.next; + list = list->next; if (list == &report_enum->report_list) return NULL; - - report = list_entry(list, struct hid_report, list); - rinfo->report_id = report->id; + rinfo->report_id = ((struct hid_report *) list)->id; break; default: @@ -132,13 +125,12 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) struct hid_field *field; if (uref->report_type < HID_REPORT_TYPE_MIN || - uref->report_type > HID_REPORT_TYPE_MAX) - return NULL; + uref->report_type > HID_REPORT_TYPE_MAX) return NULL; report_enum = hid->report_enum + (uref->report_type - HID_REPORT_TYPE_MIN); - list_for_each_entry(report, &report_enum->report_list, list) { + list_for_each_entry(report, &report_enum->report_list, list) for (i = 0; i < report->maxfield; i++) { field = report->field[i]; for (j = 0; j < field->maxusage; j++) { @@ -150,7 +142,6 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref) } } } - } return NULL; } @@ -159,9 +150,9 @@ static void hiddev_send_event(struct hid_device *hid, struct hiddev_usage_ref *uref) { struct hiddev *hiddev = hid->hiddev; - struct hiddev_list *list; + struct hiddev_list *list = hiddev->list; - list_for_each_entry(list, &hiddev->list, node) { + while (list) { if (uref->field_index != HID_FIELD_INDEX_NONE || (list->flags & HIDDEV_FLAG_REPORT) != 0) { list->buffer[list->head] = *uref; @@ -169,6 +160,8 @@ static void hiddev_send_event(struct hid_device *hid, (HIDDEV_BUFFER_SIZE - 1); kill_fasync(&list->fasync, SIGIO, POLL_IN); } + + list = list->next; } wake_up_interruptible(&hiddev->wait); @@ -187,7 +180,7 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, uref.report_type = (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : - ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); + ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); uref.report_id = field->report->id; uref.field_index = field->index; uref.usage_index = (usage - field->usage); @@ -207,7 +200,7 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report) uref.report_type = (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : - ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE : 0)); + ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); uref.report_id = report->id; uref.field_index = HID_FIELD_INDEX_NONE; @@ -220,9 +213,7 @@ static int hiddev_fasync(int fd, struct file *file, int on) { int retval; struct hiddev_list *list = file->private_data; - retval = fasync_helper(fd, file, on, &list->fasync); - return retval < 0 ? retval : 0; } @@ -233,9 +224,14 @@ static int hiddev_fasync(int fd, struct file *file, int on) static int hiddev_release(struct inode * inode, struct file * file) { struct hiddev_list *list = file->private_data; + struct hiddev_list **listptr; + listptr = &list->hiddev->list; hiddev_fasync(-1, file, 0); - list_del(&list->node); + + while (*listptr && (*listptr != list)) + listptr = &((*listptr)->next); + *listptr = (*listptr)->next; if (!--list->hiddev->open) { if (list->hiddev->exist) @@ -252,8 +248,7 @@ static int hiddev_release(struct inode * inode, struct file * file) /* * open file op */ -static int hiddev_open(struct inode *inode, struct file *file) -{ +static int hiddev_open(struct inode * inode, struct file * file) { struct hiddev_list *list; int i = iminor(inode) - HIDDEV_MINOR_BASE; @@ -265,7 +260,9 @@ static int hiddev_open(struct inode *inode, struct file *file) return -ENOMEM; list->hiddev = hiddev_table[i]; - list_add_tail(&list->node, &hiddev_table[i]->list); + list->next = hiddev_table[i]->list; + hiddev_table[i]->list = list; + file->private_data = list; if (!list->hiddev->open++) @@ -365,7 +362,6 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun static unsigned int hiddev_poll(struct file *file, poll_table *wait) { struct hiddev_list *list = file->private_data; - poll_wait(file, &list->hiddev->wait, wait); if (list->head != list->tail) return POLLIN | POLLRDNORM; @@ -386,7 +382,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd struct hiddev_collection_info cinfo; struct hiddev_report_info rinfo; struct hiddev_field_info finfo; - struct hiddev_usage_ref_multi *uref_multi = NULL; + struct hiddev_usage_ref_multi *uref_multi=NULL; struct hiddev_usage_ref *uref; struct hiddev_devinfo dinfo; struct hid_report *report; @@ -768,15 +764,15 @@ int hiddev_connect(struct hid_device *hid) } init_waitqueue_head(&hiddev->wait); - INIT_LIST_HEAD(&hiddev->list); + + hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; + hiddev->hid = hid; hiddev->exist = 1; hid->minor = hid->intf->minor; hid->hiddev = hiddev; - hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; - return 0; } diff --git a/trunk/drivers/usb/input/usbtouchscreen.c b/trunk/drivers/usb/input/usbtouchscreen.c index a338bf4c2d78..3b175aa482cd 100644 --- a/trunk/drivers/usb/input/usbtouchscreen.c +++ b/trunk/drivers/usb/input/usbtouchscreen.c @@ -286,7 +286,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press) { *x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); - *y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); + *x = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); *press = ((pkt[2] & 0x1F) << 7) | (pkt[5] & 0x7F); *touch = ~pkt[7] & 0x20; diff --git a/trunk/drivers/usb/input/yealink.c b/trunk/drivers/usb/input/yealink.c index 7b45fd3de911..575a4e672e96 100644 --- a/trunk/drivers/usb/input/yealink.c +++ b/trunk/drivers/usb/input/yealink.c @@ -810,9 +810,12 @@ static int usb_cleanup(struct yealink_dev *yld, int err) if (yld == NULL) return err; - usb_kill_urb(yld->urb_irq); /* parameter validation in core/urb */ - usb_kill_urb(yld->urb_ctl); /* parameter validation in core/urb */ - + if (yld->urb_irq) { + usb_kill_urb(yld->urb_irq); + usb_free_urb(yld->urb_irq); + } + if (yld->urb_ctl) + usb_free_urb(yld->urb_ctl); if (yld->idev) { if (err) input_free_device(yld->idev); @@ -828,9 +831,6 @@ static int usb_cleanup(struct yealink_dev *yld, int err) if (yld->irq_data) usb_buffer_free(yld->udev, USB_PKT_LEN, yld->irq_data, yld->irq_dma); - - usb_free_urb(yld->urb_irq); /* parameter validation in core/urb */ - usb_free_urb(yld->urb_ctl); /* parameter validation in core/urb */ kfree(yld); return err; } diff --git a/trunk/drivers/usb/misc/cypress_cy7c63.c b/trunk/drivers/usb/misc/cypress_cy7c63.c index 9c46746d5d00..e091d327bd9e 100644 --- a/trunk/drivers/usb/misc/cypress_cy7c63.c +++ b/trunk/drivers/usb/misc/cypress_cy7c63.c @@ -12,13 +12,8 @@ * the single I/O ports of the device. * * Supported vendors: AK Modul-Bus Computer GmbH -* (Firmware "Port-Chip") -* -* Supported devices: CY7C63001A-PC -* CY7C63001C-PXC -* CY7C63001C-SXC -* -* Supported functions: Read/Write Ports +* Supported devices: CY7C63001A-PC (to be continued...) +* Supported functions: Read/Write Ports (to be continued...) * * * This program is free software; you can redistribute it and/or @@ -208,7 +203,7 @@ static int cypress_probe(struct usb_interface *interface, /* allocate memory for our device state and initialize it */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { - dev_err(&interface->dev, "Out of memory!\n"); + dev_err(&dev->udev->dev, "Out of memory!\n"); goto error; } diff --git a/trunk/drivers/usb/misc/sisusbvga/sisusb.c b/trunk/drivers/usb/misc/sisusbvga/sisusb.c index e16582f3733c..738bd7c7451f 100644 --- a/trunk/drivers/usb/misc/sisusbvga/sisusb.c +++ b/trunk/drivers/usb/misc/sisusbvga/sisusb.c @@ -3435,8 +3435,6 @@ static void sisusb_disconnect(struct usb_interface *intf) static struct usb_device_id sisusb_table [] = { { USB_DEVICE(0x0711, 0x0900) }, - { USB_DEVICE(0x0711, 0x0901) }, - { USB_DEVICE(0x0711, 0x0902) }, { USB_DEVICE(0x182d, 0x021c) }, { USB_DEVICE(0x182d, 0x0269) }, { } diff --git a/trunk/drivers/usb/misc/usbtest.c b/trunk/drivers/usb/misc/usbtest.c index 983e104dd452..786e1dbe88ec 100644 --- a/trunk/drivers/usb/misc/usbtest.c +++ b/trunk/drivers/usb/misc/usbtest.c @@ -1242,12 +1242,11 @@ static int halt_simple (struct usbtest_dev *dev) static int ctrl_out (struct usbtest_dev *dev, unsigned count, unsigned length, unsigned vary) { - unsigned i, j, len; - int retval; + unsigned i, j, len, retval; u8 *buf; char *what = "?"; struct usb_device *udev; - + if (length < 1 || length > 0xffff || vary >= length) return -EINVAL; diff --git a/trunk/drivers/usb/net/pegasus.h b/trunk/drivers/usb/net/pegasus.h index 006438069b66..a54752ce1493 100644 --- a/trunk/drivers/usb/net/pegasus.h +++ b/trunk/drivers/usb/net/pegasus.h @@ -131,7 +131,6 @@ struct usb_eth_dev { #define VENDOR_COREGA 0x07aa #define VENDOR_DLINK 0x2001 #define VENDOR_ELCON 0x0db7 -#define VENDOR_ELECOM 0x056e #define VENDOR_ELSA 0x05cc #define VENDOR_GIGABYTE 0x1044 #define VENDOR_HAWKING 0x0e66 @@ -234,8 +233,6 @@ PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK, 0xabc1, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "GOLDPFEIL USB Adapter", VENDOR_ELCON, 0x0002, DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA ) -PEGASUS_DEV( "ELECOM USB Ethernet LD-USB20", VENDOR_ELECOM, 0x4010, - DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "EasiDock Ethernet", VENDOR_MOBILITY, 0x0304, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000, diff --git a/trunk/drivers/usb/net/rtl8150.c b/trunk/drivers/usb/net/rtl8150.c index a72685b96061..e5e6e4f3ef87 100644 --- a/trunk/drivers/usb/net/rtl8150.c +++ b/trunk/drivers/usb/net/rtl8150.c @@ -175,8 +175,6 @@ static inline struct sk_buff *pull_skb(rtl8150_t *); static void rtl8150_disconnect(struct usb_interface *intf); static int rtl8150_probe(struct usb_interface *intf, const struct usb_device_id *id); -static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message); -static int rtl8150_resume(struct usb_interface *intf); static const char driver_name [] = "rtl8150"; @@ -185,8 +183,6 @@ static struct usb_driver rtl8150_driver = { .probe = rtl8150_probe, .disconnect = rtl8150_disconnect, .id_table = rtl8150_table, - .suspend = rtl8150_suspend, - .resume = rtl8150_resume }; /* @@ -242,11 +238,9 @@ static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) usb_fill_control_urb(dev->ctrl_urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, &dev->rx_creg, size, ctrl_callback, dev); - if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) { - if (ret == -ENODEV) - netif_device_detach(dev->netdev); + if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) err("control request submission failed: %d", ret); - } else + else set_bit(RX_REG_SET, &dev->flags); return ret; @@ -422,7 +416,6 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) struct sk_buff *skb; struct net_device *netdev; u16 rx_stat; - int status; dev = urb->context; if (!dev) @@ -472,10 +465,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) goon: usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); - status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); - if (status == -ENODEV) - netif_device_detach(dev->netdev); - else if (status) { + if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { set_bit(RX_URB_FAIL, &dev->flags); goto resched; } else { @@ -491,7 +481,6 @@ static void rx_fixup(unsigned long data) { rtl8150_t *dev; struct sk_buff *skb; - int status; dev = (rtl8150_t *)data; @@ -510,13 +499,10 @@ static void rx_fixup(unsigned long data) usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); try_again: - status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC); - if (status == -ENODEV) { - netif_device_detach(dev->netdev); - } else if (status) { + if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { set_bit(RX_URB_FAIL, &dev->flags); goto tlsched; - } else { + } else { clear_bit(RX_URB_FAIL, &dev->flags); } @@ -588,43 +574,12 @@ static void intr_callback(struct urb *urb, struct pt_regs *regs) resubmit: status = usb_submit_urb (urb, SLAB_ATOMIC); - if (status == -ENODEV) - netif_device_detach(dev->netdev); - else if (status) + if (status) err ("can't resubmit intr, %s-%s/input0, status %d", dev->udev->bus->bus_name, dev->udev->devpath, status); } -static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message) -{ - rtl8150_t *dev = usb_get_intfdata(intf); - - netif_device_detach(dev->netdev); - - if (netif_running(dev->netdev)) { - usb_kill_urb(dev->rx_urb); - usb_kill_urb(dev->intr_urb); - } - return 0; -} - -static int rtl8150_resume(struct usb_interface *intf) -{ - rtl8150_t *dev = usb_get_intfdata(intf); - - netif_device_attach(dev->netdev); - if (netif_running(dev->netdev)) { - dev->rx_urb->status = 0; - dev->rx_urb->actual_length = 0; - read_bulk_callback(dev->rx_urb, NULL); - - dev->intr_urb->status = 0; - dev->intr_urb->actual_length = 0; - intr_callback(dev->intr_urb, NULL); - } - return 0; -} /* ** @@ -735,14 +690,9 @@ static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), skb->data, count, write_bulk_callback, dev); if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) { - /* Can we get/handle EPIPE here? */ - if (res == -ENODEV) - netif_device_detach(dev->netdev); - else { - warn("failed tx_urb %d\n", res); - dev->stats.tx_errors++; - netif_start_queue(netdev); - } + warn("failed tx_urb %d\n", res); + dev->stats.tx_errors++; + netif_start_queue(netdev); } else { dev->stats.tx_packets++; dev->stats.tx_bytes += skb->len; @@ -779,25 +729,16 @@ static int rtl8150_open(struct net_device *netdev) usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); - if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) { - if (res == -ENODEV) - netif_device_detach(dev->netdev); + if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) warn("%s: rx_urb submit failed: %d", __FUNCTION__, res); - return res; - } usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3), dev->intr_buff, INTBUFSIZE, intr_callback, dev, dev->intr_interval); - if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) { - if (res == -ENODEV) - netif_device_detach(dev->netdev); + if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); - usb_kill_urb(dev->rx_urb); - return res; - } + netif_start_queue(netdev); enable_net_traffic(dev); set_carrier(netdev); - netif_start_queue(netdev); return res; } @@ -972,7 +913,6 @@ static void rtl8150_disconnect(struct usb_interface *intf) if (dev) { set_bit(RTL8150_UNPLUG, &dev->flags); tasklet_disable(&dev->tl); - tasklet_kill(&dev->tl); unregister_netdev(dev->netdev); unlink_all_urbs(dev); free_all_urbs(dev); diff --git a/trunk/drivers/usb/serial/Kconfig b/trunk/drivers/usb/serial/Kconfig index f5b9438c94f0..ac33bd47cfce 100644 --- a/trunk/drivers/usb/serial/Kconfig +++ b/trunk/drivers/usb/serial/Kconfig @@ -62,6 +62,15 @@ config USB_SERIAL_AIRPRIME To compile this driver as a module, choose M here: the module will be called airprime. +config USB_SERIAL_ANYDATA + tristate "USB AnyData CDMA Wireless Driver" + depends on USB_SERIAL + help + Say Y here if you want to use a AnyData CDMA device. + + To compile this driver as a module, choose M here: the + module will be called anydata. + config USB_SERIAL_ARK3116 tristate "USB ARK Micro 3116 USB Serial Driver (EXPERIMENTAL)" depends on USB_SERIAL && EXPERIMENTAL @@ -493,18 +502,15 @@ config USB_SERIAL_XIRCOM module will be called keyspan_pda. config USB_SERIAL_OPTION - tristate "USB driver for GSM and CDMA modems" + tristate "USB driver for GSM modems" depends on USB_SERIAL help - Say Y here if you have a GSM or CDMA modem that's connected to USB. - - This driver also supports several PCMCIA cards which have a - built-in OHCI-USB adapter and an internally-connected GSM modem. - The USB bus on these cards is not accessible externally. + Say Y here if you have an "Option" GSM PCMCIA card + (or an OEM version: branded Huawei, Audiovox, or Novatel). - Supported devices include (some of?) those made by: - Option, Huawei, Audiovox, Sierra Wireless, Novatel Wireless, or - Anydata. + These cards feature a built-in OHCI-USB adapter and an + internally-connected GSM modem. The USB bus is not + accessible externally. To compile this driver as a module, choose M here: the module will be called option. diff --git a/trunk/drivers/usb/serial/Makefile b/trunk/drivers/usb/serial/Makefile index 8efed2ce1ba3..35d4acc7f1d3 100644 --- a/trunk/drivers/usb/serial/Makefile +++ b/trunk/drivers/usb/serial/Makefile @@ -12,6 +12,7 @@ usbserial-obj-$(CONFIG_USB_EZUSB) += ezusb.o usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y) obj-$(CONFIG_USB_SERIAL_AIRPRIME) += airprime.o +obj-$(CONFIG_USB_SERIAL_ANYDATA) += anydata.o obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o diff --git a/trunk/drivers/usb/serial/anydata.c b/trunk/drivers/usb/serial/anydata.c new file mode 100644 index 000000000000..01843ef8c11e --- /dev/null +++ b/trunk/drivers/usb/serial/anydata.c @@ -0,0 +1,123 @@ +/* + * AnyData CDMA Serial USB driver + * + * Copyright (C) 2005 Greg Kroah-Hartman + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +static struct usb_device_id id_table [] = { + { USB_DEVICE(0x16d5, 0x6501) }, /* AirData CDMA device */ + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* if overridden by the user, then use their value for the size of the + * read and write urbs */ +static int buffer_size; +static int debug; + +static struct usb_driver anydata_driver = { + .name = "anydata", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .no_dynamic_id = 1, +}; + +static int anydata_open(struct usb_serial_port *port, struct file *filp) +{ + char *buffer; + int result = 0; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (buffer_size) { + /* override the default buffer sizes */ + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!buffer) { + dev_err(&port->dev, "%s - out of memory.\n", + __FUNCTION__); + return -ENOMEM; + } + kfree (port->read_urb->transfer_buffer); + port->read_urb->transfer_buffer = buffer; + port->read_urb->transfer_buffer_length = buffer_size; + + buffer = kmalloc(buffer_size, GFP_KERNEL); + if (!buffer) { + dev_err(&port->dev, "%s - out of memory.\n", + __FUNCTION__); + return -ENOMEM; + } + kfree (port->write_urb->transfer_buffer); + port->write_urb->transfer_buffer = buffer; + port->write_urb->transfer_buffer_length = buffer_size; + port->bulk_out_size = buffer_size; + } + + /* Start reading from the device */ + usb_fill_bulk_urb(port->read_urb, port->serial->dev, + usb_rcvbulkpipe(port->serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + usb_serial_generic_read_bulk_callback, port); + result = usb_submit_urb(port->read_urb, GFP_KERNEL); + if (result) + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __FUNCTION__, result); + + return result; +} + +static struct usb_serial_driver anydata_device = { + .driver = { + .owner = THIS_MODULE, + .name = "anydata", + }, + .id_table = id_table, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 1, + .open = anydata_open, +}; + +static int __init anydata_init(void) +{ + int retval; + + retval = usb_serial_register(&anydata_device); + if (retval) + return retval; + retval = usb_register(&anydata_driver); + if (retval) + usb_serial_deregister(&anydata_device); + return retval; +} + +static void __exit anydata_exit(void) +{ + usb_deregister(&anydata_driver); + usb_serial_deregister(&anydata_device); +} + +module_init(anydata_init); +module_exit(anydata_exit); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); +module_param(buffer_size, int, 0); +MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers"); diff --git a/trunk/drivers/usb/serial/ftdi_sio.c b/trunk/drivers/usb/serial/ftdi_sio.c index c6115aa1b445..b458aedc5fb6 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.c +++ b/trunk/drivers/usb/serial/ftdi_sio.c @@ -306,8 +306,6 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { static struct usb_device_id id_table_combined [] = { - { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, @@ -339,7 +337,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PERLE_ULTRAPORT_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PIEGROUP_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_TNC_X_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2101_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2102_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2103_PID) }, @@ -506,7 +503,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, { USB_DEVICE(TESTO_VID, TESTO_USB_INTERFACE_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_GAMMA_SCOUT_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/trunk/drivers/usb/serial/ftdi_sio.h b/trunk/drivers/usb/serial/ftdi_sio.h index 77299996f7ee..04ef90fcb876 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.h +++ b/trunk/drivers/usb/serial/ftdi_sio.h @@ -32,12 +32,6 @@ #define FTDI_NF_RIC_PID 0x0001 /* Product Id */ -/* www.canusb.com Lawicel CANUSB device */ -#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */ - -/* AlphaMicro Components AMC-232USB01 device */ -#define FTDI_AMC232_PID 0xFF00 /* Product Id */ - /* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */ #define FTDI_ACTZWAVE_PID 0xF2D0 @@ -188,10 +182,6 @@ /* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */ #define FTDI_USB_UIRT_PID 0xF850 /* Product Id */ -/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */ - -#define FTDI_TNC_X_PID 0xEBE0 - /* * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). * All of these devices use FTDI's vendor ID (0x0403). @@ -467,11 +457,6 @@ #define TESTO_VID 0x128D #define TESTO_USB_INTERFACE_PID 0x0001 -/* - * Gamma Scout (http://gamma-scout.com/). Submitted by rsc@runtux.com. - */ -#define FTDI_GAMMA_SCOUT_PID 0xD678 /* Gamma Scout online */ - /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ diff --git a/trunk/drivers/usb/serial/ipaq.c b/trunk/drivers/usb/serial/ipaq.c index 9840bade79f9..59c5d999009a 100644 --- a/trunk/drivers/usb/serial/ipaq.c +++ b/trunk/drivers/usb/serial/ipaq.c @@ -250,9 +250,6 @@ static struct usb_device_id ipaq_id_table [] = { { USB_DEVICE(0x04C5, 0x1058) }, /* FUJITSU USB Sync */ { USB_DEVICE(0x04C5, 0x1079) }, /* FUJITSU USB Sync */ { USB_DEVICE(0x04DA, 0x2500) }, /* Panasonic USB Sync */ - { USB_DEVICE(0x04DD, 0x9102) }, /* SHARP WS003SH USB Modem */ - { USB_DEVICE(0x04DD, 0x9121) }, /* SHARP WS004SH USB Modem */ - { USB_DEVICE(0x04DD, 0x9123) }, /* SHARP WS007SH USB Modem */ { USB_DEVICE(0x04E8, 0x5F00) }, /* Samsung NEXiO USB Sync */ { USB_DEVICE(0x04E8, 0x5F01) }, /* Samsung NEXiO USB Sync */ { USB_DEVICE(0x04E8, 0x5F02) }, /* Samsung NEXiO USB Sync */ diff --git a/trunk/drivers/usb/serial/option.c b/trunk/drivers/usb/serial/option.c index c856e6f40e22..f0530c1d7b7a 100644 --- a/trunk/drivers/usb/serial/option.c +++ b/trunk/drivers/usb/serial/option.c @@ -9,14 +9,40 @@ Portions copied from the Keyspan driver by Hugh Blemings - History: see the git log. + History: + + 2005-05-19 v0.1 Initial version, based on incomplete docs + and analysis of misbehavior with the standard driver + 2005-05-20 v0.2 Extended the input buffer to avoid losing + random 64-byte chunks of data + 2005-05-21 v0.3 implemented chars_in_buffer() + turned on low_latency + simplified the code somewhat + 2005-05-24 v0.4 option_write() sometimes deadlocked under heavy load + removed some dead code + added sponsor notice + coding style clean-up + 2005-06-20 v0.4.1 add missing braces :-/ + killed end-of-line whitespace + 2005-07-15 v0.4.2 rename WLAN product to FUSION, add FUSION2 + 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard + 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes + wants to send >2000 bytes. + 2006-04-10 v0.5 fixed two array overrun errors :-/ + 2006-04-21 v0.5.1 added support for Sierra Wireless MC8755 + 2006-05-15 v0.6 re-enable multi-port support + 2006-06-01 v0.6.1 add COBRA + 2006-06-01 v0.6.2 add backwards-compatibility stuff + 2006-06-01 v0.6.3 add Novatel Wireless + 2006-06-01 v0.7 Option => GSM + 2006-06-01 v0.7.1 add COBRA2 Work sponsored by: Sigos GmbH, Germany This driver exists because the "normal" serial driver doesn't work too well with GSM modems. Issues: - data loss -- one single Receive URB is not nearly enough - - nonstandard flow (Option devices) control + - nonstandard flow (Option devices) and multiplex (Sierra) control - controlling the baud rate doesn't make sense This driver is named "option" because the most common device it's @@ -70,8 +96,8 @@ static int option_send_setup(struct usb_serial_port *port); #define OPTION_VENDOR_ID 0x0AF0 #define HUAWEI_VENDOR_ID 0x12D1 #define AUDIOVOX_VENDOR_ID 0x0F3D +#define SIERRAWIRELESS_VENDOR_ID 0x1199 #define NOVATELWIRELESS_VENDOR_ID 0x1410 -#define ANYDATA_VENDOR_ID 0x16d5 #define OPTION_PRODUCT_OLD 0x5000 #define OPTION_PRODUCT_FUSION 0x6000 @@ -80,8 +106,8 @@ static int option_send_setup(struct usb_serial_port *port); #define OPTION_PRODUCT_COBRA2 0x6600 #define HUAWEI_PRODUCT_E600 0x1001 #define AUDIOVOX_PRODUCT_AIRCARD 0x0112 +#define SIERRAWIRELESS_PRODUCT_MC8755 0x6802 #define NOVATELWIRELESS_PRODUCT_U740 0x1400 -#define ANYDATA_PRODUCT_ID 0x6501 static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) }, @@ -91,8 +117,8 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA2) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, + { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, - { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -105,7 +131,10 @@ static struct usb_device_id option_ids1[] = { { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) }, { USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) }, - { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ID) }, + { } /* Terminating entry */ +}; +static struct usb_device_id option_ids3[] = { + { USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) }, { } /* Terminating entry */ }; @@ -122,11 +151,37 @@ static struct usb_driver option_driver = { /* The card has three separate interfaces, which the serial driver * recognizes separately, thus num_port=1. */ +static struct usb_serial_driver option_3port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "option", + }, + .description = "GSM modem (3-port)", + .id_table = option_ids3, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 3, + .open = option_open, + .close = option_close, + .write = option_write, + .write_room = option_write_room, + .chars_in_buffer = option_chars_in_buffer, + .throttle = option_rx_throttle, + .unthrottle = option_rx_unthrottle, + .set_termios = option_set_termios, + .break_ctl = option_break_ctl, + .tiocmget = option_tiocmget, + .tiocmset = option_tiocmset, + .attach = option_startup, + .shutdown = option_shutdown, + .read_int_callback = option_instat_callback, +}; static struct usb_serial_driver option_1port_device = { .driver = { .owner = THIS_MODULE, - .name = "option1", + .name = "option", }, .description = "GSM modem (1-port)", .id_table = option_ids1, @@ -190,6 +245,9 @@ static int __init option_init(void) retval = usb_serial_register(&option_1port_device); if (retval) goto failed_1port_device_register; + retval = usb_serial_register(&option_3port_device); + if (retval) + goto failed_3port_device_register; retval = usb_register(&option_driver); if (retval) goto failed_driver_register; @@ -199,6 +257,8 @@ static int __init option_init(void) return 0; failed_driver_register: + usb_serial_deregister (&option_3port_device); +failed_3port_device_register: usb_serial_deregister (&option_1port_device); failed_1port_device_register: return retval; @@ -207,6 +267,7 @@ static int __init option_init(void) static void __exit option_exit(void) { usb_deregister (&option_driver); + usb_serial_deregister (&option_3port_device); usb_serial_deregister (&option_1port_device); } @@ -595,6 +656,7 @@ static void option_setup_urbs(struct usb_serial *serial) dbg("%s", __FUNCTION__); + for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; portdata = usb_get_serial_port_data(port); diff --git a/trunk/drivers/usb/serial/pl2303.c b/trunk/drivers/usb/serial/pl2303.c index 65e4d046951a..259db31b65c1 100644 --- a/trunk/drivers/usb/serial/pl2303.c +++ b/trunk/drivers/usb/serial/pl2303.c @@ -79,8 +79,8 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_PRODUCT_ID) }, { USB_DEVICE(LEADTEK_VENDOR_ID, LEADTEK_9531_PRODUCT_ID) }, { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) }, + { USB_DEVICE(OTI_VENDOR_ID, OTI_PRODUCT_ID) }, { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) }, - { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/trunk/drivers/usb/serial/pl2303.h b/trunk/drivers/usb/serial/pl2303.h index 55195e76eb6f..d9c1e6e0b4b3 100644 --- a/trunk/drivers/usb/serial/pl2303.h +++ b/trunk/drivers/usb/serial/pl2303.h @@ -82,10 +82,10 @@ #define SPEEDDRAGON_VENDOR_ID 0x0e55 #define SPEEDDRAGON_PRODUCT_ID 0x110b +/* Ours Technology Inc DKU-5 clone, chipset: Prolific Technology Inc */ +#define OTI_VENDOR_ID 0x0ea0 +#define OTI_PRODUCT_ID 0x6858 + /* DATAPILOT Universal-2 Phone Cable */ #define DATAPILOT_U2_VENDOR_ID 0x0731 #define DATAPILOT_U2_PRODUCT_ID 0x2003 - -/* Belkin "F5U257" Serial Adapter */ -#define BELKIN_VENDOR_ID 0x050d -#define BELKIN_PRODUCT_ID 0x0257 diff --git a/trunk/drivers/usb/serial/usb-serial.c b/trunk/drivers/usb/serial/usb-serial.c index e06a41bd0f3b..12c1694d322e 100644 --- a/trunk/drivers/usb/serial/usb-serial.c +++ b/trunk/drivers/usb/serial/usb-serial.c @@ -464,10 +464,8 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int length += sprintf (page+length, " path:%s", tmp); length += sprintf (page+length, "\n"); - if ((length + begin) > (off + count)) { - usb_serial_put(serial); + if ((length + begin) > (off + count)) goto done; - } if ((length + begin) < off) { begin += length; length = 0; diff --git a/trunk/drivers/usb/storage/unusual_devs.h b/trunk/drivers/usb/storage/unusual_devs.h index b130e170b4a8..a5ca449f6e64 100644 --- a/trunk/drivers/usb/storage/unusual_devs.h +++ b/trunk/drivers/usb/storage/unusual_devs.h @@ -145,13 +145,6 @@ UNUSUAL_DEV( 0x0420, 0x0001, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), -/* Reported by Mario Rettig */ -UNUSUAL_DEV( 0x0421, 0x042e, 0x0100, 0x0100, - "Nokia", - "Nokia 3250", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), - /* Reported by Sumedha Swamy and * Einar Th. Einarsson */ UNUSUAL_DEV( 0x0421, 0x0444, 0x0100, 0x0100, @@ -241,6 +234,16 @@ UNUSUAL_DEV( 0x0482, 0x0103, 0x0100, 0x0100, "Finecam S5", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), +/* Patch for Kyocera Finecam L3 + * Submitted by Michael Krauth + * and Alessandro Fracchetti + */ +UNUSUAL_DEV( 0x0482, 0x0105, 0x0100, 0x0100, + "Kyocera", + "Finecam L3", + US_SC_SCSI, US_PR_BULK, NULL, + US_FL_FIX_INQUIRY), + /* Reported by Paul Stewart * This entry is needed because the device reports Sub=ff */ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, @@ -589,13 +592,6 @@ UNUSUAL_DEV( 0x054c, 0x0099, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), -/* floppy reports multiple luns */ -UNUSUAL_DEV( 0x055d, 0x2020, 0x0000, 0x0210, - "SAMSUNG", - "SFD-321U [FW 0C]", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_SINGLE_LUN ), - UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data", @@ -631,6 +627,18 @@ UNUSUAL_DEV( 0x0595, 0x4343, 0x0000, 0x2210, "Digital Camera EX-20 DSC", US_SC_8070, US_PR_DEVICE, NULL, 0 ), +/* The entry was here before I took over, and had US_SC_RBC. It turns + * out that isn't needed. Additionally, Torsten Eriksson + * is able to use his device fine + * without this entry at all - but I don't suspect that will be true + * for all users (the protocol is likely needed), so is staying at + * this time. - Phil Dibowitz + */ +UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200, + "LaCie", + "USB Hard Disk", + US_SC_DEVICE, US_PR_CB, NULL, 0 ), + /* Submitted by Joel Bourquard * Some versions of this device need the SubClass and Protocol overrides * while others don't. @@ -1098,15 +1106,7 @@ UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff, "Optio S/S4", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), - -/* This is a virtual windows driver CD, which the zd1211rw driver automatically - * converts into a WLAN device. */ -UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101, - "ZyXEL", - "G-220F USB-WLAN Install", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_IGNORE_DEVICE ), - + #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, "ATI", @@ -1237,16 +1237,6 @@ UNUSUAL_DEV( 0x0ed1, 0x7636, 0x0103, 0x0103, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_GO_SLOW | US_FL_MAX_SECTORS_64), -/* David Kuehling : - * for MP3-Player AVOX WSX-300ER (bought in Japan). Reports lots of SCSI - * errors when trying to write. - */ -UNUSUAL_DEV( 0x0f19, 0x0105, 0x0100, 0x0100, - "C-MEX", - "A-VOX", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_IGNORE_RESIDUE ), - /* Reported by Michael Stattmann */ UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, "Sony Ericsson", @@ -1254,18 +1244,11 @@ UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NO_WP_DETECT ), -/* Reported by Emmanuel Vasilakis */ -UNUSUAL_DEV( 0x0fce, 0xe031, 0x0000, 0x0000, - "Sony Ericsson", - "M600i", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY ), - /* Reported by Kevin Cernekee * Tested on hardware version 1.10. * Entry is needed only for the initializer function override. */ -UNUSUAL_DEV( 0x1019, 0x0c55, 0x0110, 0x0110, +UNUSUAL_DEV( 0x1019, 0x0c55, 0x0000, 0x9999, "Desknote", "UCR-61S2B", US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init, diff --git a/trunk/drivers/usb/storage/usb.c b/trunk/drivers/usb/storage/usb.c index 8d7bdcb5924d..5ee19be52f65 100644 --- a/trunk/drivers/usb/storage/usb.c +++ b/trunk/drivers/usb/storage/usb.c @@ -483,7 +483,7 @@ static struct us_unusual_dev *find_unusual(const struct usb_device_id *id) } /* Get the unusual_devs entries and the string descriptors */ -static int get_device_info(struct us_data *us, const struct usb_device_id *id) +static void get_device_info(struct us_data *us, const struct usb_device_id *id) { struct usb_device *dev = us->pusb_dev; struct usb_interface_descriptor *idesc = @@ -500,11 +500,6 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id) unusual_dev->useTransport; us->flags = USB_US_ORIG_FLAGS(id->driver_info); - if (us->flags & US_FL_IGNORE_DEVICE) { - printk(KERN_INFO USB_STORAGE "device ignored\n"); - return -ENODEV; - } - /* * This flag is only needed when we're in high-speed, so let's * disable it if we're in full-speed @@ -546,8 +541,6 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id) msgs[msg], UTS_RELEASE); } - - return 0; } /* Get the transport settings */ @@ -976,9 +969,7 @@ static int storage_probe(struct usb_interface *intf, * of the match from the usb_device_id table, so we can find the * corresponding entry in the private table. */ - result = get_device_info(us, id); - if (result) - goto BadDevice; + get_device_info(us, id); /* Get the transport, protocol, and pipe settings */ result = get_transport(us); diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index 702eb933cf88..6533b0f39231 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -86,11 +86,9 @@ config FB_MACMODES default n config FB_BACKLIGHT - bool - depends on FB - select BACKLIGHT_LCD_SUPPORT - select BACKLIGHT_CLASS_DEVICE - default n + bool + depends on FB + default n config FB_MODE_HELPERS bool "Enable Video Mode Handling Helpers" @@ -422,7 +420,7 @@ config FB_OF config FB_CONTROL bool "Apple \"control\" display support" - depends on (FB = y) && PPC_PMAC && PPC32 + depends on (FB = y) && PPC_PMAC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -433,7 +431,7 @@ config FB_CONTROL config FB_PLATINUM bool "Apple \"platinum\" display support" - depends on (FB = y) && PPC_PMAC && PPC32 + depends on (FB = y) && PPC_PMAC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -444,7 +442,7 @@ config FB_PLATINUM config FB_VALKYRIE bool "Apple \"valkyrie\" display support" - depends on (FB = y) && (MAC || (PPC_PMAC && PPC32)) + depends on (FB = y) && (MAC || PPC_PMAC) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -455,7 +453,7 @@ config FB_VALKYRIE config FB_CT65550 bool "Chips 65550 display support" - depends on (FB = y) && PPC32 + depends on (FB = y) && PPC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -554,7 +552,7 @@ config FB_VESA config FB_IMAC bool "Intel-based Macintosh Framebuffer Support" - depends on (FB = y) && X86 && EFI + depends on (FB = y) && X86 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -723,8 +721,10 @@ config FB_NVIDIA_I2C config FB_NVIDIA_BACKLIGHT bool "Support for backlight control" - depends on FB_NVIDIA && PMAC_BACKLIGHT + depends on FB_NVIDIA && PPC_PMAC select FB_BACKLIGHT + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -769,8 +769,10 @@ config FB_RIVA_DEBUG config FB_RIVA_BACKLIGHT bool "Support for backlight control" - depends on FB_RIVA && PMAC_BACKLIGHT + depends on FB_RIVA && PPC_PMAC select FB_BACKLIGHT + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -1023,8 +1025,10 @@ config FB_RADEON_I2C config FB_RADEON_BACKLIGHT bool "Support for backlight control" - depends on FB_RADEON && PMAC_BACKLIGHT + depends on FB_RADEON && PPC_PMAC select FB_BACKLIGHT + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -1055,8 +1059,10 @@ config FB_ATY128 config FB_ATY128_BACKLIGHT bool "Support for backlight control" - depends on FB_ATY128 && PMAC_BACKLIGHT + depends on FB_ATY128 && PPC_PMAC select FB_BACKLIGHT + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -1105,8 +1111,10 @@ config FB_ATY_GX config FB_ATY_BACKLIGHT bool "Support for backlight control" - depends on FB_ATY && PMAC_BACKLIGHT + depends on FB_ATY && PPC_PMAC select FB_BACKLIGHT + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE default y help Say Y here if you want to control the backlight of your display. @@ -1612,7 +1620,7 @@ if FB || SGI_NEWPORT_CONSOLE source "drivers/video/logo/Kconfig" endif -if SYSFS +if FB && SYSFS source "drivers/video/backlight/Kconfig" endif diff --git a/trunk/drivers/video/Makefile b/trunk/drivers/video/Makefile index 481c6c9695f8..95563c9c6b9c 100644 --- a/trunk/drivers/video/Makefile +++ b/trunk/drivers/video/Makefile @@ -4,7 +4,6 @@ # Each configuration option enables a list of files. -obj-y += fb_notify.o obj-$(CONFIG_FB) += fb.o fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ modedb.o fbcvt.o diff --git a/trunk/drivers/video/S3triofb.c b/trunk/drivers/video/S3triofb.c index 397005eb392d..afd146f5f683 100644 --- a/trunk/drivers/video/S3triofb.c +++ b/trunk/drivers/video/S3triofb.c @@ -349,30 +349,30 @@ static void __init s3triofb_of_init(struct device_node *dp) s3trio_name[sizeof(s3trio_name)-1] = '\0'; strcpy(fb_fix.id, s3trio_name); - if((pp = get_property(dp, "vendor-id", &len)) != NULL + if((pp = (int *)get_property(dp, "vendor-id", &len)) != NULL && *pp!=PCI_VENDOR_ID_S3) { printk("%s: can't find S3 Trio board\n", dp->full_name); return; } - if((pp = get_property(dp, "device-id", &len)) != NULL + if((pp = (int *)get_property(dp, "device-id", &len)) != NULL && *pp!=PCI_DEVICE_ID_S3_TRIO) { printk("%s: can't find S3 Trio board\n", dp->full_name); return; } - if ((pp = get_property(dp, "depth", &len)) != NULL + if ((pp = (int *)get_property(dp, "depth", &len)) != NULL && len == sizeof(int) && *pp != 8) { printk("%s: can't use depth = %d\n", dp->full_name, *pp); return; } - if ((pp = get_property(dp, "width", &len)) != NULL + if ((pp = (int *)get_property(dp, "width", &len)) != NULL && len == sizeof(int)) fb_var.xres = fb_var.xres_virtual = *pp; - if ((pp = get_property(dp, "height", &len)) != NULL + if ((pp = (int *)get_property(dp, "height", &len)) != NULL && len == sizeof(int)) fb_var.yres = fb_var.yres_virtual = *pp; - if ((pp = get_property(dp, "linebytes", &len)) != NULL + if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL && len == sizeof(int)) fb_fix.line_length = *pp; else diff --git a/trunk/drivers/video/aty/aty128fb.c b/trunk/drivers/video/aty/aty128fb.c index 276a21530b95..c64a717e2d4b 100644 --- a/trunk/drivers/video/aty/aty128fb.c +++ b/trunk/drivers/video/aty/aty128fb.c @@ -455,10 +455,7 @@ static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par); static void wait_for_fifo(u16 entries, struct aty128fb_par *par); static void wait_for_idle(struct aty128fb_par *par); static u32 depth_to_dst(u32 depth); - -#ifdef CONFIG_FB_ATY128_BACKLIGHT static void aty128_bl_set_power(struct fb_info *info, int power); -#endif #define BIOS_IN8(v) (readb(bios + (v))) #define BIOS_IN16(v) (readb(bios + (v)) | \ @@ -1801,14 +1798,10 @@ static struct backlight_properties aty128_bl_data = { static void aty128_bl_set_power(struct fb_info *info, int power) { mutex_lock(&info->bl_mutex); - - if (info->bl_dev) { - down(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __aty128_bl_update_status(info->bl_dev); - up(&info->bl_dev->sem); - } - + up(&info->bl_dev->sem); + info->bl_dev->props->power = power; + __aty128_bl_update_status(info->bl_dev); + down(&info->bl_dev->sem); mutex_unlock(&info->bl_mutex); } @@ -1832,7 +1825,7 @@ static void aty128_bl_init(struct aty128fb_par *par) bd = backlight_device_register(name, par, &aty128_bl_data); if (IS_ERR(bd)) { info->bl_dev = NULL; - printk(KERN_WARNING "aty128: Backlight registration failed\n"); + printk("aty128: Backlight registration failed\n"); goto error; } @@ -1843,11 +1836,11 @@ static void aty128_bl_init(struct aty128fb_par *par) 219 * FB_BACKLIGHT_MAX / MAX_LEVEL); mutex_unlock(&info->bl_mutex); - down(&bd->sem); + up(&bd->sem); bd->props->brightness = aty128_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - up(&bd->sem); + down(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); @@ -1917,6 +1910,9 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i u8 chip_rev; u32 dac; + if (!par->vram_size) /* may have already been probed */ + par->vram_size = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF; + /* Get the chip revision */ chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F; @@ -2029,6 +2025,9 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i aty128_init_engine(par); + if (register_framebuffer(info) < 0) + return 0; + par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM); par->pdev = pdev; par->asleep = 0; @@ -2038,9 +2037,6 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i aty128_bl_init(par); #endif - if (register_framebuffer(info) < 0) - return 0; - printk(KERN_INFO "fb%d: %s frame buffer device on %s\n", info->node, info->fix.id, video_card); @@ -2090,6 +2086,7 @@ static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_ par = info->par; info->pseudo_palette = par->pseudo_palette; + info->fix = aty128fb_fix; /* Virtualize mmio region */ info->fix.mmio_start = reg_addr; diff --git a/trunk/drivers/video/aty/atyfb_base.c b/trunk/drivers/video/aty/atyfb_base.c index 19a71f045784..1507d19f481f 100644 --- a/trunk/drivers/video/aty/atyfb_base.c +++ b/trunk/drivers/video/aty/atyfb_base.c @@ -2200,14 +2200,10 @@ static struct backlight_properties aty_bl_data = { static void aty_bl_set_power(struct fb_info *info, int power) { mutex_lock(&info->bl_mutex); - - if (info->bl_dev) { - down(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __aty_bl_update_status(info->bl_dev); - up(&info->bl_dev->sem); - } - + up(&info->bl_dev->sem); + info->bl_dev->props->power = power; + __aty_bl_update_status(info->bl_dev); + down(&info->bl_dev->sem); mutex_unlock(&info->bl_mutex); } @@ -2227,7 +2223,7 @@ static void aty_bl_init(struct atyfb_par *par) bd = backlight_device_register(name, par, &aty_bl_data); if (IS_ERR(bd)) { info->bl_dev = NULL; - printk(KERN_WARNING "aty: Backlight registration failed\n"); + printk("aty: Backlight registration failed\n"); goto error; } @@ -2238,11 +2234,11 @@ static void aty_bl_init(struct atyfb_par *par) 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); mutex_unlock(&info->bl_mutex); - down(&bd->sem); + up(&bd->sem); bd->props->brightness = aty_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - up(&bd->sem); + down(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); @@ -2816,7 +2812,7 @@ static int atyfb_blank(int blank, struct fb_info *info) if (par->lock_blank || par->asleep) return 0; -#ifdef CONFIG_FB_ATY_BACKLIGHT +#ifdef CONFIG_PMAC_BACKLIGHT if (machine_is(powermac) && blank > FB_BLANK_NORMAL) aty_bl_set_power(info, FB_BLANK_POWERDOWN); #elif defined(CONFIG_FB_ATY_GENERIC_LCD) @@ -2848,7 +2844,7 @@ static int atyfb_blank(int blank, struct fb_info *info) } aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); -#ifdef CONFIG_FB_ATY_BACKLIGHT +#ifdef CONFIG_PMAC_BACKLIGHT if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) aty_bl_set_power(info, FB_BLANK_UNBLANK); #elif defined(CONFIG_FB_ATY_GENERIC_LCD) diff --git a/trunk/drivers/video/aty/radeon_backlight.c b/trunk/drivers/video/aty/radeon_backlight.c index 585eb7b9e636..1755dddf1899 100644 --- a/trunk/drivers/video/aty/radeon_backlight.c +++ b/trunk/drivers/video/aty/radeon_backlight.c @@ -195,11 +195,11 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo) 217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL); mutex_unlock(&rinfo->info->bl_mutex); - down(&bd->sem); + up(&bd->sem); bd->props->brightness = radeon_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - up(&bd->sem); + down(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); diff --git a/trunk/drivers/video/aty/radeon_base.c b/trunk/drivers/video/aty/radeon_base.c index 0ed577e7cc21..8d85fc58142e 100644 --- a/trunk/drivers/video/aty/radeon_base.c +++ b/trunk/drivers/video/aty/radeon_base.c @@ -266,8 +266,6 @@ static int force_measure_pll = 0; #ifdef CONFIG_MTRR static int nomtrr = 0; #endif -static int force_sleep; -static int ignore_devlist; /* * prototypes @@ -413,11 +411,11 @@ static int __devinit radeon_find_mem_vbios(struct radeonfb_info *rinfo) static int __devinit radeon_read_xtal_OF (struct radeonfb_info *rinfo) { struct device_node *dp = rinfo->of_node; - const u32 *val; + u32 *val; if (dp == NULL) return -ENODEV; - val = get_property(dp, "ATY,RefCLK", NULL); + val = (u32 *) get_property(dp, "ATY,RefCLK", NULL); if (!val || !*val) { printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n"); return -EINVAL; @@ -425,11 +423,11 @@ static int __devinit radeon_read_xtal_OF (struct radeonfb_info *rinfo) rinfo->pll.ref_clk = (*val) / 10; - val = get_property(dp, "ATY,SCLK", NULL); + val = (u32 *) get_property(dp, "ATY,SCLK", NULL); if (val && *val) rinfo->pll.sclk = (*val) / 10; - val = get_property(dp, "ATY,MCLK", NULL); + val = (u32 *) get_property(dp, "ATY,MCLK", NULL); if (val && *val) rinfo->pll.mclk = (*val) / 10; @@ -2329,9 +2327,9 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev, /* -2 is special: means ON on mobility chips and do not * change on others */ - radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1, ignore_devlist, force_sleep); + radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1); } else - radeonfb_pm_init(rinfo, default_dynclk, ignore_devlist, force_sleep); + radeonfb_pm_init(rinfo, default_dynclk); pci_set_drvdata(pdev, info); @@ -2479,12 +2477,6 @@ static int __init radeonfb_setup (char *options) force_measure_pll = 1; } else if (!strncmp(this_opt, "ignore_edid", 11)) { ignore_edid = 1; -#if defined(CONFIG_PM) && defined(CONFIG_X86) - } else if (!strncmp(this_opt, "force_sleep", 11)) { - force_sleep = 1; - } else if (!strncmp(this_opt, "ignore_devlist", 14)) { - ignore_devlist = 1; -#endif } else mode_option = this_opt; } @@ -2540,9 +2532,3 @@ module_param(panel_yres, int, 0); MODULE_PARM_DESC(panel_yres, "int: set panel yres"); module_param(mode_option, charp, 0); MODULE_PARM_DESC(mode_option, "Specify resolution as \"x[-][@]\" "); -#if defined(CONFIG_PM) && defined(CONFIG_X86) -module_param(force_sleep, bool, 0); -MODULE_PARM_DESC(force_sleep, "bool: force D2 sleep mode on all hardware"); -module_param(ignore_devlist, bool, 0); -MODULE_PARM_DESC(ignore_devlist, "bool: ignore workarounds for bugs in specific laptops"); -#endif diff --git a/trunk/drivers/video/aty/radeon_monitor.c b/trunk/drivers/video/aty/radeon_monitor.c index ea531a6f45d1..98c05bc0de44 100644 --- a/trunk/drivers/video/aty/radeon_monitor.c +++ b/trunk/drivers/video/aty/radeon_monitor.c @@ -64,13 +64,13 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_ { static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID2", NULL }; - const u8 *pedid = NULL; - const u8 *pmt = NULL; + u8 *pedid = NULL; + u8 *pmt = NULL; u8 *tmp; int i, mt = MT_NONE; RTRACE("analyzing OF properties...\n"); - pmt = get_property(dp, "display-type", NULL); + pmt = (u8 *)get_property(dp, "display-type", NULL); if (!pmt) return MT_NONE; RTRACE("display-type: %s\n", pmt); @@ -89,7 +89,7 @@ static int __devinit radeon_parse_montype_prop(struct device_node *dp, u8 **out_ } for (i = 0; propnames[i] != NULL; ++i) { - pedid = get_property(dp, propnames[i], NULL); + pedid = (u8 *)get_property(dp, propnames[i], NULL); if (pedid != NULL) break; } @@ -124,14 +124,14 @@ static int __devinit radeon_probe_OF_head(struct radeonfb_info *rinfo, int head_ return MT_NONE; if (rinfo->has_CRTC2) { - const char *pname; + char *pname; int len, second = 0; dp = dp->child; do { if (!dp) return MT_NONE; - pname = get_property(dp, "name", NULL); + pname = (char *)get_property(dp, "name", NULL); if (!pname) return MT_NONE; len = strlen(pname); diff --git a/trunk/drivers/video/aty/radeon_pm.c b/trunk/drivers/video/aty/radeon_pm.c index e308ed2d249a..c7091761cef4 100644 --- a/trunk/drivers/video/aty/radeon_pm.c +++ b/trunk/drivers/video/aty/radeon_pm.c @@ -27,99 +27,6 @@ #include "ati_ids.h" -static void radeon_reinitialize_M10(struct radeonfb_info *rinfo); - -/* - * Workarounds for bugs in PC laptops: - * - enable D2 sleep in some IBM Thinkpads - * - special case for Samsung P35 - * - * Whitelist by subsystem vendor/device because - * its the subsystem vendor's fault! - */ - -#if defined(CONFIG_PM) && defined(CONFIG_X86) -struct radeon_device_id { - const char *ident; /* (arbitrary) Name */ - const unsigned short subsystem_vendor; /* Subsystem Vendor ID */ - const unsigned short subsystem_device; /* Subsystem Device ID */ - const enum radeon_pm_mode pm_mode_modifier; /* modify pm_mode */ - const reinit_function_ptr new_reinit_func; /* changed reinit_func */ -}; - -#define BUGFIX(model, sv, sd, pm, fn) { \ - .ident = model, \ - .subsystem_vendor = sv, \ - .subsystem_device = sd, \ - .pm_mode_modifier = pm, \ - .new_reinit_func = fn \ -} - -static struct radeon_device_id radeon_workaround_list[] = { - BUGFIX("IBM Thinkpad R32", - PCI_VENDOR_ID_IBM, 0x1905, - radeon_pm_d2, NULL), - BUGFIX("IBM Thinkpad R40", - PCI_VENDOR_ID_IBM, 0x0526, - radeon_pm_d2, NULL), - BUGFIX("IBM Thinkpad R40", - PCI_VENDOR_ID_IBM, 0x0527, - radeon_pm_d2, NULL), - BUGFIX("IBM Thinkpad R50/R51/T40/T41", - PCI_VENDOR_ID_IBM, 0x0531, - radeon_pm_d2, NULL), - BUGFIX("IBM Thinkpad R51/T40/T41/T42", - PCI_VENDOR_ID_IBM, 0x0530, - radeon_pm_d2, NULL), - BUGFIX("IBM Thinkpad T30", - PCI_VENDOR_ID_IBM, 0x0517, - radeon_pm_d2, NULL), - BUGFIX("IBM Thinkpad T40p", - PCI_VENDOR_ID_IBM, 0x054d, - radeon_pm_d2, NULL), - BUGFIX("IBM Thinkpad T42", - PCI_VENDOR_ID_IBM, 0x0550, - radeon_pm_d2, NULL), - BUGFIX("IBM Thinkpad X31/X32", - PCI_VENDOR_ID_IBM, 0x052f, - radeon_pm_d2, NULL), - BUGFIX("Samsung P35", - PCI_VENDOR_ID_SAMSUNG, 0xc00c, - radeon_pm_off, radeon_reinitialize_M10), - { .ident = NULL } -}; - -static int radeon_apply_workarounds(struct radeonfb_info *rinfo) -{ - struct radeon_device_id *id; - - for (id = radeon_workaround_list; id->ident != NULL; id++ ) - if ((id->subsystem_vendor == rinfo->pdev->subsystem_vendor ) && - (id->subsystem_device == rinfo->pdev->subsystem_device )) { - - /* we found a device that requires workaround */ - printk(KERN_DEBUG "radeonfb: %s detected" - ", enabling workaround\n", id->ident); - - rinfo->pm_mode |= id->pm_mode_modifier; - - if (id->new_reinit_func != NULL) - rinfo->reinit_func = id->new_reinit_func; - - return 1; - } - return 0; /* not found */ -} - -#else /* defined(CONFIG_PM) && defined(CONFIG_X86) */ -static inline int radeon_apply_workarounds(struct radeonfb_info *rinfo) -{ - return 0; -} -#endif /* defined(CONFIG_PM) && defined(CONFIG_X86) */ - - - static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo) { u32 tmp; @@ -945,26 +852,18 @@ static void radeon_pm_setup_for_suspend(struct radeonfb_info *rinfo) /* because both INPLL and OUTPLL take the same lock, that's why. */ tmp = INPLL( pllMCLK_MISC) | MCLK_MISC__EN_MCLK_TRISTATE_IN_SUSPEND; OUTPLL( pllMCLK_MISC, tmp); + + /* AGP PLL control */ + if (rinfo->family <= CHIP_FAMILY_RV280) { + OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID); - /* BUS_CNTL1__MOBILE_PLATORM_SEL setting is northbridge chipset - * and radeon chip dependent. Thus we only enable it on Mac for - * now (until we get more info on how to compute the correct - * value for various X86 bridges). - */ -#ifdef CONFIG_PPC_PMAC - if (machine_is(powermac)) { - /* AGP PLL control */ - if (rinfo->family <= CHIP_FAMILY_RV280) { - OUTREG(BUS_CNTL1, INREG(BUS_CNTL1) | BUS_CNTL1__AGPCLK_VALID); - OUTREG(BUS_CNTL1, - (INREG(BUS_CNTL1) & ~BUS_CNTL1__MOBILE_PLATFORM_SEL_MASK) - | (2<of_node != NULL) { int size; - mrtable = get_property(rinfo->of_node, "ATY,MRT", &size); + mrtable = (u32 *)get_property(rinfo->of_node, "ATY,MRT", &size); if (mrtable) mrtable_size = size >> 2; else @@ -2814,7 +2713,7 @@ static void radeonfb_early_resume(void *data) #endif /* CONFIG_PM */ -void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep) +void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk) { /* Find PM registers in config space if any*/ rinfo->pm_reg = pci_find_capability(rinfo->pdev, PCI_CAP_ID_PM); @@ -2830,13 +2729,22 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlis } #if defined(CONFIG_PM) -#if defined(CONFIG_PPC_PMAC) /* Check if we can power manage on suspend/resume. We can do * D2 on M6, M7 and M9, and we can resume from D3 cold a few other * "Mac" cards, but that's all. We need more infos about what the * BIOS does tho. Right now, all this PM stuff is pmac-only for that * reason. --BenH */ + /* Special case for Samsung P35 laptops + */ + if ((rinfo->pdev->vendor == PCI_VENDOR_ID_ATI) && + (rinfo->pdev->device == PCI_CHIP_RV350_NP) && + (rinfo->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG) && + (rinfo->pdev->subsystem_device == 0xc00c)) { + rinfo->reinit_func = radeon_reinitialize_M10; + rinfo->pm_mode |= radeon_pm_off; + } +#if defined(CONFIG_PPC_PMAC) if (machine_is(powermac) && rinfo->of_node) { if (rinfo->is_mobility && rinfo->pm_reg && rinfo->family <= CHIP_FAMILY_RV250) @@ -2882,18 +2790,6 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlis } #endif /* defined(CONFIG_PPC_PMAC) */ #endif /* defined(CONFIG_PM) */ - - if (ignore_devlist) - printk(KERN_DEBUG - "radeonfb: skipping test for device workarounds\n"); - else - radeon_apply_workarounds(rinfo); - - if (force_sleep) { - printk(KERN_DEBUG - "radeonfb: forcefully enabling D2 sleep mode\n"); - rinfo->pm_mode |= radeon_pm_d2; - } } void radeonfb_pm_exit(struct radeonfb_info *rinfo) diff --git a/trunk/drivers/video/aty/radeonfb.h b/trunk/drivers/video/aty/radeonfb.h index d5ff224a6258..38657b2d10eb 100644 --- a/trunk/drivers/video/aty/radeonfb.h +++ b/trunk/drivers/video/aty/radeonfb.h @@ -273,8 +273,6 @@ enum radeon_pm_mode { radeon_pm_off = 0x00000002, /* Can resume from D3 cold */ }; -typedef void (*reinit_function_ptr)(struct radeonfb_info *rinfo); - struct radeonfb_info { struct fb_info *info; @@ -340,7 +338,7 @@ struct radeonfb_info { int dynclk; int no_schedule; enum radeon_pm_mode pm_mode; - reinit_function_ptr reinit_func; + void (*reinit_func)(struct radeonfb_info *rinfo); /* Lock on register access */ spinlock_t reg_lock; @@ -602,7 +600,7 @@ extern int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 /* PM Functions */ extern int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state); extern int radeonfb_pci_resume(struct pci_dev *pdev); -extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlist, int force_sleep); +extern void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk); extern void radeonfb_pm_exit(struct radeonfb_info *rinfo); /* Monitor probe functions */ diff --git a/trunk/drivers/video/au1100fb.c b/trunk/drivers/video/au1100fb.c index f25d5d648333..a92a91fef16f 100644 --- a/trunk/drivers/video/au1100fb.c +++ b/trunk/drivers/video/au1100fb.c @@ -156,7 +156,7 @@ int au1100fb_setmode(struct au1100fb_device *fbdev) info->fix.visual = FB_VISUAL_TRUECOLOR; info->fix.line_length = info->var.xres_virtual << 1; /* depth=16 */ - } + } } else { /* mono */ info->fix.visual = FB_VISUAL_MONO10; @@ -164,16 +164,20 @@ int au1100fb_setmode(struct au1100fb_device *fbdev) } info->screen_size = info->fix.line_length * info->var.yres_virtual; - info->var.rotate = ((fbdev->panel->control_base&LCD_CONTROL_SM_MASK) \ - >> LCD_CONTROL_SM_BIT) * 90; /* Determine BPP mode and format */ - fbdev->regs->lcd_control = fbdev->panel->control_base; + fbdev->regs->lcd_control = fbdev->panel->control_base | + ((info->var.rotate/90) << LCD_CONTROL_SM_BIT); + + fbdev->regs->lcd_intenable = 0; + fbdev->regs->lcd_intstatus = 0; + fbdev->regs->lcd_horztiming = fbdev->panel->horztiming; + fbdev->regs->lcd_verttiming = fbdev->panel->verttiming; + fbdev->regs->lcd_clkcontrol = fbdev->panel->clkcontrol_base; - fbdev->regs->lcd_intenable = 0; - fbdev->regs->lcd_intstatus = 0; + fbdev->regs->lcd_dmaaddr0 = LCD_DMA_SA_N(fbdev->fb_phys); if (panel_is_dual(fbdev->panel)) { @@ -202,8 +206,6 @@ int au1100fb_setmode(struct au1100fb_device *fbdev) /* Resume controller */ fbdev->regs->lcd_control |= LCD_CONTROL_GO; - mdelay(10); - au1100fb_fb_blank(VESA_NO_BLANKING, info); return 0; } diff --git a/trunk/drivers/video/backlight/Kconfig b/trunk/drivers/video/backlight/Kconfig index 02f15297a021..022f9d3473f5 100644 --- a/trunk/drivers/video/backlight/Kconfig +++ b/trunk/drivers/video/backlight/Kconfig @@ -10,7 +10,7 @@ menuconfig BACKLIGHT_LCD_SUPPORT config BACKLIGHT_CLASS_DEVICE tristate "Lowlevel Backlight controls" - depends on BACKLIGHT_LCD_SUPPORT + depends on BACKLIGHT_LCD_SUPPORT && FB default m help This framework adds support for low-level control of the LCD @@ -26,7 +26,7 @@ config BACKLIGHT_DEVICE config LCD_CLASS_DEVICE tristate "Lowlevel LCD controls" - depends on BACKLIGHT_LCD_SUPPORT + depends on BACKLIGHT_LCD_SUPPORT && FB default m help This framework adds support for low-level control of LCD. diff --git a/trunk/drivers/video/console/fbcon.c b/trunk/drivers/video/console/fbcon.c index 1b4f75d1f8a9..390439b3d899 100644 --- a/trunk/drivers/video/console/fbcon.c +++ b/trunk/drivers/video/console/fbcon.c @@ -3197,11 +3197,11 @@ static void fbcon_exit(void) return; #ifdef CONFIG_ATARI - free_irq(IRQ_AUTO_4, fb_vbl_handler); + free_irq(IRQ_AUTO_4, fbcon_vbl_handler); #endif #ifdef CONFIG_MAC if (MACH_IS_MAC && vbl_detected) - free_irq(IRQ_MAC_VBL, fb_vbl_handler); + free_irq(IRQ_MAC_VBL, fbcon_vbl_handler); #endif kfree((void *)softback_buf); diff --git a/trunk/drivers/video/console/mdacon.c b/trunk/drivers/video/console/mdacon.c index eb4d03fa5391..52ed12b12acc 100644 --- a/trunk/drivers/video/console/mdacon.c +++ b/trunk/drivers/video/console/mdacon.c @@ -197,7 +197,7 @@ static int __init mdacon_setup(char *str) __setup("mdacon=", mdacon_setup); #endif -static int mda_detect(void) +static int __init mda_detect(void) { int count=0; u16 *p, p_save; @@ -282,7 +282,7 @@ static int mda_detect(void) return 1; } -static void mda_initialize(void) +static void __init mda_initialize(void) { write_mda_b(97, 0x00); /* horizontal total */ write_mda_b(80, 0x01); /* horizontal displayed */ diff --git a/trunk/drivers/video/fb_notify.c b/trunk/drivers/video/fb_notify.c deleted file mode 100644 index 8c020389e4fa..000000000000 --- a/trunk/drivers/video/fb_notify.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * linux/drivers/video/fb_notify.c - * - * Copyright (C) 2006 Antonino Daplas - * - * 2001 - Documented with DocBook - * - Brad Douglas - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ -#include -#include - -static BLOCKING_NOTIFIER_HEAD(fb_notifier_list); - -/** - * fb_register_client - register a client notifier - * @nb: notifier block to callback on events - */ -int fb_register_client(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&fb_notifier_list, nb); -} -EXPORT_SYMBOL(fb_register_client); - -/** - * fb_unregister_client - unregister a client notifier - * @nb: notifier block to callback on events - */ -int fb_unregister_client(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&fb_notifier_list, nb); -} -EXPORT_SYMBOL(fb_unregister_client); - -/** - * fb_notifier_call_chain - notify clients of fb_events - * - */ -int fb_notifier_call_chain(unsigned long val, void *v) -{ - return blocking_notifier_call_chain(&fb_notifier_list, val, v); -} -EXPORT_SYMBOL_GPL(fb_notifier_call_chain); diff --git a/trunk/drivers/video/fbmem.c b/trunk/drivers/video/fbmem.c index 17961e3ecaa0..4fc9df426c1a 100644 --- a/trunk/drivers/video/fbmem.c +++ b/trunk/drivers/video/fbmem.c @@ -52,6 +52,7 @@ #define FBPIXMAPSIZE (1024 * 8) +static BLOCKING_NOTIFIER_HEAD(fb_notifier_list); struct fb_info *registered_fb[FB_MAX]; int num_registered_fb; @@ -790,7 +791,8 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) event.info = info; event.data = &mode1; - ret = fb_notifier_call_chain(FB_EVENT_MODE_DELETE, &event); + ret = blocking_notifier_call_chain(&fb_notifier_list, + FB_EVENT_MODE_DELETE, &event); } if (!ret) @@ -835,7 +837,8 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) info->flags &= ~FBINFO_MISC_USEREVENT; event.info = info; - fb_notifier_call_chain(evnt, &event); + blocking_notifier_call_chain(&fb_notifier_list, + evnt, &event); } } } @@ -858,7 +861,8 @@ fb_blank(struct fb_info *info, int blank) event.info = info; event.data = ␣ - fb_notifier_call_chain(FB_EVENT_BLANK, &event); + blocking_notifier_call_chain(&fb_notifier_list, + FB_EVENT_BLANK, &event); } return ret; @@ -929,7 +933,8 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, con2fb.framebuffer = -1; event.info = info; event.data = &con2fb; - fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); + blocking_notifier_call_chain(&fb_notifier_list, + FB_EVENT_GET_CONSOLE_MAP, &event); return copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; case FBIOPUT_CON2FBMAP: @@ -947,8 +952,9 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return -EINVAL; event.info = info; event.data = &con2fb; - return fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, - &event); + return blocking_notifier_call_chain(&fb_notifier_list, + FB_EVENT_SET_CONSOLE_MAP, + &event); case FBIOBLANK: acquire_console_sem(); info->flags |= FBINFO_MISC_USEREVENT; @@ -1324,7 +1330,8 @@ register_framebuffer(struct fb_info *fb_info) registered_fb[i] = fb_info; event.info = fb_info; - fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); + blocking_notifier_call_chain(&fb_notifier_list, + FB_EVENT_FB_REGISTERED, &event); return 0; } @@ -1358,10 +1365,29 @@ unregister_framebuffer(struct fb_info *fb_info) fb_cleanup_class_device(fb_info); class_device_destroy(fb_class, MKDEV(FB_MAJOR, i)); event.info = fb_info; - fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); + blocking_notifier_call_chain(&fb_notifier_list, + FB_EVENT_FB_UNREGISTERED, &event); return 0; } +/** + * fb_register_client - register a client notifier + * @nb: notifier block to callback on events + */ +int fb_register_client(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&fb_notifier_list, nb); +} + +/** + * fb_unregister_client - unregister a client notifier + * @nb: notifier block to callback on events + */ +int fb_unregister_client(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&fb_notifier_list, nb); +} + /** * fb_set_suspend - low level driver signals suspend * @info: framebuffer affected @@ -1377,11 +1403,13 @@ void fb_set_suspend(struct fb_info *info, int state) event.info = info; if (state) { - fb_notifier_call_chain(FB_EVENT_SUSPEND, &event); + blocking_notifier_call_chain(&fb_notifier_list, + FB_EVENT_SUSPEND, &event); info->state = FBINFO_STATE_SUSPENDED; } else { info->state = FBINFO_STATE_RUNNING; - fb_notifier_call_chain(FB_EVENT_RESUME, &event); + blocking_notifier_call_chain(&fb_notifier_list, + FB_EVENT_RESUME, &event); } } @@ -1452,7 +1480,9 @@ int fb_new_modelist(struct fb_info *info) if (!list_empty(&info->modelist)) { event.info = info; - err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event); + err = blocking_notifier_call_chain(&fb_notifier_list, + FB_EVENT_NEW_MODELIST, + &event); } return err; @@ -1564,6 +1594,8 @@ EXPORT_SYMBOL(fb_blank); EXPORT_SYMBOL(fb_pan_display); EXPORT_SYMBOL(fb_get_buffer_offset); EXPORT_SYMBOL(fb_set_suspend); +EXPORT_SYMBOL(fb_register_client); +EXPORT_SYMBOL(fb_unregister_client); EXPORT_SYMBOL(fb_get_options); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/video/imacfb.c b/trunk/drivers/video/imacfb.c index 18ea4a549105..ff233b84dec4 100644 --- a/trunk/drivers/video/imacfb.c +++ b/trunk/drivers/video/imacfb.c @@ -18,8 +18,6 @@ #include #include #include -#include -#include #include @@ -30,7 +28,7 @@ typedef enum _MAC_TYPE { M_I20, M_MINI, M_MACBOOK, - M_UNKNOWN + M_NEW } MAC_TYPE; /* --------------------------------------------------------------------- */ @@ -54,36 +52,10 @@ static struct fb_fix_screeninfo imacfb_fix __initdata = { }; static int inverse; -static int model = M_UNKNOWN; +static int model = M_NEW; static int manual_height; static int manual_width; -static int set_system(struct dmi_system_id *id) -{ - printk(KERN_INFO "imacfb: %s detected - set system to %ld\n", - id->ident, (long)id->driver_data); - - model = (long)id->driver_data; - - return 0; -} - -static struct dmi_system_id __initdata dmi_system_table[] = { - { set_system, "iMac4,1", { - DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), - DMI_MATCH(DMI_PRODUCT_NAME,"iMac4,1") }, (void*)M_I17}, - { set_system, "MacBookPro1,1", { - DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), - DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro1,1") }, (void*)M_I17}, - { set_system, "MacBook1,1", { - DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), - DMI_MATCH(DMI_PRODUCT_NAME,"MacBook1,1")}, (void *)M_MACBOOK}, - { set_system, "Macmini1,1", { - DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), - DMI_MATCH(DMI_PRODUCT_NAME,"Macmini1,1")}, (void *)M_MINI}, - {}, -}; - #define DEFAULT_FB_MEM 1024*1024*16 /* --------------------------------------------------------------------- */ @@ -177,6 +149,7 @@ static int __init imacfb_probe(struct platform_device *dev) screen_info.lfb_linelength = 1472 * 4; screen_info.lfb_base = 0x80010000; break; + case M_NEW: case M_I20: screen_info.lfb_width = 1680; screen_info.lfb_height = 1050; @@ -234,10 +207,6 @@ static int __init imacfb_probe(struct platform_device *dev) size_remap = size_total; imacfb_fix.smem_len = size_remap; -#ifndef __i386__ - screen_info.imacpm_seg = 0; -#endif - if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) { printk(KERN_WARNING "imacfb: cannot reserve video memory at 0x%lx\n", @@ -355,16 +324,8 @@ static int __init imacfb_init(void) int ret; char *option = NULL; - if (!efi_enabled) - return -ENODEV; - if (!dmi_check_system(dmi_system_table)) - return -ENODEV; - if (model == M_UNKNOWN) - return -ENODEV; - - if (fb_get_options("imacfb", &option)) - return -ENODEV; - + /* ignore error return of fb_get_options */ + fb_get_options("imacfb", &option); imacfb_setup(option); ret = platform_driver_register(&imacfb_driver); diff --git a/trunk/drivers/video/matrox/g450_pll.c b/trunk/drivers/video/matrox/g450_pll.c index 7c76e079ca7d..440272ad10e7 100644 --- a/trunk/drivers/video/matrox/g450_pll.c +++ b/trunk/drivers/video/matrox/g450_pll.c @@ -331,15 +331,7 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, tmp |= M1064_XPIXCLKCTRL_PLL_UP; } matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp); -#ifdef __powerpc__ - /* This is necessary to avoid jitter on PowerPC - * (OpenFirmware) systems, but apparently - * introduces jitter, at least on a x86-64 - * using DVI. - * A simple workaround is disable for non-PPC. - */ matroxfb_DAC_out(PMINFO M1064_XDVICLKCTRL, 0); -#endif /* __powerpc__ */ matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl); matroxfb_DAC_unlock_irqrestore(flags); diff --git a/trunk/drivers/video/nvidia/nv_backlight.c b/trunk/drivers/video/nvidia/nv_backlight.c index 5b75ae4e9457..b45f577094ac 100644 --- a/trunk/drivers/video/nvidia/nv_backlight.c +++ b/trunk/drivers/video/nvidia/nv_backlight.c @@ -113,14 +113,10 @@ static struct backlight_properties nvidia_bl_data = { void nvidia_bl_set_power(struct fb_info *info, int power) { mutex_lock(&info->bl_mutex); - - if (info->bl_dev) { - down(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __nvidia_bl_update_status(info->bl_dev); - up(&info->bl_dev->sem); - } - + up(&info->bl_dev->sem); + info->bl_dev->props->power = power; + __nvidia_bl_update_status(info->bl_dev); + down(&info->bl_dev->sem); mutex_unlock(&info->bl_mutex); } @@ -144,7 +140,7 @@ void nvidia_bl_init(struct nvidia_par *par) bd = backlight_device_register(name, par, &nvidia_bl_data); if (IS_ERR(bd)) { info->bl_dev = NULL; - printk(KERN_WARNING "nvidia: Backlight registration failed\n"); + printk("nvidia: Backlight registration failed\n"); goto error; } @@ -155,11 +151,11 @@ void nvidia_bl_init(struct nvidia_par *par) 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); mutex_unlock(&info->bl_mutex); - down(&bd->sem); + up(&bd->sem); bd->props->brightness = nvidia_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - up(&bd->sem); + down(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); diff --git a/trunk/drivers/video/nvidia/nv_of.c b/trunk/drivers/video/nvidia/nv_of.c index d9af88c2b580..8209106e26ee 100644 --- a/trunk/drivers/video/nvidia/nv_of.c +++ b/trunk/drivers/video/nvidia/nv_of.c @@ -32,7 +32,7 @@ int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid) { struct nvidia_par *par = info->par; struct device_node *parent, *dp; - const unsigned char *pedid = NULL; + unsigned char *pedid = NULL; static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL }; @@ -42,19 +42,20 @@ int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid) if (parent == NULL) return -1; if (par->twoHeads) { - const char *pname; + char *pname; int len; for (dp = NULL; (dp = of_get_next_child(parent, dp)) != NULL;) { - pname = get_property(dp, "name", NULL); + pname = (char *)get_property(dp, "name", NULL); if (!pname) continue; len = strlen(pname); if ((pname[len-1] == 'A' && conn == 1) || (pname[len-1] == 'B' && conn == 2)) { for (i = 0; propnames[i] != NULL; ++i) { - pedid = get_property(dp, propnames[i], + pedid = (unsigned char *) + get_property(dp, propnames[i], NULL); if (pedid != NULL) break; @@ -66,7 +67,8 @@ int nvidia_probe_of_connector(struct fb_info *info, int conn, u8 **out_edid) } if (pedid == NULL) { for (i = 0; propnames[i] != NULL; ++i) { - pedid = get_property(parent, propnames[i], NULL); + pedid = (unsigned char *) + get_property(parent, propnames[i], NULL); if (pedid != NULL) break; } diff --git a/trunk/drivers/video/nvidia/nvidia.c b/trunk/drivers/video/nvidia/nvidia.c index d4f850117874..9f2066f0745a 100644 --- a/trunk/drivers/video/nvidia/nvidia.c +++ b/trunk/drivers/video/nvidia/nvidia.c @@ -34,6 +34,10 @@ #include "nv_proto.h" #include "nv_dma.h" +#ifndef CONFIG_PCI /* sanity check */ +#error This driver requires PCI support. +#endif + #undef CONFIG_FB_NVIDIA_DEBUG #ifdef CONFIG_FB_NVIDIA_DEBUG #define NVTRACE printk @@ -1299,19 +1303,20 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, nvidia_save_vga(par, &par->SavedReg); - pci_set_drvdata(pd, info); - nvidia_bl_init(par); if (register_framebuffer(info) < 0) { printk(KERN_ERR PFX "error registering nVidia framebuffer\n"); goto err_out_iounmap_fb; } + pci_set_drvdata(pd, info); printk(KERN_INFO PFX "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n", info->fix.id, par->FbMapSize / (1024 * 1024), info->fix.smem_start); + nvidia_bl_init(par); + NVTRACE_LEAVE(); return 0; diff --git a/trunk/drivers/video/offb.c b/trunk/drivers/video/offb.c index bad0e98fb3b6..ce5f3031b99b 100644 --- a/trunk/drivers/video/offb.c +++ b/trunk/drivers/video/offb.c @@ -62,6 +62,8 @@ struct offb_par default_par; * Interface used by the world */ +int offb_init(void); + static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); static int offb_blank(int blank, struct fb_info *info); @@ -70,6 +72,11 @@ static int offb_blank(int blank, struct fb_info *info); extern boot_infos_t *boot_infos; #endif +static void offb_init_nodriver(struct device_node *); +static void offb_init_fb(const char *name, const char *full_name, + int width, int height, int depth, int pitch, + unsigned long address, struct device_node *dp); + static struct fb_ops offb_ops = { .owner = THIS_MODULE, .fb_setcolreg = offb_setcolreg, @@ -222,17 +229,123 @@ static int offb_blank(int blank, struct fb_info *info) return 0; } + /* + * Initialisation + */ -static void __iomem *offb_map_reg(struct device_node *np, int index, - unsigned long offset, unsigned long size) +int __init offb_init(void) { - struct resource r; + struct device_node *dp = NULL, *boot_disp = NULL; - if (of_address_to_resource(np, index, &r)) - return 0; - if ((r.start + offset + size) > r.end) - return 0; - return ioremap(r.start + offset, size); + if (fb_get_options("offb", NULL)) + return -ENODEV; + + for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { + if (get_property(dp, "linux,opened", NULL) && + get_property(dp, "linux,boot-display", NULL)) { + boot_disp = dp; + offb_init_nodriver(dp); + } + } + for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { + if (get_property(dp, "linux,opened", NULL) && + dp != boot_disp) + offb_init_nodriver(dp); + } + + return 0; +} + + +static void __init offb_init_nodriver(struct device_node *dp) +{ + unsigned int len; + int i, width = 640, height = 480, depth = 8, pitch = 640; + unsigned int flags, rsize, addr_prop = 0; + unsigned long max_size = 0; + u64 rstart, address = OF_BAD_ADDR; + u32 *pp, *addrp, *up; + u64 asize; + + pp = (u32 *)get_property(dp, "linux,bootx-depth", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "depth", &len); + if (pp && len == sizeof(u32)) + depth = *pp; + + pp = (u32 *)get_property(dp, "linux,bootx-width", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "width", &len); + if (pp && len == sizeof(u32)) + width = *pp; + + pp = (u32 *)get_property(dp, "linux,bootx-height", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "height", &len); + if (pp && len == sizeof(u32)) + height = *pp; + + pp = (u32 *)get_property(dp, "linux,bootx-linebytes", &len); + if (pp == NULL) + pp = (u32 *)get_property(dp, "linebytes", &len); + if (pp && len == sizeof(u32)) + pitch = *pp; + else + pitch = width * ((depth + 7) / 8); + + rsize = (unsigned long)pitch * (unsigned long)height; + + /* Ok, now we try to figure out the address of the framebuffer. + * + * Unfortunately, Open Firmware doesn't provide a standard way to do + * so. All we can do is a dodgy heuristic that happens to work in + * practice. On most machines, the "address" property contains what + * we need, though not on Matrox cards found in IBM machines. What I've + * found that appears to give good results is to go through the PCI + * ranges and pick one that is both big enough and if possible encloses + * the "address" property. If none match, we pick the biggest + */ + up = (u32 *)get_property(dp, "linux,bootx-addr", &len); + if (up == NULL) + up = (u32 *)get_property(dp, "address", &len); + if (up && len == sizeof(u32)) + addr_prop = *up; + + for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags)) + != NULL; i++) { + int match_addrp = 0; + + if (!(flags & IORESOURCE_MEM)) + continue; + if (asize < rsize) + continue; + rstart = of_translate_address(dp, addrp); + if (rstart == OF_BAD_ADDR) + continue; + if (addr_prop && (rstart <= addr_prop) && + ((rstart + asize) >= (addr_prop + rsize))) + match_addrp = 1; + if (match_addrp) { + address = addr_prop; + break; + } + if (rsize > max_size) { + max_size = rsize; + address = OF_BAD_ADDR; + } + + if (address == OF_BAD_ADDR) + address = rstart; + } + if (address == OF_BAD_ADDR && addr_prop) + address = (u64)addr_prop; + if (address != OF_BAD_ADDR) { + /* kludge for valkyrie */ + if (strcmp(dp->name, "valkyrie") == 0) + address += 0x1000; + offb_init_fb(dp->name, dp->full_name, width, height, depth, + pitch, address, dp); + } } static void __init offb_init_fb(const char *name, const char *full_name, @@ -289,39 +402,45 @@ static void __init offb_init_fb(const char *name, const char *full_name, par->cmap_type = cmap_unknown; if (depth == 8) { + /* Palette hacks disabled for now */ +#if 0 if (dp && !strncmp(name, "ATY,Rage128", 11)) { - par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); - if (par->cmap_adr) - par->cmap_type = cmap_r128; + unsigned long regbase = dp->addrs[2].address; + par->cmap_adr = ioremap(regbase, 0x1FFF); + par->cmap_type = cmap_r128; } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12) || !strncmp(name, "ATY,RageM3p12A", 14))) { - par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); - if (par->cmap_adr) - par->cmap_type = cmap_M3A; + unsigned long regbase = + dp->parent->addrs[2].address; + par->cmap_adr = ioremap(regbase, 0x1FFF); + par->cmap_type = cmap_M3A; } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) { - par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); - if (par->cmap_adr) - par->cmap_type = cmap_M3B; + unsigned long regbase = + dp->parent->addrs[2].address; + par->cmap_adr = ioremap(regbase, 0x1FFF); + par->cmap_type = cmap_M3B; } else if (dp && !strncmp(name, "ATY,Rage6", 9)) { - par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff); - if (par->cmap_adr) - par->cmap_type = cmap_radeon; + unsigned long regbase = dp->addrs[1].address; + par->cmap_adr = ioremap(regbase, 0x1FFF); + par->cmap_type = cmap_radeon; } else if (!strncmp(name, "ATY,", 4)) { unsigned long base = address & 0xff000000UL; par->cmap_adr = ioremap(base + 0x7ff000, 0x1000) + 0xcc0; par->cmap_data = par->cmap_adr + 1; par->cmap_type = cmap_m64; - } else if (dp && device_is_compatible(dp, "pci1014,b7")) { - par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000); - if (par->cmap_adr) - par->cmap_type = cmap_gxt2000; + } else if (device_is_compatible(dp, "pci1014,b7")) { + unsigned long regbase = dp->addrs[0].address; + par->cmap_adr = ioremap(regbase + 0x6000, 0x1000); + par->cmap_type = cmap_gxt2000; } - fix->visual = (par->cmap_type != cmap_unknown) ? - FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR; +#endif + fix->visual = par->cmap_adr ? FB_VISUAL_PSEUDOCOLOR + : FB_VISUAL_STATIC_PSEUDOCOLOR; } else - fix->visual = FB_VISUAL_TRUECOLOR; + fix->visual = /* par->cmap_adr ? FB_VISUAL_DIRECTCOLOR + : */ FB_VISUAL_TRUECOLOR; var->xoffset = var->yoffset = 0; switch (depth) { @@ -401,139 +520,5 @@ static void __init offb_init_fb(const char *name, const char *full_name, info->node, full_name); } - -static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) -{ - unsigned int len; - int i, width = 640, height = 480, depth = 8, pitch = 640; - unsigned int flags, rsize, addr_prop = 0; - unsigned long max_size = 0; - u64 rstart, address = OF_BAD_ADDR; - const u32 *pp, *addrp, *up; - u64 asize; - - pp = get_property(dp, "linux,bootx-depth", &len); - if (pp == NULL) - pp = get_property(dp, "depth", &len); - if (pp && len == sizeof(u32)) - depth = *pp; - - pp = get_property(dp, "linux,bootx-width", &len); - if (pp == NULL) - pp = get_property(dp, "width", &len); - if (pp && len == sizeof(u32)) - width = *pp; - - pp = get_property(dp, "linux,bootx-height", &len); - if (pp == NULL) - pp = get_property(dp, "height", &len); - if (pp && len == sizeof(u32)) - height = *pp; - - pp = get_property(dp, "linux,bootx-linebytes", &len); - if (pp == NULL) - pp = get_property(dp, "linebytes", &len); - if (pp && len == sizeof(u32)) - pitch = *pp; - else - pitch = width * ((depth + 7) / 8); - - rsize = (unsigned long)pitch * (unsigned long)height; - - /* Ok, now we try to figure out the address of the framebuffer. - * - * Unfortunately, Open Firmware doesn't provide a standard way to do - * so. All we can do is a dodgy heuristic that happens to work in - * practice. On most machines, the "address" property contains what - * we need, though not on Matrox cards found in IBM machines. What I've - * found that appears to give good results is to go through the PCI - * ranges and pick one that is both big enough and if possible encloses - * the "address" property. If none match, we pick the biggest - */ - up = get_property(dp, "linux,bootx-addr", &len); - if (up == NULL) - up = get_property(dp, "address", &len); - if (up && len == sizeof(u32)) - addr_prop = *up; - - /* Hack for when BootX is passing us */ - if (no_real_node) - goto skip_addr; - - for (i = 0; (addrp = of_get_address(dp, i, &asize, &flags)) - != NULL; i++) { - int match_addrp = 0; - - if (!(flags & IORESOURCE_MEM)) - continue; - if (asize < rsize) - continue; - rstart = of_translate_address(dp, addrp); - if (rstart == OF_BAD_ADDR) - continue; - if (addr_prop && (rstart <= addr_prop) && - ((rstart + asize) >= (addr_prop + rsize))) - match_addrp = 1; - if (match_addrp) { - address = addr_prop; - break; - } - if (rsize > max_size) { - max_size = rsize; - address = OF_BAD_ADDR; - } - - if (address == OF_BAD_ADDR) - address = rstart; - } - skip_addr: - if (address == OF_BAD_ADDR && addr_prop) - address = (u64)addr_prop; - if (address != OF_BAD_ADDR) { - /* kludge for valkyrie */ - if (strcmp(dp->name, "valkyrie") == 0) - address += 0x1000; - offb_init_fb(no_real_node ? "bootx" : dp->name, - no_real_node ? "display" : dp->full_name, - width, height, depth, pitch, address, - no_real_node ? dp : NULL); - } -} - -static int __init offb_init(void) -{ - struct device_node *dp = NULL, *boot_disp = NULL; - - if (fb_get_options("offb", NULL)) - return -ENODEV; - - /* Check if we have a MacOS display without a node spec */ - if (get_property(of_chosen, "linux,bootx-noscreen", NULL) != NULL) { - /* The old code tried to work out which node was the MacOS - * display based on the address. I'm dropping that since the - * lack of a node spec only happens with old BootX versions - * (users can update) and with this code, they'll still get - * a display (just not the palette hacks). - */ - offb_init_nodriver(of_chosen, 1); - } - - for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { - if (get_property(dp, "linux,opened", NULL) && - get_property(dp, "linux,boot-display", NULL)) { - boot_disp = dp; - offb_init_nodriver(dp, 0); - } - } - for (dp = NULL; (dp = of_find_node_by_type(dp, "display"));) { - if (get_property(dp, "linux,opened", NULL) && - dp != boot_disp) - offb_init_nodriver(dp, 0); - } - - return 0; -} - - module_init(offb_init); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/video/riva/fbdev.c b/trunk/drivers/video/riva/fbdev.c index 4acde4f7dbf8..33dddbae5420 100644 --- a/trunk/drivers/video/riva/fbdev.c +++ b/trunk/drivers/video/riva/fbdev.c @@ -355,14 +355,10 @@ static struct backlight_properties riva_bl_data = { static void riva_bl_set_power(struct fb_info *info, int power) { mutex_lock(&info->bl_mutex); - - if (info->bl_dev) { - down(&info->bl_dev->sem); - info->bl_dev->props->power = power; - __riva_bl_update_status(info->bl_dev); - up(&info->bl_dev->sem); - } - + up(&info->bl_dev->sem); + info->bl_dev->props->power = power; + __riva_bl_update_status(info->bl_dev); + down(&info->bl_dev->sem); mutex_unlock(&info->bl_mutex); } @@ -386,7 +382,7 @@ static void riva_bl_init(struct riva_par *par) bd = backlight_device_register(name, par, &riva_bl_data); if (IS_ERR(bd)) { info->bl_dev = NULL; - printk(KERN_WARNING "riva: Backlight registration failed\n"); + printk("riva: Backlight registration failed\n"); goto error; } @@ -397,11 +393,11 @@ static void riva_bl_init(struct riva_par *par) 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); mutex_unlock(&info->bl_mutex); - down(&bd->sem); + up(&bd->sem); bd->props->brightness = riva_bl_data.max_brightness; bd->props->power = FB_BLANK_UNBLANK; bd->props->update_status(bd); - up(&bd->sem); + down(&bd->sem); #ifdef CONFIG_PMAC_BACKLIGHT mutex_lock(&pmac_backlight_mutex); @@ -1826,8 +1822,8 @@ static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd) { struct riva_par *par = info->par; struct device_node *dp; - const unsigned char *pedid = NULL; - const unsigned char *disptype = NULL; + unsigned char *pedid = NULL; + unsigned char *disptype = NULL; static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL }; int i; @@ -1835,13 +1831,14 @@ static int __devinit riva_get_EDID_OF(struct fb_info *info, struct pci_dev *pd) NVTRACE_ENTER(); dp = pci_device_to_OF_node(pd); for (; dp != NULL; dp = dp->child) { - disptype = get_property(dp, "display-type", NULL); + disptype = (unsigned char *)get_property(dp, "display-type", NULL); if (disptype == NULL) continue; if (strncmp(disptype, "LCD", 3) != 0) continue; for (i = 0; propnames[i] != NULL; ++i) { - pedid = get_property(dp, propnames[i], NULL); + pedid = (unsigned char *) + get_property(dp, propnames[i], NULL); if (pedid != NULL) { par->EDID = pedid; NVTRACE("LCD found.\n"); @@ -2135,9 +2132,6 @@ static int __devinit rivafb_probe(struct pci_dev *pd, fb_destroy_modedb(info->monspecs.modedb); info->monspecs.modedb = NULL; - - pci_set_drvdata(pd, info); - riva_bl_init(info->par); ret = register_framebuffer(info); if (ret < 0) { printk(KERN_ERR PFX @@ -2145,6 +2139,8 @@ static int __devinit rivafb_probe(struct pci_dev *pd, goto err_iounmap_screen_base; } + pci_set_drvdata(pd, info); + printk(KERN_INFO PFX "PCI nVidia %s framebuffer ver %s (%dMB @ 0x%lX)\n", info->fix.id, @@ -2152,6 +2148,8 @@ static int __devinit rivafb_probe(struct pci_dev *pd, info->fix.smem_len / (1024 * 1024), info->fix.smem_start); + riva_bl_init(info->par); + NVTRACE_LEAVE(); return 0; diff --git a/trunk/fs/9p/conv.c b/trunk/fs/9p/conv.c index 56d88c1a09c5..1e898144eb7c 100644 --- a/trunk/fs/9p/conv.c +++ b/trunk/fs/9p/conv.c @@ -673,10 +673,8 @@ struct v9fs_fcall *v9fs_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, struct cbuf *bufp = &buffer; size = 4 + 2 + strlen(name) + 4 + 1; /* fid[4] name[s] perm[4] mode[1] */ - if (extended) { - size += 2 + /* extension[s] */ - (extension == NULL ? 0 : strlen(extension)); - } + if (extended && extension!=NULL) + size += 2 + strlen(extension); /* extension[s] */ fc = v9fs_create_common(bufp, size, TCREATE); if (IS_ERR(fc)) diff --git a/trunk/fs/9p/vfs_inode.c b/trunk/fs/9p/vfs_inode.c index eae50c9d6dc4..2f580a197b8d 100644 --- a/trunk/fs/9p/vfs_inode.c +++ b/trunk/fs/9p/vfs_inode.c @@ -434,11 +434,11 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir) result = v9fs_t_remove(v9ses, fid, &fcall); if (result < 0) { PRINT_FCALL_ERROR("remove fails", fcall); + } else { + v9fs_put_idpool(fid, &v9ses->fidpool); + v9fs_fid_destroy(v9fid); } - v9fs_put_idpool(fid, &v9ses->fidpool); - v9fs_fid_destroy(v9fid); - kfree(fcall); return result; } diff --git a/trunk/fs/Kconfig b/trunk/fs/Kconfig index a27002668bd3..3f00a9faabcb 100644 --- a/trunk/fs/Kconfig +++ b/trunk/fs/Kconfig @@ -325,8 +325,8 @@ config FS_POSIX_ACL source "fs/xfs/Kconfig" config OCFS2_FS - tristate "OCFS2 file system support" - depends on NET && SYSFS + tristate "OCFS2 file system support (EXPERIMENTAL)" + depends on NET && SYSFS && EXPERIMENTAL select CONFIGFS_FS select JBD select CRC32 @@ -1471,8 +1471,8 @@ config NFS_V4 If unsure, say N. config NFS_DIRECTIO - bool "Allow direct I/O on NFS files" - depends on NFS_FS + bool "Allow direct I/O on NFS files (EXPERIMENTAL)" + depends on NFS_FS && EXPERIMENTAL help This option enables applications to perform uncached I/O on files in NFS file systems using the O_DIRECT open() flag. When O_DIRECT diff --git a/trunk/fs/adfs/super.c b/trunk/fs/adfs/super.c index 82011019494c..ba1c88af49fe 100644 --- a/trunk/fs/adfs/super.c +++ b/trunk/fs/adfs/super.c @@ -308,7 +308,7 @@ static struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_di if (adfs_checkmap(sb, dm)) return dm; - adfs_error(sb, "map corrupted"); + adfs_error(sb, NULL, "map corrupted"); error_free: while (--zone >= 0) diff --git a/trunk/fs/befs/linuxvfs.c b/trunk/fs/befs/linuxvfs.c index 50cfca5c7efd..fcaeead9696b 100644 --- a/trunk/fs/befs/linuxvfs.c +++ b/trunk/fs/befs/linuxvfs.c @@ -512,11 +512,7 @@ befs_utf2nls(struct super_block *sb, const char *in, wchar_t uni; int unilen, utflen; char *result; - /* The utf8->nls conversion won't make the final nls string bigger - * than the utf one, but if the string is pure ascii they'll have the - * same width and an extra char is needed to save the additional \0 - */ - int maxlen = in_len + 1; + int maxlen = in_len; /* The utf8->nls conversion can't make more chars */ befs_debug(sb, "---> utf2nls()"); @@ -592,10 +588,7 @@ befs_nls2utf(struct super_block *sb, const char *in, wchar_t uni; int unilen, utflen; char *result; - /* There're nls characters that will translate to 3-chars-wide UTF-8 - * characters, a additional byte is needed to save the final \0 - * in special cases */ - int maxlen = (3 * in_len) + 1; + int maxlen = 3 * in_len; befs_debug(sb, "---> nls2utf()\n"); diff --git a/trunk/fs/block_dev.c b/trunk/fs/block_dev.c index 045f98854f14..37534573960b 100644 --- a/trunk/fs/block_dev.c +++ b/trunk/fs/block_dev.c @@ -884,61 +884,6 @@ void bd_set_size(struct block_device *bdev, loff_t size) } EXPORT_SYMBOL(bd_set_size); -static int __blkdev_put(struct block_device *bdev, unsigned int subclass) -{ - int ret = 0; - struct inode *bd_inode = bdev->bd_inode; - struct gendisk *disk = bdev->bd_disk; - - mutex_lock_nested(&bdev->bd_mutex, subclass); - lock_kernel(); - if (!--bdev->bd_openers) { - sync_blockdev(bdev); - kill_bdev(bdev); - } - if (bdev->bd_contains == bdev) { - if (disk->fops->release) - ret = disk->fops->release(bd_inode, NULL); - } else { - mutex_lock_nested(&bdev->bd_contains->bd_mutex, - subclass + 1); - bdev->bd_contains->bd_part_count--; - mutex_unlock(&bdev->bd_contains->bd_mutex); - } - if (!bdev->bd_openers) { - struct module *owner = disk->fops->owner; - - put_disk(disk); - module_put(owner); - - if (bdev->bd_contains != bdev) { - kobject_put(&bdev->bd_part->kobj); - bdev->bd_part = NULL; - } - bdev->bd_disk = NULL; - bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; - if (bdev != bdev->bd_contains) - __blkdev_put(bdev->bd_contains, subclass + 1); - bdev->bd_contains = NULL; - } - unlock_kernel(); - mutex_unlock(&bdev->bd_mutex); - bdput(bdev); - return ret; -} - -int blkdev_put(struct block_device *bdev) -{ - return __blkdev_put(bdev, BD_MUTEX_NORMAL); -} -EXPORT_SYMBOL(blkdev_put); - -int blkdev_put_partition(struct block_device *bdev) -{ - return __blkdev_put(bdev, BD_MUTEX_PARTITION); -} -EXPORT_SYMBOL(blkdev_put_partition); - static int blkdev_get_whole(struct block_device *bdev, mode_t mode, unsigned flags); @@ -1035,7 +980,7 @@ do_open(struct block_device *bdev, struct file *file, unsigned int subclass) bdev->bd_disk = NULL; bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; if (bdev != bdev->bd_contains) - __blkdev_put(bdev->bd_contains, BD_MUTEX_WHOLE); + blkdev_put(bdev->bd_contains); bdev->bd_contains = NULL; put_disk(disk); module_put(owner); @@ -1134,6 +1079,63 @@ static int blkdev_open(struct inode * inode, struct file * filp) return res; } +static int __blkdev_put(struct block_device *bdev, unsigned int subclass) +{ + int ret = 0; + struct inode *bd_inode = bdev->bd_inode; + struct gendisk *disk = bdev->bd_disk; + + mutex_lock_nested(&bdev->bd_mutex, subclass); + lock_kernel(); + if (!--bdev->bd_openers) { + sync_blockdev(bdev); + kill_bdev(bdev); + } + if (bdev->bd_contains == bdev) { + if (disk->fops->release) + ret = disk->fops->release(bd_inode, NULL); + } else { + mutex_lock_nested(&bdev->bd_contains->bd_mutex, + subclass + 1); + bdev->bd_contains->bd_part_count--; + mutex_unlock(&bdev->bd_contains->bd_mutex); + } + if (!bdev->bd_openers) { + struct module *owner = disk->fops->owner; + + put_disk(disk); + module_put(owner); + + if (bdev->bd_contains != bdev) { + kobject_put(&bdev->bd_part->kobj); + bdev->bd_part = NULL; + } + bdev->bd_disk = NULL; + bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; + if (bdev != bdev->bd_contains) + __blkdev_put(bdev->bd_contains, subclass + 1); + bdev->bd_contains = NULL; + } + unlock_kernel(); + mutex_unlock(&bdev->bd_mutex); + bdput(bdev); + return ret; +} + +int blkdev_put(struct block_device *bdev) +{ + return __blkdev_put(bdev, BD_MUTEX_NORMAL); +} + +EXPORT_SYMBOL(blkdev_put); + +int blkdev_put_partition(struct block_device *bdev) +{ + return __blkdev_put(bdev, BD_MUTEX_PARTITION); +} + +EXPORT_SYMBOL(blkdev_put_partition); + static int blkdev_close(struct inode * inode, struct file * filp) { struct block_device *bdev = I_BDEV(filp->f_mapping->host); diff --git a/trunk/fs/buffer.c b/trunk/fs/buffer.c index 71649ef9b658..3660dcb97591 100644 --- a/trunk/fs/buffer.c +++ b/trunk/fs/buffer.c @@ -470,18 +470,13 @@ __find_get_block_slow(struct block_device *bdev, sector_t block) pass does the actual I/O. */ void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers) { - struct address_space *mapping = bdev->bd_inode->i_mapping; - - if (mapping->nrpages == 0) - return; - invalidate_bh_lrus(); /* * FIXME: what about destroy_dirty_buffers? * We really want to use invalidate_inode_pages2() for * that, but not until that's cleaned up. */ - invalidate_inode_pages(mapping); + invalidate_inode_pages(bdev->bd_inode->i_mapping); } /* diff --git a/trunk/fs/cifs/CHANGES b/trunk/fs/cifs/CHANGES index 1eb9a2ec0a3b..a61d17ed1827 100644 --- a/trunk/fs/cifs/CHANGES +++ b/trunk/fs/cifs/CHANGES @@ -1,18 +1,3 @@ -Version 1.46 ------------- -Support deep tree mounts. Better support OS/2, Win9x (DOS) time stamps. - -Version 1.45 ------------- -Do not time out lockw calls when using posix extensions. Do not -time out requests if server still responding reasonably fast -on requests on other threads. Improve POSIX locking emulation, -(lock cancel now works, and unlock of merged range works even -to Windows servers now). Fix oops on mount to lanman servers -(win9x, os/2 etc.) when null password. Do not send listxattr -(SMB to query all EAs) if nouser_xattr specified. Fix SE Linux -problem (instantiate inodes/dentries in right order for readdir). - Version 1.44 ------------ Rewritten sessionsetup support, including support for legacy SMB diff --git a/trunk/fs/cifs/README b/trunk/fs/cifs/README index 5f0e1bd64fee..7986d0d97ace 100644 --- a/trunk/fs/cifs/README +++ b/trunk/fs/cifs/README @@ -408,7 +408,7 @@ A partial list of the supported mount options follows: user_xattr Allow getting and setting user xattrs as OS/2 EAs (extended attributes) to the server (default) e.g. via setfattr and getfattr utilities. - nouser_xattr Do not allow getfattr/setfattr to get/set/list xattrs + nouser_xattr Do not allow getfattr/setfattr to get/set xattrs mapchars Translate six of the seven reserved characters (not backslash) *?<>|: to the remap range (above 0xF000), which also diff --git a/trunk/fs/cifs/cifs_fs_sb.h b/trunk/fs/cifs/cifs_fs_sb.h index fd1e52ebcee6..ad58eb0c4d6d 100644 --- a/trunk/fs/cifs/cifs_fs_sb.h +++ b/trunk/fs/cifs/cifs_fs_sb.h @@ -40,7 +40,5 @@ struct cifs_sb_info { mode_t mnt_file_mode; mode_t mnt_dir_mode; int mnt_cifs_flags; - int prepathlen; - char * prepath; }; #endif /* _CIFS_FS_SB_H */ diff --git a/trunk/fs/cifs/cifsencrypt.c b/trunk/fs/cifs/cifsencrypt.c index 4bc250b2d9fc..a89efaf78a26 100644 --- a/trunk/fs/cifs/cifsencrypt.c +++ b/trunk/fs/cifs/cifsencrypt.c @@ -277,8 +277,7 @@ void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key) return; memset(password_with_pad, 0, CIFS_ENCPWD_SIZE); - if(ses->password) - strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE); + strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE); if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0) if(extended_security & CIFSSEC_MAY_PLNTXT) { diff --git a/trunk/fs/cifs/cifsfs.c b/trunk/fs/cifs/cifsfs.c index c3ef1c0d0e68..c28ede599946 100644 --- a/trunk/fs/cifs/cifsfs.c +++ b/trunk/fs/cifs/cifsfs.c @@ -189,6 +189,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_files = 0; /* undefined */ buf->f_ffree = 0; /* unlimited */ +#ifdef CONFIG_CIFS_EXPERIMENTAL /* BB we could add a second check for a QFS Unix capability bit */ /* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */ if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS & @@ -198,6 +199,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) /* Only need to call the old QFSInfo if failed on newer one */ if(rc) +#endif /* CIFS_EXPERIMENTAL */ rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* Old Windows servers do not support level 103, retry with level @@ -400,6 +402,7 @@ static struct quotactl_ops cifs_quotactl_ops = { }; #endif +#ifdef CONFIG_CIFS_EXPERIMENTAL static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags) { struct cifs_sb_info *cifs_sb; @@ -419,7 +422,7 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags) tcon->tidStatus = CifsExiting; up(&tcon->tconSem); - /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */ + /* cancel_brl_requests(tcon); */ /* cancel_notify_requests(tcon); */ if(tcon->ses && tcon->ses->server) { @@ -435,6 +438,7 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags) return; } +#endif static int cifs_remount(struct super_block *sb, int *flags, char *data) { @@ -453,7 +457,9 @@ struct super_operations cifs_super_ops = { unless later we add lazy close of inodes or unless the kernel forgets to call us with the same number of releases (closes) as opens */ .show_options = cifs_show_options, +#ifdef CONFIG_CIFS_EXPERIMENTAL .umount_begin = cifs_umount_begin, +#endif .remount_fs = cifs_remount, }; diff --git a/trunk/fs/cifs/cifsfs.h b/trunk/fs/cifs/cifsfs.h index bea875d9a46a..8f75c6f24701 100644 --- a/trunk/fs/cifs/cifsfs.h +++ b/trunk/fs/cifs/cifsfs.h @@ -100,5 +100,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg); -#define CIFS_VERSION "1.46" +#define CIFS_VERSION "1.44" #endif /* _CIFSFS_H */ diff --git a/trunk/fs/cifs/cifsglob.h b/trunk/fs/cifs/cifsglob.h index b24006c47df1..6d7cf5f3bc0b 100644 --- a/trunk/fs/cifs/cifsglob.h +++ b/trunk/fs/cifs/cifsglob.h @@ -3,7 +3,6 @@ * * Copyright (C) International Business Machines Corp., 2002,2006 * Author(s): Steve French (sfrench@us.ibm.com) - * Jeremy Allison (jra@samba.org) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published @@ -159,8 +158,7 @@ struct TCP_Server_Info { /* 16th byte of RFC1001 workstation name is always null */ char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL]; __u32 sequence_number; /* needed for CIFS PDU signature */ - char mac_signing_key[CIFS_SESS_KEY_SIZE + 16]; - unsigned long lstrp; /* when we got last response from this server */ + char mac_signing_key[CIFS_SESS_KEY_SIZE + 16]; }; /* @@ -268,14 +266,14 @@ struct cifsTconInfo { }; /* - * This info hangs off the cifsFileInfo structure, pointed to by llist. - * This is used to track byte stream locks on the file + * This info hangs off the cifsFileInfo structure. This is used to track + * byte stream locks on the file */ struct cifsLockInfo { - struct list_head llist; /* pointer to next cifsLockInfo */ - __u64 offset; - __u64 length; - __u8 type; + struct cifsLockInfo *next; + int start; + int length; + int type; }; /* @@ -306,8 +304,6 @@ struct cifsFileInfo { /* lock scope id (0 if none) */ struct file * pfile; /* needed for writepage */ struct inode * pInode; /* needed for oplock break */ - struct semaphore lock_sem; - struct list_head llist; /* list of byte range locks we have. */ unsigned closePend:1; /* file is marked to close */ unsigned invalidHandle:1; /* file closed via session abend */ atomic_t wrtPending; /* handle in use - defer close */ diff --git a/trunk/fs/cifs/cifspdu.h b/trunk/fs/cifs/cifspdu.h index 81df2bf8e75a..86239023545b 100644 --- a/trunk/fs/cifs/cifspdu.h +++ b/trunk/fs/cifs/cifspdu.h @@ -1344,7 +1344,6 @@ struct smb_t2_rsp { #define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */ #define SMB_QUERY_POSIX_PERMISSION 0x207 #define SMB_QUERY_POSIX_LOCK 0x208 -/* #define SMB_POSIX_OPEN 0x209 */ #define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee #define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 #define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ @@ -1364,7 +1363,6 @@ struct smb_t2_rsp { #define SMB_SET_XATTR 0x205 #define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */ #define SMB_SET_POSIX_LOCK 0x208 -#define SMB_POSIX_OPEN 0x209 #define SMB_SET_FILE_BASIC_INFO2 0x3ec #define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ #define SMB_FILE_ALL_INFO2 0x3fa diff --git a/trunk/fs/cifs/cifsproto.h b/trunk/fs/cifs/cifsproto.h index b35c55c3c8bb..a5ddc62d6fe6 100644 --- a/trunk/fs/cifs/cifsproto.h +++ b/trunk/fs/cifs/cifsproto.h @@ -50,10 +50,6 @@ extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *, extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *, struct kvec *, int /* nvec to send */, int * /* type of buf returned */ , const int long_op); -extern int SendReceiveBlockingLock(const unsigned int /* xid */ , struct cifsTconInfo *, - struct smb_hdr * /* input */ , - struct smb_hdr * /* out */ , - int * /* bytes returned */); extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid); extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length); extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); diff --git a/trunk/fs/cifs/cifssmb.c b/trunk/fs/cifs/cifssmb.c index 075d8fb3d376..19678c575dfc 100644 --- a/trunk/fs/cifs/cifssmb.c +++ b/trunk/fs/cifs/cifssmb.c @@ -477,7 +477,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) /* BB get server time for time conversions and add code to use it and timezone since this is not UTC */ - if (rsp->EncryptionKeyLength == cpu_to_le16(CIFS_CRYPTO_KEY_SIZE)) { + if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) { memcpy(server->cryptKey, rsp->EncryptionKey, CIFS_CRYPTO_KEY_SIZE); } else if (server->secMode & SECMODE_PW_ENCRYPT) { @@ -1460,13 +1460,8 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, pSMB->hdr.smb_buf_length += count; pSMB->ByteCount = cpu_to_le16(count); - if (waitFlag) { - rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned); - } else { - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, (struct smb_hdr *) pSMBr, &bytes_returned, timeout); - } cifs_stats_inc(&tcon->num_locks); if (rc) { cFYI(1, ("Send error in Lock = %d", rc)); @@ -1489,7 +1484,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, char *data_offset; struct cifs_posix_lock *parm_data; int rc = 0; - int timeout = 0; int bytes_returned = 0; __u16 params, param_offset, offset, byte_count, count; @@ -1509,6 +1503,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; + pSMB->Timeout = 0; pSMB->Reserved2 = 0; param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; offset = param_offset + params; @@ -1534,13 +1529,8 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, (((char *) &pSMB->hdr.Protocol) + offset); parm_data->lock_type = cpu_to_le16(lock_type); - if(waitFlag) { - timeout = 3; /* blocking operation, no timeout */ + if(waitFlag) parm_data->lock_flags = cpu_to_le16(1); - pSMB->Timeout = cpu_to_le32(-1); - } else - pSMB->Timeout = 0; - parm_data->pid = cpu_to_le32(current->tgid); parm_data->start = cpu_to_le64(pLockData->fl_start); parm_data->length = cpu_to_le64(len); /* normalize negative numbers */ @@ -1551,14 +1541,8 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon, pSMB->Reserved4 = 0; pSMB->hdr.smb_buf_length += byte_count; pSMB->ByteCount = cpu_to_le16(byte_count); - if (waitFlag) { - rc = SendReceiveBlockingLock(xid, tcon, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned); - } else { - rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, - (struct smb_hdr *) pSMBr, &bytes_returned, timeout); - } - + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc) { cFYI(1, ("Send error in Posix Lock = %d", rc)); } else if (get_flag) { diff --git a/trunk/fs/cifs/connect.c b/trunk/fs/cifs/connect.c index 0e9ba0b9d71e..876eb9ef85fe 100644 --- a/trunk/fs/cifs/connect.c +++ b/trunk/fs/cifs/connect.c @@ -89,7 +89,6 @@ struct smb_vol { unsigned int wsize; unsigned int sockopt; unsigned short int port; - char * prepath; }; static int ipv4_connect(struct sockaddr_in *psin_server, @@ -183,7 +182,6 @@ cifs_reconnect(struct TCP_Server_Info *server) while ((server->tcpStatus != CifsExiting) && (server->tcpStatus != CifsGood)) { - try_to_freeze(); if(server->protocolType == IPV6) { rc = ipv6_connect(&server->addr.sockAddr6,&server->ssocket); } else { @@ -614,10 +612,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) #ifdef CONFIG_CIFS_STATS2 mid_entry->when_received = jiffies; #endif - /* so we do not time out requests to server - which is still responding (since server could - be busy but not dead) */ - server->lstrp = jiffies; break; } } @@ -994,28 +988,6 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) printk(KERN_WARNING "CIFS: domain name too long\n"); return 1; } - } else if (strnicmp(data, "prefixpath", 10) == 0) { - if (!value || !*value) { - printk(KERN_WARNING - "CIFS: invalid path prefix\n"); - return 1; /* needs_arg; */ - } - if ((temp_len = strnlen(value, 1024)) < 1024) { - if(value[0] != '/') - temp_len++; /* missing leading slash */ - vol->prepath = kmalloc(temp_len+1,GFP_KERNEL); - if(vol->prepath == NULL) - return 1; - if(value[0] != '/') { - vol->prepath[0] = '/'; - strcpy(vol->prepath+1,value); - } else - strcpy(vol->prepath,value); - cFYI(1,("prefix path %s",vol->prepath)); - } else { - printk(KERN_WARNING "CIFS: prefix too long\n"); - return 1; - } } else if (strnicmp(data, "iocharset", 9) == 0) { if (!value || !*value) { printk(KERN_WARNING "CIFS: invalid iocharset specified\n"); @@ -1294,35 +1266,33 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName) read_lock(&GlobalSMBSeslock); list_for_each(tmp, &GlobalTreeConnectionList) { - cFYI(1, ("Next tcon")); + cFYI(1, ("Next tcon - ")); tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); if (tcon->ses) { if (tcon->ses->server) { cFYI(1, - ("old ip addr: %x == new ip %x ?", + (" old ip addr: %x == new ip %x ?", tcon->ses->server->addr.sockAddr.sin_addr. s_addr, new_target_ip_addr)); if (tcon->ses->server->addr.sockAddr.sin_addr. s_addr == new_target_ip_addr) { - /* BB lock tcon, server and tcp session and increment use count here? */ + /* BB lock tcon and server and tcp session and increment use count here? */ /* found a match on the TCP session */ /* BB check if reconnection needed */ - cFYI(1,("IP match, old UNC: %s new: %s", + cFYI(1,("Matched ip, old UNC: %s == new: %s ?", tcon->treeName, uncName)); if (strncmp (tcon->treeName, uncName, MAX_TREE_SIZE) == 0) { cFYI(1, - ("and old usr: %s new: %s", + ("Matched UNC, old user: %s == new: %s ?", tcon->treeName, uncName)); if (strncmp (tcon->ses->userName, userName, MAX_USERNAME_SIZE) == 0) { read_unlock(&GlobalSMBSeslock); - /* matched smb session - (user name */ - return tcon; + return tcon;/* also matched user (smb session)*/ } } } @@ -1628,7 +1598,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if (cifs_parse_mount_options(mount_data, devname, &volume_info)) { kfree(volume_info.UNC); kfree(volume_info.password); - kfree(volume_info.prepath); FreeXid(xid); return -EINVAL; } @@ -1643,7 +1612,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, locations such as env variables and files on disk */ kfree(volume_info.UNC); kfree(volume_info.password); - kfree(volume_info.prepath); FreeXid(xid); return -EINVAL; } @@ -1664,7 +1632,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, /* we failed translating address */ kfree(volume_info.UNC); kfree(volume_info.password); - kfree(volume_info.prepath); FreeXid(xid); return -EINVAL; } @@ -1677,7 +1644,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cERROR(1,("Connecting to DFS root not implemented yet")); kfree(volume_info.UNC); kfree(volume_info.password); - kfree(volume_info.prepath); FreeXid(xid); return -EINVAL; } else /* which servers DFS root would we conect to */ { @@ -1685,7 +1651,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ("CIFS mount error: No UNC path (e.g. -o unc=//192.168.1.100/public) specified")); kfree(volume_info.UNC); kfree(volume_info.password); - kfree(volume_info.prepath); FreeXid(xid); return -EINVAL; } @@ -1700,7 +1665,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cERROR(1,("CIFS mount error: iocharset %s not found",volume_info.iocharset)); kfree(volume_info.UNC); kfree(volume_info.password); - kfree(volume_info.prepath); FreeXid(xid); return -ELIBACC; } @@ -1717,7 +1681,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, else { kfree(volume_info.UNC); kfree(volume_info.password); - kfree(volume_info.prepath); FreeXid(xid); return -EINVAL; } @@ -1740,7 +1703,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, sock_release(csocket); kfree(volume_info.UNC); kfree(volume_info.password); - kfree(volume_info.prepath); FreeXid(xid); return rc; } @@ -1751,7 +1713,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, sock_release(csocket); kfree(volume_info.UNC); kfree(volume_info.password); - kfree(volume_info.prepath); FreeXid(xid); return rc; } else { @@ -1776,7 +1737,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, sock_release(csocket); kfree(volume_info.UNC); kfree(volume_info.password); - kfree(volume_info.prepath); FreeXid(xid); return rc; } @@ -1864,14 +1824,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, /* Windows ME may prefer this */ cFYI(1,("readsize set to minimum 2048")); } - /* calculate prepath */ - cifs_sb->prepath = volume_info.prepath; - if(cifs_sb->prepath) { - cifs_sb->prepathlen = strlen(cifs_sb->prepath); - cifs_sb->prepath[0] = CIFS_DIR_SEP(cifs_sb); - volume_info.prepath = NULL; - } else - cifs_sb->prepathlen = 0; cifs_sb->mnt_uid = volume_info.linux_uid; cifs_sb->mnt_gid = volume_info.linux_gid; cifs_sb->mnt_file_mode = volume_info.file_mode; @@ -2017,18 +1969,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, } cFYI(1,("Negotiate caps 0x%x",(int)cap)); -#ifdef CONFIG_CIFS_DEBUG2 - if(cap & CIFS_UNIX_FCNTL_CAP) - cFYI(1,("FCNTL cap")); - if(cap & CIFS_UNIX_EXTATTR_CAP) - cFYI(1,("EXTATTR cap")); - if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) - cFYI(1,("POSIX path cap")); - if(cap & CIFS_UNIX_XATTR_CAP) - cFYI(1,("XATTR cap")); - if(cap & CIFS_UNIX_POSIX_ACL_CAP) - cFYI(1,("POSIX ACL cap")); -#endif /* CIFS_DEBUG2 */ + if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) { cFYI(1,("setting capabilities failed")); } @@ -2049,7 +1990,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, the password ptr is put in the new session structure (in which case the password will be freed at unmount time) */ kfree(volume_info.UNC); - kfree(volume_info.prepath); FreeXid(xid); return rc; } @@ -3237,7 +3177,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) int xid; struct cifsSesInfo *ses = NULL; struct task_struct *cifsd_task; - char * tmp; xid = GetXid(); @@ -3271,10 +3210,6 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) } cifs_sb->tcon = NULL; - tmp = cifs_sb->prepath; - cifs_sb->prepathlen = 0; - cifs_sb->prepath = NULL; - kfree(tmp); if (ses) schedule_timeout_interruptible(msecs_to_jiffies(500)); if (ses) diff --git a/trunk/fs/cifs/dir.c b/trunk/fs/cifs/dir.c index 66b825ade3e1..ba4cbe9b0684 100644 --- a/trunk/fs/cifs/dir.c +++ b/trunk/fs/cifs/dir.c @@ -46,8 +46,7 @@ char * build_path_from_dentry(struct dentry *direntry) { struct dentry *temp; - int namelen; - int pplen; + int namelen = 0; char *full_path; char dirsep; @@ -57,9 +56,7 @@ build_path_from_dentry(struct dentry *direntry) when the server crashed */ dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); - pplen = CIFS_SB(direntry->d_sb)->prepathlen; cifs_bp_rename_retry: - namelen = pplen; for (temp = direntry; !IS_ROOT(temp);) { namelen += (1 + temp->d_name.len); temp = temp->d_parent; @@ -73,6 +70,7 @@ build_path_from_dentry(struct dentry *direntry) if(full_path == NULL) return full_path; full_path[namelen] = 0; /* trailing null */ + for (temp = direntry; !IS_ROOT(temp);) { namelen -= 1 + temp->d_name.len; if (namelen < 0) { @@ -81,7 +79,7 @@ build_path_from_dentry(struct dentry *direntry) full_path[namelen] = dirsep; strncpy(full_path + namelen + 1, temp->d_name.name, temp->d_name.len); - cFYI(0, ("name: %s", full_path + namelen)); + cFYI(0, (" name: %s ", full_path + namelen)); } temp = temp->d_parent; if(temp == NULL) { @@ -90,23 +88,18 @@ build_path_from_dentry(struct dentry *direntry) return NULL; } } - if (namelen != pplen) { + if (namelen != 0) { cERROR(1, - ("did not end path lookup where expected namelen is %d", + ("We did not end path lookup where we expected namelen is %d", namelen)); - /* presumably this is only possible if racing with a rename + /* presumably this is only possible if we were racing with a rename of one of the parent directories (we can not lock the dentries above us to prevent this, but retrying should be harmless) */ kfree(full_path); + namelen = 0; goto cifs_bp_rename_retry; } - /* DIR_SEP already set for byte 0 / vs \ but not for - subsequent slashes in prepath which currently must - be entered the right way - not sure if there is an alternative - since the '\' is a valid posix character so we can not switch - those safely to '/' if any are found in the middle of the prepath */ - /* BB test paths to Windows with '/' in the midst of prepath */ - strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen); + return full_path; } @@ -274,10 +267,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, pCifsFile->invalidHandle = FALSE; pCifsFile->closePend = FALSE; init_MUTEX(&pCifsFile->fh_sem); - init_MUTEX(&pCifsFile->lock_sem); - INIT_LIST_HEAD(&pCifsFile->llist); - atomic_set(&pCifsFile->wrtPending,0); - /* set the following in open now pCifsFile->pfile = file; */ write_lock(&GlobalSMBSeslock); diff --git a/trunk/fs/cifs/file.c b/trunk/fs/cifs/file.c index ddb012a68023..944d2b9e092d 100644 --- a/trunk/fs/cifs/file.c +++ b/trunk/fs/cifs/file.c @@ -5,7 +5,6 @@ * * Copyright (C) International Business Machines Corp., 2002,2003 * Author(s): Steve French (sfrench@us.ibm.com) - * Jeremy Allison (jra@samba.org) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published @@ -48,8 +47,6 @@ static inline struct cifsFileInfo *cifs_init_private( private_data->netfid = netfid; private_data->pid = current->tgid; init_MUTEX(&private_data->fh_sem); - init_MUTEX(&private_data->lock_sem); - INIT_LIST_HEAD(&private_data->llist); private_data->pfile = file; /* needed for writepage */ private_data->pInode = inode; private_data->invalidHandle = FALSE; @@ -476,8 +473,6 @@ int cifs_close(struct inode *inode, struct file *file) cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; if (pSMBFile) { - struct cifsLockInfo *li, *tmp; - pSMBFile->closePend = TRUE; if (pTcon) { /* no sense reconnecting to close a file that is @@ -501,16 +496,6 @@ int cifs_close(struct inode *inode, struct file *file) pSMBFile->netfid); } } - - /* Delete any outstanding lock records. - We'll lose them when the file is closed anyway. */ - down(&pSMBFile->lock_sem); - list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) { - list_del(&li->llist); - kfree(li); - } - up(&pSMBFile->lock_sem); - write_lock(&GlobalSMBSeslock); list_del(&pSMBFile->flist); list_del(&pSMBFile->tlist); @@ -585,21 +570,6 @@ int cifs_closedir(struct inode *inode, struct file *file) return rc; } -static int store_file_lock(struct cifsFileInfo *fid, __u64 len, - __u64 offset, __u8 lockType) -{ - struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); - if (li == NULL) - return -ENOMEM; - li->offset = offset; - li->length = len; - li->type = lockType; - down(&fid->lock_sem); - list_add(&li->llist, &fid->llist); - up(&fid->lock_sem); - return 0; -} - int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) { int rc, xid; @@ -611,7 +581,6 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) struct cifsTconInfo *pTcon; __u16 netfid; __u8 lockType = LOCKING_ANDX_LARGE_FILES; - int posix_locking; length = 1 + pfLock->fl_end - pfLock->fl_start; rc = -EACCES; @@ -670,14 +639,15 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) } netfid = ((struct cifsFileInfo *)file->private_data)->netfid; - posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && - (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability)); /* BB add code here to normalize offset and length to account for negative length which we can not accept over the wire */ if (IS_GETLK(cmd)) { - if(posix_locking) { + if(experimEnabled && + (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && + (CIFS_UNIX_FCNTL_CAP & + le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { int posix_lock_type; if(lockType & LOCKING_ANDX_SHARED_LOCK) posix_lock_type = CIFS_RDLCK; @@ -713,15 +683,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) FreeXid(xid); return rc; } - - if (!numLock && !numUnlock) { - /* if no lock or unlock then nothing - to do since we do not know what it is */ - FreeXid(xid); - return -EOPNOTSUPP; - } - - if (posix_locking) { + if (experimEnabled && + (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && + (CIFS_UNIX_FCNTL_CAP & + le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { int posix_lock_type; if(lockType & LOCKING_ANDX_SHARED_LOCK) posix_lock_type = CIFS_RDLCK; @@ -730,47 +695,18 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) if(numUnlock == 1) posix_lock_type = CIFS_UNLCK; - + else if(numLock == 0) { + /* if no lock or unlock then nothing + to do since we do not know what it is */ + FreeXid(xid); + return -EOPNOTSUPP; + } rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, length, pfLock, posix_lock_type, wait_flag); - } else { - struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data; - - if (numLock) { - rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, - 0, numLock, lockType, wait_flag); - - if (rc == 0) { - /* For Windows locks we must store them. */ - rc = store_file_lock(fid, length, - pfLock->fl_start, lockType); - } - } else if (numUnlock) { - /* For each stored lock that this unlock overlaps - completely, unlock it. */ - int stored_rc = 0; - struct cifsLockInfo *li, *tmp; - - rc = 0; - down(&fid->lock_sem); - list_for_each_entry_safe(li, tmp, &fid->llist, llist) { - if (pfLock->fl_start <= li->offset && - length >= li->length) { - stored_rc = CIFSSMBLock(xid, pTcon, netfid, - li->length, li->offset, - 1, 0, li->type, FALSE); - if (stored_rc) - rc = stored_rc; - - list_del(&li->llist); - kfree(li); - } - } - up(&fid->lock_sem); - } - } - + } else + rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, + numUnlock, numLock, lockType, wait_flag); if (pfLock->fl_flags & FL_POSIX) posix_lock_file_wait(file, pfLock); FreeXid(xid); diff --git a/trunk/fs/cifs/netmisc.c b/trunk/fs/cifs/netmisc.c index ce87550e918f..b66eff5dc624 100644 --- a/trunk/fs/cifs/netmisc.c +++ b/trunk/fs/cifs/netmisc.c @@ -72,7 +72,6 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = { {ERRinvlevel,-EOPNOTSUPP}, {ERRdirnotempty, -ENOTEMPTY}, {ERRnotlocked, -ENOLCK}, - {ERRcancelviolation, -ENOLCK}, {ERRalreadyexists, -EEXIST}, {ERRmoredata, -EOVERFLOW}, {ERReasnotsupported,-EOPNOTSUPP}, diff --git a/trunk/fs/cifs/readdir.c b/trunk/fs/cifs/readdir.c index 9aeb58a7d369..03bbcb377913 100644 --- a/trunk/fs/cifs/readdir.c +++ b/trunk/fs/cifs/readdir.c @@ -82,6 +82,7 @@ static int construct_dentry(struct qstr *qstring, struct file *file, if(*ptmp_inode == NULL) return rc; rc = 1; + d_instantiate(tmp_dentry, *ptmp_inode); } } else { tmp_dentry = d_alloc(file->f_dentry, qstring); @@ -98,7 +99,9 @@ static int construct_dentry(struct qstr *qstring, struct file *file, tmp_dentry->d_op = &cifs_dentry_ops; if(*ptmp_inode == NULL) return rc; - rc = 2; + rc = 1; + d_instantiate(tmp_dentry, *ptmp_inode); + d_rehash(tmp_dentry); } tmp_dentry->d_time = jiffies; @@ -553,7 +556,7 @@ static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile) FIND_FILE_STANDARD_INFO * pFindData = (FIND_FILE_STANDARD_INFO *)current_entry; filename = &pFindData->FileName[0]; - len = pFindData->FileNameLength; + len = le32_to_cpu(pFindData->FileNameLength); } else { cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level)); } @@ -867,12 +870,6 @@ static int cifs_filldir(char *pfindEntry, struct file *file, pfindEntry, &obj_type, rc); else fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc); - - if(rc) /* new inode - needs to be tied to dentry */ { - d_instantiate(tmp_dentry, tmp_inode); - if(rc == 2) - d_rehash(tmp_dentry); - } rc = filldir(direntry,qstring.name,qstring.len,file->f_pos, diff --git a/trunk/fs/cifs/sess.c b/trunk/fs/cifs/sess.c index d1705ab8136e..7202d534ef0b 100644 --- a/trunk/fs/cifs/sess.c +++ b/trunk/fs/cifs/sess.c @@ -372,7 +372,7 @@ CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, /* no capabilities flags in old lanman negotiation */ - pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); + pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE; /* BB calculate hash with password */ /* and copy into bcc */ diff --git a/trunk/fs/cifs/smberr.h b/trunk/fs/cifs/smberr.h index 212c3c296409..cd41c67ff8d3 100644 --- a/trunk/fs/cifs/smberr.h +++ b/trunk/fs/cifs/smberr.h @@ -95,7 +95,6 @@ #define ERRinvlevel 124 #define ERRdirnotempty 145 #define ERRnotlocked 158 -#define ERRcancelviolation 173 #define ERRalreadyexists 183 #define ERRbadpipe 230 #define ERRpipebusy 231 diff --git a/trunk/fs/cifs/transport.c b/trunk/fs/cifs/transport.c index 48d47b46b1fb..17ba329e2b3d 100644 --- a/trunk/fs/cifs/transport.c +++ b/trunk/fs/cifs/transport.c @@ -3,8 +3,7 @@ * * Copyright (C) International Business Machines Corp., 2002,2005 * Author(s): Steve French (sfrench@us.ibm.com) - * Jeremy Allison (jra@samba.org) 2006. - * + * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or @@ -37,7 +36,7 @@ extern mempool_t *cifs_mid_poolp; extern kmem_cache_t *cifs_oplock_cachep; static struct mid_q_entry * -AllocMidQEntry(const struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) +AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) { struct mid_q_entry *temp; @@ -204,10 +203,6 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, rc = 0; } - /* Don't want to modify the buffer as a - side effect of this call. */ - smb_buffer->smb_buf_length = smb_buf_length; - return rc; } @@ -222,7 +217,6 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, unsigned int len = iov[0].iov_len; unsigned int total_len; int first_vec = 0; - unsigned int smb_buf_length = smb_buffer->smb_buf_length; if(ssocket == NULL) return -ENOTSOCK; /* BB eventually add reconnect code here */ @@ -299,15 +293,36 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, } else rc = 0; - /* Don't want to modify the buffer as a - side effect of this call. */ - smb_buffer->smb_buf_length = smb_buf_length; - return rc; } -static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) +int +SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, + struct kvec *iov, int n_vec, int * pRespBufType /* ret */, + const int long_op) { + int rc = 0; + unsigned int receive_len; + unsigned long timeout; + struct mid_q_entry *midQ; + struct smb_hdr *in_buf = iov[0].iov_base; + + *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ + + if ((ses == NULL) || (ses->server == NULL)) { + cifs_small_buf_release(in_buf); + cERROR(1,("Null session")); + return -EIO; + } + + if(ses->server->tcpStatus == CifsExiting) { + cifs_small_buf_release(in_buf); + return -ENOENT; + } + + /* Ensure that we do not send more than 50 overlapping requests + to the same server. We may make this configurable later or + use ses->maxReq */ if(long_op == -1) { /* oplock breaks must not be held up */ atomic_inc(&ses->server->inFlight); @@ -330,140 +345,53 @@ static int wait_for_free_request(struct cifsSesInfo *ses, const int long_op) } else { if(ses->server->tcpStatus == CifsExiting) { spin_unlock(&GlobalMid_Lock); + cifs_small_buf_release(in_buf); return -ENOENT; } - /* can not count locking commands against total since - they are allowed to block on server */ + /* can not count locking commands against total since + they are allowed to block on server */ + if(long_op < 3) { /* update # of requests on the wire to server */ - if (long_op < 3) atomic_inc(&ses->server->inFlight); + } spin_unlock(&GlobalMid_Lock); break; } } } - return 0; -} + /* make sure that we sign in the same order that we send on this socket + and avoid races inside tcp sendmsg code that could cause corruption + of smb data */ + + down(&ses->server->tcpSem); -static int allocate_mid(struct cifsSesInfo *ses, struct smb_hdr *in_buf, - struct mid_q_entry **ppmidQ) -{ if (ses->server->tcpStatus == CifsExiting) { - return -ENOENT; + rc = -ENOENT; + goto out_unlock2; } else if (ses->server->tcpStatus == CifsNeedReconnect) { cFYI(1,("tcp session dead - return to caller to retry")); - return -EAGAIN; + rc = -EAGAIN; + goto out_unlock2; } else if (ses->status != CifsGood) { /* check if SMB session is bad because we are setting it up */ if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && (in_buf->Command != SMB_COM_NEGOTIATE)) { - return -EAGAIN; + rc = -EAGAIN; + goto out_unlock2; } /* else ok - we are setting up session */ } - *ppmidQ = AllocMidQEntry(in_buf, ses); - if (*ppmidQ == NULL) { - return -ENOMEM; - } - return 0; -} - -static int wait_for_response(struct cifsSesInfo *ses, - struct mid_q_entry *midQ, - unsigned long timeout, - unsigned long time_to_wait) -{ - unsigned long curr_timeout; - - for (;;) { - curr_timeout = timeout + jiffies; - wait_event(ses->server->response_q, - (!(midQ->midState == MID_REQUEST_SUBMITTED)) || - time_after(jiffies, curr_timeout) || - ((ses->server->tcpStatus != CifsGood) && - (ses->server->tcpStatus != CifsNew))); - - if (time_after(jiffies, curr_timeout) && - (midQ->midState == MID_REQUEST_SUBMITTED) && - ((ses->server->tcpStatus == CifsGood) || - (ses->server->tcpStatus == CifsNew))) { - - unsigned long lrt; - - /* We timed out. Is the server still - sending replies ? */ - spin_lock(&GlobalMid_Lock); - lrt = ses->server->lstrp; - spin_unlock(&GlobalMid_Lock); - - /* Calculate time_to_wait past last receive time. - Although we prefer not to time out if the - server is still responding - we will time - out if the server takes more than 15 (or 45 - or 180) seconds to respond to this request - and has not responded to any request from - other threads on the client within 10 seconds */ - lrt += time_to_wait; - if (time_after(jiffies, lrt)) { - /* No replies for time_to_wait. */ - cERROR(1,("server not responding")); - return -1; - } - } else { - return 0; - } - } -} - -int -SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, - struct kvec *iov, int n_vec, int * pRespBufType /* ret */, - const int long_op) -{ - int rc = 0; - unsigned int receive_len; - unsigned long timeout; - struct mid_q_entry *midQ; - struct smb_hdr *in_buf = iov[0].iov_base; - - *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ - - if ((ses == NULL) || (ses->server == NULL)) { - cifs_small_buf_release(in_buf); - cERROR(1,("Null session")); - return -EIO; - } - - if(ses->server->tcpStatus == CifsExiting) { - cifs_small_buf_release(in_buf); - return -ENOENT; - } - - /* Ensure that we do not send more than 50 overlapping requests - to the same server. We may make this configurable later or - use ses->maxReq */ - - rc = wait_for_free_request(ses, long_op); - if (rc) { - cifs_small_buf_release(in_buf); - return rc; - } - - /* make sure that we sign in the same order that we send on this socket - and avoid races inside tcp sendmsg code that could cause corruption - of smb data */ - - down(&ses->server->tcpSem); - - rc = allocate_mid(ses, in_buf, &midQ); - if (rc) { + midQ = AllocMidQEntry(in_buf, ses); + if (midQ == NULL) { up(&ses->server->tcpSem); cifs_small_buf_release(in_buf); - /* Update # of requests on wire to server */ - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); - return rc; + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } + return -ENOMEM; } rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); @@ -478,23 +406,32 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, atomic_dec(&ses->server->inSend); midQ->when_sent = jiffies; #endif - - up(&ses->server->tcpSem); - cifs_small_buf_release(in_buf); - - if(rc < 0) - goto out; + if(rc < 0) { + DeleteMidQEntry(midQ); + up(&ses->server->tcpSem); + cifs_small_buf_release(in_buf); + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } + return rc; + } else { + up(&ses->server->tcpSem); + cifs_small_buf_release(in_buf); + } if (long_op == -1) - goto out; + goto cifs_no_response_exit2; else if (long_op == 2) /* writes past end of file can take loong time */ timeout = 180 * HZ; else if (long_op == 1) timeout = 45 * HZ; /* should be greater than servers oplock break timeout (about 43 seconds) */ - else + else if (long_op > 2) { + timeout = MAX_SCHEDULE_TIMEOUT; + } else timeout = 15 * HZ; - /* wait for 15 seconds or until woken up due to response arriving or due to last connection to this server being unmounted */ if (signal_pending(current)) { @@ -504,7 +441,19 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, } /* No user interrupts in wait - wreaks havoc with performance */ - wait_for_response(ses, midQ, timeout, 10 * HZ); + if(timeout != MAX_SCHEDULE_TIMEOUT) { + timeout += jiffies; + wait_event(ses->server->response_q, + (!(midQ->midState & MID_REQUEST_SUBMITTED)) || + time_after(jiffies, timeout) || + ((ses->server->tcpStatus != CifsGood) && + (ses->server->tcpStatus != CifsNew))); + } else { + wait_event(ses->server->response_q, + (!(midQ->midState & MID_REQUEST_SUBMITTED)) || + ((ses->server->tcpStatus != CifsGood) && + (ses->server->tcpStatus != CifsNew))); + } spin_lock(&GlobalMid_Lock); if (midQ->resp_buf) { @@ -532,9 +481,11 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, } spin_unlock(&GlobalMid_Lock); DeleteMidQEntry(midQ); - /* Update # of requests on wire to server */ - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } return rc; } @@ -585,12 +536,24 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, cFYI(1,("Bad MID state?")); } } +cifs_no_response_exit2: + DeleteMidQEntry(midQ); + + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } -out: + return rc; - DeleteMidQEntry(midQ); - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); +out_unlock2: + up(&ses->server->tcpSem); + cifs_small_buf_release(in_buf); + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } return rc; } @@ -620,34 +583,85 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, /* Ensure that we do not send more than 50 overlapping requests to the same server. We may make this configurable later or use ses->maxReq */ + if(long_op == -1) { + /* oplock breaks must not be held up */ + atomic_inc(&ses->server->inFlight); + } else { + spin_lock(&GlobalMid_Lock); + while(1) { + if(atomic_read(&ses->server->inFlight) >= + cifs_max_pending){ + spin_unlock(&GlobalMid_Lock); +#ifdef CONFIG_CIFS_STATS2 + atomic_inc(&ses->server->num_waiters); +#endif + wait_event(ses->server->request_q, + atomic_read(&ses->server->inFlight) + < cifs_max_pending); +#ifdef CONFIG_CIFS_STATS2 + atomic_dec(&ses->server->num_waiters); +#endif + spin_lock(&GlobalMid_Lock); + } else { + if(ses->server->tcpStatus == CifsExiting) { + spin_unlock(&GlobalMid_Lock); + return -ENOENT; + } - rc = wait_for_free_request(ses, long_op); - if (rc) - return rc; - + /* can not count locking commands against total since + they are allowed to block on server */ + + if(long_op < 3) { + /* update # of requests on the wire to server */ + atomic_inc(&ses->server->inFlight); + } + spin_unlock(&GlobalMid_Lock); + break; + } + } + } /* make sure that we sign in the same order that we send on this socket and avoid races inside tcp sendmsg code that could cause corruption of smb data */ down(&ses->server->tcpSem); - rc = allocate_mid(ses, in_buf, &midQ); - if (rc) { + if (ses->server->tcpStatus == CifsExiting) { + rc = -ENOENT; + goto out_unlock; + } else if (ses->server->tcpStatus == CifsNeedReconnect) { + cFYI(1,("tcp session dead - return to caller to retry")); + rc = -EAGAIN; + goto out_unlock; + } else if (ses->status != CifsGood) { + /* check if SMB session is bad because we are setting it up */ + if((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && + (in_buf->Command != SMB_COM_NEGOTIATE)) { + rc = -EAGAIN; + goto out_unlock; + } /* else ok - we are setting up session */ + } + midQ = AllocMidQEntry(in_buf, ses); + if (midQ == NULL) { up(&ses->server->tcpSem); - /* Update # of requests on wire to server */ - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); - return rc; + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } + return -ENOMEM; } if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { + up(&ses->server->tcpSem); cERROR(1, ("Illegal length, greater than maximum frame, %d", in_buf->smb_buf_length)); DeleteMidQEntry(midQ); - up(&ses->server->tcpSem); - /* Update # of requests on wire to server */ - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } return -EIO; } @@ -663,19 +677,27 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, atomic_dec(&ses->server->inSend); midQ->when_sent = jiffies; #endif - up(&ses->server->tcpSem); - - if(rc < 0) - goto out; - + if(rc < 0) { + DeleteMidQEntry(midQ); + up(&ses->server->tcpSem); + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } + return rc; + } else + up(&ses->server->tcpSem); if (long_op == -1) - goto out; + goto cifs_no_response_exit; else if (long_op == 2) /* writes past end of file can take loong time */ timeout = 180 * HZ; else if (long_op == 1) timeout = 45 * HZ; /* should be greater than servers oplock break timeout (about 43 seconds) */ - else + else if (long_op > 2) { + timeout = MAX_SCHEDULE_TIMEOUT; + } else timeout = 15 * HZ; /* wait for 15 seconds or until woken up due to response arriving or due to last connection to this server being unmounted */ @@ -686,7 +708,19 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, } /* No user interrupts in wait - wreaks havoc with performance */ - wait_for_response(ses, midQ, timeout, 10 * HZ); + if(timeout != MAX_SCHEDULE_TIMEOUT) { + timeout += jiffies; + wait_event(ses->server->response_q, + (!(midQ->midState & MID_REQUEST_SUBMITTED)) || + time_after(jiffies, timeout) || + ((ses->server->tcpStatus != CifsGood) && + (ses->server->tcpStatus != CifsNew))); + } else { + wait_event(ses->server->response_q, + (!(midQ->midState & MID_REQUEST_SUBMITTED)) || + ((ses->server->tcpStatus != CifsGood) && + (ses->server->tcpStatus != CifsNew))); + } spin_lock(&GlobalMid_Lock); if (midQ->resp_buf) { @@ -714,9 +748,11 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, } spin_unlock(&GlobalMid_Lock); DeleteMidQEntry(midQ); - /* Update # of requests on wire to server */ - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); + } return rc; } @@ -763,253 +799,23 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, cERROR(1,("Bad MID state?")); } } - -out: - +cifs_no_response_exit: DeleteMidQEntry(midQ); - atomic_dec(&ses->server->inFlight); - wake_up(&ses->server->request_q); - - return rc; -} - -/* Send an NT_CANCEL SMB to cause the POSIX blocking lock to return. */ - -static int -send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf, - struct mid_q_entry *midQ) -{ - int rc = 0; - struct cifsSesInfo *ses = tcon->ses; - __u16 mid = in_buf->Mid; - - header_assemble(in_buf, SMB_COM_NT_CANCEL, tcon, 0); - in_buf->Mid = mid; - down(&ses->server->tcpSem); - rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); - if (rc) { - up(&ses->server->tcpSem); - return rc; - } - rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, - (struct sockaddr *) &(ses->server->addr.sockAddr)); - up(&ses->server->tcpSem); - return rc; -} - -/* We send a LOCKINGX_CANCEL_LOCK to cause the Windows - blocking lock to return. */ - -static int -send_lock_cancel(const unsigned int xid, struct cifsTconInfo *tcon, - struct smb_hdr *in_buf, - struct smb_hdr *out_buf) -{ - int bytes_returned; - struct cifsSesInfo *ses = tcon->ses; - LOCK_REQ *pSMB = (LOCK_REQ *)in_buf; - - /* We just modify the current in_buf to change - the type of lock from LOCKING_ANDX_SHARED_LOCK - or LOCKING_ANDX_EXCLUSIVE_LOCK to - LOCKING_ANDX_CANCEL_LOCK. */ - - pSMB->LockType = LOCKING_ANDX_CANCEL_LOCK|LOCKING_ANDX_LARGE_FILES; - pSMB->Timeout = 0; - pSMB->hdr.Mid = GetNextMid(ses->server); - - return SendReceive(xid, ses, in_buf, out_buf, - &bytes_returned, 0); -} -int -SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, - struct smb_hdr *in_buf, struct smb_hdr *out_buf, - int *pbytes_returned) -{ - int rc = 0; - int rstart = 0; - unsigned int receive_len; - struct mid_q_entry *midQ; - struct cifsSesInfo *ses; - - if (tcon == NULL || tcon->ses == NULL) { - cERROR(1,("Null smb session")); - return -EIO; - } - ses = tcon->ses; - - if(ses->server == NULL) { - cERROR(1,("Null tcp session")); - return -EIO; - } - - if(ses->server->tcpStatus == CifsExiting) - return -ENOENT; - - /* Ensure that we do not send more than 50 overlapping requests - to the same server. We may make this configurable later or - use ses->maxReq */ - - rc = wait_for_free_request(ses, 3); - if (rc) - return rc; - - /* make sure that we sign in the same order that we send on this socket - and avoid races inside tcp sendmsg code that could cause corruption - of smb data */ - - down(&ses->server->tcpSem); - - rc = allocate_mid(ses, in_buf, &midQ); - if (rc) { - up(&ses->server->tcpSem); - return rc; - } - - if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { - up(&ses->server->tcpSem); - cERROR(1, ("Illegal length, greater than maximum frame, %d", - in_buf->smb_buf_length)); - DeleteMidQEntry(midQ); - return -EIO; + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); } - rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); + return rc; - midQ->midState = MID_REQUEST_SUBMITTED; -#ifdef CONFIG_CIFS_STATS2 - atomic_inc(&ses->server->inSend); -#endif - rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, - (struct sockaddr *) &(ses->server->addr.sockAddr)); -#ifdef CONFIG_CIFS_STATS2 - atomic_dec(&ses->server->inSend); - midQ->when_sent = jiffies; -#endif +out_unlock: up(&ses->server->tcpSem); - - if(rc < 0) { - DeleteMidQEntry(midQ); - return rc; - } - - /* Wait for a reply - allow signals to interrupt. */ - rc = wait_event_interruptible(ses->server->response_q, - (!(midQ->midState == MID_REQUEST_SUBMITTED)) || - ((ses->server->tcpStatus != CifsGood) && - (ses->server->tcpStatus != CifsNew))); - - /* Were we interrupted by a signal ? */ - if ((rc == -ERESTARTSYS) && - (midQ->midState == MID_REQUEST_SUBMITTED) && - ((ses->server->tcpStatus == CifsGood) || - (ses->server->tcpStatus == CifsNew))) { - - if (in_buf->Command == SMB_COM_TRANSACTION2) { - /* POSIX lock. We send a NT_CANCEL SMB to cause the - blocking lock to return. */ - - rc = send_nt_cancel(tcon, in_buf, midQ); - if (rc) { - DeleteMidQEntry(midQ); - return rc; - } - } else { - /* Windows lock. We send a LOCKINGX_CANCEL_LOCK - to cause the blocking lock to return. */ - - rc = send_lock_cancel(xid, tcon, in_buf, out_buf); - - /* If we get -ENOLCK back the lock may have - already been removed. Don't exit in this case. */ - if (rc && rc != -ENOLCK) { - DeleteMidQEntry(midQ); - return rc; - } - } - - /* Wait 5 seconds for the response. */ - if (wait_for_response(ses, midQ, 5 * HZ, 5 * HZ)==0) { - /* We got the response - restart system call. */ - rstart = 1; - } - } - - spin_lock(&GlobalMid_Lock); - if (midQ->resp_buf) { - spin_unlock(&GlobalMid_Lock); - receive_len = midQ->resp_buf->smb_buf_length; - } else { - cERROR(1,("No response for cmd %d mid %d", - midQ->command, midQ->mid)); - if(midQ->midState == MID_REQUEST_SUBMITTED) { - if(ses->server->tcpStatus == CifsExiting) - rc = -EHOSTDOWN; - else { - ses->server->tcpStatus = CifsNeedReconnect; - midQ->midState = MID_RETRY_NEEDED; - } - } - - if (rc != -EHOSTDOWN) { - if(midQ->midState == MID_RETRY_NEEDED) { - rc = -EAGAIN; - cFYI(1,("marking request for retry")); - } else { - rc = -EIO; - } - } - spin_unlock(&GlobalMid_Lock); - DeleteMidQEntry(midQ); - return rc; + /* If not lock req, update # of requests on wire to server */ + if(long_op < 3) { + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); } - - if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { - cERROR(1, ("Frame too large received. Length: %d Xid: %d", - receive_len, xid)); - rc = -EIO; - } else { /* rcvd frame is ok */ - - if (midQ->resp_buf && out_buf - && (midQ->midState == MID_RESPONSE_RECEIVED)) { - out_buf->smb_buf_length = receive_len; - memcpy((char *)out_buf + 4, - (char *)midQ->resp_buf + 4, - receive_len); - - dump_smb(out_buf, 92); - /* convert the length into a more usable form */ - if((receive_len > 24) && - (ses->server->secMode & (SECMODE_SIGN_REQUIRED | - SECMODE_SIGN_ENABLED))) { - rc = cifs_verify_signature(out_buf, - ses->server->mac_signing_key, - midQ->sequence_number+1); - if(rc) { - cERROR(1,("Unexpected SMB signature")); - /* BB FIXME add code to kill session */ - } - } - - *pbytes_returned = out_buf->smb_buf_length; - - /* BB special case reconnect tid and uid here? */ - rc = map_smb_to_linux_error(out_buf); - /* convert ByteCount if necessary */ - if (receive_len >= - sizeof (struct smb_hdr) - - 4 /* do not count RFC1001 header */ + - (2 * out_buf->WordCount) + 2 /* bcc */ ) - BCC(out_buf) = le16_to_cpu(BCC_LE(out_buf)); - } else { - rc = -EIO; - cERROR(1,("Bad MID state?")); - } - } - DeleteMidQEntry(midQ); - if (rstart && rc == -EACCES) - return -ERESTARTSYS; return rc; } diff --git a/trunk/fs/cifs/xattr.c b/trunk/fs/cifs/xattr.c index 18fcec190f8b..7754d641775e 100644 --- a/trunk/fs/cifs/xattr.c +++ b/trunk/fs/cifs/xattr.c @@ -269,7 +269,7 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, ea_value, buf_size, ACL_TYPE_ACCESS); - CIFSSMBClose(xid, pTcon, fid); + CIFSSMBClose(xid, pTcon, fid) } } */ /* BB enable after fixing up return data */ @@ -330,15 +330,11 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size) sb = direntry->d_inode->i_sb; if(sb == NULL) return -EIO; + xid = GetXid(); cifs_sb = CIFS_SB(sb); pTcon = cifs_sb->tcon; - if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) - return -EOPNOTSUPP; - - xid = GetXid(); - full_path = build_path_from_dentry(direntry); if(full_path == NULL) { FreeXid(xid); diff --git a/trunk/fs/coda/file.c b/trunk/fs/coda/file.c index dbfbcfa5b3c0..cc66c681bd11 100644 --- a/trunk/fs/coda/file.c +++ b/trunk/fs/coda/file.c @@ -136,8 +136,10 @@ int coda_open(struct inode *coda_inode, struct file *coda_file) coda_vfs_stat.open++; cfi = kmalloc(sizeof(struct coda_file_info), GFP_KERNEL); - if (!cfi) + if (!cfi) { + unlock_kernel(); return -ENOMEM; + } lock_kernel(); diff --git a/trunk/fs/configfs/dir.c b/trunk/fs/configfs/dir.c index 816e8ef64560..df025453dd97 100644 --- a/trunk/fs/configfs/dir.c +++ b/trunk/fs/configfs/dir.c @@ -86,32 +86,6 @@ static struct configfs_dirent *configfs_new_dirent(struct configfs_dirent * pare return sd; } -/* - * - * Return -EEXIST if there is already a configfs element with the same - * name for the same parent. - * - * called with parent inode's i_mutex held - */ -int configfs_dirent_exists(struct configfs_dirent *parent_sd, - const unsigned char *new) -{ - struct configfs_dirent * sd; - - list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { - if (sd->s_element) { - const unsigned char *existing = configfs_get_name(sd); - if (strcmp(existing, new)) - continue; - else - return -EEXIST; - } - } - - return 0; -} - - int configfs_make_dirent(struct configfs_dirent * parent_sd, struct dentry * dentry, void * element, umode_t mode, int type) @@ -162,10 +136,8 @@ static int create_dir(struct config_item * k, struct dentry * p, int error; umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO; - error = configfs_dirent_exists(p->d_fsdata, d->d_name.name); - if (!error) - error = configfs_make_dirent(p->d_fsdata, d, k, mode, - CONFIGFS_DIR); + error = configfs_make_dirent(p->d_fsdata, d, k, mode, + CONFIGFS_DIR); if (!error) { error = configfs_create(d, mode, init_dir); if (!error) { diff --git a/trunk/fs/dcache.c b/trunk/fs/dcache.c index 17b392a2049e..1b4a3a34ec57 100644 --- a/trunk/fs/dcache.c +++ b/trunk/fs/dcache.c @@ -828,19 +828,17 @@ void d_instantiate(struct dentry *entry, struct inode * inode) * (or otherwise set) by the caller to indicate that it is now * in use by the dcache. */ -static struct dentry *__d_instantiate_unique(struct dentry *entry, - struct inode *inode) +struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode) { struct dentry *alias; int len = entry->d_name.len; const char *name = entry->d_name.name; unsigned int hash = entry->d_name.hash; - if (!inode) { - entry->d_inode = NULL; - return NULL; - } - + BUG_ON(!list_empty(&entry->d_alias)); + spin_lock(&dcache_lock); + if (!inode) + goto do_negative; list_for_each_entry(alias, &inode->i_dentry, d_alias) { struct qstr *qstr = &alias->d_name; @@ -853,35 +851,19 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry, if (memcmp(qstr->name, name, len)) continue; dget_locked(alias); + spin_unlock(&dcache_lock); + BUG_ON(!d_unhashed(alias)); + iput(inode); return alias; } - list_add(&entry->d_alias, &inode->i_dentry); +do_negative: entry->d_inode = inode; fsnotify_d_instantiate(entry, inode); - return NULL; -} - -struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode) -{ - struct dentry *result; - - BUG_ON(!list_empty(&entry->d_alias)); - - spin_lock(&dcache_lock); - result = __d_instantiate_unique(entry, inode); spin_unlock(&dcache_lock); - - if (!result) { - security_d_instantiate(entry, inode); - return NULL; - } - - BUG_ON(!d_unhashed(result)); - iput(inode); - return result; + security_d_instantiate(entry, inode); + return NULL; } - EXPORT_SYMBOL(d_instantiate_unique); /** @@ -1253,11 +1235,6 @@ static void __d_rehash(struct dentry * entry, struct hlist_head *list) hlist_add_head_rcu(&entry->d_hash, list); } -static void _d_rehash(struct dentry * entry) -{ - __d_rehash(entry, d_hash(entry->d_parent, entry->d_name.hash)); -} - /** * d_rehash - add an entry back to the hash * @entry: dentry to add to the hash @@ -1267,9 +1244,11 @@ static void _d_rehash(struct dentry * entry) void d_rehash(struct dentry * entry) { + struct hlist_head *list = d_hash(entry->d_parent, entry->d_name.hash); + spin_lock(&dcache_lock); spin_lock(&entry->d_lock); - _d_rehash(entry); + __d_rehash(entry, list); spin_unlock(&entry->d_lock); spin_unlock(&dcache_lock); } @@ -1407,120 +1386,6 @@ void d_move(struct dentry * dentry, struct dentry * target) spin_unlock(&dcache_lock); } -/* - * Prepare an anonymous dentry for life in the superblock's dentry tree as a - * named dentry in place of the dentry to be replaced. - */ -static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon) -{ - struct dentry *dparent, *aparent; - - switch_names(dentry, anon); - do_switch(dentry->d_name.len, anon->d_name.len); - do_switch(dentry->d_name.hash, anon->d_name.hash); - - dparent = dentry->d_parent; - aparent = anon->d_parent; - - dentry->d_parent = (aparent == anon) ? dentry : aparent; - list_del(&dentry->d_u.d_child); - if (!IS_ROOT(dentry)) - list_add(&dentry->d_u.d_child, &dentry->d_parent->d_subdirs); - else - INIT_LIST_HEAD(&dentry->d_u.d_child); - - anon->d_parent = (dparent == dentry) ? anon : dparent; - list_del(&anon->d_u.d_child); - if (!IS_ROOT(anon)) - list_add(&anon->d_u.d_child, &anon->d_parent->d_subdirs); - else - INIT_LIST_HEAD(&anon->d_u.d_child); - - anon->d_flags &= ~DCACHE_DISCONNECTED; -} - -/** - * d_materialise_unique - introduce an inode into the tree - * @dentry: candidate dentry - * @inode: inode to bind to the dentry, to which aliases may be attached - * - * Introduces an dentry into the tree, substituting an extant disconnected - * root directory alias in its place if there is one - */ -struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) -{ - struct dentry *alias, *actual; - - BUG_ON(!d_unhashed(dentry)); - - spin_lock(&dcache_lock); - - if (!inode) { - actual = dentry; - dentry->d_inode = NULL; - goto found_lock; - } - - /* See if a disconnected directory already exists as an anonymous root - * that we should splice into the tree instead */ - if (S_ISDIR(inode->i_mode) && (alias = __d_find_alias(inode, 1))) { - spin_lock(&alias->d_lock); - - /* Is this a mountpoint that we could splice into our tree? */ - if (IS_ROOT(alias)) - goto connect_mountpoint; - - if (alias->d_name.len == dentry->d_name.len && - alias->d_parent == dentry->d_parent && - memcmp(alias->d_name.name, - dentry->d_name.name, - dentry->d_name.len) == 0) - goto replace_with_alias; - - spin_unlock(&alias->d_lock); - - /* Doh! Seem to be aliasing directories for some reason... */ - dput(alias); - } - - /* Add a unique reference */ - actual = __d_instantiate_unique(dentry, inode); - if (!actual) - actual = dentry; - else if (unlikely(!d_unhashed(actual))) - goto shouldnt_be_hashed; - -found_lock: - spin_lock(&actual->d_lock); -found: - _d_rehash(actual); - spin_unlock(&actual->d_lock); - spin_unlock(&dcache_lock); - - if (actual == dentry) { - security_d_instantiate(dentry, inode); - return NULL; - } - - iput(inode); - return actual; - - /* Convert the anonymous/root alias into an ordinary dentry */ -connect_mountpoint: - __d_materialise_dentry(dentry, alias); - - /* Replace the candidate dentry with the alias in the tree */ -replace_with_alias: - __d_drop(alias); - actual = alias; - goto found; - -shouldnt_be_hashed: - spin_unlock(&dcache_lock); - BUG(); - goto shouldnt_be_hashed; -} - /** * d_path - return the path of a dentry * @dentry: dentry to report @@ -1919,7 +1784,6 @@ EXPORT_SYMBOL(d_instantiate); EXPORT_SYMBOL(d_invalidate); EXPORT_SYMBOL(d_lookup); EXPORT_SYMBOL(d_move); -EXPORT_SYMBOL_GPL(d_materialise_unique); EXPORT_SYMBOL(d_path); EXPORT_SYMBOL(d_prune_aliases); EXPORT_SYMBOL(d_rehash); diff --git a/trunk/fs/efs/symlink.c b/trunk/fs/efs/symlink.c index 1d30d2ff440f..e249cf733a6b 100644 --- a/trunk/fs/efs/symlink.c +++ b/trunk/fs/efs/symlink.c @@ -22,7 +22,7 @@ static int efs_symlink_readpage(struct file *file, struct page *page) err = -ENAMETOOLONG; if (size > 2 * EFS_BLOCKSIZE) - goto fail_notlocked; + goto fail; lock_kernel(); /* read first 512 bytes of link target */ @@ -47,7 +47,6 @@ static int efs_symlink_readpage(struct file *file, struct page *page) return 0; fail: unlock_kernel(); -fail_notlocked: SetPageError(page); kunmap(page); unlock_page(page); diff --git a/trunk/fs/eventpoll.c b/trunk/fs/eventpoll.c index 3a3567433b92..19ffb043abbc 100644 --- a/trunk/fs/eventpoll.c +++ b/trunk/fs/eventpoll.c @@ -1168,7 +1168,7 @@ static int ep_unlink(struct eventpoll *ep, struct epitem *epi) eexit_1: DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_unlink(%p, %p) = %d\n", - current, ep, epi->ffd.file, error)); + current, ep, epi->file, error)); return error; } @@ -1236,7 +1236,7 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k struct eventpoll *ep = epi->ep; DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n", - current, epi->ffd.file, epi, ep)); + current, epi->file, epi, ep)); write_lock_irqsave(&ep->lock, flags); diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index 54135df2a966..8344ba73a2a6 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -486,6 +486,8 @@ struct file *open_exec(const char *name) if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && S_ISREG(inode->i_mode)) { int err = vfs_permission(&nd, MAY_EXEC); + if (!err && !(inode->i_mode & 0111)) + err = -EACCES; file = ERR_PTR(err); if (!err) { file = nameidata_to_filp(&nd, O_RDONLY); @@ -751,7 +753,7 @@ static int de_thread(struct task_struct *tsk) write_lock_irq(&tasklist_lock); spin_lock(&oldsighand->siglock); - spin_lock_nested(&newsighand->siglock, SINGLE_DEPTH_NESTING); + spin_lock(&newsighand->siglock); rcu_assign_pointer(current->sighand, newsighand); recalc_sigpending(); @@ -920,6 +922,12 @@ int prepare_binprm(struct linux_binprm *bprm) int retval; mode = inode->i_mode; + /* + * Check execute perms again - if the caller has CAP_DAC_OVERRIDE, + * generic_permission lets a non-executable through + */ + if (!(mode & 0111)) /* with at least _one_ execute bit set */ + return -EACCES; if (bprm->file->f_op == NULL) return -EACCES; diff --git a/trunk/fs/ext2/balloc.c b/trunk/fs/ext2/balloc.c index b1981d0e95ad..d4870432ecfc 100644 --- a/trunk/fs/ext2/balloc.c +++ b/trunk/fs/ext2/balloc.c @@ -539,6 +539,7 @@ unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars) #endif /* EXT2FS_DEBUG */ +/* Superblock must be locked */ unsigned long ext2_count_free_blocks (struct super_block * sb) { struct ext2_group_desc * desc; diff --git a/trunk/fs/ext2/ialloc.c b/trunk/fs/ext2/ialloc.c index 695f69ccf908..de85c61c58c5 100644 --- a/trunk/fs/ext2/ialloc.c +++ b/trunk/fs/ext2/ialloc.c @@ -637,6 +637,7 @@ struct inode *ext2_new_inode(struct inode *dir, int mode) return ERR_PTR(err); } +/* Superblock must be locked */ unsigned long ext2_count_free_inodes (struct super_block * sb) { struct ext2_group_desc *desc; diff --git a/trunk/fs/ext2/super.c b/trunk/fs/ext2/super.c index 4286ff6330b6..f2702cda9779 100644 --- a/trunk/fs/ext2/super.c +++ b/trunk/fs/ext2/super.c @@ -251,44 +251,6 @@ static struct super_operations ext2_sops = { #endif }; -static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp) -{ - __u32 *objp = vobjp; - unsigned long ino = objp[0]; - __u32 generation = objp[1]; - struct inode *inode; - struct dentry *result; - - if (ino < EXT2_FIRST_INO(sb) && ino != EXT2_ROOT_INO) - return ERR_PTR(-ESTALE); - if (ino > le32_to_cpu(EXT2_SB(sb)->s_es->s_inodes_count)) - return ERR_PTR(-ESTALE); - - /* iget isn't really right if the inode is currently unallocated!! - * ext2_read_inode currently does appropriate checks, but - * it might be "neater" to call ext2_get_inode first and check - * if the inode is valid..... - */ - inode = iget(sb, ino); - if (inode == NULL) - return ERR_PTR(-ENOMEM); - if (is_bad_inode(inode) || - (generation && inode->i_generation != generation)) { - /* we didn't find the right inode.. */ - iput(inode); - return ERR_PTR(-ESTALE); - } - /* now to find a dentry. - * If possible, get a well-connected one - */ - result = d_alloc_anon(inode); - if (!result) { - iput(inode); - return ERR_PTR(-ENOMEM); - } - return result; -} - /* Yes, most of these are left as NULL!! * A NULL value implies the default, which works with ext2-like file * systems, but can be improved upon. @@ -296,7 +258,6 @@ static struct dentry *ext2_get_dentry(struct super_block *sb, void *vobjp) */ static struct export_operations ext2_export_ops = { .get_parent = ext2_get_parent, - .get_dentry = ext2_get_dentry, }; static unsigned long get_sb_block(void **data) @@ -814,7 +775,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) if (EXT2_INODE_SIZE(sb) == 0) goto cantfind_ext2; sbi->s_inodes_per_block = sb->s_blocksize / EXT2_INODE_SIZE(sb); - if (sbi->s_inodes_per_block == 0 || sbi->s_inodes_per_group == 0) + if (sbi->s_inodes_per_block == 0) goto cantfind_ext2; sbi->s_itb_per_group = sbi->s_inodes_per_group / sbi->s_inodes_per_block; @@ -1083,6 +1044,7 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf) unsigned long overhead; int i; + lock_super(sb); if (test_opt (sb, MINIX_DF)) overhead = 0; else { @@ -1123,6 +1085,7 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf) buf->f_files = le32_to_cpu(sbi->s_es->s_inodes_count); buf->f_ffree = ext2_count_free_inodes (sb); buf->f_namelen = EXT2_NAME_LEN; + unlock_super(sb); return 0; } diff --git a/trunk/fs/ext3/balloc.c b/trunk/fs/ext3/balloc.c index 063d994bda0b..a504a40d6d29 100644 --- a/trunk/fs/ext3/balloc.c +++ b/trunk/fs/ext3/balloc.c @@ -1269,12 +1269,12 @@ ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode, goal = le32_to_cpu(es->s_first_data_block); group_no = (goal - le32_to_cpu(es->s_first_data_block)) / EXT3_BLOCKS_PER_GROUP(sb); - goal_group = group_no; -retry_alloc: gdp = ext3_get_group_desc(sb, group_no, &gdp_bh); if (!gdp) goto io_error; + goal_group = group_no; +retry: free_blocks = le16_to_cpu(gdp->bg_free_blocks_count); /* * if there is not enough free blocks to make a new resevation @@ -1349,7 +1349,7 @@ ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode, if (my_rsv) { my_rsv = NULL; group_no = goal_group; - goto retry_alloc; + goto retry; } /* No space left on the device */ *errp = -ENOSPC; diff --git a/trunk/fs/ext3/inode.c b/trunk/fs/ext3/inode.c index 84be02e93652..f804d5e9d60c 100644 --- a/trunk/fs/ext3/inode.c +++ b/trunk/fs/ext3/inode.c @@ -925,7 +925,7 @@ int ext3_get_blocks_handle(handle_t *handle, struct inode *inode, set_buffer_new(bh_result); got_it: map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key)); - if (count > blocks_to_boundary) + if (blocks_to_boundary == 0) set_buffer_boundary(bh_result); err = count; /* Clean up and exit */ @@ -1009,14 +1009,11 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode *inode, buffer_trace_init(&dummy.b_history); err = ext3_get_blocks_handle(handle, inode, block, 1, &dummy, create, 1); - /* - * ext3_get_blocks_handle() returns number of blocks - * mapped. 0 in case of a HOLE. - */ - if (err > 0) { - if (err > 1) - WARN_ON(1); + if (err == 1) { err = 0; + } else if (err >= 0) { + WARN_ON(1); + err = -EIO; } *errp = err; if (!err && buffer_mapped(&dummy)) { @@ -1161,7 +1158,7 @@ static int ext3_prepare_write(struct file *file, struct page *page, ret = PTR_ERR(handle); goto out; } - if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) + if (test_opt(inode->i_sb, NOBH)) ret = nobh_prepare_write(page, from, to, ext3_get_block); else ret = block_prepare_write(page, from, to, ext3_get_block); @@ -1247,7 +1244,7 @@ static int ext3_writeback_commit_write(struct file *file, struct page *page, if (new_i_size > EXT3_I(inode)->i_disksize) EXT3_I(inode)->i_disksize = new_i_size; - if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) + if (test_opt(inode->i_sb, NOBH)) ret = nobh_commit_write(file, page, from, to); else ret = generic_commit_write(file, page, from, to); @@ -1497,7 +1494,7 @@ static int ext3_writeback_writepage(struct page *page, goto out_fail; } - if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) + if (test_opt(inode->i_sb, NOBH)) ret = nobh_writepage(page, ext3_get_block, wbc); else ret = block_write_full_page(page, ext3_get_block, wbc); @@ -2405,15 +2402,14 @@ static ext3_fsblk_t ext3_get_inode_block(struct super_block *sb, struct buffer_head *bh; struct ext3_group_desc * gdp; - if (!ext3_valid_inum(sb, ino)) { - /* - * This error is already checked for in namei.c unless we are - * looking at an NFS filehandle, in which case no error - * report is needed - */ + + if ((ino != EXT3_ROOT_INO && ino != EXT3_JOURNAL_INO && + ino != EXT3_RESIZE_INO && ino < EXT3_FIRST_INO(sb)) || + ino > le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count)) { + ext3_error(sb, "ext3_get_inode_block", + "bad inode number: %lu", ino); return 0; } - block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb); if (block_group >= EXT3_SB(sb)->s_groups_count) { ext3_error(sb,"ext3_get_inode_block","group >= groups count"); diff --git a/trunk/fs/ext3/namei.c b/trunk/fs/ext3/namei.c index 2aa7101b27cd..d9176dba3698 100644 --- a/trunk/fs/ext3/namei.c +++ b/trunk/fs/ext3/namei.c @@ -1000,12 +1000,7 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str if (bh) { unsigned long ino = le32_to_cpu(de->inode); brelse (bh); - if (!ext3_valid_inum(dir->i_sb, ino)) { - ext3_error(dir->i_sb, "ext3_lookup", - "bad inode number: %lu", ino); - inode = NULL; - } else - inode = iget(dir->i_sb, ino); + inode = iget(dir->i_sb, ino); if (!inode) return ERR_PTR(-EACCES); @@ -1033,13 +1028,7 @@ struct dentry *ext3_get_parent(struct dentry *child) return ERR_PTR(-ENOENT); ino = le32_to_cpu(de->inode); brelse(bh); - - if (!ext3_valid_inum(child->d_inode->i_sb, ino)) { - ext3_error(child->d_inode->i_sb, "ext3_get_parent", - "bad inode number: %lu", ino); - inode = NULL; - } else - inode = iget(child->d_inode->i_sb, ino); + inode = iget(child->d_inode->i_sb, ino); if (!inode) return ERR_PTR(-EACCES); diff --git a/trunk/fs/ext3/super.c b/trunk/fs/ext3/super.c index 3559086eee5f..813d589cc6c0 100644 --- a/trunk/fs/ext3/super.c +++ b/trunk/fs/ext3/super.c @@ -554,47 +554,6 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs) return 0; } - -static struct dentry *ext3_get_dentry(struct super_block *sb, void *vobjp) -{ - __u32 *objp = vobjp; - unsigned long ino = objp[0]; - __u32 generation = objp[1]; - struct inode *inode; - struct dentry *result; - - if (ino < EXT3_FIRST_INO(sb) && ino != EXT3_ROOT_INO) - return ERR_PTR(-ESTALE); - if (ino > le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count)) - return ERR_PTR(-ESTALE); - - /* iget isn't really right if the inode is currently unallocated!! - * - * ext3_read_inode will return a bad_inode if the inode had been - * deleted, so we should be safe. - * - * Currently we don't know the generation for parent directory, so - * a generation of 0 means "accept any" - */ - inode = iget(sb, ino); - if (inode == NULL) - return ERR_PTR(-ENOMEM); - if (is_bad_inode(inode) || - (generation && inode->i_generation != generation)) { - iput(inode); - return ERR_PTR(-ESTALE); - } - /* now to find a dentry. - * If possible, get a well-connected one - */ - result = d_alloc_anon(inode); - if (!result) { - iput(inode); - return ERR_PTR(-ENOMEM); - } - return result; -} - #ifdef CONFIG_QUOTA #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group") #define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA)) @@ -663,7 +622,6 @@ static struct super_operations ext3_sops = { static struct export_operations ext3_export_ops = { .get_parent = ext3_get_parent, - .get_dentry = ext3_get_dentry, }; enum { diff --git a/trunk/fs/freevxfs/vxfs_lookup.c b/trunk/fs/freevxfs/vxfs_lookup.c index 43886fa00a2a..29cce456c7ce 100644 --- a/trunk/fs/freevxfs/vxfs_lookup.c +++ b/trunk/fs/freevxfs/vxfs_lookup.c @@ -246,8 +246,6 @@ vxfs_readdir(struct file *fp, void *retp, filldir_t filler) u_long page, npages, block, pblocks, nblocks, offset; loff_t pos; - lock_kernel(); - switch ((long)fp->f_pos) { case 0: if (filler(retp, ".", 1, fp->f_pos, ip->i_ino, DT_DIR) < 0) diff --git a/trunk/fs/fuse/control.c b/trunk/fs/fuse/control.c index 46fe60b2da23..a3bce3a77253 100644 --- a/trunk/fs/fuse/control.c +++ b/trunk/fs/fuse/control.c @@ -105,7 +105,7 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent, /* * Add a connection to the control filesystem (if it exists). Caller - * must hold fuse_mutex + * must host fuse_mutex */ int fuse_ctl_add_conn(struct fuse_conn *fc) { @@ -139,7 +139,7 @@ int fuse_ctl_add_conn(struct fuse_conn *fc) /* * Remove a connection from the control filesystem (if it exists). - * Caller must hold fuse_mutex + * Caller must host fuse_mutex */ void fuse_ctl_remove_conn(struct fuse_conn *fc) { diff --git a/trunk/fs/fuse/dir.c b/trunk/fs/fuse/dir.c index 409ce6a7cca4..72a74cde6de8 100644 --- a/trunk/fs/fuse/dir.c +++ b/trunk/fs/fuse/dir.c @@ -14,33 +14,6 @@ #include #include -#if BITS_PER_LONG >= 64 -static inline void fuse_dentry_settime(struct dentry *entry, u64 time) -{ - entry->d_time = time; -} - -static inline u64 fuse_dentry_time(struct dentry *entry) -{ - return entry->d_time; -} -#else -/* - * On 32 bit archs store the high 32 bits of time in d_fsdata - */ -static void fuse_dentry_settime(struct dentry *entry, u64 time) -{ - entry->d_time = time; - entry->d_fsdata = (void *) (unsigned long) (time >> 32); -} - -static u64 fuse_dentry_time(struct dentry *entry) -{ - return (u64) entry->d_time + - ((u64) (unsigned long) entry->d_fsdata << 32); -} -#endif - /* * FUSE caches dentries and attributes with separate timeout. The * time in jiffies until the dentry/attributes are valid is stored in @@ -50,13 +23,10 @@ static u64 fuse_dentry_time(struct dentry *entry) /* * Calculate the time in jiffies until a dentry/attributes are valid */ -static u64 time_to_jiffies(unsigned long sec, unsigned long nsec) +static unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec) { - if (sec || nsec) { - struct timespec ts = {sec, nsec}; - return get_jiffies_64() + timespec_to_jiffies(&ts); - } else - return 0; + struct timespec ts = {sec, nsec}; + return jiffies + timespec_to_jiffies(&ts); } /* @@ -65,8 +35,7 @@ static u64 time_to_jiffies(unsigned long sec, unsigned long nsec) */ static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o) { - fuse_dentry_settime(entry, - time_to_jiffies(o->entry_valid, o->entry_valid_nsec)); + entry->d_time = time_to_jiffies(o->entry_valid, o->entry_valid_nsec); if (entry->d_inode) get_fuse_inode(entry->d_inode)->i_time = time_to_jiffies(o->attr_valid, o->attr_valid_nsec); @@ -78,7 +47,7 @@ static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o) */ void fuse_invalidate_attr(struct inode *inode) { - get_fuse_inode(inode)->i_time = 0; + get_fuse_inode(inode)->i_time = jiffies - 1; } /* @@ -91,7 +60,7 @@ void fuse_invalidate_attr(struct inode *inode) */ static void fuse_invalidate_entry_cache(struct dentry *entry) { - fuse_dentry_settime(entry, 0); + entry->d_time = jiffies - 1; } /* @@ -133,7 +102,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) if (inode && is_bad_inode(inode)) return 0; - else if (fuse_dentry_time(entry) < get_jiffies_64()) { + else if (time_after(jiffies, entry->d_time)) { int err; struct fuse_entry_out outarg; struct fuse_conn *fc; @@ -697,7 +666,7 @@ static int fuse_revalidate(struct dentry *entry) if (!fuse_allow_task(fc, current)) return -EACCES; if (get_node_id(inode) != FUSE_ROOT_ID && - fi->i_time >= get_jiffies_64()) + time_before_eq(jiffies, fi->i_time)) return 0; return fuse_do_getattr(inode); diff --git a/trunk/fs/fuse/file.c b/trunk/fs/fuse/file.c index 5c4fcd1dbf59..63614ed16336 100644 --- a/trunk/fs/fuse/file.c +++ b/trunk/fs/fuse/file.c @@ -395,16 +395,14 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, struct fuse_readpages_data data; int err; - err = -EIO; if (is_bad_inode(inode)) - goto clean_pages_up; + return -EIO; data.file = file; data.inode = inode; data.req = fuse_get_req(fc); - err = PTR_ERR(data.req); if (IS_ERR(data.req)) - goto clean_pages_up; + return PTR_ERR(data.req); err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); if (!err) { @@ -414,10 +412,6 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, fuse_put_request(fc, data.req); } return err; - -clean_pages_up: - put_pages_list(pages); - return err; } static size_t fuse_send_write(struct fuse_req *req, struct file *file, diff --git a/trunk/fs/fuse/fuse_i.h b/trunk/fs/fuse/fuse_i.h index 69c7750d55b8..0dbf96621841 100644 --- a/trunk/fs/fuse/fuse_i.h +++ b/trunk/fs/fuse/fuse_i.h @@ -59,7 +59,7 @@ struct fuse_inode { struct fuse_req *forget_req; /** Time in jiffies until the file attributes are valid */ - u64 i_time; + unsigned long i_time; }; /** FUSE specific file data */ diff --git a/trunk/fs/fuse/inode.c b/trunk/fs/fuse/inode.c index 7d25092262ae..dcaaabd3b9c4 100644 --- a/trunk/fs/fuse/inode.c +++ b/trunk/fs/fuse/inode.c @@ -51,7 +51,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) return NULL; fi = get_fuse_inode(inode); - fi->i_time = 0; + fi->i_time = jiffies - 1; fi->nodeid = 0; fi->nlookup = 0; fi->forget_req = fuse_request_alloc(); diff --git a/trunk/fs/inotify_user.c b/trunk/fs/inotify_user.c index 017cb0f134d6..f2386442adee 100644 --- a/trunk/fs/inotify_user.c +++ b/trunk/fs/inotify_user.c @@ -187,7 +187,7 @@ static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie, { struct inotify_kernel_event *kevent; - kevent = kmem_cache_alloc(event_cachep, GFP_NOFS); + kevent = kmem_cache_alloc(event_cachep, GFP_KERNEL); if (unlikely(!kevent)) return NULL; diff --git a/trunk/fs/ioprio.c b/trunk/fs/ioprio.c index 78b1deae3fa2..93aa5715f224 100644 --- a/trunk/fs/ioprio.c +++ b/trunk/fs/ioprio.c @@ -44,9 +44,6 @@ static int set_task_ioprio(struct task_struct *task, int ioprio) task->ioprio = ioprio; ioc = task->io_context; - /* see wmb() in current_io_context() */ - smp_read_barrier_depends(); - if (ioc && ioc->set_ioprio) ioc->set_ioprio(ioc, ioprio); @@ -114,9 +111,9 @@ asmlinkage long sys_ioprio_set(int which, int who, int ioprio) continue; ret = set_task_ioprio(p, ioprio); if (ret) - goto free_uid; + break; } while_each_thread(g, p); -free_uid: + if (who) free_uid(user); break; @@ -140,29 +137,6 @@ static int get_task_ioprio(struct task_struct *p) return ret; } -int ioprio_best(unsigned short aprio, unsigned short bprio) -{ - unsigned short aclass = IOPRIO_PRIO_CLASS(aprio); - unsigned short bclass = IOPRIO_PRIO_CLASS(bprio); - - if (!ioprio_valid(aprio)) - return bprio; - if (!ioprio_valid(bprio)) - return aprio; - - if (aclass == IOPRIO_CLASS_NONE) - aclass = IOPRIO_CLASS_BE; - if (bclass == IOPRIO_CLASS_NONE) - bclass = IOPRIO_CLASS_BE; - - if (aclass == bclass) - return min(aprio, bprio); - if (aclass > bclass) - return bprio; - else - return aprio; -} - asmlinkage long sys_ioprio_get(int which, int who) { struct task_struct *g, *p; diff --git a/trunk/fs/jbd/commit.c b/trunk/fs/jbd/commit.c index 42da60784311..0971814c38b8 100644 --- a/trunk/fs/jbd/commit.c +++ b/trunk/fs/jbd/commit.c @@ -261,7 +261,7 @@ void journal_commit_transaction(journal_t *journal) struct buffer_head *bh = jh2bh(jh); jbd_lock_bh_state(bh); - jbd_slab_free(jh->b_committed_data, bh->b_size); + kfree(jh->b_committed_data); jh->b_committed_data = NULL; jbd_unlock_bh_state(bh); } @@ -745,14 +745,14 @@ void journal_commit_transaction(journal_t *journal) * Otherwise, we can just throw away the frozen data now. */ if (jh->b_committed_data) { - jbd_slab_free(jh->b_committed_data, bh->b_size); + kfree(jh->b_committed_data); jh->b_committed_data = NULL; if (jh->b_frozen_data) { jh->b_committed_data = jh->b_frozen_data; jh->b_frozen_data = NULL; } } else if (jh->b_frozen_data) { - jbd_slab_free(jh->b_frozen_data, bh->b_size); + kfree(jh->b_frozen_data); jh->b_frozen_data = NULL; } diff --git a/trunk/fs/jbd/journal.c b/trunk/fs/jbd/journal.c index f66724ce443a..8c9b28dff119 100644 --- a/trunk/fs/jbd/journal.c +++ b/trunk/fs/jbd/journal.c @@ -84,7 +84,6 @@ EXPORT_SYMBOL(journal_force_commit); static int journal_convert_superblock_v1(journal_t *, journal_superblock_t *); static void __journal_abort_soft (journal_t *journal, int errno); -static int journal_create_jbd_slab(size_t slab_size); /* * Helper function used to manage commit timeouts @@ -329,10 +328,10 @@ int journal_write_metadata_buffer(transaction_t *transaction, char *tmp; jbd_unlock_bh_state(bh_in); - tmp = jbd_slab_alloc(bh_in->b_size, GFP_NOFS); + tmp = jbd_rep_kmalloc(bh_in->b_size, GFP_NOFS); jbd_lock_bh_state(bh_in); if (jh_in->b_frozen_data) { - jbd_slab_free(tmp, bh_in->b_size); + kfree(tmp); goto repeat; } @@ -1070,17 +1069,17 @@ static int load_superblock(journal_t *journal) int journal_load(journal_t *journal) { int err; - journal_superblock_t *sb; err = load_superblock(journal); if (err) return err; - sb = journal->j_superblock; /* If this is a V2 superblock, then we have to check the * features flags on it. */ if (journal->j_format_version >= 2) { + journal_superblock_t *sb = journal->j_superblock; + if ((sb->s_feature_ro_compat & ~cpu_to_be32(JFS_KNOWN_ROCOMPAT_FEATURES)) || (sb->s_feature_incompat & @@ -1091,13 +1090,6 @@ int journal_load(journal_t *journal) } } - /* - * Create a slab for this blocksize - */ - err = journal_create_jbd_slab(cpu_to_be32(sb->s_blocksize)); - if (err) - return err; - /* Let the recovery code check whether it needs to recover any * data from the journal. */ if (journal_recover(journal)) @@ -1619,77 +1611,6 @@ void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry) return kmalloc(size, flags | (retry ? __GFP_NOFAIL : 0)); } -/* - * jbd slab management: create 1k, 2k, 4k, 8k slabs as needed - * and allocate frozen and commit buffers from these slabs. - * - * Reason for doing this is to avoid, SLAB_DEBUG - since it could - * cause bh to cross page boundary. - */ - -#define JBD_MAX_SLABS 5 -#define JBD_SLAB_INDEX(size) (size >> 11) - -static kmem_cache_t *jbd_slab[JBD_MAX_SLABS]; -static const char *jbd_slab_names[JBD_MAX_SLABS] = { - "jbd_1k", "jbd_2k", "jbd_4k", NULL, "jbd_8k" -}; - -static void journal_destroy_jbd_slabs(void) -{ - int i; - - for (i = 0; i < JBD_MAX_SLABS; i++) { - if (jbd_slab[i]) - kmem_cache_destroy(jbd_slab[i]); - jbd_slab[i] = NULL; - } -} - -static int journal_create_jbd_slab(size_t slab_size) -{ - int i = JBD_SLAB_INDEX(slab_size); - - BUG_ON(i >= JBD_MAX_SLABS); - - /* - * Check if we already have a slab created for this size - */ - if (jbd_slab[i]) - return 0; - - /* - * Create a slab and force alignment to be same as slabsize - - * this will make sure that allocations won't cross the page - * boundary. - */ - jbd_slab[i] = kmem_cache_create(jbd_slab_names[i], - slab_size, slab_size, 0, NULL, NULL); - if (!jbd_slab[i]) { - printk(KERN_EMERG "JBD: no memory for jbd_slab cache\n"); - return -ENOMEM; - } - return 0; -} - -void * jbd_slab_alloc(size_t size, gfp_t flags) -{ - int idx; - - idx = JBD_SLAB_INDEX(size); - BUG_ON(jbd_slab[idx] == NULL); - return kmem_cache_alloc(jbd_slab[idx], flags | __GFP_NOFAIL); -} - -void jbd_slab_free(void *ptr, size_t size) -{ - int idx; - - idx = JBD_SLAB_INDEX(size); - BUG_ON(jbd_slab[idx] == NULL); - kmem_cache_free(jbd_slab[idx], ptr); -} - /* * Journal_head storage management */ @@ -1878,13 +1799,13 @@ static void __journal_remove_journal_head(struct buffer_head *bh) printk(KERN_WARNING "%s: freeing " "b_frozen_data\n", __FUNCTION__); - jbd_slab_free(jh->b_frozen_data, bh->b_size); + kfree(jh->b_frozen_data); } if (jh->b_committed_data) { printk(KERN_WARNING "%s: freeing " "b_committed_data\n", __FUNCTION__); - jbd_slab_free(jh->b_committed_data, bh->b_size); + kfree(jh->b_committed_data); } bh->b_private = NULL; jh->b_bh = NULL; /* debug, really */ @@ -2040,7 +1961,6 @@ static void journal_destroy_caches(void) journal_destroy_revoke_caches(); journal_destroy_journal_head_cache(); journal_destroy_handle_cache(); - journal_destroy_jbd_slabs(); } static int __init journal_init(void) diff --git a/trunk/fs/jbd/transaction.c b/trunk/fs/jbd/transaction.c index f5169a96260e..508b2ea91f43 100644 --- a/trunk/fs/jbd/transaction.c +++ b/trunk/fs/jbd/transaction.c @@ -666,9 +666,8 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, if (!frozen_buffer) { JBUFFER_TRACE(jh, "allocate memory for buffer"); jbd_unlock_bh_state(bh); - frozen_buffer = - jbd_slab_alloc(jh2bh(jh)->b_size, - GFP_NOFS); + frozen_buffer = jbd_kmalloc(jh2bh(jh)->b_size, + GFP_NOFS); if (!frozen_buffer) { printk(KERN_EMERG "%s: OOM for frozen_buffer\n", @@ -727,7 +726,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh, out: if (unlikely(frozen_buffer)) /* It's usually NULL */ - jbd_slab_free(frozen_buffer, bh->b_size); + kfree(frozen_buffer); JBUFFER_TRACE(jh, "exit"); return error; @@ -880,7 +879,7 @@ int journal_get_undo_access(handle_t *handle, struct buffer_head *bh) repeat: if (!jh->b_committed_data) { - committed_data = jbd_slab_alloc(jh2bh(jh)->b_size, GFP_NOFS); + committed_data = jbd_kmalloc(jh2bh(jh)->b_size, GFP_NOFS); if (!committed_data) { printk(KERN_EMERG "%s: No memory for committed data\n", __FUNCTION__); @@ -907,7 +906,7 @@ int journal_get_undo_access(handle_t *handle, struct buffer_head *bh) out: journal_put_journal_head(jh); if (unlikely(committed_data)) - jbd_slab_free(committed_data, bh->b_size); + kfree(committed_data); return err; } diff --git a/trunk/fs/jffs2/jffs2_fs_i.h b/trunk/fs/jffs2/jffs2_fs_i.h index 3a566077ac95..2e0cc8e00b85 100644 --- a/trunk/fs/jffs2/jffs2_fs_i.h +++ b/trunk/fs/jffs2/jffs2_fs_i.h @@ -41,7 +41,11 @@ struct jffs2_inode_info { uint16_t flags; uint8_t usercompr; +#if !defined (__ECOS) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2) struct inode vfs_inode; +#endif +#endif #ifdef CONFIG_JFFS2_FS_POSIX_ACL struct posix_acl *i_acl_access; struct posix_acl *i_acl_default; diff --git a/trunk/fs/jffs2/nodelist.c b/trunk/fs/jffs2/nodelist.c index 5a6b4d64206c..7675b33396c7 100644 --- a/trunk/fs/jffs2/nodelist.c +++ b/trunk/fs/jffs2/nodelist.c @@ -21,9 +21,6 @@ #include #include "nodelist.h" -static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, - struct jffs2_node_frag *this); - void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) { struct jffs2_full_dirent **prev = list; @@ -90,8 +87,7 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint } } -static void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, - struct jffs2_node_frag *this) +void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this) { if (this->node) { this->node->frags--; diff --git a/trunk/fs/jffs2/nodelist.h b/trunk/fs/jffs2/nodelist.h index 0ddfd70307fb..cae92c14116d 100644 --- a/trunk/fs/jffs2/nodelist.h +++ b/trunk/fs/jffs2/nodelist.h @@ -334,6 +334,7 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c_delete); struct rb_node *rb_next(struct rb_node *); struct rb_node *rb_prev(struct rb_node *); void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root); +void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *this); int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); diff --git a/trunk/fs/jffs2/summary.c b/trunk/fs/jffs2/summary.c index e52cef526d90..c19bd476e8ec 100644 --- a/trunk/fs/jffs2/summary.c +++ b/trunk/fs/jffs2/summary.c @@ -252,11 +252,6 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, union jffs2_node_union *node; struct jffs2_eraseblock *jeb; - if (c->summary->sum_size == JFFS2_SUMMARY_NOSUM_SIZE) { - dbg_summary("Summary is disabled for this jeb! Skipping summary info!\n"); - return 0; - } - node = invecs[0].iov_base; jeb = &c->blocks[ofs / c->sector_size]; ofs -= jeb->offset; diff --git a/trunk/fs/jffs2/xattr.c b/trunk/fs/jffs2/xattr.c index 4da09ce1d1f5..25bc1ae08648 100644 --- a/trunk/fs/jffs2/xattr.c +++ b/trunk/fs/jffs2/xattr.c @@ -1215,6 +1215,7 @@ int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xatt rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); if (rc) { JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen); + rc = rc ? rc : -EBADFD; goto out; } rc = save_xattr_datum(c, xd); diff --git a/trunk/fs/jfs/inode.c b/trunk/fs/jfs/inode.c index a223cf4faa9b..43e3f566aad6 100644 --- a/trunk/fs/jfs/inode.c +++ b/trunk/fs/jfs/inode.c @@ -168,15 +168,16 @@ void jfs_dirty_inode(struct inode *inode) set_cflag(COMMIT_Dirty, inode); } -int jfs_get_block(struct inode *ip, sector_t lblock, - struct buffer_head *bh_result, int create) +static int +jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks, + struct buffer_head *bh_result, int create) { s64 lblock64 = lblock; int rc = 0; xad_t xad; s64 xaddr; int xflag; - s32 xlen = bh_result->b_size >> ip->i_blkbits; + s32 xlen = max_blocks; /* * Take appropriate lock on inode @@ -187,7 +188,7 @@ int jfs_get_block(struct inode *ip, sector_t lblock, IREAD_LOCK(ip); if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && - (!xtLookup(ip, lblock64, xlen, &xflag, &xaddr, &xlen, 0)) && + (!xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)) && xaddr) { if (xflag & XAD_NOTRECORDED) { if (!create) @@ -254,6 +255,13 @@ int jfs_get_block(struct inode *ip, sector_t lblock, return rc; } +static int jfs_get_block(struct inode *ip, sector_t lblock, + struct buffer_head *bh_result, int create) +{ + return jfs_get_blocks(ip, lblock, bh_result->b_size >> ip->i_blkbits, + bh_result, create); +} + static int jfs_writepage(struct page *page, struct writeback_control *wbc) { return nobh_writepage(page, jfs_get_block, wbc); diff --git a/trunk/fs/jfs/jfs_inode.h b/trunk/fs/jfs/jfs_inode.h index 1fc48df670c8..b5c7da6190dc 100644 --- a/trunk/fs/jfs/jfs_inode.h +++ b/trunk/fs/jfs/jfs_inode.h @@ -32,7 +32,6 @@ extern void jfs_truncate_nolock(struct inode *, loff_t); extern void jfs_free_zero_link(struct inode *); extern struct dentry *jfs_get_parent(struct dentry *dentry); extern void jfs_set_inode_flags(struct inode *); -extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int); extern const struct address_space_operations jfs_aops; extern struct inode_operations jfs_dir_inode_operations; diff --git a/trunk/fs/jfs/super.c b/trunk/fs/jfs/super.c index 143bcd1d5eaa..4f6cfebc82db 100644 --- a/trunk/fs/jfs/super.c +++ b/trunk/fs/jfs/super.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -299,7 +298,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, break; } -#ifdef CONFIG_QUOTA +#if defined(CONFIG_QUOTA) case Opt_quota: case Opt_usrquota: *flag |= JFS_USRQUOTA; @@ -598,7 +597,7 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs) if (sbi->flag & JFS_NOINTEGRITY) seq_puts(seq, ",nointegrity"); -#ifdef CONFIG_QUOTA +#if defined(CONFIG_QUOTA) if (sbi->flag & JFS_USRQUOTA) seq_puts(seq, ",usrquota"); @@ -609,113 +608,6 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs) return 0; } -#ifdef CONFIG_QUOTA - -/* Read data from quotafile - avoid pagecache and such because we cannot afford - * acquiring the locks... As quota files are never truncated and quota code - * itself serializes the operations (and noone else should touch the files) - * we don't have to be afraid of races */ -static ssize_t jfs_quota_read(struct super_block *sb, int type, char *data, - size_t len, loff_t off) -{ - struct inode *inode = sb_dqopt(sb)->files[type]; - sector_t blk = off >> sb->s_blocksize_bits; - int err = 0; - int offset = off & (sb->s_blocksize - 1); - int tocopy; - size_t toread; - struct buffer_head tmp_bh; - struct buffer_head *bh; - loff_t i_size = i_size_read(inode); - - if (off > i_size) - return 0; - if (off+len > i_size) - len = i_size-off; - toread = len; - while (toread > 0) { - tocopy = sb->s_blocksize - offset < toread ? - sb->s_blocksize - offset : toread; - - tmp_bh.b_state = 0; - tmp_bh.b_size = 1 << inode->i_blkbits; - err = jfs_get_block(inode, blk, &tmp_bh, 0); - if (err) - return err; - if (!buffer_mapped(&tmp_bh)) /* A hole? */ - memset(data, 0, tocopy); - else { - bh = sb_bread(sb, tmp_bh.b_blocknr); - if (!bh) - return -EIO; - memcpy(data, bh->b_data+offset, tocopy); - brelse(bh); - } - offset = 0; - toread -= tocopy; - data += tocopy; - blk++; - } - return len; -} - -/* Write to quotafile */ -static ssize_t jfs_quota_write(struct super_block *sb, int type, - const char *data, size_t len, loff_t off) -{ - struct inode *inode = sb_dqopt(sb)->files[type]; - sector_t blk = off >> sb->s_blocksize_bits; - int err = 0; - int offset = off & (sb->s_blocksize - 1); - int tocopy; - size_t towrite = len; - struct buffer_head tmp_bh; - struct buffer_head *bh; - - mutex_lock(&inode->i_mutex); - while (towrite > 0) { - tocopy = sb->s_blocksize - offset < towrite ? - sb->s_blocksize - offset : towrite; - - tmp_bh.b_state = 0; - tmp_bh.b_size = 1 << inode->i_blkbits; - err = jfs_get_block(inode, blk, &tmp_bh, 1); - if (err) - goto out; - if (offset || tocopy != sb->s_blocksize) - bh = sb_bread(sb, tmp_bh.b_blocknr); - else - bh = sb_getblk(sb, tmp_bh.b_blocknr); - if (!bh) { - err = -EIO; - goto out; - } - lock_buffer(bh); - memcpy(bh->b_data+offset, data, tocopy); - flush_dcache_page(bh->b_page); - set_buffer_uptodate(bh); - mark_buffer_dirty(bh); - unlock_buffer(bh); - brelse(bh); - offset = 0; - towrite -= tocopy; - data += tocopy; - blk++; - } -out: - if (len == towrite) - return err; - if (inode->i_size < off+len-towrite) - i_size_write(inode, off+len-towrite); - inode->i_version++; - inode->i_mtime = inode->i_ctime = CURRENT_TIME; - mark_inode_dirty(inode); - mutex_unlock(&inode->i_mutex); - return len - towrite; -} - -#endif - static struct super_operations jfs_super_operations = { .alloc_inode = jfs_alloc_inode, .destroy_inode = jfs_destroy_inode, @@ -729,11 +621,7 @@ static struct super_operations jfs_super_operations = { .unlockfs = jfs_unlockfs, .statfs = jfs_statfs, .remount_fs = jfs_remount, - .show_options = jfs_show_options, -#ifdef CONFIG_QUOTA - .quota_read = jfs_quota_read, - .quota_write = jfs_quota_write, -#endif + .show_options = jfs_show_options }; static struct export_operations jfs_export_operations = { diff --git a/trunk/fs/lockd/clntproc.c b/trunk/fs/lockd/clntproc.c index 50dbb67ae0c4..89ba0df14c22 100644 --- a/trunk/fs/lockd/clntproc.c +++ b/trunk/fs/lockd/clntproc.c @@ -151,13 +151,11 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req) int nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) { - struct rpc_clnt *client = NFS_CLIENT(inode); - struct sockaddr_in addr; struct nlm_host *host; struct nlm_rqst *call; sigset_t oldset; unsigned long flags; - int status, vers; + int status, proto, vers; vers = (NFS_PROTO(inode)->version == 3) ? 4 : 1; if (NFS_PROTO(inode)->version > 3) { @@ -165,8 +163,10 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) return -ENOLCK; } - rpc_peeraddr(client, (struct sockaddr *) &addr, sizeof(addr)); - host = nlmclnt_lookup_host(&addr, client->cl_xprt->prot, vers); + /* Retrieve transport protocol from NFS client */ + proto = NFS_CLIENT(inode)->cl_xprt->prot; + + host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers); if (host == NULL) return -ENOLCK; diff --git a/trunk/fs/lockd/host.c b/trunk/fs/lockd/host.c index 703fb038c813..38b0e8a1aec0 100644 --- a/trunk/fs/lockd/host.c +++ b/trunk/fs/lockd/host.c @@ -26,6 +26,7 @@ #define NLM_HOST_REBIND (60 * HZ) #define NLM_HOST_EXPIRE ((nrhosts > NLM_HOST_MAX)? 300 * HZ : 120 * HZ) #define NLM_HOST_COLLECT ((nrhosts > NLM_HOST_MAX)? 120 * HZ : 60 * HZ) +#define NLM_HOST_ADDR(sv) (&(sv)->s_nlmclnt->cl_xprt->addr) static struct nlm_host * nlm_hosts[NLM_HOST_NRHASH]; static unsigned long next_gc; @@ -166,6 +167,7 @@ struct rpc_clnt * nlm_bind_host(struct nlm_host *host) { struct rpc_clnt *clnt; + struct rpc_xprt *xprt; dprintk("lockd: nlm_bind_host(%08x)\n", (unsigned)ntohl(host->h_addr.sin_addr.s_addr)); @@ -177,6 +179,7 @@ nlm_bind_host(struct nlm_host *host) * RPC rebind is required */ if ((clnt = host->h_rpcclnt) != NULL) { + xprt = clnt->cl_xprt; if (time_after_eq(jiffies, host->h_nextrebind)) { rpc_force_rebind(clnt); host->h_nextrebind = jiffies + NLM_HOST_REBIND; @@ -184,37 +187,31 @@ nlm_bind_host(struct nlm_host *host) host->h_nextrebind - jiffies); } } else { - unsigned long increment = nlmsvc_timeout * HZ; - struct rpc_timeout timeparms = { - .to_initval = increment, - .to_increment = increment, - .to_maxval = increment * 6UL, - .to_retries = 5U, - }; - struct rpc_create_args args = { - .protocol = host->h_proto, - .address = (struct sockaddr *)&host->h_addr, - .addrsize = sizeof(host->h_addr), - .timeout = &timeparms, - .servername = host->h_name, - .program = &nlm_program, - .version = host->h_version, - .authflavor = RPC_AUTH_UNIX, - .flags = (RPC_CLNT_CREATE_HARDRTRY | - RPC_CLNT_CREATE_AUTOBIND), - }; - - clnt = rpc_create(&args); - if (!IS_ERR(clnt)) - host->h_rpcclnt = clnt; - else { - printk("lockd: couldn't create RPC handle for %s\n", host->h_name); - clnt = NULL; - } + xprt = xprt_create_proto(host->h_proto, &host->h_addr, NULL); + if (IS_ERR(xprt)) + goto forgetit; + + xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout); + xprt->resvport = 1; /* NLM requires a reserved port */ + + /* Existing NLM servers accept AUTH_UNIX only */ + clnt = rpc_new_client(xprt, host->h_name, &nlm_program, + host->h_version, RPC_AUTH_UNIX); + if (IS_ERR(clnt)) + goto forgetit; + clnt->cl_autobind = 1; /* turn on pmap queries */ + clnt->cl_softrtry = 1; /* All queries are soft */ + + host->h_rpcclnt = clnt; } mutex_unlock(&host->h_mutex); return clnt; + +forgetit: + printk("lockd: couldn't create RPC handle for %s\n", host->h_name); + mutex_unlock(&host->h_mutex); + return NULL; } /* diff --git a/trunk/fs/lockd/mon.c b/trunk/fs/lockd/mon.c index 5954dcb497e4..3fc683f46b3e 100644 --- a/trunk/fs/lockd/mon.c +++ b/trunk/fs/lockd/mon.c @@ -109,23 +109,30 @@ nsm_unmonitor(struct nlm_host *host) static struct rpc_clnt * nsm_create(void) { - struct sockaddr_in sin = { - .sin_family = AF_INET, - .sin_addr.s_addr = htonl(INADDR_LOOPBACK), - .sin_port = 0, - }; - struct rpc_create_args args = { - .protocol = IPPROTO_UDP, - .address = (struct sockaddr *)&sin, - .addrsize = sizeof(sin), - .servername = "localhost", - .program = &nsm_program, - .version = SM_VERSION, - .authflavor = RPC_AUTH_NULL, - .flags = (RPC_CLNT_CREATE_ONESHOT), - }; - - return rpc_create(&args); + struct rpc_xprt *xprt; + struct rpc_clnt *clnt; + struct sockaddr_in sin; + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + sin.sin_port = 0; + + xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL); + if (IS_ERR(xprt)) + return (struct rpc_clnt *)xprt; + xprt->resvport = 1; /* NSM requires a reserved port */ + + clnt = rpc_create_client(xprt, "localhost", + &nsm_program, SM_VERSION, + RPC_AUTH_NULL); + if (IS_ERR(clnt)) + goto out_err; + clnt->cl_softrtry = 1; + clnt->cl_oneshot = 1; + return clnt; + +out_err: + return clnt; } /* diff --git a/trunk/fs/lockd/svclock.c b/trunk/fs/lockd/svclock.c index c9d419703cf3..baf5ae513481 100644 --- a/trunk/fs/lockd/svclock.c +++ b/trunk/fs/lockd/svclock.c @@ -638,6 +638,9 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) if (task->tk_status < 0) { /* RPC error: Re-insert for retransmission */ timeout = 10 * HZ; + } else if (block->b_done) { + /* Block already removed, kill it for real */ + timeout = 0; } else { /* Call was successful, now wait for client callback */ timeout = 60 * HZ; @@ -706,10 +709,13 @@ nlmsvc_retry_blocked(void) break; if (time_after(block->b_when,jiffies)) break; - dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", - block, block->b_when); + dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n", + block, block->b_when, block->b_done); kref_get(&block->b_count); - nlmsvc_grant_blocked(block); + if (block->b_done) + nlmsvc_unlink_block(block); + else + nlmsvc_grant_blocked(block); nlmsvc_release_block(block); } diff --git a/trunk/fs/lockd/svcsubs.c b/trunk/fs/lockd/svcsubs.c index 01b4db9e5466..2a4df9b3779a 100644 --- a/trunk/fs/lockd/svcsubs.c +++ b/trunk/fs/lockd/svcsubs.c @@ -237,22 +237,19 @@ static int nlm_traverse_files(struct nlm_host *host, int action) { struct nlm_file *file, **fp; - int i, ret = 0; + int i; mutex_lock(&nlm_file_mutex); for (i = 0; i < FILE_NRHASH; i++) { fp = nlm_files + i; while ((file = *fp) != NULL) { - file->f_count++; - mutex_unlock(&nlm_file_mutex); - /* Traverse locks, blocks and shares of this file * and update file->f_locks count */ - if (nlm_inspect_file(host, file, action)) - ret = 1; + if (nlm_inspect_file(host, file, action)) { + mutex_unlock(&nlm_file_mutex); + return 1; + } - mutex_lock(&nlm_file_mutex); - file->f_count--; /* No more references to this file. Let go of it. */ if (!file->f_blocks && !file->f_locks && !file->f_shares && !file->f_count) { @@ -265,7 +262,7 @@ nlm_traverse_files(struct nlm_host *host, int action) } } mutex_unlock(&nlm_file_mutex); - return ret; + return 0; } /* diff --git a/trunk/fs/locks.c b/trunk/fs/locks.c index d7c53392cac1..b0b41a64e10b 100644 --- a/trunk/fs/locks.c +++ b/trunk/fs/locks.c @@ -1421,9 +1421,8 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp) if (!leases_enable) goto out; - error = -ENOMEM; - fl = locks_alloc_lock(); - if (fl == NULL) + error = lease_alloc(filp, arg, &fl); + if (error) goto out; locks_copy_lock(fl, lease); @@ -1431,7 +1430,6 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp) locks_insert_lock(before, fl); *flp = fl; - error = 0; out: return error; } diff --git a/trunk/fs/minix/inode.c b/trunk/fs/minix/inode.c index 330ff9fc7cf0..9ea91c5eeb7b 100644 --- a/trunk/fs/minix/inode.c +++ b/trunk/fs/minix/inode.c @@ -204,8 +204,6 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) /* * Allocate the buffer map to keep the superblock small. */ - if (sbi->s_imap_blocks == 0 || sbi->s_zmap_blocks == 0) - goto out_illegal_sb; i = (sbi->s_imap_blocks + sbi->s_zmap_blocks) * sizeof(bh); map = kmalloc(i, GFP_KERNEL); if (!map) @@ -265,7 +263,7 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) out_no_bitmap: printk("MINIX-fs: bad superblock or unable to read bitmaps\n"); -out_freemap: + out_freemap: for (i = 0; i < sbi->s_imap_blocks; i++) brelse(sbi->s_imap[i]); for (i = 0; i < sbi->s_zmap_blocks; i++) @@ -278,16 +276,11 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) printk("MINIX-fs: can't allocate map\n"); goto out_release; -out_illegal_sb: - if (!silent) - printk("MINIX-fs: bad superblock\n"); - goto out_release; - out_no_fs: if (!silent) printk("VFS: Can't find a Minix or Minix V2 filesystem " "on device %s\n", s->s_id); -out_release: + out_release: brelse(bh); goto out; @@ -297,7 +290,7 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) out_bad_sb: printk("MINIX-fs: unable to read superblock\n"); -out: + out: s->s_fs_info = NULL; kfree(sbi); return -EINVAL; diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index 432d6bc6fab0..e01070d7bf58 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -159,7 +159,7 @@ char * getname(const char __user * filename) #ifdef CONFIG_AUDITSYSCALL void putname(const char *name) { - if (unlikely(!audit_dummy_context())) + if (unlikely(current->audit_context)) audit_putname(name); else __putname(name); @@ -227,10 +227,10 @@ int generic_permission(struct inode *inode, int mask, int permission(struct inode *inode, int mask, struct nameidata *nd) { - umode_t mode = inode->i_mode; int retval, submask; if (mask & MAY_WRITE) { + umode_t mode = inode->i_mode; /* * Nobody gets write access to a read-only fs. @@ -247,13 +247,6 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) } - /* - * MAY_EXEC on regular files requires special handling: We override - * filesystem execute permissions if the mode bits aren't set. - */ - if ((mask & MAY_EXEC) && S_ISREG(mode) && !(mode & S_IXUGO)) - return -EACCES; - /* Ordinary permission routines do not understand MAY_APPEND. */ submask = mask & ~MAY_APPEND; if (inode->i_op && inode->i_op->permission) @@ -1132,7 +1125,7 @@ static int fastcall do_path_lookup(int dfd, const char *name, retval = link_path_walk(name, nd); out: if (likely(retval == 0)) { - if (unlikely(!audit_dummy_context() && nd && nd->dentry && + if (unlikely(current->audit_context && nd && nd->dentry && nd->dentry->d_inode)) audit_inode(name, nd->dentry->d_inode); } @@ -1364,7 +1357,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) return -ENOENT; BUG_ON(victim->d_parent->d_inode != dir); - audit_inode_child(victim->d_name.name, victim->d_inode, dir); + audit_inode_child(victim->d_name.name, victim->d_inode, dir->i_ino); error = permission(dir,MAY_WRITE | MAY_EXEC, NULL); if (error) @@ -1666,7 +1659,6 @@ int open_namei(int dfd, const char *pathname, int flag, * It already exists. */ mutex_unlock(&dir->d_inode->i_mutex); - audit_inode_update(path.dentry->d_inode); error = -EEXIST; if (flag & O_EXCL) @@ -1677,7 +1669,6 @@ int open_namei(int dfd, const char *pathname, int flag, if (flag & O_NOFOLLOW) goto exit_dput; } - error = -ENOENT; if (!path.dentry->d_inode) goto exit_dput; @@ -1774,8 +1765,6 @@ struct dentry *lookup_create(struct nameidata *nd, int is_dir) if (nd->last_type != LAST_NORM) goto fail; nd->flags &= ~LOOKUP_PARENT; - nd->flags |= LOOKUP_CREATE; - nd->intent.open.flags = O_EXCL; /* * Do the final lookup. diff --git a/trunk/fs/nfs/Makefile b/trunk/fs/nfs/Makefile index f4580b44eef4..0b572a0c1967 100644 --- a/trunk/fs/nfs/Makefile +++ b/trunk/fs/nfs/Makefile @@ -4,9 +4,9 @@ obj-$(CONFIG_NFS_FS) += nfs.o -nfs-y := client.o dir.o file.o getroot.o inode.o super.o nfs2xdr.o \ - pagelist.o proc.o read.o symlink.o unlink.o \ - write.o namespace.o +nfs-y := dir.o file.o inode.o super.o nfs2xdr.o pagelist.o \ + proc.o read.o symlink.o unlink.o write.o \ + namespace.o nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o diff --git a/trunk/fs/nfs/callback.c b/trunk/fs/nfs/callback.c index a3ee11364db0..fe0a6b8ac149 100644 --- a/trunk/fs/nfs/callback.c +++ b/trunk/fs/nfs/callback.c @@ -19,7 +19,6 @@ #include "nfs4_fs.h" #include "callback.h" -#include "internal.h" #define NFSDBG_FACILITY NFSDBG_CALLBACK @@ -37,21 +36,6 @@ static struct svc_program nfs4_callback_program; unsigned int nfs_callback_set_tcpport; unsigned short nfs_callback_tcpport; -static const int nfs_set_port_min = 0; -static const int nfs_set_port_max = 65535; - -static int param_set_port(const char *val, struct kernel_param *kp) -{ - char *endp; - int num = simple_strtol(val, &endp, 0); - if (endp == val || *endp || num < nfs_set_port_min || num > nfs_set_port_max) - return -EINVAL; - *((int *)kp->arg) = num; - return 0; -} - -module_param_call(callback_tcpport, param_set_port, param_get_int, - &nfs_callback_set_tcpport, 0644); /* * This is the callback kernel thread. @@ -150,8 +134,10 @@ int nfs_callback_up(void) /* * Kill the server process if it is not already up. */ -void nfs_callback_down(void) +int nfs_callback_down(void) { + int ret = 0; + lock_kernel(); mutex_lock(&nfs_callback_mutex); nfs_callback_info.users--; @@ -163,19 +149,20 @@ void nfs_callback_down(void) } while (wait_for_completion_timeout(&nfs_callback_info.stopped, 5*HZ) == 0); mutex_unlock(&nfs_callback_mutex); unlock_kernel(); + return ret; } static int nfs_callback_authenticate(struct svc_rqst *rqstp) { - struct sockaddr_in *addr = &rqstp->rq_addr; - struct nfs_client *clp; + struct in_addr *addr = &rqstp->rq_addr.sin_addr; + struct nfs4_client *clp; /* Don't talk to strangers */ - clp = nfs_find_client(addr, 4); + clp = nfs4_find_client(addr); if (clp == NULL) return SVC_DROP; - dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr->sin_addr)); - nfs_put_client(clp); + dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr)); + nfs4_put_client(clp); switch (rqstp->rq_authop->flavour) { case RPC_AUTH_NULL: if (rqstp->rq_proc != CB_NULL) diff --git a/trunk/fs/nfs/callback.h b/trunk/fs/nfs/callback.h index 5676163d26e8..b252e7fe53a5 100644 --- a/trunk/fs/nfs/callback.h +++ b/trunk/fs/nfs/callback.h @@ -62,13 +62,8 @@ struct cb_recallargs { extern unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res); extern unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy); -#ifdef CONFIG_NFS_V4 extern int nfs_callback_up(void); -extern void nfs_callback_down(void); -#else -#define nfs_callback_up() (0) -#define nfs_callback_down() do {} while(0) -#endif +extern int nfs_callback_down(void); extern unsigned int nfs_callback_set_tcpport; extern unsigned short nfs_callback_tcpport; diff --git a/trunk/fs/nfs/callback_proc.c b/trunk/fs/nfs/callback_proc.c index 97cf8f71451f..7719483ecdfc 100644 --- a/trunk/fs/nfs/callback_proc.c +++ b/trunk/fs/nfs/callback_proc.c @@ -10,20 +10,19 @@ #include "nfs4_fs.h" #include "callback.h" #include "delegation.h" -#include "internal.h" #define NFSDBG_FACILITY NFSDBG_CALLBACK unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res) { - struct nfs_client *clp; + struct nfs4_client *clp; struct nfs_delegation *delegation; struct nfs_inode *nfsi; struct inode *inode; res->bitmap[0] = res->bitmap[1] = 0; res->status = htonl(NFS4ERR_BADHANDLE); - clp = nfs_find_client(args->addr, 4); + clp = nfs4_find_client(&args->addr->sin_addr); if (clp == NULL) goto out; inode = nfs_delegation_find_inode(clp, &args->fh); @@ -49,7 +48,7 @@ unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres up_read(&nfsi->rwsem); iput(inode); out_putclient: - nfs_put_client(clp); + nfs4_put_client(clp); out: dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res->status)); return res->status; @@ -57,12 +56,12 @@ unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy) { - struct nfs_client *clp; + struct nfs4_client *clp; struct inode *inode; unsigned res; res = htonl(NFS4ERR_BADHANDLE); - clp = nfs_find_client(args->addr, 4); + clp = nfs4_find_client(&args->addr->sin_addr); if (clp == NULL) goto out; inode = nfs_delegation_find_inode(clp, &args->fh); @@ -81,7 +80,7 @@ unsigned nfs4_callback_recall(struct cb_recallargs *args, void *dummy) } iput(inode); out_putclient: - nfs_put_client(clp); + nfs4_put_client(clp); out: dprintk("%s: exit with status = %d\n", __FUNCTION__, ntohl(res)); return res; diff --git a/trunk/fs/nfs/client.c b/trunk/fs/nfs/client.c deleted file mode 100644 index ec1938d4b814..000000000000 --- a/trunk/fs/nfs/client.c +++ /dev/null @@ -1,1448 +0,0 @@ -/* client.c: NFS client sharing and management code - * - * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "nfs4_fs.h" -#include "callback.h" -#include "delegation.h" -#include "iostat.h" -#include "internal.h" - -#define NFSDBG_FACILITY NFSDBG_CLIENT - -static DEFINE_SPINLOCK(nfs_client_lock); -static LIST_HEAD(nfs_client_list); -static LIST_HEAD(nfs_volume_list); -static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); - -/* - * RPC cruft for NFS - */ -static struct rpc_version *nfs_version[5] = { - [2] = &nfs_version2, -#ifdef CONFIG_NFS_V3 - [3] = &nfs_version3, -#endif -#ifdef CONFIG_NFS_V4 - [4] = &nfs_version4, -#endif -}; - -struct rpc_program nfs_program = { - .name = "nfs", - .number = NFS_PROGRAM, - .nrvers = ARRAY_SIZE(nfs_version), - .version = nfs_version, - .stats = &nfs_rpcstat, - .pipe_dir_name = "/nfs", -}; - -struct rpc_stat nfs_rpcstat = { - .program = &nfs_program -}; - - -#ifdef CONFIG_NFS_V3_ACL -static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; -static struct rpc_version * nfsacl_version[] = { - [3] = &nfsacl_version3, -}; - -struct rpc_program nfsacl_program = { - .name = "nfsacl", - .number = NFS_ACL_PROGRAM, - .nrvers = ARRAY_SIZE(nfsacl_version), - .version = nfsacl_version, - .stats = &nfsacl_rpcstat, -}; -#endif /* CONFIG_NFS_V3_ACL */ - -/* - * Allocate a shared client record - * - * Since these are allocated/deallocated very rarely, we don't - * bother putting them in a slab cache... - */ -static struct nfs_client *nfs_alloc_client(const char *hostname, - const struct sockaddr_in *addr, - int nfsversion) -{ - struct nfs_client *clp; - int error; - - if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) - goto error_0; - - error = rpciod_up(); - if (error < 0) { - dprintk("%s: couldn't start rpciod! Error = %d\n", - __FUNCTION__, error); - goto error_1; - } - __set_bit(NFS_CS_RPCIOD, &clp->cl_res_state); - - if (nfsversion == 4) { - if (nfs_callback_up() < 0) - goto error_2; - __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state); - } - - atomic_set(&clp->cl_count, 1); - clp->cl_cons_state = NFS_CS_INITING; - - clp->cl_nfsversion = nfsversion; - memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr)); - - if (hostname) { - clp->cl_hostname = kstrdup(hostname, GFP_KERNEL); - if (!clp->cl_hostname) - goto error_3; - } - - INIT_LIST_HEAD(&clp->cl_superblocks); - clp->cl_rpcclient = ERR_PTR(-EINVAL); - -#ifdef CONFIG_NFS_V4 - init_rwsem(&clp->cl_sem); - INIT_LIST_HEAD(&clp->cl_delegations); - INIT_LIST_HEAD(&clp->cl_state_owners); - INIT_LIST_HEAD(&clp->cl_unused); - spin_lock_init(&clp->cl_lock); - INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); - rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); - clp->cl_boot_time = CURRENT_TIME; - clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; -#endif - - return clp; - -error_3: - if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) - nfs_callback_down(); -error_2: - rpciod_down(); - __clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state); -error_1: - kfree(clp); -error_0: - return NULL; -} - -static void nfs4_shutdown_client(struct nfs_client *clp) -{ -#ifdef CONFIG_NFS_V4 - if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state)) - nfs4_kill_renewd(clp); - while (!list_empty(&clp->cl_unused)) { - struct nfs4_state_owner *sp; - - sp = list_entry(clp->cl_unused.next, - struct nfs4_state_owner, - so_list); - list_del(&sp->so_list); - kfree(sp); - } - BUG_ON(!list_empty(&clp->cl_state_owners)); - if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) - nfs_idmap_delete(clp); -#endif -} - -/* - * Destroy a shared client record - */ -static void nfs_free_client(struct nfs_client *clp) -{ - dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion); - - nfs4_shutdown_client(clp); - - /* -EIO all pending I/O */ - if (!IS_ERR(clp->cl_rpcclient)) - rpc_shutdown_client(clp->cl_rpcclient); - - if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) - nfs_callback_down(); - - if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state)) - rpciod_down(); - - kfree(clp->cl_hostname); - kfree(clp); - - dprintk("<-- nfs_free_client()\n"); -} - -/* - * Release a reference to a shared client record - */ -void nfs_put_client(struct nfs_client *clp) -{ - if (!clp) - return; - - dprintk("--> nfs_put_client({%d})\n", atomic_read(&clp->cl_count)); - - if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) { - list_del(&clp->cl_share_link); - spin_unlock(&nfs_client_lock); - - BUG_ON(!list_empty(&clp->cl_superblocks)); - - nfs_free_client(clp); - } -} - -/* - * Find a client by address - * - caller must hold nfs_client_lock - */ -static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion) -{ - struct nfs_client *clp; - - list_for_each_entry(clp, &nfs_client_list, cl_share_link) { - /* Different NFS versions cannot share the same nfs_client */ - if (clp->cl_nfsversion != nfsversion) - continue; - - if (memcmp(&clp->cl_addr.sin_addr, &addr->sin_addr, - sizeof(clp->cl_addr.sin_addr)) != 0) - continue; - - if (clp->cl_addr.sin_port == addr->sin_port) - goto found; - } - - return NULL; - -found: - atomic_inc(&clp->cl_count); - return clp; -} - -/* - * Find a client by IP address and protocol version - * - returns NULL if no such client - */ -struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversion) -{ - struct nfs_client *clp; - - spin_lock(&nfs_client_lock); - clp = __nfs_find_client(addr, nfsversion); - spin_unlock(&nfs_client_lock); - - BUG_ON(clp && clp->cl_cons_state == 0); - - return clp; -} - -/* - * Look up a client by IP address and protocol version - * - creates a new record if one doesn't yet exist - */ -static struct nfs_client *nfs_get_client(const char *hostname, - const struct sockaddr_in *addr, - int nfsversion) -{ - struct nfs_client *clp, *new = NULL; - int error; - - dprintk("--> nfs_get_client(%s,"NIPQUAD_FMT":%d,%d)\n", - hostname ?: "", NIPQUAD(addr->sin_addr), - addr->sin_port, nfsversion); - - /* see if the client already exists */ - do { - spin_lock(&nfs_client_lock); - - clp = __nfs_find_client(addr, nfsversion); - if (clp) - goto found_client; - if (new) - goto install_client; - - spin_unlock(&nfs_client_lock); - - new = nfs_alloc_client(hostname, addr, nfsversion); - } while (new); - - return ERR_PTR(-ENOMEM); - - /* install a new client and return with it unready */ -install_client: - clp = new; - list_add(&clp->cl_share_link, &nfs_client_list); - spin_unlock(&nfs_client_lock); - dprintk("--> nfs_get_client() = %p [new]\n", clp); - return clp; - - /* found an existing client - * - make sure it's ready before returning - */ -found_client: - spin_unlock(&nfs_client_lock); - - if (new) - nfs_free_client(new); - - if (clp->cl_cons_state == NFS_CS_INITING) { - DECLARE_WAITQUEUE(myself, current); - - add_wait_queue(&nfs_client_active_wq, &myself); - - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (signal_pending(current) || - clp->cl_cons_state > NFS_CS_READY) - break; - schedule(); - } - - remove_wait_queue(&nfs_client_active_wq, &myself); - - if (signal_pending(current)) { - nfs_put_client(clp); - return ERR_PTR(-ERESTARTSYS); - } - } - - if (clp->cl_cons_state < NFS_CS_READY) { - error = clp->cl_cons_state; - nfs_put_client(clp); - return ERR_PTR(error); - } - - BUG_ON(clp->cl_cons_state != NFS_CS_READY); - - dprintk("--> nfs_get_client() = %p [share]\n", clp); - return clp; -} - -/* - * Mark a server as ready or failed - */ -static void nfs_mark_client_ready(struct nfs_client *clp, int state) -{ - clp->cl_cons_state = state; - wake_up_all(&nfs_client_active_wq); -} - -/* - * Initialise the timeout values for a connection - */ -static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, - unsigned int timeo, unsigned int retrans) -{ - to->to_initval = timeo * HZ / 10; - to->to_retries = retrans; - if (!to->to_retries) - to->to_retries = 2; - - switch (proto) { - case IPPROTO_TCP: - if (!to->to_initval) - to->to_initval = 60 * HZ; - if (to->to_initval > NFS_MAX_TCP_TIMEOUT) - to->to_initval = NFS_MAX_TCP_TIMEOUT; - to->to_increment = to->to_initval; - to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); - to->to_exponential = 0; - break; - case IPPROTO_UDP: - default: - if (!to->to_initval) - to->to_initval = 11 * HZ / 10; - if (to->to_initval > NFS_MAX_UDP_TIMEOUT) - to->to_initval = NFS_MAX_UDP_TIMEOUT; - to->to_maxval = NFS_MAX_UDP_TIMEOUT; - to->to_exponential = 1; - break; - } -} - -/* - * Create an RPC client handle - */ -static int nfs_create_rpc_client(struct nfs_client *clp, int proto, - unsigned int timeo, - unsigned int retrans, - rpc_authflavor_t flavor) -{ - struct rpc_timeout timeparms; - struct rpc_clnt *clnt = NULL; - struct rpc_create_args args = { - .protocol = proto, - .address = (struct sockaddr *)&clp->cl_addr, - .addrsize = sizeof(clp->cl_addr), - .timeout = &timeparms, - .servername = clp->cl_hostname, - .program = &nfs_program, - .version = clp->rpc_ops->version, - .authflavor = flavor, - }; - - if (!IS_ERR(clp->cl_rpcclient)) - return 0; - - nfs_init_timeout_values(&timeparms, proto, timeo, retrans); - clp->retrans_timeo = timeparms.to_initval; - clp->retrans_count = timeparms.to_retries; - - clnt = rpc_create(&args); - if (IS_ERR(clnt)) { - dprintk("%s: cannot create RPC client. Error = %ld\n", - __FUNCTION__, PTR_ERR(clnt)); - return PTR_ERR(clnt); - } - - clp->cl_rpcclient = clnt; - return 0; -} - -/* - * Version 2 or 3 client destruction - */ -static void nfs_destroy_server(struct nfs_server *server) -{ - if (!IS_ERR(server->client_acl)) - rpc_shutdown_client(server->client_acl); - - if (!(server->flags & NFS_MOUNT_NONLM)) - lockd_down(); /* release rpc.lockd */ -} - -/* - * Version 2 or 3 lockd setup - */ -static int nfs_start_lockd(struct nfs_server *server) -{ - int error = 0; - - if (server->nfs_client->cl_nfsversion > 3) - goto out; - if (server->flags & NFS_MOUNT_NONLM) - goto out; - error = lockd_up(); - if (error < 0) - server->flags |= NFS_MOUNT_NONLM; - else - server->destroy = nfs_destroy_server; -out: - return error; -} - -/* - * Initialise an NFSv3 ACL client connection - */ -#ifdef CONFIG_NFS_V3_ACL -static void nfs_init_server_aclclient(struct nfs_server *server) -{ - if (server->nfs_client->cl_nfsversion != 3) - goto out_noacl; - if (server->flags & NFS_MOUNT_NOACL) - goto out_noacl; - - server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); - if (IS_ERR(server->client_acl)) - goto out_noacl; - - /* No errors! Assume that Sun nfsacls are supported */ - server->caps |= NFS_CAP_ACLS; - return; - -out_noacl: - server->caps &= ~NFS_CAP_ACLS; -} -#else -static inline void nfs_init_server_aclclient(struct nfs_server *server) -{ - server->flags &= ~NFS_MOUNT_NOACL; - server->caps &= ~NFS_CAP_ACLS; -} -#endif - -/* - * Create a general RPC client - */ -static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t pseudoflavour) -{ - struct nfs_client *clp = server->nfs_client; - - server->client = rpc_clone_client(clp->cl_rpcclient); - if (IS_ERR(server->client)) { - dprintk("%s: couldn't create rpc_client!\n", __FUNCTION__); - return PTR_ERR(server->client); - } - - if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) { - struct rpc_auth *auth; - - auth = rpcauth_create(pseudoflavour, server->client); - if (IS_ERR(auth)) { - dprintk("%s: couldn't create credcache!\n", __FUNCTION__); - return PTR_ERR(auth); - } - } - server->client->cl_softrtry = 0; - if (server->flags & NFS_MOUNT_SOFT) - server->client->cl_softrtry = 1; - - server->client->cl_intr = 0; - if (server->flags & NFS4_MOUNT_INTR) - server->client->cl_intr = 1; - - return 0; -} - -/* - * Initialise an NFS2 or NFS3 client - */ -static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *data) -{ - int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; - int error; - - if (clp->cl_cons_state == NFS_CS_READY) { - /* the client is already initialised */ - dprintk("<-- nfs_init_client() = 0 [already %p]\n", clp); - return 0; - } - - /* Check NFS protocol revision and initialize RPC op vector */ - clp->rpc_ops = &nfs_v2_clientops; -#ifdef CONFIG_NFS_V3 - if (clp->cl_nfsversion == 3) - clp->rpc_ops = &nfs_v3_clientops; -#endif - /* - * Create a client RPC handle for doing FSSTAT with UNIX auth only - * - RFC 2623, sec 2.3.2 - */ - error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans, - RPC_AUTH_UNIX); - if (error < 0) - goto error; - nfs_mark_client_ready(clp, NFS_CS_READY); - return 0; - -error: - nfs_mark_client_ready(clp, error); - dprintk("<-- nfs_init_client() = xerror %d\n", error); - return error; -} - -/* - * Create a version 2 or 3 client - */ -static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_data *data) -{ - struct nfs_client *clp; - int error, nfsvers = 2; - - dprintk("--> nfs_init_server()\n"); - -#ifdef CONFIG_NFS_V3 - if (data->flags & NFS_MOUNT_VER3) - nfsvers = 3; -#endif - - /* Allocate or find a client reference we can use */ - clp = nfs_get_client(data->hostname, &data->addr, nfsvers); - if (IS_ERR(clp)) { - dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); - return PTR_ERR(clp); - } - - error = nfs_init_client(clp, data); - if (error < 0) - goto error; - - server->nfs_client = clp; - - /* Initialise the client representation from the mount data */ - server->flags = data->flags & NFS_MOUNT_FLAGMASK; - - if (data->rsize) - server->rsize = nfs_block_size(data->rsize, NULL); - if (data->wsize) - server->wsize = nfs_block_size(data->wsize, NULL); - - server->acregmin = data->acregmin * HZ; - server->acregmax = data->acregmax * HZ; - server->acdirmin = data->acdirmin * HZ; - server->acdirmax = data->acdirmax * HZ; - - /* Start lockd here, before we might error out */ - error = nfs_start_lockd(server); - if (error < 0) - goto error; - - error = nfs_init_server_rpcclient(server, data->pseudoflavor); - if (error < 0) - goto error; - - server->namelen = data->namlen; - /* Create a client RPC handle for the NFSv3 ACL management interface */ - nfs_init_server_aclclient(server); - if (clp->cl_nfsversion == 3) { - if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) - server->namelen = NFS3_MAXNAMLEN; - server->caps |= NFS_CAP_READDIRPLUS; - } else { - if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) - server->namelen = NFS2_MAXNAMLEN; - } - - dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp); - return 0; - -error: - server->nfs_client = NULL; - nfs_put_client(clp); - dprintk("<-- nfs_init_server() = xerror %d\n", error); - return error; -} - -/* - * Load up the server record from information gained in an fsinfo record - */ -static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *fsinfo) -{ - unsigned long max_rpc_payload; - - /* Work out a lot of parameters */ - if (server->rsize == 0) - server->rsize = nfs_block_size(fsinfo->rtpref, NULL); - if (server->wsize == 0) - server->wsize = nfs_block_size(fsinfo->wtpref, NULL); - - if (fsinfo->rtmax >= 512 && server->rsize > fsinfo->rtmax) - server->rsize = nfs_block_size(fsinfo->rtmax, NULL); - if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax) - server->wsize = nfs_block_size(fsinfo->wtmax, NULL); - - max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL); - if (server->rsize > max_rpc_payload) - server->rsize = max_rpc_payload; - if (server->rsize > NFS_MAX_FILE_IO_SIZE) - server->rsize = NFS_MAX_FILE_IO_SIZE; - server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD; - - if (server->wsize > max_rpc_payload) - server->wsize = max_rpc_payload; - if (server->wsize > NFS_MAX_FILE_IO_SIZE) - server->wsize = NFS_MAX_FILE_IO_SIZE; - server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); - - server->dtsize = nfs_block_size(fsinfo->dtpref, NULL); - if (server->dtsize > PAGE_CACHE_SIZE) - server->dtsize = PAGE_CACHE_SIZE; - if (server->dtsize > server->rsize) - server->dtsize = server->rsize; - - if (server->flags & NFS_MOUNT_NOAC) { - server->acregmin = server->acregmax = 0; - server->acdirmin = server->acdirmax = 0; - } - - server->maxfilesize = fsinfo->maxfilesize; - - /* We're airborne Set socket buffersize */ - rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100); -} - -/* - * Probe filesystem information, including the FSID on v2/v3 - */ -static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr) -{ - struct nfs_fsinfo fsinfo; - struct nfs_client *clp = server->nfs_client; - int error; - - dprintk("--> nfs_probe_fsinfo()\n"); - - if (clp->rpc_ops->set_capabilities != NULL) { - error = clp->rpc_ops->set_capabilities(server, mntfh); - if (error < 0) - goto out_error; - } - - fsinfo.fattr = fattr; - nfs_fattr_init(fattr); - error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo); - if (error < 0) - goto out_error; - - nfs_server_set_fsinfo(server, &fsinfo); - - /* Get some general file system info */ - if (server->namelen == 0) { - struct nfs_pathconf pathinfo; - - pathinfo.fattr = fattr; - nfs_fattr_init(fattr); - - if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0) - server->namelen = pathinfo.max_namelen; - } - - dprintk("<-- nfs_probe_fsinfo() = 0\n"); - return 0; - -out_error: - dprintk("nfs_probe_fsinfo: error = %d\n", -error); - return error; -} - -/* - * Copy useful information when duplicating a server record - */ -static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) -{ - target->flags = source->flags; - target->acregmin = source->acregmin; - target->acregmax = source->acregmax; - target->acdirmin = source->acdirmin; - target->acdirmax = source->acdirmax; - target->caps = source->caps; -} - -/* - * Allocate and initialise a server record - */ -static struct nfs_server *nfs_alloc_server(void) -{ - struct nfs_server *server; - - server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); - if (!server) - return NULL; - - server->client = server->client_acl = ERR_PTR(-EINVAL); - - /* Zero out the NFS state stuff */ - INIT_LIST_HEAD(&server->client_link); - INIT_LIST_HEAD(&server->master_link); - - server->io_stats = nfs_alloc_iostats(); - if (!server->io_stats) { - kfree(server); - return NULL; - } - - return server; -} - -/* - * Free up a server record - */ -void nfs_free_server(struct nfs_server *server) -{ - dprintk("--> nfs_free_server()\n"); - - spin_lock(&nfs_client_lock); - list_del(&server->client_link); - list_del(&server->master_link); - spin_unlock(&nfs_client_lock); - - if (server->destroy != NULL) - server->destroy(server); - if (!IS_ERR(server->client)) - rpc_shutdown_client(server->client); - - nfs_put_client(server->nfs_client); - - nfs_free_iostats(server->io_stats); - kfree(server); - nfs_release_automount_timer(); - dprintk("<-- nfs_free_server()\n"); -} - -/* - * Create a version 2 or 3 volume record - * - keyed on server and FSID - */ -struct nfs_server *nfs_create_server(const struct nfs_mount_data *data, - struct nfs_fh *mntfh) -{ - struct nfs_server *server; - struct nfs_fattr fattr; - int error; - - server = nfs_alloc_server(); - if (!server) - return ERR_PTR(-ENOMEM); - - /* Get a client representation */ - error = nfs_init_server(server, data); - if (error < 0) - goto error; - - BUG_ON(!server->nfs_client); - BUG_ON(!server->nfs_client->rpc_ops); - BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); - - /* Probe the root fh to retrieve its FSID */ - error = nfs_probe_fsinfo(server, mntfh, &fattr); - if (error < 0) - goto error; - if (!(fattr.valid & NFS_ATTR_FATTR)) { - error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); - if (error < 0) { - dprintk("nfs_create_server: getattr error = %d\n", -error); - goto error; - } - } - memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid)); - - dprintk("Server FSID: %llx:%llx\n", - (unsigned long long) server->fsid.major, - (unsigned long long) server->fsid.minor); - - BUG_ON(!server->nfs_client); - BUG_ON(!server->nfs_client->rpc_ops); - BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); - - spin_lock(&nfs_client_lock); - list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); - list_add_tail(&server->master_link, &nfs_volume_list); - spin_unlock(&nfs_client_lock); - - server->mount_time = jiffies; - return server; - -error: - nfs_free_server(server); - return ERR_PTR(error); -} - -#ifdef CONFIG_NFS_V4 -/* - * Initialise an NFS4 client record - */ -static int nfs4_init_client(struct nfs_client *clp, - int proto, int timeo, int retrans, - rpc_authflavor_t authflavour) -{ - int error; - - if (clp->cl_cons_state == NFS_CS_READY) { - /* the client is initialised already */ - dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp); - return 0; - } - - /* Check NFS protocol revision and initialize RPC op vector */ - clp->rpc_ops = &nfs_v4_clientops; - - error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour); - if (error < 0) - goto error; - - error = nfs_idmap_new(clp); - if (error < 0) { - dprintk("%s: failed to create idmapper. Error = %d\n", - __FUNCTION__, error); - goto error; - } - __set_bit(NFS_CS_IDMAP, &clp->cl_res_state); - - nfs_mark_client_ready(clp, NFS_CS_READY); - return 0; - -error: - nfs_mark_client_ready(clp, error); - dprintk("<-- nfs4_init_client() = xerror %d\n", error); - return error; -} - -/* - * Set up an NFS4 client - */ -static int nfs4_set_client(struct nfs_server *server, - const char *hostname, const struct sockaddr_in *addr, - rpc_authflavor_t authflavour, - int proto, int timeo, int retrans) -{ - struct nfs_client *clp; - int error; - - dprintk("--> nfs4_set_client()\n"); - - /* Allocate or find a client reference we can use */ - clp = nfs_get_client(hostname, addr, 4); - if (IS_ERR(clp)) { - error = PTR_ERR(clp); - goto error; - } - error = nfs4_init_client(clp, proto, timeo, retrans, authflavour); - if (error < 0) - goto error_put; - - server->nfs_client = clp; - dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp); - return 0; - -error_put: - nfs_put_client(clp); -error: - dprintk("<-- nfs4_set_client() = xerror %d\n", error); - return error; -} - -/* - * Create a version 4 volume record - */ -static int nfs4_init_server(struct nfs_server *server, - const struct nfs4_mount_data *data, rpc_authflavor_t authflavour) -{ - int error; - - dprintk("--> nfs4_init_server()\n"); - - /* Initialise the client representation from the mount data */ - server->flags = data->flags & NFS_MOUNT_FLAGMASK; - server->caps |= NFS_CAP_ATOMIC_OPEN; - - if (data->rsize) - server->rsize = nfs_block_size(data->rsize, NULL); - if (data->wsize) - server->wsize = nfs_block_size(data->wsize, NULL); - - server->acregmin = data->acregmin * HZ; - server->acregmax = data->acregmax * HZ; - server->acdirmin = data->acdirmin * HZ; - server->acdirmax = data->acdirmax * HZ; - - error = nfs_init_server_rpcclient(server, authflavour); - - /* Done */ - dprintk("<-- nfs4_init_server() = %d\n", error); - return error; -} - -/* - * Create a version 4 volume record - * - keyed on server and FSID - */ -struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data, - const char *hostname, - const struct sockaddr_in *addr, - const char *mntpath, - const char *ip_addr, - rpc_authflavor_t authflavour, - struct nfs_fh *mntfh) -{ - struct nfs_fattr fattr; - struct nfs_server *server; - int error; - - dprintk("--> nfs4_create_server()\n"); - - server = nfs_alloc_server(); - if (!server) - return ERR_PTR(-ENOMEM); - - /* Get a client record */ - error = nfs4_set_client(server, hostname, addr, authflavour, - data->proto, data->timeo, data->retrans); - if (error < 0) - goto error; - - /* set up the general RPC client */ - error = nfs4_init_server(server, data, authflavour); - if (error < 0) - goto error; - - BUG_ON(!server->nfs_client); - BUG_ON(!server->nfs_client->rpc_ops); - BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); - - /* Probe the root fh to retrieve its FSID */ - error = nfs4_path_walk(server, mntfh, mntpath); - if (error < 0) - goto error; - - dprintk("Server FSID: %llx:%llx\n", - (unsigned long long) server->fsid.major, - (unsigned long long) server->fsid.minor); - dprintk("Mount FH: %d\n", mntfh->size); - - error = nfs_probe_fsinfo(server, mntfh, &fattr); - if (error < 0) - goto error; - - BUG_ON(!server->nfs_client); - BUG_ON(!server->nfs_client->rpc_ops); - BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); - - spin_lock(&nfs_client_lock); - list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); - list_add_tail(&server->master_link, &nfs_volume_list); - spin_unlock(&nfs_client_lock); - - server->mount_time = jiffies; - dprintk("<-- nfs4_create_server() = %p\n", server); - return server; - -error: - nfs_free_server(server); - dprintk("<-- nfs4_create_server() = error %d\n", error); - return ERR_PTR(error); -} - -/* - * Create an NFS4 referral server record - */ -struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, - struct nfs_fh *fh) -{ - struct nfs_client *parent_client; - struct nfs_server *server, *parent_server; - struct nfs_fattr fattr; - int error; - - dprintk("--> nfs4_create_referral_server()\n"); - - server = nfs_alloc_server(); - if (!server) - return ERR_PTR(-ENOMEM); - - parent_server = NFS_SB(data->sb); - parent_client = parent_server->nfs_client; - - /* Get a client representation. - * Note: NFSv4 always uses TCP, */ - error = nfs4_set_client(server, data->hostname, data->addr, - data->authflavor, - parent_server->client->cl_xprt->prot, - parent_client->retrans_timeo, - parent_client->retrans_count); - if (error < 0) - goto error; - - /* Initialise the client representation from the parent server */ - nfs_server_copy_userdata(server, parent_server); - server->caps |= NFS_CAP_ATOMIC_OPEN; - - error = nfs_init_server_rpcclient(server, data->authflavor); - if (error < 0) - goto error; - - BUG_ON(!server->nfs_client); - BUG_ON(!server->nfs_client->rpc_ops); - BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); - - /* probe the filesystem info for this server filesystem */ - error = nfs_probe_fsinfo(server, fh, &fattr); - if (error < 0) - goto error; - - dprintk("Referral FSID: %llx:%llx\n", - (unsigned long long) server->fsid.major, - (unsigned long long) server->fsid.minor); - - spin_lock(&nfs_client_lock); - list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); - list_add_tail(&server->master_link, &nfs_volume_list); - spin_unlock(&nfs_client_lock); - - server->mount_time = jiffies; - - dprintk("<-- nfs_create_referral_server() = %p\n", server); - return server; - -error: - nfs_free_server(server); - dprintk("<-- nfs4_create_referral_server() = error %d\n", error); - return ERR_PTR(error); -} - -#endif /* CONFIG_NFS_V4 */ - -/* - * Clone an NFS2, NFS3 or NFS4 server record - */ -struct nfs_server *nfs_clone_server(struct nfs_server *source, - struct nfs_fh *fh, - struct nfs_fattr *fattr) -{ - struct nfs_server *server; - struct nfs_fattr fattr_fsinfo; - int error; - - dprintk("--> nfs_clone_server(,%llx:%llx,)\n", - (unsigned long long) fattr->fsid.major, - (unsigned long long) fattr->fsid.minor); - - server = nfs_alloc_server(); - if (!server) - return ERR_PTR(-ENOMEM); - - /* Copy data from the source */ - server->nfs_client = source->nfs_client; - atomic_inc(&server->nfs_client->cl_count); - nfs_server_copy_userdata(server, source); - - server->fsid = fattr->fsid; - - error = nfs_init_server_rpcclient(server, source->client->cl_auth->au_flavor); - if (error < 0) - goto out_free_server; - if (!IS_ERR(source->client_acl)) - nfs_init_server_aclclient(server); - - /* probe the filesystem info for this server filesystem */ - error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo); - if (error < 0) - goto out_free_server; - - dprintk("Cloned FSID: %llx:%llx\n", - (unsigned long long) server->fsid.major, - (unsigned long long) server->fsid.minor); - - error = nfs_start_lockd(server); - if (error < 0) - goto out_free_server; - - spin_lock(&nfs_client_lock); - list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); - list_add_tail(&server->master_link, &nfs_volume_list); - spin_unlock(&nfs_client_lock); - - server->mount_time = jiffies; - - dprintk("<-- nfs_clone_server() = %p\n", server); - return server; - -out_free_server: - nfs_free_server(server); - dprintk("<-- nfs_clone_server() = error %d\n", error); - return ERR_PTR(error); -} - -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry *proc_fs_nfs; - -static int nfs_server_list_open(struct inode *inode, struct file *file); -static void *nfs_server_list_start(struct seq_file *p, loff_t *pos); -static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos); -static void nfs_server_list_stop(struct seq_file *p, void *v); -static int nfs_server_list_show(struct seq_file *m, void *v); - -static struct seq_operations nfs_server_list_ops = { - .start = nfs_server_list_start, - .next = nfs_server_list_next, - .stop = nfs_server_list_stop, - .show = nfs_server_list_show, -}; - -static struct file_operations nfs_server_list_fops = { - .open = nfs_server_list_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int nfs_volume_list_open(struct inode *inode, struct file *file); -static void *nfs_volume_list_start(struct seq_file *p, loff_t *pos); -static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos); -static void nfs_volume_list_stop(struct seq_file *p, void *v); -static int nfs_volume_list_show(struct seq_file *m, void *v); - -static struct seq_operations nfs_volume_list_ops = { - .start = nfs_volume_list_start, - .next = nfs_volume_list_next, - .stop = nfs_volume_list_stop, - .show = nfs_volume_list_show, -}; - -static struct file_operations nfs_volume_list_fops = { - .open = nfs_volume_list_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -/* - * open "/proc/fs/nfsfs/servers" which provides a summary of servers with which - * we're dealing - */ -static int nfs_server_list_open(struct inode *inode, struct file *file) -{ - struct seq_file *m; - int ret; - - ret = seq_open(file, &nfs_server_list_ops); - if (ret < 0) - return ret; - - m = file->private_data; - m->private = PDE(inode)->data; - - return 0; -} - -/* - * set up the iterator to start reading from the server list and return the first item - */ -static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) -{ - struct list_head *_p; - loff_t pos = *_pos; - - /* lock the list against modification */ - spin_lock(&nfs_client_lock); - - /* allow for the header line */ - if (!pos) - return SEQ_START_TOKEN; - pos--; - - /* find the n'th element in the list */ - list_for_each(_p, &nfs_client_list) - if (!pos--) - break; - - return _p != &nfs_client_list ? _p : NULL; -} - -/* - * move to next server - */ -static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos) -{ - struct list_head *_p; - - (*pos)++; - - _p = v; - _p = (v == SEQ_START_TOKEN) ? nfs_client_list.next : _p->next; - - return _p != &nfs_client_list ? _p : NULL; -} - -/* - * clean up after reading from the transports list - */ -static void nfs_server_list_stop(struct seq_file *p, void *v) -{ - spin_unlock(&nfs_client_lock); -} - -/* - * display a header line followed by a load of call lines - */ -static int nfs_server_list_show(struct seq_file *m, void *v) -{ - struct nfs_client *clp; - - /* display header on line 1 */ - if (v == SEQ_START_TOKEN) { - seq_puts(m, "NV SERVER PORT USE HOSTNAME\n"); - return 0; - } - - /* display one transport per line on subsequent lines */ - clp = list_entry(v, struct nfs_client, cl_share_link); - - seq_printf(m, "v%d %02x%02x%02x%02x %4hx %3d %s\n", - clp->cl_nfsversion, - NIPQUAD(clp->cl_addr.sin_addr), - ntohs(clp->cl_addr.sin_port), - atomic_read(&clp->cl_count), - clp->cl_hostname); - - return 0; -} - -/* - * open "/proc/fs/nfsfs/volumes" which provides a summary of extant volumes - */ -static int nfs_volume_list_open(struct inode *inode, struct file *file) -{ - struct seq_file *m; - int ret; - - ret = seq_open(file, &nfs_volume_list_ops); - if (ret < 0) - return ret; - - m = file->private_data; - m->private = PDE(inode)->data; - - return 0; -} - -/* - * set up the iterator to start reading from the volume list and return the first item - */ -static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) -{ - struct list_head *_p; - loff_t pos = *_pos; - - /* lock the list against modification */ - spin_lock(&nfs_client_lock); - - /* allow for the header line */ - if (!pos) - return SEQ_START_TOKEN; - pos--; - - /* find the n'th element in the list */ - list_for_each(_p, &nfs_volume_list) - if (!pos--) - break; - - return _p != &nfs_volume_list ? _p : NULL; -} - -/* - * move to next volume - */ -static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos) -{ - struct list_head *_p; - - (*pos)++; - - _p = v; - _p = (v == SEQ_START_TOKEN) ? nfs_volume_list.next : _p->next; - - return _p != &nfs_volume_list ? _p : NULL; -} - -/* - * clean up after reading from the transports list - */ -static void nfs_volume_list_stop(struct seq_file *p, void *v) -{ - spin_unlock(&nfs_client_lock); -} - -/* - * display a header line followed by a load of call lines - */ -static int nfs_volume_list_show(struct seq_file *m, void *v) -{ - struct nfs_server *server; - struct nfs_client *clp; - char dev[8], fsid[17]; - - /* display header on line 1 */ - if (v == SEQ_START_TOKEN) { - seq_puts(m, "NV SERVER PORT DEV FSID\n"); - return 0; - } - /* display one transport per line on subsequent lines */ - server = list_entry(v, struct nfs_server, master_link); - clp = server->nfs_client; - - snprintf(dev, 8, "%u:%u", - MAJOR(server->s_dev), MINOR(server->s_dev)); - - snprintf(fsid, 17, "%llx:%llx", - (unsigned long long) server->fsid.major, - (unsigned long long) server->fsid.minor); - - seq_printf(m, "v%d %02x%02x%02x%02x %4hx %-7s %-17s\n", - clp->cl_nfsversion, - NIPQUAD(clp->cl_addr.sin_addr), - ntohs(clp->cl_addr.sin_port), - dev, - fsid); - - return 0; -} - -/* - * initialise the /proc/fs/nfsfs/ directory - */ -int __init nfs_fs_proc_init(void) -{ - struct proc_dir_entry *p; - - proc_fs_nfs = proc_mkdir("nfsfs", proc_root_fs); - if (!proc_fs_nfs) - goto error_0; - - proc_fs_nfs->owner = THIS_MODULE; - - /* a file of servers with which we're dealing */ - p = create_proc_entry("servers", S_IFREG|S_IRUGO, proc_fs_nfs); - if (!p) - goto error_1; - - p->proc_fops = &nfs_server_list_fops; - p->owner = THIS_MODULE; - - /* a file of volumes that we have mounted */ - p = create_proc_entry("volumes", S_IFREG|S_IRUGO, proc_fs_nfs); - if (!p) - goto error_2; - - p->proc_fops = &nfs_volume_list_fops; - p->owner = THIS_MODULE; - return 0; - -error_2: - remove_proc_entry("servers", proc_fs_nfs); -error_1: - remove_proc_entry("nfsfs", proc_root_fs); -error_0: - return -ENOMEM; -} - -/* - * clean up the /proc/fs/nfsfs/ directory - */ -void nfs_fs_proc_exit(void) -{ - remove_proc_entry("volumes", proc_fs_nfs); - remove_proc_entry("servers", proc_fs_nfs); - remove_proc_entry("nfsfs", proc_root_fs); -} - -#endif /* CONFIG_PROC_FS */ diff --git a/trunk/fs/nfs/delegation.c b/trunk/fs/nfs/delegation.c index 57133678db16..9540a316c05e 100644 --- a/trunk/fs/nfs/delegation.c +++ b/trunk/fs/nfs/delegation.c @@ -18,7 +18,6 @@ #include "nfs4_fs.h" #include "delegation.h" -#include "internal.h" static struct nfs_delegation *nfs_alloc_delegation(void) { @@ -53,7 +52,7 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_ case -NFS4ERR_EXPIRED: /* kill_proc(fl->fl_pid, SIGLOST, 1); */ case -NFS4ERR_STALE_CLIENTID: - nfs4_schedule_state_recovery(NFS_SERVER(inode)->nfs_client); + nfs4_schedule_state_recovery(NFS_SERVER(inode)->nfs4_state); goto out_err; } } @@ -115,7 +114,7 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st */ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) { - struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; + struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state; struct nfs_inode *nfsi = NFS_I(inode); struct nfs_delegation *delegation; int status = 0; @@ -146,7 +145,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct sizeof(delegation->stateid)) != 0 || delegation->type != nfsi->delegation->type) { printk("%s: server %u.%u.%u.%u, handed out a duplicate delegation!\n", - __FUNCTION__, NIPQUAD(clp->cl_addr.sin_addr)); + __FUNCTION__, NIPQUAD(clp->cl_addr)); status = -EIO; } } @@ -177,7 +176,7 @@ static void nfs_msync_inode(struct inode *inode) */ int __nfs_inode_return_delegation(struct inode *inode) { - struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; + struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state; struct nfs_inode *nfsi = NFS_I(inode); struct nfs_delegation *delegation; int res = 0; @@ -209,7 +208,7 @@ int __nfs_inode_return_delegation(struct inode *inode) */ void nfs_return_all_delegations(struct super_block *sb) { - struct nfs_client *clp = NFS_SB(sb)->nfs_client; + struct nfs4_client *clp = NFS_SB(sb)->nfs4_state; struct nfs_delegation *delegation; struct inode *inode; @@ -233,7 +232,7 @@ void nfs_return_all_delegations(struct super_block *sb) int nfs_do_expire_all_delegations(void *ptr) { - struct nfs_client *clp = ptr; + struct nfs4_client *clp = ptr; struct nfs_delegation *delegation; struct inode *inode; @@ -255,11 +254,11 @@ int nfs_do_expire_all_delegations(void *ptr) } out: spin_unlock(&clp->cl_lock); - nfs_put_client(clp); + nfs4_put_client(clp); module_put_and_exit(0); } -void nfs_expire_all_delegations(struct nfs_client *clp) +void nfs_expire_all_delegations(struct nfs4_client *clp) { struct task_struct *task; @@ -267,17 +266,17 @@ void nfs_expire_all_delegations(struct nfs_client *clp) atomic_inc(&clp->cl_count); task = kthread_run(nfs_do_expire_all_delegations, clp, "%u.%u.%u.%u-delegreturn", - NIPQUAD(clp->cl_addr.sin_addr)); + NIPQUAD(clp->cl_addr)); if (!IS_ERR(task)) return; - nfs_put_client(clp); + nfs4_put_client(clp); module_put(THIS_MODULE); } /* * Return all delegations following an NFS4ERR_CB_PATH_DOWN error. */ -void nfs_handle_cb_pathdown(struct nfs_client *clp) +void nfs_handle_cb_pathdown(struct nfs4_client *clp) { struct nfs_delegation *delegation; struct inode *inode; @@ -300,7 +299,7 @@ void nfs_handle_cb_pathdown(struct nfs_client *clp) struct recall_threadargs { struct inode *inode; - struct nfs_client *clp; + struct nfs4_client *clp; const nfs4_stateid *stateid; struct completion started; @@ -311,7 +310,7 @@ static int recall_thread(void *data) { struct recall_threadargs *args = (struct recall_threadargs *)data; struct inode *inode = igrab(args->inode); - struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; + struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state; struct nfs_inode *nfsi = NFS_I(inode); struct nfs_delegation *delegation; @@ -372,7 +371,7 @@ int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *s /* * Retrieve the inode associated with a delegation */ -struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle) +struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle) { struct nfs_delegation *delegation; struct inode *res = NULL; @@ -390,7 +389,7 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs /* * Mark all delegations as needing to be reclaimed */ -void nfs_delegation_mark_reclaim(struct nfs_client *clp) +void nfs_delegation_mark_reclaim(struct nfs4_client *clp) { struct nfs_delegation *delegation; spin_lock(&clp->cl_lock); @@ -402,7 +401,7 @@ void nfs_delegation_mark_reclaim(struct nfs_client *clp) /* * Reap all unclaimed delegations after reboot recovery is done */ -void nfs_delegation_reap_unclaimed(struct nfs_client *clp) +void nfs_delegation_reap_unclaimed(struct nfs4_client *clp) { struct nfs_delegation *delegation, *n; LIST_HEAD(head); @@ -424,7 +423,7 @@ void nfs_delegation_reap_unclaimed(struct nfs_client *clp) int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode) { - struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; + struct nfs4_client *clp = NFS_SERVER(inode)->nfs4_state; struct nfs_inode *nfsi = NFS_I(inode); struct nfs_delegation *delegation; int res = 0; diff --git a/trunk/fs/nfs/delegation.h b/trunk/fs/nfs/delegation.h index 2cfd4b24c7fe..3858694652fa 100644 --- a/trunk/fs/nfs/delegation.h +++ b/trunk/fs/nfs/delegation.h @@ -29,13 +29,13 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st int __nfs_inode_return_delegation(struct inode *inode); int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid); -struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle); +struct inode *nfs_delegation_find_inode(struct nfs4_client *clp, const struct nfs_fh *fhandle); void nfs_return_all_delegations(struct super_block *sb); -void nfs_expire_all_delegations(struct nfs_client *clp); -void nfs_handle_cb_pathdown(struct nfs_client *clp); +void nfs_expire_all_delegations(struct nfs4_client *clp); +void nfs_handle_cb_pathdown(struct nfs4_client *clp); -void nfs_delegation_mark_reclaim(struct nfs_client *clp); -void nfs_delegation_reap_unclaimed(struct nfs_client *clp); +void nfs_delegation_mark_reclaim(struct nfs4_client *clp); +void nfs_delegation_reap_unclaimed(struct nfs4_client *clp); /* NFSv4 delegation-related procedures */ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid); diff --git a/trunk/fs/nfs/dir.c b/trunk/fs/nfs/dir.c index 3419c2da9ba9..e7ffb4deb3e5 100644 --- a/trunk/fs/nfs/dir.c +++ b/trunk/fs/nfs/dir.c @@ -30,9 +30,7 @@ #include #include #include -#include #include -#include #include "nfs4_fs.h" #include "delegation.h" @@ -872,14 +870,14 @@ int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd) return (nd->intent.open.flags & O_EXCL) != 0; } -static inline int nfs_reval_fsid(struct vfsmount *mnt, struct inode *dir, - struct nfs_fh *fh, struct nfs_fattr *fattr) +static inline int nfs_reval_fsid(struct inode *dir, + struct nfs_fh *fh, struct nfs_fattr *fattr) { struct nfs_server *server = NFS_SERVER(dir); if (!nfs_fsid_equal(&server->fsid, &fattr->fsid)) /* Revalidate fsid on root dir */ - return __nfs_revalidate_inode(server, mnt->mnt_root->d_inode); + return __nfs_revalidate_inode(server, dir->i_sb->s_root->d_inode); return 0; } @@ -904,15 +902,9 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru lock_kernel(); - /* - * If we're doing an exclusive create, optimize away the lookup - * but don't hash the dentry. - */ - if (nfs_is_exclusive_create(dir, nd)) { - d_instantiate(dentry, NULL); - res = NULL; - goto out_unlock; - } + /* If we're doing an exclusive create, optimize away the lookup */ + if (nfs_is_exclusive_create(dir, nd)) + goto no_entry; error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr); if (error == -ENOENT) @@ -921,7 +913,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru res = ERR_PTR(error); goto out_unlock; } - error = nfs_reval_fsid(nd->mnt, dir, &fhandle, &fattr); + error = nfs_reval_fsid(dir, &fhandle, &fattr); if (error < 0) { res = ERR_PTR(error); goto out_unlock; @@ -930,9 +922,8 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru res = (struct dentry *)inode; if (IS_ERR(res)) goto out_unlock; - no_entry: - res = d_materialise_unique(dentry, inode); + res = d_add_unique(dentry, inode); if (res != NULL) dentry = res; nfs_renew_times(dentry); @@ -1126,13 +1117,11 @@ static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc) dput(dentry); return NULL; } - - alias = d_materialise_unique(dentry, inode); + alias = d_add_unique(dentry, inode); if (alias != NULL) { dput(dentry); dentry = alias; } - nfs_renew_times(dentry); nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); return dentry; @@ -1154,22 +1143,23 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle, struct inode *dir = dentry->d_parent->d_inode; error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr); if (error) - return error; + goto out_err; } if (!(fattr->valid & NFS_ATTR_FATTR)) { struct nfs_server *server = NFS_SB(dentry->d_sb); - error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr); + error = server->rpc_ops->getattr(server, fhandle, fattr); if (error < 0) - return error; + goto out_err; } inode = nfs_fhget(dentry->d_sb, fhandle, fattr); error = PTR_ERR(inode); if (IS_ERR(inode)) - return error; + goto out_err; d_instantiate(dentry, inode); - if (d_unhashed(dentry)) - d_rehash(dentry); return 0; +out_err: + d_drop(dentry); + return error; } /* @@ -1450,82 +1440,48 @@ static int nfs_unlink(struct inode *dir, struct dentry *dentry) return error; } -/* - * To create a symbolic link, most file systems instantiate a new inode, - * add a page to it containing the path, then write it out to the disk - * using prepare_write/commit_write. - * - * Unfortunately the NFS client can't create the in-core inode first - * because it needs a file handle to create an in-core inode (see - * fs/nfs/inode.c:nfs_fhget). We only have a file handle *after* the - * symlink request has completed on the server. - * - * So instead we allocate a raw page, copy the symname into it, then do - * the SYMLINK request with the page as the buffer. If it succeeds, we - * now have a new file handle and can instantiate an in-core NFS inode - * and move the raw page into its mapping. - */ -static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) +static int +nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) { - struct pagevec lru_pvec; - struct page *page; - char *kaddr; struct iattr attr; - unsigned int pathlen = strlen(symname); + struct nfs_fattr sym_attr; + struct nfs_fh sym_fh; + struct qstr qsymname; int error; dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id, dir->i_ino, dentry->d_name.name, symname); - if (pathlen > PAGE_SIZE) - return -ENAMETOOLONG; - - attr.ia_mode = S_IFLNK | S_IRWXUGO; +#ifdef NFS_PARANOIA +if (dentry->d_inode) +printk("nfs_proc_symlink: %s/%s not negative!\n", +dentry->d_parent->d_name.name, dentry->d_name.name); +#endif + /* + * Fill in the sattr for the call. + * Note: SunOS 4.1.2 crashes if the mode isn't initialized! + */ attr.ia_valid = ATTR_MODE; + attr.ia_mode = S_IFLNK | S_IRWXUGO; - lock_kernel(); - - page = alloc_page(GFP_KERNEL); - if (!page) { - unlock_kernel(); - return -ENOMEM; - } - - kaddr = kmap_atomic(page, KM_USER0); - memcpy(kaddr, symname, pathlen); - if (pathlen < PAGE_SIZE) - memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen); - kunmap_atomic(kaddr, KM_USER0); + qsymname.name = symname; + qsymname.len = strlen(symname); + lock_kernel(); nfs_begin_data_update(dir); - error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); + error = NFS_PROTO(dir)->symlink(dir, &dentry->d_name, &qsymname, + &attr, &sym_fh, &sym_attr); nfs_end_data_update(dir); - if (error != 0) { - dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n", - dir->i_sb->s_id, dir->i_ino, - dentry->d_name.name, symname, error); + if (!error) { + error = nfs_instantiate(dentry, &sym_fh, &sym_attr); + } else { + if (error == -EEXIST) + printk("nfs_proc_symlink: %s/%s already exists??\n", + dentry->d_parent->d_name.name, dentry->d_name.name); d_drop(dentry); - __free_page(page); - unlock_kernel(); - return error; } - - /* - * No big deal if we can't add this page to the page cache here. - * READLINK will get the missing page from the server if needed. - */ - pagevec_init(&lru_pvec, 0); - if (!add_to_page_cache(page, dentry->d_inode->i_mapping, 0, - GFP_KERNEL)) { - if (!pagevec_add(&lru_pvec, page)) - __pagevec_lru_add(&lru_pvec); - SetPageUptodate(page); - unlock_page(page); - } else - __free_page(page); - unlock_kernel(); - return 0; + return error; } static int @@ -1682,211 +1638,35 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, return error; } -static DEFINE_SPINLOCK(nfs_access_lru_lock); -static LIST_HEAD(nfs_access_lru_list); -static atomic_long_t nfs_access_nr_entries; - -static void nfs_access_free_entry(struct nfs_access_entry *entry) -{ - put_rpccred(entry->cred); - kfree(entry); - smp_mb__before_atomic_dec(); - atomic_long_dec(&nfs_access_nr_entries); - smp_mb__after_atomic_dec(); -} - -int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask) -{ - LIST_HEAD(head); - struct nfs_inode *nfsi; - struct nfs_access_entry *cache; - - spin_lock(&nfs_access_lru_lock); -restart: - list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) { - struct inode *inode; - - if (nr_to_scan-- == 0) - break; - inode = igrab(&nfsi->vfs_inode); - if (inode == NULL) - continue; - spin_lock(&inode->i_lock); - if (list_empty(&nfsi->access_cache_entry_lru)) - goto remove_lru_entry; - cache = list_entry(nfsi->access_cache_entry_lru.next, - struct nfs_access_entry, lru); - list_move(&cache->lru, &head); - rb_erase(&cache->rb_node, &nfsi->access_cache); - if (!list_empty(&nfsi->access_cache_entry_lru)) - list_move_tail(&nfsi->access_cache_inode_lru, - &nfs_access_lru_list); - else { -remove_lru_entry: - list_del_init(&nfsi->access_cache_inode_lru); - clear_bit(NFS_INO_ACL_LRU_SET, &nfsi->flags); - } - spin_unlock(&inode->i_lock); - iput(inode); - goto restart; - } - spin_unlock(&nfs_access_lru_lock); - while (!list_empty(&head)) { - cache = list_entry(head.next, struct nfs_access_entry, lru); - list_del(&cache->lru); - nfs_access_free_entry(cache); - } - return (atomic_long_read(&nfs_access_nr_entries) / 100) * sysctl_vfs_cache_pressure; -} - -static void __nfs_access_zap_cache(struct inode *inode) -{ - struct nfs_inode *nfsi = NFS_I(inode); - struct rb_root *root_node = &nfsi->access_cache; - struct rb_node *n, *dispose = NULL; - struct nfs_access_entry *entry; - - /* Unhook entries from the cache */ - while ((n = rb_first(root_node)) != NULL) { - entry = rb_entry(n, struct nfs_access_entry, rb_node); - rb_erase(n, root_node); - list_del(&entry->lru); - n->rb_left = dispose; - dispose = n; - } - nfsi->cache_validity &= ~NFS_INO_INVALID_ACCESS; - spin_unlock(&inode->i_lock); - - /* Now kill them all! */ - while (dispose != NULL) { - n = dispose; - dispose = n->rb_left; - nfs_access_free_entry(rb_entry(n, struct nfs_access_entry, rb_node)); - } -} - -void nfs_access_zap_cache(struct inode *inode) -{ - /* Remove from global LRU init */ - if (test_and_clear_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) { - spin_lock(&nfs_access_lru_lock); - list_del_init(&NFS_I(inode)->access_cache_inode_lru); - spin_unlock(&nfs_access_lru_lock); - } - - spin_lock(&inode->i_lock); - /* This will release the spinlock */ - __nfs_access_zap_cache(inode); -} - -static struct nfs_access_entry *nfs_access_search_rbtree(struct inode *inode, struct rpc_cred *cred) -{ - struct rb_node *n = NFS_I(inode)->access_cache.rb_node; - struct nfs_access_entry *entry; - - while (n != NULL) { - entry = rb_entry(n, struct nfs_access_entry, rb_node); - - if (cred < entry->cred) - n = n->rb_left; - else if (cred > entry->cred) - n = n->rb_right; - else - return entry; - } - return NULL; -} - int nfs_access_get_cached(struct inode *inode, struct rpc_cred *cred, struct nfs_access_entry *res) { struct nfs_inode *nfsi = NFS_I(inode); - struct nfs_access_entry *cache; - int err = -ENOENT; + struct nfs_access_entry *cache = &nfsi->cache_access; - spin_lock(&inode->i_lock); - if (nfsi->cache_validity & NFS_INO_INVALID_ACCESS) - goto out_zap; - cache = nfs_access_search_rbtree(inode, cred); - if (cache == NULL) - goto out; - if (time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode))) - goto out_stale; - res->jiffies = cache->jiffies; - res->cred = cache->cred; - res->mask = cache->mask; - list_move_tail(&cache->lru, &nfsi->access_cache_entry_lru); - err = 0; -out: - spin_unlock(&inode->i_lock); - return err; -out_stale: - rb_erase(&cache->rb_node, &nfsi->access_cache); - list_del(&cache->lru); - spin_unlock(&inode->i_lock); - nfs_access_free_entry(cache); - return -ENOENT; -out_zap: - /* This will release the spinlock */ - __nfs_access_zap_cache(inode); - return -ENOENT; + if (cache->cred != cred + || time_after(jiffies, cache->jiffies + NFS_ATTRTIMEO(inode)) + || (nfsi->cache_validity & NFS_INO_INVALID_ACCESS)) + return -ENOENT; + memcpy(res, cache, sizeof(*res)); + return 0; } -static void nfs_access_add_rbtree(struct inode *inode, struct nfs_access_entry *set) +void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) { struct nfs_inode *nfsi = NFS_I(inode); - struct rb_root *root_node = &nfsi->access_cache; - struct rb_node **p = &root_node->rb_node; - struct rb_node *parent = NULL; - struct nfs_access_entry *entry; + struct nfs_access_entry *cache = &nfsi->cache_access; - spin_lock(&inode->i_lock); - while (*p != NULL) { - parent = *p; - entry = rb_entry(parent, struct nfs_access_entry, rb_node); - - if (set->cred < entry->cred) - p = &parent->rb_left; - else if (set->cred > entry->cred) - p = &parent->rb_right; - else - goto found; + if (cache->cred != set->cred) { + if (cache->cred) + put_rpccred(cache->cred); + cache->cred = get_rpccred(set->cred); } - rb_link_node(&set->rb_node, parent, p); - rb_insert_color(&set->rb_node, root_node); - list_add_tail(&set->lru, &nfsi->access_cache_entry_lru); - spin_unlock(&inode->i_lock); - return; -found: - rb_replace_node(parent, &set->rb_node, root_node); - list_add_tail(&set->lru, &nfsi->access_cache_entry_lru); - list_del(&entry->lru); + /* FIXME: replace current access_cache BKL reliance with inode->i_lock */ + spin_lock(&inode->i_lock); + nfsi->cache_validity &= ~NFS_INO_INVALID_ACCESS; spin_unlock(&inode->i_lock); - nfs_access_free_entry(entry); -} - -void nfs_access_add_cache(struct inode *inode, struct nfs_access_entry *set) -{ - struct nfs_access_entry *cache = kmalloc(sizeof(*cache), GFP_KERNEL); - if (cache == NULL) - return; - RB_CLEAR_NODE(&cache->rb_node); cache->jiffies = set->jiffies; - cache->cred = get_rpccred(set->cred); cache->mask = set->mask; - - nfs_access_add_rbtree(inode, cache); - - /* Update accounting */ - smp_mb__before_atomic_inc(); - atomic_long_inc(&nfs_access_nr_entries); - smp_mb__after_atomic_inc(); - - /* Add inode to global LRU list */ - if (!test_and_set_bit(NFS_INO_ACL_LRU_SET, &NFS_FLAGS(inode))) { - spin_lock(&nfs_access_lru_lock); - list_add_tail(&NFS_I(inode)->access_cache_inode_lru, &nfs_access_lru_list); - spin_unlock(&nfs_access_lru_lock); - } } static int nfs_do_access(struct inode *inode, struct rpc_cred *cred, int mask) diff --git a/trunk/fs/nfs/direct.c b/trunk/fs/nfs/direct.c index 76ca1cbc38f9..fecd3b095deb 100644 --- a/trunk/fs/nfs/direct.c +++ b/trunk/fs/nfs/direct.c @@ -100,6 +100,25 @@ static inline int put_dreq(struct nfs_direct_req *dreq) return atomic_dec_and_test(&dreq->io_count); } +/* + * "size" is never larger than rsize or wsize. + */ +static inline int nfs_direct_count_pages(unsigned long user_addr, size_t size) +{ + int page_count; + + page_count = (user_addr + size + PAGE_SIZE - 1) >> PAGE_SHIFT; + page_count -= user_addr >> PAGE_SHIFT; + BUG_ON(page_count < 0); + + return page_count; +} + +static inline unsigned int nfs_max_pages(unsigned int size) +{ + return (size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; +} + /** * nfs_direct_IO - NFS address space operation for direct I/O * @rw: direction (read or write) @@ -257,24 +276,28 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo struct nfs_open_context *ctx = dreq->ctx; struct inode *inode = ctx->dentry->d_inode; size_t rsize = NFS_SERVER(inode)->rsize; + unsigned int rpages = nfs_max_pages(rsize); unsigned int pgbase; int result; ssize_t started = 0; get_dreq(dreq); + pgbase = user_addr & ~PAGE_MASK; do { struct nfs_read_data *data; size_t bytes; - pgbase = user_addr & ~PAGE_MASK; - bytes = min(rsize,count); - result = -ENOMEM; - data = nfs_readdata_alloc(pgbase + bytes); + data = nfs_readdata_alloc(rpages); if (unlikely(!data)) break; + bytes = rsize; + if (count < rsize) + bytes = count; + + data->npages = nfs_direct_count_pages(user_addr, bytes); down_read(¤t->mm->mmap_sem); result = get_user_pages(current, current->mm, user_addr, data->npages, 1, 0, data->pagevec, NULL); @@ -321,10 +344,8 @@ static ssize_t nfs_direct_read_schedule(struct nfs_direct_req *dreq, unsigned lo started += bytes; user_addr += bytes; pos += bytes; - /* FIXME: Remove this unnecessary math from final patch */ pgbase += bytes; pgbase &= ~PAGE_MASK; - BUG_ON(pgbase != (user_addr & ~PAGE_MASK)); count -= bytes; } while (count != 0); @@ -503,7 +524,7 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode static void nfs_alloc_commit_data(struct nfs_direct_req *dreq) { - dreq->commit_data = nfs_commit_alloc(); + dreq->commit_data = nfs_commit_alloc(0); if (dreq->commit_data != NULL) dreq->commit_data->req = (struct nfs_page *) dreq; } @@ -584,24 +605,28 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l struct nfs_open_context *ctx = dreq->ctx; struct inode *inode = ctx->dentry->d_inode; size_t wsize = NFS_SERVER(inode)->wsize; + unsigned int wpages = nfs_max_pages(wsize); unsigned int pgbase; int result; ssize_t started = 0; get_dreq(dreq); + pgbase = user_addr & ~PAGE_MASK; do { struct nfs_write_data *data; size_t bytes; - pgbase = user_addr & ~PAGE_MASK; - bytes = min(wsize,count); - result = -ENOMEM; - data = nfs_writedata_alloc(pgbase + bytes); + data = nfs_writedata_alloc(wpages); if (unlikely(!data)) break; + bytes = wsize; + if (count < wsize) + bytes = count; + + data->npages = nfs_direct_count_pages(user_addr, bytes); down_read(¤t->mm->mmap_sem); result = get_user_pages(current, current->mm, user_addr, data->npages, 0, 0, data->pagevec, NULL); @@ -651,11 +676,8 @@ static ssize_t nfs_direct_write_schedule(struct nfs_direct_req *dreq, unsigned l started += bytes; user_addr += bytes; pos += bytes; - - /* FIXME: Remove this useless math from the final patch */ pgbase += bytes; pgbase &= ~PAGE_MASK; - BUG_ON(pgbase != (user_addr & ~PAGE_MASK)); count -= bytes; } while (count != 0); diff --git a/trunk/fs/nfs/file.c b/trunk/fs/nfs/file.c index be997d649127..cc2b874ad5a4 100644 --- a/trunk/fs/nfs/file.c +++ b/trunk/fs/nfs/file.c @@ -111,7 +111,7 @@ nfs_file_open(struct inode *inode, struct file *filp) nfs_inc_stats(inode, NFSIOS_VFSOPEN); lock_kernel(); - res = NFS_PROTO(inode)->file_open(inode, filp); + res = NFS_SERVER(inode)->rpc_ops->file_open(inode, filp); unlock_kernel(); return res; } @@ -157,7 +157,7 @@ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) { /* origin == SEEK_END => we must revalidate the cached file length */ - if (origin == SEEK_END) { + if (origin == 2) { struct inode *inode = filp->f_mapping->host; int retval = nfs_revalidate_file_size(inode, filp); if (retval < 0) @@ -312,13 +312,7 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset) static int nfs_release_page(struct page *page, gfp_t gfp) { - if (gfp & __GFP_FS) - return !nfs_wb_page(page->mapping->host, page); - else - /* - * Avoid deadlock on nfs_wait_on_request(). - */ - return 0; + return !nfs_wb_page(page->mapping->host, page); } const struct address_space_operations nfs_file_aops = { diff --git a/trunk/fs/nfs/getroot.c b/trunk/fs/nfs/getroot.c deleted file mode 100644 index 76b08ae9ed82..000000000000 --- a/trunk/fs/nfs/getroot.c +++ /dev/null @@ -1,311 +0,0 @@ -/* getroot.c: get the root dentry for an NFS mount - * - * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "nfs4_fs.h" -#include "delegation.h" -#include "internal.h" - -#define NFSDBG_FACILITY NFSDBG_CLIENT -#define NFS_PARANOIA 1 - -/* - * get an NFS2/NFS3 root dentry from the root filehandle - */ -struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) -{ - struct nfs_server *server = NFS_SB(sb); - struct nfs_fsinfo fsinfo; - struct nfs_fattr fattr; - struct dentry *mntroot; - struct inode *inode; - int error; - - /* create a dummy root dentry with dummy inode for this superblock */ - if (!sb->s_root) { - struct nfs_fh dummyfh; - struct dentry *root; - struct inode *iroot; - - memset(&dummyfh, 0, sizeof(dummyfh)); - memset(&fattr, 0, sizeof(fattr)); - nfs_fattr_init(&fattr); - fattr.valid = NFS_ATTR_FATTR; - fattr.type = NFDIR; - fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; - fattr.nlink = 2; - - iroot = nfs_fhget(sb, &dummyfh, &fattr); - if (IS_ERR(iroot)) - return ERR_PTR(PTR_ERR(iroot)); - - root = d_alloc_root(iroot); - if (!root) { - iput(iroot); - return ERR_PTR(-ENOMEM); - } - - sb->s_root = root; - } - - /* get the actual root for this mount */ - fsinfo.fattr = &fattr; - - error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); - if (error < 0) { - dprintk("nfs_get_root: getattr error = %d\n", -error); - return ERR_PTR(error); - } - - inode = nfs_fhget(sb, mntfh, fsinfo.fattr); - if (IS_ERR(inode)) { - dprintk("nfs_get_root: get root inode failed\n"); - return ERR_PTR(PTR_ERR(inode)); - } - - /* root dentries normally start off anonymous and get spliced in later - * if the dentry tree reaches them; however if the dentry already - * exists, we'll pick it up at this point and use it as the root - */ - mntroot = d_alloc_anon(inode); - if (!mntroot) { - iput(inode); - dprintk("nfs_get_root: get root dentry failed\n"); - return ERR_PTR(-ENOMEM); - } - - security_d_instantiate(mntroot, inode); - - if (!mntroot->d_op) - mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops; - - return mntroot; -} - -#ifdef CONFIG_NFS_V4 - -/* - * Do a simple pathwalk from the root FH of the server to the nominated target - * of the mountpoint - * - give error on symlinks - * - give error on ".." occurring in the path - * - follow traversals - */ -int nfs4_path_walk(struct nfs_server *server, - struct nfs_fh *mntfh, - const char *path) -{ - struct nfs_fsinfo fsinfo; - struct nfs_fattr fattr; - struct nfs_fh lastfh; - struct qstr name; - int ret; - //int referral_count = 0; - - dprintk("--> nfs4_path_walk(,,%s)\n", path); - - fsinfo.fattr = &fattr; - nfs_fattr_init(&fattr); - - if (*path++ != '/') { - dprintk("nfs4_get_root: Path does not begin with a slash\n"); - return -EINVAL; - } - - /* Start by getting the root filehandle from the server */ - ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); - if (ret < 0) { - dprintk("nfs4_get_root: getroot error = %d\n", -ret); - return ret; - } - - if (fattr.type != NFDIR) { - printk(KERN_ERR "nfs4_get_root:" - " getroot encountered non-directory\n"); - return -ENOTDIR; - } - - if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { - printk(KERN_ERR "nfs4_get_root:" - " getroot obtained referral\n"); - return -EREMOTE; - } - -next_component: - dprintk("Next: %s\n", path); - - /* extract the next bit of the path */ - if (!*path) - goto path_walk_complete; - - name.name = path; - while (*path && *path != '/') - path++; - name.len = path - (const char *) name.name; - -eat_dot_dir: - while (*path == '/') - path++; - - if (path[0] == '.' && (path[1] == '/' || !path[1])) { - path += 2; - goto eat_dot_dir; - } - - if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || !path[2]) - ) { - printk(KERN_ERR "nfs4_get_root:" - " Mount path contains reference to \"..\"\n"); - return -EINVAL; - } - - /* lookup the next FH in the sequence */ - memcpy(&lastfh, mntfh, sizeof(lastfh)); - - dprintk("LookupFH: %*.*s [%s]\n", name.len, name.len, name.name, path); - - ret = server->nfs_client->rpc_ops->lookupfh(server, &lastfh, &name, - mntfh, &fattr); - if (ret < 0) { - dprintk("nfs4_get_root: getroot error = %d\n", -ret); - return ret; - } - - if (fattr.type != NFDIR) { - printk(KERN_ERR "nfs4_get_root:" - " lookupfh encountered non-directory\n"); - return -ENOTDIR; - } - - if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { - printk(KERN_ERR "nfs4_get_root:" - " lookupfh obtained referral\n"); - return -EREMOTE; - } - - goto next_component; - -path_walk_complete: - memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid)); - dprintk("<-- nfs4_path_walk() = 0\n"); - return 0; -} - -/* - * get an NFS4 root dentry from the root filehandle - */ -struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) -{ - struct nfs_server *server = NFS_SB(sb); - struct nfs_fattr fattr; - struct dentry *mntroot; - struct inode *inode; - int error; - - dprintk("--> nfs4_get_root()\n"); - - /* create a dummy root dentry with dummy inode for this superblock */ - if (!sb->s_root) { - struct nfs_fh dummyfh; - struct dentry *root; - struct inode *iroot; - - memset(&dummyfh, 0, sizeof(dummyfh)); - memset(&fattr, 0, sizeof(fattr)); - nfs_fattr_init(&fattr); - fattr.valid = NFS_ATTR_FATTR; - fattr.type = NFDIR; - fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; - fattr.nlink = 2; - - iroot = nfs_fhget(sb, &dummyfh, &fattr); - if (IS_ERR(iroot)) - return ERR_PTR(PTR_ERR(iroot)); - - root = d_alloc_root(iroot); - if (!root) { - iput(iroot); - return ERR_PTR(-ENOMEM); - } - - sb->s_root = root; - } - - /* get the info about the server and filesystem */ - error = nfs4_server_capabilities(server, mntfh); - if (error < 0) { - dprintk("nfs_get_root: getcaps error = %d\n", - -error); - return ERR_PTR(error); - } - - /* get the actual root for this mount */ - error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); - if (error < 0) { - dprintk("nfs_get_root: getattr error = %d\n", -error); - return ERR_PTR(error); - } - - inode = nfs_fhget(sb, mntfh, &fattr); - if (IS_ERR(inode)) { - dprintk("nfs_get_root: get root inode failed\n"); - return ERR_PTR(PTR_ERR(inode)); - } - - /* root dentries normally start off anonymous and get spliced in later - * if the dentry tree reaches them; however if the dentry already - * exists, we'll pick it up at this point and use it as the root - */ - mntroot = d_alloc_anon(inode); - if (!mntroot) { - iput(inode); - dprintk("nfs_get_root: get root dentry failed\n"); - return ERR_PTR(-ENOMEM); - } - - security_d_instantiate(mntroot, inode); - - if (!mntroot->d_op) - mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops; - - dprintk("<-- nfs4_get_root()\n"); - return mntroot; -} - -#endif /* CONFIG_NFS_V4 */ diff --git a/trunk/fs/nfs/idmap.c b/trunk/fs/nfs/idmap.c index 82ad7110a1c0..b81e7ed3c902 100644 --- a/trunk/fs/nfs/idmap.c +++ b/trunk/fs/nfs/idmap.c @@ -57,20 +57,6 @@ /* Default cache timeout is 10 minutes */ unsigned int nfs_idmap_cache_timeout = 600 * HZ; -static int param_set_idmap_timeout(const char *val, struct kernel_param *kp) -{ - char *endp; - int num = simple_strtol(val, &endp, 0); - int jif = num * HZ; - if (endp == val || *endp || num < 0 || jif < num) - return -EINVAL; - *((int *)kp->arg) = jif; - return 0; -} - -module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int, - &nfs_idmap_cache_timeout, 0644); - struct idmap_hashent { unsigned long ih_expires; __u32 ih_id; @@ -84,6 +70,7 @@ struct idmap_hashtable { }; struct idmap { + char idmap_path[48]; struct dentry *idmap_dentry; wait_queue_head_t idmap_wq; struct idmap_msg idmap_im; @@ -107,23 +94,24 @@ static struct rpc_pipe_ops idmap_upcall_ops = { .destroy_msg = idmap_pipe_destroy_msg, }; -int -nfs_idmap_new(struct nfs_client *clp) +void +nfs_idmap_new(struct nfs4_client *clp) { struct idmap *idmap; - int error; - - BUG_ON(clp->cl_idmap != NULL); + if (clp->cl_idmap != NULL) + return; if ((idmap = kzalloc(sizeof(*idmap), GFP_KERNEL)) == NULL) - return -ENOMEM; + return; - idmap->idmap_dentry = rpc_mkpipe(clp->cl_rpcclient->cl_dentry, "idmap", + snprintf(idmap->idmap_path, sizeof(idmap->idmap_path), + "%s/idmap", clp->cl_rpcclient->cl_pathname); + + idmap->idmap_dentry = rpc_mkpipe(idmap->idmap_path, idmap, &idmap_upcall_ops, 0); if (IS_ERR(idmap->idmap_dentry)) { - error = PTR_ERR(idmap->idmap_dentry); kfree(idmap); - return error; + return; } mutex_init(&idmap->idmap_lock); @@ -133,17 +121,18 @@ nfs_idmap_new(struct nfs_client *clp) idmap->idmap_group_hash.h_type = IDMAP_TYPE_GROUP; clp->cl_idmap = idmap; - return 0; } void -nfs_idmap_delete(struct nfs_client *clp) +nfs_idmap_delete(struct nfs4_client *clp) { struct idmap *idmap = clp->cl_idmap; if (!idmap) return; - rpc_unlink(idmap->idmap_dentry); + dput(idmap->idmap_dentry); + idmap->idmap_dentry = NULL; + rpc_unlink(idmap->idmap_path); clp->cl_idmap = NULL; kfree(idmap); } @@ -490,27 +479,27 @@ static unsigned int fnvhash32(const void *buf, size_t buflen) return (hash); } -int nfs_map_name_to_uid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid) +int nfs_map_name_to_uid(struct nfs4_client *clp, const char *name, size_t namelen, __u32 *uid) { struct idmap *idmap = clp->cl_idmap; return nfs_idmap_id(idmap, &idmap->idmap_user_hash, name, namelen, uid); } -int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid) +int nfs_map_group_to_gid(struct nfs4_client *clp, const char *name, size_t namelen, __u32 *uid) { struct idmap *idmap = clp->cl_idmap; return nfs_idmap_id(idmap, &idmap->idmap_group_hash, name, namelen, uid); } -int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf) +int nfs_map_uid_to_name(struct nfs4_client *clp, __u32 uid, char *buf) { struct idmap *idmap = clp->cl_idmap; return nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf); } -int nfs_map_gid_to_group(struct nfs_client *clp, __u32 uid, char *buf) +int nfs_map_gid_to_group(struct nfs4_client *clp, __u32 uid, char *buf) { struct idmap *idmap = clp->cl_idmap; diff --git a/trunk/fs/nfs/inode.c b/trunk/fs/nfs/inode.c index e8c143d182c4..d349fb2245da 100644 --- a/trunk/fs/nfs/inode.c +++ b/trunk/fs/nfs/inode.c @@ -76,14 +76,19 @@ int nfs_write_inode(struct inode *inode, int sync) void nfs_clear_inode(struct inode *inode) { + struct nfs_inode *nfsi = NFS_I(inode); + struct rpc_cred *cred; + /* * The following should never happen... */ BUG_ON(nfs_have_writebacks(inode)); - BUG_ON(!list_empty(&NFS_I(inode)->open_files)); - BUG_ON(atomic_read(&NFS_I(inode)->data_updates) != 0); + BUG_ON (!list_empty(&nfsi->open_files)); nfs_zap_acl_cache(inode); - nfs_access_zap_cache(inode); + cred = nfsi->cache_access.cred; + if (cred) + put_rpccred(cred); + BUG_ON(atomic_read(&nfsi->data_updates) != 0); } /** @@ -237,13 +242,13 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) /* Why so? Because we want revalidate for devices/FIFOs, and * that's precisely what we have in nfs_file_inode_operations. */ - inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->file_inode_ops; + inode->i_op = NFS_SB(sb)->rpc_ops->file_inode_ops; if (S_ISREG(inode->i_mode)) { inode->i_fop = &nfs_file_operations; inode->i_data.a_ops = &nfs_file_aops; inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info; } else if (S_ISDIR(inode->i_mode)) { - inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops; + inode->i_op = NFS_SB(sb)->rpc_ops->dir_inode_ops; inode->i_fop = &nfs_dir_operations; if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS) && fattr->size <= NFS_LIMIT_READDIRPLUS) @@ -285,7 +290,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); nfsi->attrtimeo_timestamp = jiffies; memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); - nfsi->access_cache = RB_ROOT; + nfsi->cache_access.cred = NULL; unlock_new_inode(inode); } else @@ -717,11 +722,13 @@ void nfs_end_data_update(struct inode *inode) { struct nfs_inode *nfsi = NFS_I(inode); - /* Directories: invalidate page cache */ - if (S_ISDIR(inode->i_mode)) { - spin_lock(&inode->i_lock); - nfsi->cache_validity |= NFS_INO_INVALID_DATA; - spin_unlock(&inode->i_lock); + if (!nfs_have_delegation(inode, FMODE_READ)) { + /* Directories and symlinks: invalidate page cache */ + if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { + spin_lock(&inode->i_lock); + nfsi->cache_validity |= NFS_INO_INVALID_DATA; + spin_unlock(&inode->i_lock); + } } nfsi->cache_change_attribute = jiffies; atomic_dec(&nfsi->data_updates); @@ -840,12 +847,6 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) * * After an operation that has changed the inode metadata, mark the * attribute cache as being invalid, then try to update it. - * - * NB: if the server didn't return any post op attributes, this - * function will force the retrieval of attributes before the next - * NFS request. Thus it should be used only for operations that - * are expected to change one or more attributes, to avoid - * unnecessary NFS requests and trips through nfs_update_inode(). */ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) { @@ -1024,7 +1025,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) out_fileid: printk(KERN_ERR "NFS: server %s error: fileid changed\n" "fsid %s: expected fileid 0x%Lx, got 0x%Lx\n", - NFS_SERVER(inode)->nfs_client->cl_hostname, inode->i_sb->s_id, + NFS_SERVER(inode)->hostname, inode->i_sb->s_id, (long long)nfsi->fileid, (long long)fattr->fileid); goto out_err; } @@ -1108,8 +1109,6 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) INIT_LIST_HEAD(&nfsi->dirty); INIT_LIST_HEAD(&nfsi->commit); INIT_LIST_HEAD(&nfsi->open_files); - INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); - INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); atomic_set(&nfsi->data_updates, 0); nfsi->ndirty = 0; @@ -1145,10 +1144,6 @@ static int __init init_nfs_fs(void) { int err; - err = nfs_fs_proc_init(); - if (err) - goto out5; - err = nfs_init_nfspagecache(); if (err) goto out4; @@ -1189,8 +1184,6 @@ static int __init init_nfs_fs(void) out3: nfs_destroy_nfspagecache(); out4: - nfs_fs_proc_exit(); -out5: return err; } @@ -1205,7 +1198,6 @@ static void __exit exit_nfs_fs(void) rpc_proc_unregister("nfs"); #endif unregister_nfs_fs(); - nfs_fs_proc_exit(); } /* Not quite true; I just maintain it */ diff --git a/trunk/fs/nfs/internal.h b/trunk/fs/nfs/internal.h index bea0b016bd70..e4f4e5def0fc 100644 --- a/trunk/fs/nfs/internal.h +++ b/trunk/fs/nfs/internal.h @@ -4,18 +4,6 @@ #include -struct nfs_string; -struct nfs_mount_data; -struct nfs4_mount_data; - -/* Maximum number of readahead requests - * FIXME: this should really be a sysctl so that users may tune it to suit - * their needs. People that do NFS over a slow network, might for - * instance want to reduce it to something closer to 1 for improved - * interactive response. - */ -#define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) - struct nfs_clone_mount { const struct super_block *sb; const struct dentry *dentry; @@ -27,40 +15,7 @@ struct nfs_clone_mount { rpc_authflavor_t authflavor; }; -/* client.c */ -extern struct rpc_program nfs_program; - -extern void nfs_put_client(struct nfs_client *); -extern struct nfs_client *nfs_find_client(const struct sockaddr_in *, int); -extern struct nfs_server *nfs_create_server(const struct nfs_mount_data *, - struct nfs_fh *); -extern struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *, - const char *, - const struct sockaddr_in *, - const char *, - const char *, - rpc_authflavor_t, - struct nfs_fh *); -extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, - struct nfs_fh *); -extern void nfs_free_server(struct nfs_server *server); -extern struct nfs_server *nfs_clone_server(struct nfs_server *, - struct nfs_fh *, - struct nfs_fattr *); -#ifdef CONFIG_PROC_FS -extern int __init nfs_fs_proc_init(void); -extern void nfs_fs_proc_exit(void); -#else -static inline int nfs_fs_proc_init(void) -{ - return 0; -} -static inline void nfs_fs_proc_exit(void) -{ -} -#endif - -/* nfs4namespace.c */ +/* namespace-nfs4.c */ #ifdef CONFIG_NFS_V4 extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry); #else @@ -91,7 +46,6 @@ extern void nfs_destroy_directcache(void); #endif /* nfs2xdr.c */ -extern int nfs_stat_to_errno(int); extern struct rpc_procinfo nfs_procedures[]; extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int); @@ -100,9 +54,8 @@ extern struct rpc_procinfo nfs3_procedures[]; extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); /* nfs4xdr.c */ -#ifdef CONFIG_NFS_V4 +extern int nfs_stat_to_errno(int); extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus); -#endif /* nfs4proc.c */ #ifdef CONFIG_NFS_V4 @@ -113,9 +66,6 @@ extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, struct page *page); #endif -/* dir.c */ -extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); - /* inode.c */ extern struct inode *nfs_alloc_inode(struct super_block *sb); extern void nfs_destroy_inode(struct inode *); @@ -126,10 +76,10 @@ extern void nfs4_clear_inode(struct inode *); #endif /* super.c */ -extern struct file_system_type nfs_xdev_fs_type; +extern struct file_system_type nfs_referral_nfs4_fs_type; +extern struct file_system_type clone_nfs_fs_type; #ifdef CONFIG_NFS_V4 -extern struct file_system_type nfs4_xdev_fs_type; -extern struct file_system_type nfs4_referral_fs_type; +extern struct file_system_type clone_nfs4_fs_type; #endif extern struct rpc_stat nfs_rpcstat; @@ -138,30 +88,30 @@ extern int __init register_nfs_fs(void); extern void __exit unregister_nfs_fs(void); /* namespace.c */ -extern char *nfs_path(const char *base, - const struct dentry *droot, - const struct dentry *dentry, +extern char *nfs_path(const char *base, const struct dentry *dentry, char *buffer, ssize_t buflen); -/* getroot.c */ -extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *); +/* + * Determine the mount path as a string + */ +static inline char * +nfs4_path(const struct dentry *dentry, char *buffer, ssize_t buflen) +{ #ifdef CONFIG_NFS_V4 -extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *); - -extern int nfs4_path_walk(struct nfs_server *server, - struct nfs_fh *mntfh, - const char *path); + return nfs_path(NFS_SB(dentry->d_sb)->mnt_path, dentry, buffer, buflen); +#else + return NULL; #endif +} /* * Determine the device name as a string */ static inline char *nfs_devname(const struct vfsmount *mnt_parent, - const struct dentry *dentry, - char *buffer, ssize_t buflen) + const struct dentry *dentry, + char *buffer, ssize_t buflen) { - return nfs_path(mnt_parent->mnt_devname, mnt_parent->mnt_root, - dentry, buffer, buflen); + return nfs_path(mnt_parent->mnt_devname, dentry, buffer, buflen); } /* @@ -217,3 +167,20 @@ void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize) if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0) sb->s_maxbytes = MAX_LFS_FILESIZE; } + +/* + * Check if the string represents a "valid" IPv4 address + */ +static inline int valid_ipaddr4(const char *buf) +{ + int rc, count, in[4]; + + rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]); + if (rc != 4) + return -EINVAL; + for (count = 0; count < 4; count++) { + if (in[count] > 255) + return -EINVAL; + } + return 0; +} diff --git a/trunk/fs/nfs/mount_clnt.c b/trunk/fs/nfs/mount_clnt.c index d507b021207f..445abb4d4214 100644 --- a/trunk/fs/nfs/mount_clnt.c +++ b/trunk/fs/nfs/mount_clnt.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -76,19 +77,22 @@ static struct rpc_clnt * mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version, int protocol) { - struct rpc_create_args args = { - .protocol = protocol, - .address = (struct sockaddr *)srvaddr, - .addrsize = sizeof(*srvaddr), - .servername = hostname, - .program = &mnt_program, - .version = version, - .authflavor = RPC_AUTH_UNIX, - .flags = (RPC_CLNT_CREATE_ONESHOT | - RPC_CLNT_CREATE_INTR), - }; - - return rpc_create(&args); + struct rpc_xprt *xprt; + struct rpc_clnt *clnt; + + xprt = xprt_create_proto(protocol, srvaddr, NULL); + if (IS_ERR(xprt)) + return (struct rpc_clnt *)xprt; + + clnt = rpc_create_client(xprt, hostname, + &mnt_program, version, + RPC_AUTH_UNIX); + if (!IS_ERR(clnt)) { + clnt->cl_softrtry = 1; + clnt->cl_oneshot = 1; + clnt->cl_intr = 1; + } + return clnt; } /* diff --git a/trunk/fs/nfs/namespace.c b/trunk/fs/nfs/namespace.c index 77b00684894d..19b98ca468eb 100644 --- a/trunk/fs/nfs/namespace.c +++ b/trunk/fs/nfs/namespace.c @@ -2,7 +2,6 @@ * linux/fs/nfs/namespace.c * * Copyright (C) 2005 Trond Myklebust - * - Modified by David Howells * * NFS namespace */ @@ -29,7 +28,6 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; /* * nfs_path - reconstruct the path given an arbitrary dentry * @base - arbitrary string to prepend to the path - * @droot - pointer to root dentry for mountpoint * @dentry - pointer to dentry * @buffer - result buffer * @buflen - length of buffer @@ -40,9 +38,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ; * This is mainly for use in figuring out the path on the * server side when automounting on top of an existing partition. */ -char *nfs_path(const char *base, - const struct dentry *droot, - const struct dentry *dentry, +char *nfs_path(const char *base, const struct dentry *dentry, char *buffer, ssize_t buflen) { char *end = buffer+buflen; @@ -51,11 +47,11 @@ char *nfs_path(const char *base, *--end = '\0'; buflen--; spin_lock(&dcache_lock); - while (!IS_ROOT(dentry) && dentry != droot) { + while (!IS_ROOT(dentry)) { namelen = dentry->d_name.len; buflen -= namelen + 1; if (buflen < 0) - goto Elong_unlock; + goto Elong; end -= namelen; memcpy(end, dentry->d_name.name, namelen); *--end = '/'; @@ -72,8 +68,6 @@ char *nfs_path(const char *base, end -= namelen; memcpy(end, base, namelen); return end; -Elong_unlock: - spin_unlock(&dcache_lock); Elong: return ERR_PTR(-ENAMETOOLONG); } @@ -100,18 +94,15 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) struct nfs_fattr fattr; int err; - dprintk("--> nfs_follow_mountpoint()\n"); - BUG_ON(IS_ROOT(dentry)); dprintk("%s: enter\n", __FUNCTION__); dput(nd->dentry); nd->dentry = dget(dentry); - + if (d_mountpoint(nd->dentry)) + goto out_follow; /* Look it up again */ parent = dget_parent(nd->dentry); - err = server->nfs_client->rpc_ops->lookup(parent->d_inode, - &nd->dentry->d_name, - &fh, &fattr); + err = server->rpc_ops->lookup(parent->d_inode, &nd->dentry->d_name, &fh, &fattr); dput(parent); if (err != 0) goto out_err; @@ -139,8 +130,6 @@ static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout); out: dprintk("%s: done, returned %d\n", __FUNCTION__, err); - - dprintk("<-- nfs_follow_mountpoint() = %d\n", err); return ERR_PTR(err); out_err: path_release(nd); @@ -181,23 +170,22 @@ void nfs_release_automount_timer(void) /* * Clone a mountpoint of the appropriate type */ -static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, - const char *devname, +static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, char *devname, struct nfs_clone_mount *mountdata) { #ifdef CONFIG_NFS_V4 struct vfsmount *mnt = NULL; - switch (server->nfs_client->cl_nfsversion) { + switch (server->rpc_ops->version) { case 2: case 3: - mnt = vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata); + mnt = vfs_kern_mount(&clone_nfs_fs_type, 0, devname, mountdata); break; case 4: - mnt = vfs_kern_mount(&nfs4_xdev_fs_type, 0, devname, mountdata); + mnt = vfs_kern_mount(&clone_nfs4_fs_type, 0, devname, mountdata); } return mnt; #else - return vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata); + return vfs_kern_mount(&clone_nfs_fs_type, 0, devname, mountdata); #endif } @@ -223,8 +211,6 @@ struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent, char *page = (char *) __get_free_page(GFP_USER); char *devname; - dprintk("--> nfs_do_submount()\n"); - dprintk("%s: submounting on %s/%s\n", __FUNCTION__, dentry->d_parent->d_name.name, dentry->d_name.name); @@ -239,7 +225,5 @@ struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent, free_page((unsigned long)page); out: dprintk("%s: done\n", __FUNCTION__); - - dprintk("<-- nfs_do_submount() = %p\n", mnt); return mnt; } diff --git a/trunk/fs/nfs/nfs2xdr.c b/trunk/fs/nfs/nfs2xdr.c index b49501fc0a79..67391eef6b93 100644 --- a/trunk/fs/nfs/nfs2xdr.c +++ b/trunk/fs/nfs/nfs2xdr.c @@ -51,7 +51,7 @@ #define NFS_createargs_sz (NFS_diropargs_sz+NFS_sattr_sz) #define NFS_renameargs_sz (NFS_diropargs_sz+NFS_diropargs_sz) #define NFS_linkargs_sz (NFS_fhandle_sz+NFS_diropargs_sz) -#define NFS_symlinkargs_sz (NFS_diropargs_sz+1+NFS_sattr_sz) +#define NFS_symlinkargs_sz (NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz) #define NFS_readdirargs_sz (NFS_fhandle_sz+2) #define NFS_attrstat_sz (1+NFS_fattr_sz) @@ -351,26 +351,11 @@ nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args) static int nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args) { - struct xdr_buf *sndbuf = &req->rq_snd_buf; - size_t pad; - p = xdr_encode_fhandle(p, args->fromfh); p = xdr_encode_array(p, args->fromname, args->fromlen); - *p++ = htonl(args->pathlen); - sndbuf->len = xdr_adjust_iovec(sndbuf->head, p); - - xdr_encode_pages(sndbuf, args->pages, 0, args->pathlen); - - /* - * xdr_encode_pages may have added a few bytes to ensure the - * pathname ends on a 4-byte boundary. Start encoding the - * attributes after the pad bytes. - */ - pad = sndbuf->tail->iov_len; - if (pad > 0) - p++; + p = xdr_encode_array(p, args->topath, args->tolen); p = xdr_encode_sattr(p, args->sattr); - sndbuf->len += xdr_adjust_iovec(sndbuf->tail, p) - pad; + req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); return 0; } diff --git a/trunk/fs/nfs/nfs3proc.c b/trunk/fs/nfs/nfs3proc.c index f8688eaa0001..7143b1f82cea 100644 --- a/trunk/fs/nfs/nfs3proc.c +++ b/trunk/fs/nfs/nfs3proc.c @@ -81,7 +81,7 @@ do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle, } /* - * Bare-bones access to getattr: this is for nfs_get_root/nfs_get_sb + * Bare-bones access to getattr: this is for nfs_read_super. */ static int nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, @@ -90,8 +90,8 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, int status; status = do_proc_get_root(server->client, fhandle, info); - if (status && server->nfs_client->cl_rpcclient != server->client) - status = do_proc_get_root(server->nfs_client->cl_rpcclient, fhandle, info); + if (status && server->client_sys != server->client) + status = do_proc_get_root(server->client_sys, fhandle, info); return status; } @@ -544,23 +544,23 @@ nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) } static int -nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, - unsigned int len, struct iattr *sattr) +nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, + struct iattr *sattr, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) { - struct nfs_fh fhandle; - struct nfs_fattr fattr, dir_attr; + struct nfs_fattr dir_attr; struct nfs3_symlinkargs arg = { .fromfh = NFS_FH(dir), - .fromname = dentry->d_name.name, - .fromlen = dentry->d_name.len, - .pages = &page, - .pathlen = len, + .fromname = name->name, + .fromlen = name->len, + .topath = path->name, + .tolen = path->len, .sattr = sattr }; struct nfs3_diropres res = { .dir_attr = &dir_attr, - .fh = &fhandle, - .fattr = &fattr + .fh = fhandle, + .fattr = fattr }; struct rpc_message msg = { .rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK], @@ -569,19 +569,13 @@ nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, }; int status; - if (len > NFS3_MAXPATHLEN) + if (path->len > NFS3_MAXPATHLEN) return -ENAMETOOLONG; - - dprintk("NFS call symlink %s\n", dentry->d_name.name); - + dprintk("NFS call symlink %s -> %s\n", name->name, path->name); nfs_fattr_init(&dir_attr); - nfs_fattr_init(&fattr); + nfs_fattr_init(fattr); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); nfs_post_op_update_inode(dir, &dir_attr); - if (status != 0) - goto out; - status = nfs_instantiate(dentry, &fhandle, &fattr); -out: dprintk("NFS reply symlink: %d\n", status); return status; } @@ -791,7 +785,7 @@ nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, dprintk("NFS call fsinfo\n"); nfs_fattr_init(info->fattr); - status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); + status = rpc_call_sync(server->client_sys, &msg, 0); dprintk("NFS reply fsinfo: %d\n", status); return status; } @@ -892,7 +886,7 @@ nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl) return nlmclnt_proc(filp->f_dentry->d_inode, cmd, fl); } -const struct nfs_rpc_ops nfs_v3_clientops = { +struct nfs_rpc_ops nfs_v3_clientops = { .version = 3, /* protocol version */ .dentry_ops = &nfs_dentry_operations, .dir_inode_ops = &nfs3_dir_inode_operations, diff --git a/trunk/fs/nfs/nfs3xdr.c b/trunk/fs/nfs/nfs3xdr.c index 16556fa4effb..0250269e9753 100644 --- a/trunk/fs/nfs/nfs3xdr.c +++ b/trunk/fs/nfs/nfs3xdr.c @@ -56,7 +56,7 @@ #define NFS3_writeargs_sz (NFS3_fh_sz+5) #define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz) #define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz) -#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz) +#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+NFS3_path_sz+NFS3_sattr_sz) #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz) #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz) #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz) @@ -398,11 +398,8 @@ nfs3_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_symlinkargs *args p = xdr_encode_fhandle(p, args->fromfh); p = xdr_encode_array(p, args->fromname, args->fromlen); p = xdr_encode_sattr(p, args->sattr); - *p++ = htonl(args->pathlen); + p = xdr_encode_array(p, args->topath, args->tolen); req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); - - /* Copy the page */ - xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen); return 0; } diff --git a/trunk/fs/nfs/nfs4_fs.h b/trunk/fs/nfs/nfs4_fs.h index 61095fe4b5ca..9a102860df37 100644 --- a/trunk/fs/nfs/nfs4_fs.h +++ b/trunk/fs/nfs/nfs4_fs.h @@ -42,6 +42,55 @@ enum nfs4_client_state { NFS4CLNT_LEASE_EXPIRED, }; +/* + * The nfs4_client identifies our client state to the server. + */ +struct nfs4_client { + struct list_head cl_servers; /* Global list of servers */ + struct in_addr cl_addr; /* Server identifier */ + u64 cl_clientid; /* constant */ + nfs4_verifier cl_confirm; + unsigned long cl_state; + + u32 cl_lockowner_id; + + /* + * The following rwsem ensures exclusive access to the server + * while we recover the state following a lease expiration. + */ + struct rw_semaphore cl_sem; + + struct list_head cl_delegations; + struct list_head cl_state_owners; + struct list_head cl_unused; + int cl_nunused; + spinlock_t cl_lock; + atomic_t cl_count; + + struct rpc_clnt * cl_rpcclient; + + struct list_head cl_superblocks; /* List of nfs_server structs */ + + unsigned long cl_lease_time; + unsigned long cl_last_renewal; + struct work_struct cl_renewd; + struct work_struct cl_recoverd; + + struct rpc_wait_queue cl_rpcwaitq; + + /* used for the setclientid verifier */ + struct timespec cl_boot_time; + + /* idmapper */ + struct idmap * cl_idmap; + + /* Our own IP address, as a null-terminated string. + * This is used to generate the clientid, and the callback address. + */ + char cl_ipaddr[16]; + unsigned char cl_id_uniquifier; +}; + /* * struct rpc_sequence ensures that RPC calls are sent in the exact * order that they appear on the list. @@ -78,7 +127,7 @@ static inline void nfs_confirm_seqid(struct nfs_seqid_counter *seqid, int status struct nfs4_state_owner { spinlock_t so_lock; struct list_head so_list; /* per-clientid list of state_owners */ - struct nfs_client *so_client; + struct nfs4_client *so_client; u32 so_id; /* 32-bit identifier, unique */ atomic_t so_count; @@ -161,10 +210,10 @@ extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t); /* nfs4proc.c */ extern int nfs4_map_errors(int err); -extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *); -extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct rpc_cred *); -extern int nfs4_proc_async_renew(struct nfs_client *, struct rpc_cred *); -extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *); +extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short, struct rpc_cred *); +extern int nfs4_proc_setclientid_confirm(struct nfs4_client *, struct rpc_cred *); +extern int nfs4_proc_async_renew(struct nfs4_client *, struct rpc_cred *); +extern int nfs4_proc_renew(struct nfs4_client *, struct rpc_cred *); extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state); extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *); extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *); @@ -182,14 +231,19 @@ extern const u32 nfs4_fsinfo_bitmap[2]; extern const u32 nfs4_fs_locations_bitmap[2]; /* nfs4renewd.c */ -extern void nfs4_schedule_state_renewal(struct nfs_client *); +extern void nfs4_schedule_state_renewal(struct nfs4_client *); extern void nfs4_renewd_prepare_shutdown(struct nfs_server *); -extern void nfs4_kill_renewd(struct nfs_client *); +extern void nfs4_kill_renewd(struct nfs4_client *); extern void nfs4_renew_state(void *); /* nfs4state.c */ -struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp); -extern u32 nfs4_alloc_lockowner_id(struct nfs_client *); +extern void init_nfsv4_state(struct nfs_server *); +extern void destroy_nfsv4_state(struct nfs_server *); +extern struct nfs4_client *nfs4_get_client(struct in_addr *); +extern void nfs4_put_client(struct nfs4_client *clp); +extern struct nfs4_client *nfs4_find_client(struct in_addr *); +struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp); +extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *); extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *); extern void nfs4_put_state_owner(struct nfs4_state_owner *); @@ -198,7 +252,7 @@ extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state extern void nfs4_put_open_state(struct nfs4_state *); extern void nfs4_close_state(struct nfs4_state *, mode_t); extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t); -extern void nfs4_schedule_state_recovery(struct nfs_client *); +extern void nfs4_schedule_state_recovery(struct nfs4_client *); extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); @@ -222,6 +276,10 @@ extern struct svc_version nfs4_callback_version1; #else +#define init_nfsv4_state(server) do { } while (0) +#define destroy_nfsv4_state(server) do { } while (0) +#define nfs4_put_state_owner(inode, owner) do { } while (0) +#define nfs4_put_open_state(state) do { } while (0) #define nfs4_close_state(a, b) do { } while (0) #endif /* CONFIG_NFS_V4 */ diff --git a/trunk/fs/nfs/nfs4namespace.c b/trunk/fs/nfs/nfs4namespace.c index 24e47f3bbd17..ea38d27b74e6 100644 --- a/trunk/fs/nfs/nfs4namespace.c +++ b/trunk/fs/nfs/nfs4namespace.c @@ -2,7 +2,6 @@ * linux/fs/nfs/nfs4namespace.c * * Copyright (C) 2005 Trond Myklebust - * - Modified by David Howells * * NFSv4 namespace */ @@ -24,7 +23,7 @@ /* * Check if fs_root is valid */ -static inline char *nfs4_pathname_string(const struct nfs4_pathname *pathname, +static inline char *nfs4_pathname_string(struct nfs4_pathname *pathname, char *buffer, ssize_t buflen) { char *end = buffer + buflen; @@ -35,7 +34,7 @@ static inline char *nfs4_pathname_string(const struct nfs4_pathname *pathname, n = pathname->ncomponents; while (--n >= 0) { - const struct nfs4_string *component = &pathname->components[n]; + struct nfs4_string *component = &pathname->components[n]; buflen -= component->len + 1; if (buflen < 0) goto Elong; @@ -48,68 +47,6 @@ static inline char *nfs4_pathname_string(const struct nfs4_pathname *pathname, return ERR_PTR(-ENAMETOOLONG); } -/* - * Determine the mount path as a string - */ -static char *nfs4_path(const struct vfsmount *mnt_parent, - const struct dentry *dentry, - char *buffer, ssize_t buflen) -{ - const char *srvpath; - - srvpath = strchr(mnt_parent->mnt_devname, ':'); - if (srvpath) - srvpath++; - else - srvpath = mnt_parent->mnt_devname; - - return nfs_path(srvpath, mnt_parent->mnt_root, dentry, buffer, buflen); -} - -/* - * Check that fs_locations::fs_root [RFC3530 6.3] is a prefix for what we - * believe to be the server path to this dentry - */ -static int nfs4_validate_fspath(const struct vfsmount *mnt_parent, - const struct dentry *dentry, - const struct nfs4_fs_locations *locations, - char *page, char *page2) -{ - const char *path, *fs_path; - - path = nfs4_path(mnt_parent, dentry, page, PAGE_SIZE); - if (IS_ERR(path)) - return PTR_ERR(path); - - fs_path = nfs4_pathname_string(&locations->fs_path, page2, PAGE_SIZE); - if (IS_ERR(fs_path)) - return PTR_ERR(fs_path); - - if (strncmp(path, fs_path, strlen(fs_path)) != 0) { - dprintk("%s: path %s does not begin with fsroot %s\n", - __FUNCTION__, path, fs_path); - return -ENOENT; - } - - return 0; -} - -/* - * Check if the string represents a "valid" IPv4 address - */ -static inline int valid_ipaddr4(const char *buf) -{ - int rc, count, in[4]; - - rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]); - if (rc != 4) - return -EINVAL; - for (count = 0; count < 4; count++) { - if (in[count] > 255) - return -EINVAL; - } - return 0; -} /** * nfs_follow_referral - set up mountpoint when hitting a referral on moved error @@ -123,7 +60,7 @@ static inline int valid_ipaddr4(const char *buf) */ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, const struct dentry *dentry, - const struct nfs4_fs_locations *locations) + struct nfs4_fs_locations *locations) { struct vfsmount *mnt = ERR_PTR(-ENOENT); struct nfs_clone_mount mountdata = { @@ -131,9 +68,10 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, .dentry = dentry, .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor, }; - char *page = NULL, *page2 = NULL; + char *page, *page2; + char *path, *fs_path; char *devname; - int loc, s, error; + int loc, s; if (locations == NULL || locations->nlocations <= 0) goto out; @@ -141,30 +79,36 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, dprintk("%s: referral at %s/%s\n", __FUNCTION__, dentry->d_parent->d_name.name, dentry->d_name.name); + /* Ensure fs path is a prefix of current dentry path */ page = (char *) __get_free_page(GFP_USER); - if (!page) + if (page == NULL) goto out; - page2 = (char *) __get_free_page(GFP_USER); - if (!page2) + if (page2 == NULL) goto out; - /* Ensure fs path is a prefix of current dentry path */ - error = nfs4_validate_fspath(mnt_parent, dentry, locations, page, page2); - if (error < 0) { - mnt = ERR_PTR(error); - goto out; + path = nfs4_path(dentry, page, PAGE_SIZE); + if (IS_ERR(path)) + goto out_free; + + fs_path = nfs4_pathname_string(&locations->fs_path, page2, PAGE_SIZE); + if (IS_ERR(fs_path)) + goto out_free; + + if (strncmp(path, fs_path, strlen(fs_path)) != 0) { + dprintk("%s: path %s does not begin with fsroot %s\n", __FUNCTION__, path, fs_path); + goto out_free; } devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE); if (IS_ERR(devname)) { mnt = (struct vfsmount *)devname; - goto out; + goto out_free; } loc = 0; while (loc < locations->nlocations && IS_ERR(mnt)) { - const struct nfs4_fs_location *location = &locations->locations[loc]; + struct nfs4_fs_location *location = &locations->locations[loc]; char *mnt_path; if (location == NULL || location->nservers <= 0 || @@ -196,7 +140,7 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, addr.sin_port = htons(NFS_PORT); mountdata.addr = &addr; - mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, devname, &mountdata); + mnt = vfs_kern_mount(&nfs_referral_nfs4_fs_type, 0, devname, &mountdata); if (!IS_ERR(mnt)) { break; } @@ -205,9 +149,10 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, loc++; } +out_free: + free_page((unsigned long)page); + free_page((unsigned long)page2); out: - free_page((unsigned long) page); - free_page((unsigned long) page2); dprintk("%s: done\n", __FUNCTION__); return mnt; } @@ -220,7 +165,7 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, */ struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry) { - struct vfsmount *mnt = ERR_PTR(-ENOMEM); + struct vfsmount *mnt = ERR_PTR(-ENOENT); struct dentry *parent; struct nfs4_fs_locations *fs_locations = NULL; struct page *page; @@ -238,16 +183,11 @@ struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentr goto out_free; /* Get locations */ - mnt = ERR_PTR(-ENOENT); - parent = dget_parent(dentry); - dprintk("%s: getting locations for %s/%s\n", - __FUNCTION__, parent->d_name.name, dentry->d_name.name); - + dprintk("%s: getting locations for %s/%s\n", __FUNCTION__, parent->d_name.name, dentry->d_name.name); err = nfs4_proc_fs_locations(parent->d_inode, dentry, fs_locations, page); dput(parent); - if (err != 0 || - fs_locations->nlocations <= 0 || + if (err != 0 || fs_locations->nlocations <= 0 || fs_locations->fs_path.ncomponents <= 0) goto out_free; diff --git a/trunk/fs/nfs/nfs4proc.c b/trunk/fs/nfs/nfs4proc.c index 47c7e6e3910d..e6ee97f19d81 100644 --- a/trunk/fs/nfs/nfs4proc.c +++ b/trunk/fs/nfs/nfs4proc.c @@ -55,7 +55,7 @@ #define NFSDBG_FACILITY NFSDBG_PROC -#define NFS4_POLL_RETRY_MIN (HZ/10) +#define NFS4_POLL_RETRY_MIN (1*HZ) #define NFS4_POLL_RETRY_MAX (15*HZ) struct nfs4_opendata; @@ -64,7 +64,7 @@ static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinf static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *); static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry); static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception); -static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp); +static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp); /* Prevent leaks of NFSv4 errors into userland */ int nfs4_map_errors(int err) @@ -195,7 +195,7 @@ static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry, static void renew_lease(const struct nfs_server *server, unsigned long timestamp) { - struct nfs_client *clp = server->nfs_client; + struct nfs4_client *clp = server->nfs4_state; spin_lock(&clp->cl_lock); if (time_before(clp->cl_last_renewal,timestamp)) clp->cl_last_renewal = timestamp; @@ -252,7 +252,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, atomic_inc(&sp->so_count); p->o_arg.fh = NFS_FH(dir); p->o_arg.open_flags = flags, - p->o_arg.clientid = server->nfs_client->cl_clientid; + p->o_arg.clientid = server->nfs4_state->cl_clientid; p->o_arg.id = sp->so_id; p->o_arg.name = &dentry->d_name; p->o_arg.server = server; @@ -550,7 +550,7 @@ int nfs4_open_delegation_recall(struct dentry *dentry, struct nfs4_state *state) case -NFS4ERR_STALE_STATEID: case -NFS4ERR_EXPIRED: /* Don't recall a delegation if it was lost */ - nfs4_schedule_state_recovery(server->nfs_client); + nfs4_schedule_state_recovery(server->nfs4_state); return err; } err = nfs4_handle_exception(server, err, &exception); @@ -758,7 +758,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data) } nfs_confirm_seqid(&data->owner->so_seqid, 0); if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) - return server->nfs_client->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); + return server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr); return 0; } @@ -792,18 +792,11 @@ static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openf int nfs4_recover_expired_lease(struct nfs_server *server) { - struct nfs_client *clp = server->nfs_client; - int ret; + struct nfs4_client *clp = server->nfs4_state; - for (;;) { - ret = nfs4_wait_clnt_recover(server->client, clp); - if (ret != 0) - return ret; - if (!test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) - break; + if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) nfs4_schedule_state_recovery(clp); - } - return 0; + return nfs4_wait_clnt_recover(server->client, clp); } /* @@ -874,7 +867,7 @@ static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred { struct nfs_delegation *delegation; struct nfs_server *server = NFS_SERVER(inode); - struct nfs_client *clp = server->nfs_client; + struct nfs4_client *clp = server->nfs4_state; struct nfs_inode *nfsi = NFS_I(inode); struct nfs4_state_owner *sp = NULL; struct nfs4_state *state = NULL; @@ -960,7 +953,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st struct nfs4_state_owner *sp; struct nfs4_state *state = NULL; struct nfs_server *server = NFS_SERVER(dir); - struct nfs_client *clp = server->nfs_client; + struct nfs4_client *clp = server->nfs4_state; struct nfs4_opendata *opendata; int status; @@ -977,7 +970,7 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st status = -ENOMEM; opendata = nfs4_opendata_alloc(dentry, sp, flags, sattr); if (opendata == NULL) - goto err_release_rwsem; + goto err_put_state_owner; status = _nfs4_proc_open(opendata); if (status != 0) @@ -996,11 +989,11 @@ static int _nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, st return 0; err_opendata_free: nfs4_opendata_free(opendata); -err_release_rwsem: - up_read(&clp->cl_sem); err_put_state_owner: nfs4_put_state_owner(sp); out_err: + /* Note: clp->cl_sem must be released before nfs4_put_open_state()! */ + up_read(&clp->cl_sem); *res = NULL; return status; } @@ -1140,7 +1133,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) break; case -NFS4ERR_STALE_STATEID: case -NFS4ERR_EXPIRED: - nfs4_schedule_state_recovery(server->nfs_client); + nfs4_schedule_state_recovery(server->nfs4_state); break; default: if (nfs4_async_handle_error(task, server) == -EAGAIN) { @@ -1275,7 +1268,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) BUG_ON(nd->intent.open.flags & O_CREAT); } - cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0); + cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); if (IS_ERR(cred)) return (struct dentry *)cred; state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred); @@ -1298,7 +1291,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st struct rpc_cred *cred; struct nfs4_state *state; - cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0); + cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); if (IS_ERR(cred)) return PTR_ERR(cred); state = nfs4_open_delegated(dentry->d_inode, openflags, cred); @@ -1400,19 +1393,70 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, return err; } -/* - * get the file handle for the "/" directory on the server - */ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, - struct nfs_fsinfo *info) + struct nfs_fsinfo *info) { + struct nfs_fattr * fattr = info->fattr; + unsigned char * p; + struct qstr q; + struct nfs4_lookup_arg args = { + .dir_fh = fhandle, + .name = &q, + .bitmask = nfs4_fattr_bitmap, + }; + struct nfs4_lookup_res res = { + .server = server, + .fattr = fattr, + .fh = fhandle, + }; + struct rpc_message msg = { + .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP], + .rpc_argp = &args, + .rpc_resp = &res, + }; int status; + /* + * Now we do a separate LOOKUP for each component of the mount path. + * The LOOKUPs are done separately so that we can conveniently + * catch an ERR_WRONGSEC if it occurs along the way... + */ status = nfs4_lookup_root(server, fhandle, info); + if (status) + goto out; + + p = server->mnt_path; + for (;;) { + struct nfs4_exception exception = { }; + + while (*p == '/') + p++; + if (!*p) + break; + q.name = p; + while (*p && (*p != '/')) + p++; + q.len = p - q.name; + + do { + nfs_fattr_init(fattr); + status = nfs4_handle_exception(server, + rpc_call_sync(server->client, &msg, 0), + &exception); + } while (exception.retry); + if (status == 0) + continue; + if (status == -ENOENT) { + printk(KERN_NOTICE "NFS: mount path %s does not exist!\n", server->mnt_path); + printk(KERN_NOTICE "NFS: suggestion: try mounting '/' instead.\n"); + } + break; + } if (status == 0) status = nfs4_server_capabilities(server, fhandle); if (status == 0) status = nfs4_do_fsinfo(server, fhandle, info); +out: return nfs4_map_errors(status); } @@ -1521,7 +1565,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, nfs_fattr_init(fattr); - cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0); + cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); if (IS_ERR(cred)) return PTR_ERR(cred); @@ -1539,52 +1583,6 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, return status; } -static int _nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, - struct qstr *name, struct nfs_fh *fhandle, - struct nfs_fattr *fattr) -{ - int status; - struct nfs4_lookup_arg args = { - .bitmask = server->attr_bitmask, - .dir_fh = dirfh, - .name = name, - }; - struct nfs4_lookup_res res = { - .server = server, - .fattr = fattr, - .fh = fhandle, - }; - struct rpc_message msg = { - .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LOOKUP], - .rpc_argp = &args, - .rpc_resp = &res, - }; - - nfs_fattr_init(fattr); - - dprintk("NFS call lookupfh %s\n", name->name); - status = rpc_call_sync(server->client, &msg, 0); - dprintk("NFS reply lookupfh: %d\n", status); - if (status == -NFS4ERR_MOVED) - status = -EREMOTE; - return status; -} - -static int nfs4_proc_lookupfh(struct nfs_server *server, struct nfs_fh *dirfh, - struct qstr *name, struct nfs_fh *fhandle, - struct nfs_fattr *fattr) -{ - struct nfs4_exception exception = { }; - int err; - do { - err = nfs4_handle_exception(server, - _nfs4_proc_lookupfh(server, dirfh, name, - fhandle, fattr), - &exception); - } while (exception.retry); - return err; -} - static int _nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { @@ -1883,7 +1881,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, struct rpc_cred *cred; int status = 0; - cred = rpcauth_lookupcred(NFS_CLIENT(dir)->cl_auth, 0); + cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); if (IS_ERR(cred)) { status = PTR_ERR(cred); goto out; @@ -2091,24 +2089,24 @@ static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *n return err; } -static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, - struct page *page, unsigned int len, struct iattr *sattr) +static int _nfs4_proc_symlink(struct inode *dir, struct qstr *name, + struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) { struct nfs_server *server = NFS_SERVER(dir); - struct nfs_fh fhandle; - struct nfs_fattr fattr, dir_fattr; + struct nfs_fattr dir_fattr; struct nfs4_create_arg arg = { .dir_fh = NFS_FH(dir), .server = server, - .name = &dentry->d_name, + .name = name, .attrs = sattr, .ftype = NF4LNK, .bitmask = server->attr_bitmask, }; struct nfs4_create_res res = { .server = server, - .fh = &fhandle, - .fattr = &fattr, + .fh = fhandle, + .fattr = fattr, .dir_fattr = &dir_fattr, }; struct rpc_message msg = { @@ -2118,32 +2116,29 @@ static int _nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, }; int status; - if (len > NFS4_MAXPATHLEN) + if (path->len > NFS4_MAXPATHLEN) return -ENAMETOOLONG; - - arg.u.symlink.pages = &page; - arg.u.symlink.len = len; - nfs_fattr_init(&fattr); + arg.u.symlink = path; + nfs_fattr_init(fattr); nfs_fattr_init(&dir_fattr); status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); - if (!status) { + if (!status) update_changeattr(dir, &res.dir_cinfo); - nfs_post_op_update_inode(dir, res.dir_fattr); - status = nfs_instantiate(dentry, &fhandle, &fattr); - } + nfs_post_op_update_inode(dir, res.dir_fattr); return status; } -static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, - struct page *page, unsigned int len, struct iattr *sattr) +static int nfs4_proc_symlink(struct inode *dir, struct qstr *name, + struct qstr *path, struct iattr *sattr, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) { struct nfs4_exception exception = { }; int err; do { err = nfs4_handle_exception(NFS_SERVER(dir), - _nfs4_proc_symlink(dir, dentry, page, - len, sattr), + _nfs4_proc_symlink(dir, name, path, sattr, + fhandle, fattr), &exception); } while (exception.retry); return err; @@ -2526,7 +2521,7 @@ static void nfs4_proc_commit_setup(struct nfs_write_data *data, int how) */ static void nfs4_renew_done(struct rpc_task *task, void *data) { - struct nfs_client *clp = (struct nfs_client *)task->tk_msg.rpc_argp; + struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp; unsigned long timestamp = (unsigned long)data; if (task->tk_status < 0) { @@ -2548,7 +2543,7 @@ static const struct rpc_call_ops nfs4_renew_ops = { .rpc_call_done = nfs4_renew_done, }; -int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) +int nfs4_proc_async_renew(struct nfs4_client *clp, struct rpc_cred *cred) { struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], @@ -2560,7 +2555,7 @@ int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) &nfs4_renew_ops, (void *)jiffies); } -int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) +int nfs4_proc_renew(struct nfs4_client *clp, struct rpc_cred *cred) { struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], @@ -2673,7 +2668,7 @@ static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t a nfs4_set_cached_acl(inode, acl); } -static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen) +static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen) { struct page *pages[NFS4ACL_MAXPAGES]; struct nfs_getaclargs args = { @@ -2726,19 +2721,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu return ret; } -static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen) -{ - struct nfs4_exception exception = { }; - ssize_t ret; - do { - ret = __nfs4_get_acl_uncached(inode, buf, buflen); - if (ret >= 0) - break; - ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception); - } while (exception.retry); - return ret; -} - static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) { struct nfs_server *server = NFS_SERVER(inode); @@ -2755,7 +2737,7 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) return nfs4_get_acl_uncached(inode, buf, buflen); } -static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen) +static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen) { struct nfs_server *server = NFS_SERVER(inode); struct page *pages[NFS4ACL_MAXPAGES]; @@ -2775,28 +2757,16 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl return -EOPNOTSUPP; nfs_inode_return_delegation(inode); buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); - ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0); + ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0); if (ret == 0) nfs4_write_cached_acl(inode, buf, buflen); return ret; } -static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen) -{ - struct nfs4_exception exception = { }; - int err; - do { - err = nfs4_handle_exception(NFS_SERVER(inode), - __nfs4_proc_set_acl(inode, buf, buflen), - &exception); - } while (exception.retry); - return err; -} - static int nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) { - struct nfs_client *clp = server->nfs_client; + struct nfs4_client *clp = server->nfs4_state; if (!clp || task->tk_status >= 0) return 0; @@ -2833,7 +2803,7 @@ static int nfs4_wait_bit_interruptible(void *word) return 0; } -static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs_client *clp) +static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp) { sigset_t oldset; int res; @@ -2876,7 +2846,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) */ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception) { - struct nfs_client *clp = server->nfs_client; + struct nfs4_client *clp = server->nfs4_state; int ret = errorcode; exception->retry = 0; @@ -2891,7 +2861,6 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct if (ret == 0) exception->retry = 1; break; - case -NFS4ERR_FILE_OPEN: case -NFS4ERR_GRACE: case -NFS4ERR_DELAY: ret = nfs4_delay(server->client, &exception->timeout); @@ -2904,7 +2873,7 @@ int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct return nfs4_map_errors(ret); } -int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short port, struct rpc_cred *cred) +int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port, struct rpc_cred *cred) { nfs4_verifier sc_verifier; struct nfs4_setclientid setclientid = { @@ -2928,7 +2897,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po for(;;) { setclientid.sc_name_len = scnprintf(setclientid.sc_name, sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u", - clp->cl_ipaddr, NIPQUAD(clp->cl_addr.sin_addr), + clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr), cred->cr_ops->cr_name, clp->cl_id_uniquifier); setclientid.sc_netid_len = scnprintf(setclientid.sc_netid, @@ -2951,7 +2920,7 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, unsigned short po return status; } -static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred) +static int _nfs4_proc_setclientid_confirm(struct nfs4_client *clp, struct rpc_cred *cred) { struct nfs_fsinfo fsinfo; struct rpc_message msg = { @@ -2975,7 +2944,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cre return status; } -int nfs4_proc_setclientid_confirm(struct nfs_client *clp, struct rpc_cred *cred) +int nfs4_proc_setclientid_confirm(struct nfs4_client *clp, struct rpc_cred *cred) { long timeout; int err; @@ -3083,7 +3052,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 switch (err) { case -NFS4ERR_STALE_STATEID: case -NFS4ERR_EXPIRED: - nfs4_schedule_state_recovery(server->nfs_client); + nfs4_schedule_state_recovery(server->nfs4_state); case 0: return 0; } @@ -3112,7 +3081,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock { struct inode *inode = state->inode; struct nfs_server *server = NFS_SERVER(inode); - struct nfs_client *clp = server->nfs_client; + struct nfs4_client *clp = server->nfs4_state; struct nfs_lockt_args arg = { .fh = NFS_FH(inode), .fl = request, @@ -3237,7 +3206,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) break; case -NFS4ERR_STALE_STATEID: case -NFS4ERR_EXPIRED: - nfs4_schedule_state_recovery(calldata->server->nfs_client); + nfs4_schedule_state_recovery(calldata->server->nfs4_state); break; default: if (nfs4_async_handle_error(task, calldata->server) == -EAGAIN) { @@ -3349,7 +3318,7 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl, if (p->arg.lock_seqid == NULL) goto out_free; p->arg.lock_stateid = &lsp->ls_stateid; - p->arg.lock_owner.clientid = server->nfs_client->cl_clientid; + p->arg.lock_owner.clientid = server->nfs4_state->cl_clientid; p->arg.lock_owner.id = lsp->ls_id; p->lsp = lsp; atomic_inc(&lsp->ls_count); @@ -3519,7 +3488,7 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) { - struct nfs_client *clp = state->owner->so_client; + struct nfs4_client *clp = state->owner->so_client; unsigned char fl_flags = request->fl_flags; int status; @@ -3721,7 +3690,7 @@ static struct inode_operations nfs4_file_inode_operations = { .listxattr = nfs4_listxattr, }; -const struct nfs_rpc_ops nfs_v4_clientops = { +struct nfs_rpc_ops nfs_v4_clientops = { .version = 4, /* protocol version */ .dentry_ops = &nfs4_dentry_operations, .dir_inode_ops = &nfs4_dir_inode_operations, @@ -3729,7 +3698,6 @@ const struct nfs_rpc_ops nfs_v4_clientops = { .getroot = nfs4_proc_get_root, .getattr = nfs4_proc_getattr, .setattr = nfs4_proc_setattr, - .lookupfh = nfs4_proc_lookupfh, .lookup = nfs4_proc_lookup, .access = nfs4_proc_access, .readlink = nfs4_proc_readlink, @@ -3750,7 +3718,6 @@ const struct nfs_rpc_ops nfs_v4_clientops = { .statfs = nfs4_proc_statfs, .fsinfo = nfs4_proc_fsinfo, .pathconf = nfs4_proc_pathconf, - .set_capabilities = nfs4_server_capabilities, .decode_dirent = nfs4_decode_dirent, .read_setup = nfs4_proc_read_setup, .read_done = nfs4_read_done, diff --git a/trunk/fs/nfs/nfs4renewd.c b/trunk/fs/nfs/nfs4renewd.c index 7b6df1852e75..5d764d8e6d8a 100644 --- a/trunk/fs/nfs/nfs4renewd.c +++ b/trunk/fs/nfs/nfs4renewd.c @@ -61,7 +61,7 @@ void nfs4_renew_state(void *data) { - struct nfs_client *clp = (struct nfs_client *)data; + struct nfs4_client *clp = (struct nfs4_client *)data; struct rpc_cred *cred; long lease, timeout; unsigned long last, now; @@ -108,7 +108,7 @@ nfs4_renew_state(void *data) /* Must be called with clp->cl_sem locked for writes */ void -nfs4_schedule_state_renewal(struct nfs_client *clp) +nfs4_schedule_state_renewal(struct nfs4_client *clp) { long timeout; @@ -121,20 +121,32 @@ nfs4_schedule_state_renewal(struct nfs_client *clp) __FUNCTION__, (timeout + HZ - 1) / HZ); cancel_delayed_work(&clp->cl_renewd); schedule_delayed_work(&clp->cl_renewd, timeout); - set_bit(NFS_CS_RENEWD, &clp->cl_res_state); spin_unlock(&clp->cl_lock); } void nfs4_renewd_prepare_shutdown(struct nfs_server *server) { + struct nfs4_client *clp = server->nfs4_state; + + if (!clp) + return; flush_scheduled_work(); + down_write(&clp->cl_sem); + if (!list_empty(&server->nfs4_siblings)) + list_del_init(&server->nfs4_siblings); + up_write(&clp->cl_sem); } +/* Must be called with clp->cl_sem locked for writes */ void -nfs4_kill_renewd(struct nfs_client *clp) +nfs4_kill_renewd(struct nfs4_client *clp) { down_read(&clp->cl_sem); + if (!list_empty(&clp->cl_superblocks)) { + up_read(&clp->cl_sem); + return; + } cancel_delayed_work(&clp->cl_renewd); up_read(&clp->cl_sem); flush_scheduled_work(); diff --git a/trunk/fs/nfs/nfs4state.c b/trunk/fs/nfs/nfs4state.c index 5fffbdfa971f..090a36b07a22 100644 --- a/trunk/fs/nfs/nfs4state.c +++ b/trunk/fs/nfs/nfs4state.c @@ -50,15 +50,149 @@ #include "nfs4_fs.h" #include "callback.h" #include "delegation.h" -#include "internal.h" #define OPENOWNER_POOL_SIZE 8 const nfs4_stateid zero_stateid; +static DEFINE_SPINLOCK(state_spinlock); static LIST_HEAD(nfs4_clientid_list); -static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred) +void +init_nfsv4_state(struct nfs_server *server) +{ + server->nfs4_state = NULL; + INIT_LIST_HEAD(&server->nfs4_siblings); +} + +void +destroy_nfsv4_state(struct nfs_server *server) +{ + kfree(server->mnt_path); + server->mnt_path = NULL; + if (server->nfs4_state) { + nfs4_put_client(server->nfs4_state); + server->nfs4_state = NULL; + } +} + +/* + * nfs4_get_client(): returns an empty client structure + * nfs4_put_client(): drops reference to client structure + * + * Since these are allocated/deallocated very rarely, we don't + * bother putting them in a slab cache... + */ +static struct nfs4_client * +nfs4_alloc_client(struct in_addr *addr) +{ + struct nfs4_client *clp; + + if (nfs_callback_up() < 0) + return NULL; + if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) { + nfs_callback_down(); + return NULL; + } + memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr)); + init_rwsem(&clp->cl_sem); + INIT_LIST_HEAD(&clp->cl_delegations); + INIT_LIST_HEAD(&clp->cl_state_owners); + INIT_LIST_HEAD(&clp->cl_unused); + spin_lock_init(&clp->cl_lock); + atomic_set(&clp->cl_count, 1); + INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); + INIT_LIST_HEAD(&clp->cl_superblocks); + rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client"); + clp->cl_rpcclient = ERR_PTR(-EINVAL); + clp->cl_boot_time = CURRENT_TIME; + clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; + return clp; +} + +static void +nfs4_free_client(struct nfs4_client *clp) +{ + struct nfs4_state_owner *sp; + + while (!list_empty(&clp->cl_unused)) { + sp = list_entry(clp->cl_unused.next, + struct nfs4_state_owner, + so_list); + list_del(&sp->so_list); + kfree(sp); + } + BUG_ON(!list_empty(&clp->cl_state_owners)); + nfs_idmap_delete(clp); + if (!IS_ERR(clp->cl_rpcclient)) + rpc_shutdown_client(clp->cl_rpcclient); + kfree(clp); + nfs_callback_down(); +} + +static struct nfs4_client *__nfs4_find_client(struct in_addr *addr) +{ + struct nfs4_client *clp; + list_for_each_entry(clp, &nfs4_clientid_list, cl_servers) { + if (memcmp(&clp->cl_addr, addr, sizeof(clp->cl_addr)) == 0) { + atomic_inc(&clp->cl_count); + return clp; + } + } + return NULL; +} + +struct nfs4_client *nfs4_find_client(struct in_addr *addr) +{ + struct nfs4_client *clp; + spin_lock(&state_spinlock); + clp = __nfs4_find_client(addr); + spin_unlock(&state_spinlock); + return clp; +} + +struct nfs4_client * +nfs4_get_client(struct in_addr *addr) +{ + struct nfs4_client *clp, *new = NULL; + + spin_lock(&state_spinlock); + for (;;) { + clp = __nfs4_find_client(addr); + if (clp != NULL) + break; + clp = new; + if (clp != NULL) { + list_add(&clp->cl_servers, &nfs4_clientid_list); + new = NULL; + break; + } + spin_unlock(&state_spinlock); + new = nfs4_alloc_client(addr); + spin_lock(&state_spinlock); + if (new == NULL) + break; + } + spin_unlock(&state_spinlock); + if (new) + nfs4_free_client(new); + return clp; +} + +void +nfs4_put_client(struct nfs4_client *clp) +{ + if (!atomic_dec_and_lock(&clp->cl_count, &state_spinlock)) + return; + list_del(&clp->cl_servers); + spin_unlock(&state_spinlock); + BUG_ON(!list_empty(&clp->cl_superblocks)); + rpc_wake_up(&clp->cl_rpcwaitq); + nfs4_kill_renewd(clp); + nfs4_free_client(clp); +} + +static int nfs4_init_client(struct nfs4_client *clp, struct rpc_cred *cred) { int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, nfs_callback_tcpport, cred); @@ -70,13 +204,13 @@ static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred) } u32 -nfs4_alloc_lockowner_id(struct nfs_client *clp) +nfs4_alloc_lockowner_id(struct nfs4_client *clp) { return clp->cl_lockowner_id ++; } static struct nfs4_state_owner * -nfs4_client_grab_unused(struct nfs_client *clp, struct rpc_cred *cred) +nfs4_client_grab_unused(struct nfs4_client *clp, struct rpc_cred *cred) { struct nfs4_state_owner *sp = NULL; @@ -90,7 +224,7 @@ nfs4_client_grab_unused(struct nfs_client *clp, struct rpc_cred *cred) return sp; } -struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp) +struct rpc_cred *nfs4_get_renew_cred(struct nfs4_client *clp) { struct nfs4_state_owner *sp; struct rpc_cred *cred = NULL; @@ -104,7 +238,7 @@ struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp) return cred; } -struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp) +struct rpc_cred *nfs4_get_setclientid_cred(struct nfs4_client *clp) { struct nfs4_state_owner *sp; @@ -117,7 +251,7 @@ struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp) } static struct nfs4_state_owner * -nfs4_find_state_owner(struct nfs_client *clp, struct rpc_cred *cred) +nfs4_find_state_owner(struct nfs4_client *clp, struct rpc_cred *cred) { struct nfs4_state_owner *sp, *res = NULL; @@ -160,7 +294,7 @@ nfs4_alloc_state_owner(void) void nfs4_drop_state_owner(struct nfs4_state_owner *sp) { - struct nfs_client *clp = sp->so_client; + struct nfs4_client *clp = sp->so_client; spin_lock(&clp->cl_lock); list_del_init(&sp->so_list); spin_unlock(&clp->cl_lock); @@ -172,7 +306,7 @@ nfs4_drop_state_owner(struct nfs4_state_owner *sp) */ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct rpc_cred *cred) { - struct nfs_client *clp = server->nfs_client; + struct nfs4_client *clp = server->nfs4_state; struct nfs4_state_owner *sp, *new; get_rpccred(cred); @@ -203,7 +337,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct */ void nfs4_put_state_owner(struct nfs4_state_owner *sp) { - struct nfs_client *clp = sp->so_client; + struct nfs4_client *clp = sp->so_client; struct rpc_cred *cred = sp->so_cred; if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock)) @@ -406,7 +540,7 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) { struct nfs4_lock_state *lsp; - struct nfs_client *clp = state->owner->so_client; + struct nfs4_client *clp = state->owner->so_client; lsp = kzalloc(sizeof(*lsp), GFP_KERNEL); if (lsp == NULL) @@ -618,7 +752,7 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task) static int reclaimer(void *); -static inline void nfs4_clear_recover_bit(struct nfs_client *clp) +static inline void nfs4_clear_recover_bit(struct nfs4_client *clp) { smp_mb__before_clear_bit(); clear_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state); @@ -630,25 +764,25 @@ static inline void nfs4_clear_recover_bit(struct nfs_client *clp) /* * State recovery routine */ -static void nfs4_recover_state(struct nfs_client *clp) +static void nfs4_recover_state(struct nfs4_client *clp) { struct task_struct *task; __module_get(THIS_MODULE); atomic_inc(&clp->cl_count); task = kthread_run(reclaimer, clp, "%u.%u.%u.%u-reclaim", - NIPQUAD(clp->cl_addr.sin_addr)); + NIPQUAD(clp->cl_addr)); if (!IS_ERR(task)) return; nfs4_clear_recover_bit(clp); - nfs_put_client(clp); + nfs4_put_client(clp); module_put(THIS_MODULE); } /* * Schedule a state recovery attempt */ -void nfs4_schedule_state_recovery(struct nfs_client *clp) +void nfs4_schedule_state_recovery(struct nfs4_client *clp) { if (!clp) return; @@ -745,7 +879,7 @@ static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct n return status; } -static void nfs4_state_mark_reclaim(struct nfs_client *clp) +static void nfs4_state_mark_reclaim(struct nfs4_client *clp) { struct nfs4_state_owner *sp; struct nfs4_state *state; @@ -769,7 +903,7 @@ static void nfs4_state_mark_reclaim(struct nfs_client *clp) static int reclaimer(void *ptr) { - struct nfs_client *clp = ptr; + struct nfs4_client *clp = ptr; struct nfs4_state_owner *sp; struct nfs4_state_recovery_ops *ops; struct rpc_cred *cred; @@ -836,12 +970,12 @@ static int reclaimer(void *ptr) if (status == -NFS4ERR_CB_PATH_DOWN) nfs_handle_cb_pathdown(clp); nfs4_clear_recover_bit(clp); - nfs_put_client(clp); + nfs4_put_client(clp); module_put_and_exit(0); return 0; out_error: printk(KERN_WARNING "Error: state recovery failed on NFSv4 server %u.%u.%u.%u with error %d\n", - NIPQUAD(clp->cl_addr.sin_addr), -status); + NIPQUAD(clp->cl_addr.s_addr), -status); set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); goto out; } diff --git a/trunk/fs/nfs/nfs4xdr.c b/trunk/fs/nfs/nfs4xdr.c index 3dd413f52da1..1750d996f49f 100644 --- a/trunk/fs/nfs/nfs4xdr.c +++ b/trunk/fs/nfs/nfs4xdr.c @@ -58,7 +58,7 @@ /* Mapping from NFS error code to "errno" error code. */ #define errno_NFSERR_IO EIO -static int nfs4_stat_to_errno(int); +static int nfs_stat_to_errno(int); /* NFSv4 COMPOUND tags are only wanted for debugging purposes */ #ifdef DEBUG @@ -128,7 +128,7 @@ static int nfs4_stat_to_errno(int); #define decode_link_maxsz (op_decode_hdr_maxsz + 5) #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ 1 + nfs4_name_maxsz + \ - 1 + \ + nfs4_path_maxsz + \ nfs4_fattr_maxsz) #define decode_symlink_maxsz (op_decode_hdr_maxsz + 8) #define encode_create_maxsz (op_encode_hdr_maxsz + \ @@ -529,7 +529,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s if (iap->ia_valid & ATTR_MODE) len += 4; if (iap->ia_valid & ATTR_UID) { - owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name); + owner_namelen = nfs_map_uid_to_name(server->nfs4_state, iap->ia_uid, owner_name); if (owner_namelen < 0) { printk(KERN_WARNING "nfs: couldn't resolve uid %d to string\n", iap->ia_uid); @@ -541,7 +541,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s len += 4 + (XDR_QUADLEN(owner_namelen) << 2); } if (iap->ia_valid & ATTR_GID) { - owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group); + owner_grouplen = nfs_map_gid_to_group(server->nfs4_state, iap->ia_gid, owner_group); if (owner_grouplen < 0) { printk(KERN_WARNING "nfs4: couldn't resolve gid %d to string\n", iap->ia_gid); @@ -673,9 +673,9 @@ static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *c switch (create->ftype) { case NF4LNK: - RESERVE_SPACE(4); - WRITE32(create->u.symlink.len); - xdr_write_pages(xdr, create->u.symlink.pages, 0, create->u.symlink.len); + RESERVE_SPACE(4 + create->u.symlink->len); + WRITE32(create->u.symlink->len); + WRITEMEM(create->u.symlink->name, create->u.symlink->len); break; case NF4BLK: case NF4CHR: @@ -1160,7 +1160,7 @@ static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, con return 0; } -static int encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid) +static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client_stateid) { uint32_t *p; @@ -1246,7 +1246,7 @@ static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclien return 0; } -static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_client *client_state) +static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_client *client_state) { uint32_t *p; @@ -1945,7 +1945,7 @@ static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, uint32_t *p, const str /* * a RENEW request */ -static int nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs_client *clp) +static int nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs4_client *clp) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -1975,7 +1975,7 @@ static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, uint32_t *p, struct nf /* * a SETCLIENTID_CONFIRM request */ -static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs_client *clp) +static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs4_client *clp) { struct xdr_stream xdr; struct compound_hdr hdr = { @@ -2127,12 +2127,12 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) } READ32(nfserr); if (nfserr != NFS_OK) - return -nfs4_stat_to_errno(nfserr); + return -nfs_stat_to_errno(nfserr); return 0; } /* Dummy routine */ -static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp) +static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs4_client *clp) { uint32_t *p; unsigned int strlen; @@ -2636,7 +2636,7 @@ static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t return 0; } -static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *uid) +static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_client *clp, int32_t *uid) { uint32_t len, *p; @@ -2660,7 +2660,7 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nf return 0; } -static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, int32_t *gid) +static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_client *clp, int32_t *gid) { uint32_t len, *p; @@ -3051,9 +3051,9 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, cons fattr->mode |= fmode; if ((status = decode_attr_nlink(xdr, bitmap, &fattr->nlink)) != 0) goto xdr_error; - if ((status = decode_attr_owner(xdr, bitmap, server->nfs_client, &fattr->uid)) != 0) + if ((status = decode_attr_owner(xdr, bitmap, server->nfs4_state, &fattr->uid)) != 0) goto xdr_error; - if ((status = decode_attr_group(xdr, bitmap, server->nfs_client, &fattr->gid)) != 0) + if ((status = decode_attr_group(xdr, bitmap, server->nfs4_state, &fattr->gid)) != 0) goto xdr_error; if ((status = decode_attr_rdev(xdr, bitmap, &fattr->rdev)) != 0) goto xdr_error; @@ -3254,7 +3254,7 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res) if (decode_space_limit(xdr, &res->maxsize) < 0) return -EIO; } - return decode_ace(xdr, NULL, res->server->nfs_client); + return decode_ace(xdr, NULL, res->server->nfs4_state); } static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) @@ -3355,7 +3355,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n struct kvec *iov = rcvbuf->head; unsigned int nr, pglen = rcvbuf->page_len; uint32_t *end, *entry, *p, *kaddr; - uint32_t len, attrlen, xlen; + uint32_t len, attrlen; int hdrlen, recvd, status; status = decode_op_hdr(xdr, OP_READDIR); @@ -3377,10 +3377,10 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE); kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0); - end = p + ((pglen + readdir->pgbase) >> 2); + end = (uint32_t *) ((char *)p + pglen + readdir->pgbase); entry = p; for (nr = 0; *p++; nr++) { - if (end - p < 3) + if (p + 3 > end) goto short_pkt; dprintk("cookie = %Lu, ", *((unsigned long long *)p)); p += 2; /* cookie */ @@ -3389,19 +3389,18 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len); goto err_unmap; } - xlen = XDR_QUADLEN(len); - if (end - p < xlen + 1) - goto short_pkt; dprintk("filename = %*s\n", len, (char *)p); - p += xlen; - len = ntohl(*p++); /* bitmap length */ - if (end - p < len + 1) + p += XDR_QUADLEN(len); + if (p + 1 > end) goto short_pkt; + len = ntohl(*p++); /* bitmap length */ p += len; - attrlen = XDR_QUADLEN(ntohl(*p++)); - if (end - p < attrlen + 2) + if (p + 1 > end) goto short_pkt; + attrlen = XDR_QUADLEN(ntohl(*p++)); p += attrlen; /* attributes */ + if (p + 2 > end) + goto short_pkt; entry = p; } if (!nr && (entry[0] != 0 || entry[1] == 0)) @@ -3565,7 +3564,7 @@ static int decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res) return 0; } -static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp) +static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_client *clp) { uint32_t *p; uint32_t opnum; @@ -3598,7 +3597,7 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp) READ_BUF(len); return -NFSERR_CLID_INUSE; } else - return -nfs4_stat_to_errno(nfserr); + return -nfs_stat_to_errno(nfserr); return 0; } @@ -4256,7 +4255,7 @@ static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs_fsi if (!status) status = decode_fsinfo(&xdr, fsinfo); if (!status) - status = -nfs4_stat_to_errno(hdr.status); + status = -nfs_stat_to_errno(hdr.status); return status; } @@ -4335,7 +4334,7 @@ static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, uint32_t *p, void *dummy) * a SETCLIENTID request */ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p, - struct nfs_client *clp) + struct nfs4_client *clp) { struct xdr_stream xdr; struct compound_hdr hdr; @@ -4346,7 +4345,7 @@ static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p, if (!status) status = decode_setclientid(&xdr, clp); if (!status) - status = -nfs4_stat_to_errno(hdr.status); + status = -nfs_stat_to_errno(hdr.status); return status; } @@ -4368,7 +4367,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s if (!status) status = decode_fsinfo(&xdr, fsinfo); if (!status) - status = -nfs4_stat_to_errno(hdr.status); + status = -nfs_stat_to_errno(hdr.status); return status; } @@ -4521,7 +4520,7 @@ static struct { * This one is used jointly by NFSv2 and NFSv3. */ static int -nfs4_stat_to_errno(int stat) +nfs_stat_to_errno(int stat) { int i; for (i = 0; nfs_errtbl[i].stat != -1; i++) { diff --git a/trunk/fs/nfs/proc.c b/trunk/fs/nfs/proc.c index 630e50647bbb..b3899ea3229e 100644 --- a/trunk/fs/nfs/proc.c +++ b/trunk/fs/nfs/proc.c @@ -66,14 +66,14 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, dprintk("%s: call getattr\n", __FUNCTION__); nfs_fattr_init(fattr); - status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); + status = rpc_call_sync(server->client_sys, &msg, 0); dprintk("%s: reply getattr: %d\n", __FUNCTION__, status); if (status) return status; dprintk("%s: call statfs\n", __FUNCTION__); msg.rpc_proc = &nfs_procedures[NFSPROC_STATFS]; msg.rpc_resp = &fsinfo; - status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0); + status = rpc_call_sync(server->client_sys, &msg, 0); dprintk("%s: reply statfs: %d\n", __FUNCTION__, status); if (status) return status; @@ -425,17 +425,16 @@ nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) } static int -nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, - unsigned int len, struct iattr *sattr) +nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path, + struct iattr *sattr, struct nfs_fh *fhandle, + struct nfs_fattr *fattr) { - struct nfs_fh fhandle; - struct nfs_fattr fattr; struct nfs_symlinkargs arg = { .fromfh = NFS_FH(dir), - .fromname = dentry->d_name.name, - .fromlen = dentry->d_name.len, - .pages = &page, - .pathlen = len, + .fromname = name->name, + .fromlen = name->len, + .topath = path->name, + .tolen = path->len, .sattr = sattr }; struct rpc_message msg = { @@ -444,25 +443,13 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, }; int status; - if (len > NFS2_MAXPATHLEN) + if (path->len > NFS2_MAXPATHLEN) return -ENAMETOOLONG; - - dprintk("NFS call symlink %s\n", dentry->d_name.name); - + dprintk("NFS call symlink %s -> %s\n", name->name, path->name); + nfs_fattr_init(fattr); + fhandle->size = 0; status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); nfs_mark_for_revalidate(dir); - - /* - * V2 SYMLINK requests don't return any attributes. Setting the - * filehandle size to zero indicates to nfs_instantiate that it - * should fill in the data with a LOOKUP call on the wire. - */ - if (status == 0) { - nfs_fattr_init(&fattr); - fhandle.size = 0; - status = nfs_instantiate(dentry, &fhandle, &fattr); - } - dprintk("NFS reply symlink: %d\n", status); return status; } @@ -684,7 +671,7 @@ nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl) } -const struct nfs_rpc_ops nfs_v2_clientops = { +struct nfs_rpc_ops nfs_v2_clientops = { .version = 2, /* protocol version */ .dentry_ops = &nfs_dentry_operations, .dir_inode_ops = &nfs_dir_inode_operations, diff --git a/trunk/fs/nfs/read.c b/trunk/fs/nfs/read.c index 69f1549da2b9..52bf634260a1 100644 --- a/trunk/fs/nfs/read.c +++ b/trunk/fs/nfs/read.c @@ -43,15 +43,13 @@ static mempool_t *nfs_rdata_mempool; #define MIN_POOL_READ (32) -struct nfs_read_data *nfs_readdata_alloc(size_t len) +struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) { - unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, SLAB_NOFS); if (p) { memset(p, 0, sizeof(*p)); INIT_LIST_HEAD(&p->pages); - p->npages = pagecount; if (pagecount <= ARRAY_SIZE(p->page_array)) p->pagevec = p->page_array; else { @@ -65,7 +63,7 @@ struct nfs_read_data *nfs_readdata_alloc(size_t len) return p; } -static void nfs_readdata_free(struct nfs_read_data *p) +void nfs_readdata_free(struct nfs_read_data *p) { if (p && (p->pagevec != &p->page_array[0])) kfree(p->pagevec); @@ -118,17 +116,10 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data) pages = &data->args.pages[base >> PAGE_CACHE_SHIFT]; base &= ~PAGE_CACHE_MASK; pglen = PAGE_CACHE_SIZE - base; - for (;;) { - if (remainder <= pglen) { - memclear_highpage_flush(*pages, base, remainder); - break; - } + if (pglen < remainder) memclear_highpage_flush(*pages, base, pglen); - pages++; - remainder -= pglen; - pglen = PAGE_CACHE_SIZE; - base = 0; - } + else + memclear_highpage_flush(*pages, base, remainder); } /* @@ -142,7 +133,7 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode, int result; struct nfs_read_data *rdata; - rdata = nfs_readdata_alloc(count); + rdata = nfs_readdata_alloc(1); if (!rdata) return -ENOMEM; @@ -171,7 +162,7 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode, rdata->args.offset = page_offset(page) + rdata->args.pgbase; dprintk("NFS: nfs_proc_read(%s, (%s/%Ld), %Lu, %u)\n", - NFS_SERVER(inode)->nfs_client->cl_hostname, + NFS_SERVER(inode)->hostname, inode->i_sb->s_id, (long long)NFS_FILEID(inode), (unsigned long long)rdata->args.pgbase, @@ -204,11 +195,9 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode, NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; spin_unlock(&inode->i_lock); - if (rdata->res.eof || rdata->res.count == rdata->args.count) { + nfs_readpage_truncate_uninitialised_page(rdata); + if (rdata->res.eof || rdata->res.count == rdata->args.count) SetPageUptodate(page); - if (rdata->res.eof && count != 0) - memclear_highpage_flush(page, rdata->args.pgbase, count); - } result = 0; io_error: @@ -340,25 +329,25 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode) struct nfs_page *req = nfs_list_entry(head->next); struct page *page = req->wb_page; struct nfs_read_data *data; - size_t rsize = NFS_SERVER(inode)->rsize, nbytes; - unsigned int offset; + unsigned int rsize = NFS_SERVER(inode)->rsize; + unsigned int nbytes, offset; int requests = 0; LIST_HEAD(list); nfs_list_remove_request(req); nbytes = req->wb_bytes; - do { - size_t len = min(nbytes,rsize); - - data = nfs_readdata_alloc(len); + for(;;) { + data = nfs_readdata_alloc(1); if (!data) goto out_bad; INIT_LIST_HEAD(&data->pages); list_add(&data->pages, &list); requests++; - nbytes -= len; - } while(nbytes != 0); + if (nbytes <= rsize) + break; + nbytes -= rsize; + } atomic_set(&req->wb_complete, requests); ClearPageError(page); @@ -406,7 +395,7 @@ static int nfs_pagein_one(struct list_head *head, struct inode *inode) if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE) return nfs_pagein_multi(head, inode); - data = nfs_readdata_alloc(NFS_SERVER(inode)->rsize); + data = nfs_readdata_alloc(NFS_SERVER(inode)->rpages); if (!data) goto out_bad; @@ -487,8 +476,6 @@ static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data) unsigned int base = data->args.pgbase; struct page **pages; - if (data->res.eof) - count = data->args.count; if (unlikely(count == 0)) return; pages = &data->args.pages[base >> PAGE_CACHE_SHIFT]; @@ -496,7 +483,11 @@ static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data) count += base; for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++) SetPageUptodate(*pages); - if (count != 0) + /* + * Was this an eof or a short read? If the latter, don't mark the page + * as uptodate yet. + */ + if (count > 0 && (data->res.eof || data->args.count == data->res.count)) SetPageUptodate(*pages); } @@ -511,8 +502,6 @@ static void nfs_readpage_set_pages_error(struct nfs_read_data *data) count += base; for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++) SetPageError(*pages); - if (count != 0) - SetPageError(*pages); } /* @@ -568,13 +557,8 @@ int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data) nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, resp->count); - if (task->tk_status < 0) { - if (task->tk_status == -ESTALE) { - set_bit(NFS_INO_STALE, &NFS_FLAGS(data->inode)); - nfs_mark_for_revalidate(data->inode); - } - } else if (resp->count < argp->count && !resp->eof) { - /* This is a short read! */ + /* Is this a short read? */ + if (task->tk_status >= 0 && resp->count < argp->count && !resp->eof) { nfs_inc_stats(data->inode, NFSIOS_SHORTREAD); /* Has the server at least made some progress? */ if (resp->count != 0) { @@ -621,10 +605,6 @@ int nfs_readpage(struct file *file, struct page *page) if (error) goto out_error; - error = -ESTALE; - if (NFS_STALE(inode)) - goto out_error; - if (file == NULL) { ctx = nfs_find_open_context(inode, NULL, FMODE_READ); if (ctx == NULL) @@ -687,7 +667,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, }; struct inode *inode = mapping->host; struct nfs_server *server = NFS_SERVER(inode); - int ret = -ESTALE; + int ret; dprintk("NFS: nfs_readpages (%s/%Ld %d)\n", inode->i_sb->s_id, @@ -695,9 +675,6 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, nr_pages); nfs_inc_stats(inode, NFSIOS_VFSREADPAGES); - if (NFS_STALE(inode)) - goto out; - if (filp == NULL) { desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ); if (desc.ctx == NULL) @@ -713,7 +690,6 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, ret = err; } put_nfs_open_context(desc.ctx); -out: return ret; } diff --git a/trunk/fs/nfs/super.c b/trunk/fs/nfs/super.c index b99113b0f65f..e8a9bee74d9d 100644 --- a/trunk/fs/nfs/super.c +++ b/trunk/fs/nfs/super.c @@ -13,11 +13,6 @@ * * Split from inode.c by David Howells * - * - superblocks are indexed on server only - all inodes, dentries, etc. associated with a - * particular server are held in the same superblock - * - NFS superblocks can have several effective roots to the dentry tree - * - directory type roots are spliced into the tree when a path from one root reaches the root - * of another (see nfs_lookup()) */ #include @@ -57,12 +52,66 @@ #define NFSDBG_FACILITY NFSDBG_VFS +/* Maximum number of readahead requests + * FIXME: this should really be a sysctl so that users may tune it to suit + * their needs. People that do NFS over a slow network, might for + * instance want to reduce it to something closer to 1 for improved + * interactive response. + */ +#define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) + +/* + * RPC cruft for NFS + */ +static struct rpc_version * nfs_version[] = { + NULL, + NULL, + &nfs_version2, +#if defined(CONFIG_NFS_V3) + &nfs_version3, +#elif defined(CONFIG_NFS_V4) + NULL, +#endif +#if defined(CONFIG_NFS_V4) + &nfs_version4, +#endif +}; + +static struct rpc_program nfs_program = { + .name = "nfs", + .number = NFS_PROGRAM, + .nrvers = ARRAY_SIZE(nfs_version), + .version = nfs_version, + .stats = &nfs_rpcstat, + .pipe_dir_name = "/nfs", +}; + +struct rpc_stat nfs_rpcstat = { + .program = &nfs_program +}; + + +#ifdef CONFIG_NFS_V3_ACL +static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; +static struct rpc_version * nfsacl_version[] = { + [3] = &nfsacl_version3, +}; + +struct rpc_program nfsacl_program = { + .name = "nfsacl", + .number = NFS_ACL_PROGRAM, + .nrvers = ARRAY_SIZE(nfsacl_version), + .version = nfsacl_version, + .stats = &nfsacl_rpcstat, +}; +#endif /* CONFIG_NFS_V3_ACL */ + static void nfs_umount_begin(struct vfsmount *, int); static int nfs_statfs(struct dentry *, struct kstatfs *); static int nfs_show_options(struct seq_file *, struct vfsmount *); static int nfs_show_stats(struct seq_file *, struct vfsmount *); static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); -static int nfs_xdev_get_sb(struct file_system_type *fs_type, +static int nfs_clone_nfs_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); static void nfs_kill_super(struct super_block *); @@ -74,10 +123,10 @@ static struct file_system_type nfs_fs_type = { .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, }; -struct file_system_type nfs_xdev_fs_type = { +struct file_system_type clone_nfs_fs_type = { .owner = THIS_MODULE, .name = "nfs", - .get_sb = nfs_xdev_get_sb, + .get_sb = nfs_clone_nfs_sb, .kill_sb = nfs_kill_super, .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, }; @@ -96,10 +145,10 @@ static struct super_operations nfs_sops = { #ifdef CONFIG_NFS_V4 static int nfs4_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); -static int nfs4_xdev_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); -static int nfs4_referral_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); +static int nfs_clone_nfs4_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); +static int nfs_referral_nfs4_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); static void nfs4_kill_super(struct super_block *sb); static struct file_system_type nfs4_fs_type = { @@ -110,18 +159,18 @@ static struct file_system_type nfs4_fs_type = { .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, }; -struct file_system_type nfs4_xdev_fs_type = { +struct file_system_type clone_nfs4_fs_type = { .owner = THIS_MODULE, .name = "nfs4", - .get_sb = nfs4_xdev_get_sb, + .get_sb = nfs_clone_nfs4_sb, .kill_sb = nfs4_kill_super, .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, }; -struct file_system_type nfs4_referral_fs_type = { +struct file_system_type nfs_referral_nfs4_fs_type = { .owner = THIS_MODULE, .name = "nfs4", - .get_sb = nfs4_referral_get_sb, + .get_sb = nfs_referral_nfs4_sb, .kill_sb = nfs4_kill_super, .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, }; @@ -138,7 +187,39 @@ static struct super_operations nfs4_sops = { }; #endif -static struct shrinker *acl_shrinker; +#ifdef CONFIG_NFS_V4 +static const int nfs_set_port_min = 0; +static const int nfs_set_port_max = 65535; + +static int param_set_port(const char *val, struct kernel_param *kp) +{ + char *endp; + int num = simple_strtol(val, &endp, 0); + if (endp == val || *endp || num < nfs_set_port_min || num > nfs_set_port_max) + return -EINVAL; + *((int *)kp->arg) = num; + return 0; +} + +module_param_call(callback_tcpport, param_set_port, param_get_int, + &nfs_callback_set_tcpport, 0644); +#endif + +#ifdef CONFIG_NFS_V4 +static int param_set_idmap_timeout(const char *val, struct kernel_param *kp) +{ + char *endp; + int num = simple_strtol(val, &endp, 0); + int jif = num * HZ; + if (endp == val || *endp || num < 0 || jif < num) + return -EINVAL; + *((int *)kp->arg) = jif; + return 0; +} + +module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int, + &nfs_idmap_cache_timeout, 0644); +#endif /* * Register the NFS filesystems @@ -159,7 +240,6 @@ int __init register_nfs_fs(void) if (ret < 0) goto error_2; #endif - acl_shrinker = set_shrinker(DEFAULT_SEEKS, nfs_access_cache_shrinker); return 0; #ifdef CONFIG_NFS_V4 @@ -177,8 +257,6 @@ int __init register_nfs_fs(void) */ void __exit unregister_nfs_fs(void) { - if (acl_shrinker != NULL) - remove_shrinker(acl_shrinker); #ifdef CONFIG_NFS_V4 unregister_filesystem(&nfs4_fs_type); nfs_unregister_sysctl(); @@ -191,10 +269,11 @@ void __exit unregister_nfs_fs(void) */ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct nfs_server *server = NFS_SB(dentry->d_sb); + struct super_block *sb = dentry->d_sb; + struct nfs_server *server = NFS_SB(sb); unsigned char blockbits; unsigned long blockres; - struct nfs_fh *fh = NFS_FH(dentry->d_inode); + struct nfs_fh *rootfh = NFS_FH(sb->s_root->d_inode); struct nfs_fattr fattr; struct nfs_fsstat res = { .fattr = &fattr, @@ -203,7 +282,7 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) lock_kernel(); - error = server->nfs_client->rpc_ops->statfs(server, fh, &res); + error = server->rpc_ops->statfs(server, rootfh, &res); buf->f_type = NFS_SUPER_MAGIC; if (error < 0) goto out_err; @@ -213,7 +292,7 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) * case where f_frsize != f_bsize. Eventually we want to * report the value of wtmult in this field. */ - buf->f_frsize = dentry->d_sb->s_blocksize; + buf->f_frsize = sb->s_blocksize; /* * On most *nix systems, f_blocks, f_bfree, and f_bavail @@ -222,8 +301,8 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) * thus historically Linux's sys_statfs reports these * fields in units of f_bsize. */ - buf->f_bsize = dentry->d_sb->s_blocksize; - blockbits = dentry->d_sb->s_blocksize_bits; + buf->f_bsize = sb->s_blocksize; + blockbits = sb->s_blocksize_bits; blockres = (1 << blockbits) - 1; buf->f_blocks = (res.tbytes + blockres) >> blockbits; buf->f_bfree = (res.fbytes + blockres) >> blockbits; @@ -244,12 +323,9 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) } -/* - * Map the security flavour number to a name - */ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour) { - static const struct { + static struct { rpc_authflavor_t flavour; const char *str; } sec_flavours[] = { @@ -280,10 +356,10 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour) */ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults) { - static const struct proc_nfs_info { + static struct proc_nfs_info { int flag; - const char *str; - const char *nostr; + char *str; + char *nostr; } nfs_info[] = { { NFS_MOUNT_SOFT, ",soft", ",hard" }, { NFS_MOUNT_INTR, ",intr", "" }, @@ -293,12 +369,11 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, { NFS_MOUNT_NOACL, ",noacl", "" }, { 0, NULL, NULL } }; - const struct proc_nfs_info *nfs_infop; - struct nfs_client *clp = nfss->nfs_client; + struct proc_nfs_info *nfs_infop; char buf[12]; - const char *proto; + char *proto; - seq_printf(m, ",vers=%d", clp->rpc_ops->version); + seq_printf(m, ",vers=%d", nfss->rpc_ops->version); seq_printf(m, ",rsize=%d", nfss->rsize); seq_printf(m, ",wsize=%d", nfss->wsize); if (nfss->acregmin != 3*HZ || showdefaults) @@ -327,8 +402,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, proto = buf; } seq_printf(m, ",proto=%s", proto); - seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ); - seq_printf(m, ",retrans=%u", clp->retrans_count); + seq_printf(m, ",timeo=%lu", 10U * nfss->retrans_timeo / HZ); + seq_printf(m, ",retrans=%u", nfss->retrans_count); seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); } @@ -342,7 +417,7 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) nfs_show_mount_options(m, nfss, 0); seq_puts(m, ",addr="); - seq_escape(m, nfss->nfs_client->cl_hostname, " \t\n\\"); + seq_escape(m, nfss->hostname, " \t\n\\"); return 0; } @@ -379,7 +454,7 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) seq_printf(m, ",namelen=%d", nfss->namelen); #ifdef CONFIG_NFS_V4 - if (nfss->nfs_client->cl_nfsversion == 4) { + if (nfss->rpc_ops->version == 4) { seq_printf(m, "\n\tnfsv4:\t"); seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); @@ -426,353 +501,782 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) /* * Begin unmount by attempting to remove all automounted mountpoints we added - * in response to xdev traversals and referrals + * in response to traversals */ static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags) { + struct nfs_server *server; + struct rpc_clnt *rpc; + shrink_submounts(vfsmnt, &nfs_automount_list); + if (!(flags & MNT_FORCE)) + return; + /* -EIO all pending I/O */ + server = NFS_SB(vfsmnt->mnt_sb); + rpc = server->client; + if (!IS_ERR(rpc)) + rpc_killall_tasks(rpc); + rpc = server->client_acl; + if (!IS_ERR(rpc)) + rpc_killall_tasks(rpc); } /* - * Validate the NFS2/NFS3 mount data - * - fills in the mount root filehandle + * Obtain the root inode of the file system. */ -static int nfs_validate_mount_data(struct nfs_mount_data *data, - struct nfs_fh *mntfh) +static struct inode * +nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo) { - if (data == NULL) { - dprintk("%s: missing data argument\n", __FUNCTION__); - return -EINVAL; - } + struct nfs_server *server = NFS_SB(sb); + int error; - if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { - dprintk("%s: bad mount version\n", __FUNCTION__); - return -EINVAL; + error = server->rpc_ops->getroot(server, rootfh, fsinfo); + if (error < 0) { + dprintk("nfs_get_root: getattr error = %d\n", -error); + return ERR_PTR(error); } - switch (data->version) { - case 1: - data->namlen = 0; - case 2: - data->bsize = 0; - case 3: - if (data->flags & NFS_MOUNT_VER3) { - dprintk("%s: mount structure version %d does not support NFSv3\n", - __FUNCTION__, - data->version); - return -EINVAL; - } - data->root.size = NFS2_FHSIZE; - memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); - case 4: - if (data->flags & NFS_MOUNT_SECFLAVOUR) { - dprintk("%s: mount structure version %d does not support strong security\n", - __FUNCTION__, - data->version); - return -EINVAL; - } - case 5: - memset(data->context, 0, sizeof(data->context)); - } + server->fsid = fsinfo->fattr->fsid; + return nfs_fhget(sb, rootfh, fsinfo->fattr); +} - /* Set the pseudoflavor */ - if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) - data->pseudoflavor = RPC_AUTH_UNIX; +/* + * Do NFS version-independent mount processing, and sanity checking + */ +static int +nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor) +{ + struct nfs_server *server; + struct inode *root_inode; + struct nfs_fattr fattr; + struct nfs_fsinfo fsinfo = { + .fattr = &fattr, + }; + struct nfs_pathconf pathinfo = { + .fattr = &fattr, + }; + int no_root_error = 0; + unsigned long max_rpc_payload; -#ifndef CONFIG_NFS_V3 - /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ - if (data->flags & NFS_MOUNT_VER3) { - dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); - return -EPROTONOSUPPORT; - } -#endif /* CONFIG_NFS_V3 */ + /* We probably want something more informative here */ + snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev)); - /* We now require that the mount process passes the remote address */ - if (data->addr.sin_addr.s_addr == INADDR_ANY) { - dprintk("%s: mount program didn't pass remote address!\n", - __FUNCTION__); - return -EINVAL; - } + server = NFS_SB(sb); - /* Prepare the root filehandle */ - if (data->flags & NFS_MOUNT_VER3) - mntfh->size = data->root.size; - else - mntfh->size = NFS2_FHSIZE; + sb->s_magic = NFS_SUPER_MAGIC; - if (mntfh->size > sizeof(mntfh->data)) { - dprintk("%s: invalid root filehandle\n", __FUNCTION__); - return -EINVAL; + server->io_stats = nfs_alloc_iostats(); + if (server->io_stats == NULL) + return -ENOMEM; + + root_inode = nfs_get_root(sb, &server->fh, &fsinfo); + /* Did getting the root inode fail? */ + if (IS_ERR(root_inode)) { + no_root_error = PTR_ERR(root_inode); + goto out_no_root; + } + sb->s_root = d_alloc_root(root_inode); + if (!sb->s_root) { + no_root_error = -ENOMEM; + goto out_no_root; } + sb->s_root->d_op = server->rpc_ops->dentry_ops; + + /* mount time stamp, in seconds */ + server->mount_time = jiffies; + + /* Get some general file system info */ + if (server->namelen == 0 && + server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0) + server->namelen = pathinfo.max_namelen; + /* Work out a lot of parameters */ + if (server->rsize == 0) + server->rsize = nfs_block_size(fsinfo.rtpref, NULL); + if (server->wsize == 0) + server->wsize = nfs_block_size(fsinfo.wtpref, NULL); + + if (fsinfo.rtmax >= 512 && server->rsize > fsinfo.rtmax) + server->rsize = nfs_block_size(fsinfo.rtmax, NULL); + if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax) + server->wsize = nfs_block_size(fsinfo.wtmax, NULL); + + max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL); + if (server->rsize > max_rpc_payload) + server->rsize = max_rpc_payload; + if (server->rsize > NFS_MAX_FILE_IO_SIZE) + server->rsize = NFS_MAX_FILE_IO_SIZE; + server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + + if (server->wsize > max_rpc_payload) + server->wsize = max_rpc_payload; + if (server->wsize > NFS_MAX_FILE_IO_SIZE) + server->wsize = NFS_MAX_FILE_IO_SIZE; + server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - memcpy(mntfh->data, data->root.data, mntfh->size); - if (mntfh->size < sizeof(mntfh->data)) - memset(mntfh->data + mntfh->size, 0, - sizeof(mntfh->data) - mntfh->size); + if (sb->s_blocksize == 0) + sb->s_blocksize = nfs_block_bits(server->wsize, + &sb->s_blocksize_bits); + server->wtmult = nfs_block_bits(fsinfo.wtmult, NULL); + + server->dtsize = nfs_block_size(fsinfo.dtpref, NULL); + if (server->dtsize > PAGE_CACHE_SIZE) + server->dtsize = PAGE_CACHE_SIZE; + if (server->dtsize > server->rsize) + server->dtsize = server->rsize; + + if (server->flags & NFS_MOUNT_NOAC) { + server->acregmin = server->acregmax = 0; + server->acdirmin = server->acdirmax = 0; + sb->s_flags |= MS_SYNCHRONOUS; + } + server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD; + nfs_super_set_maxbytes(sb, fsinfo.maxfilesize); + + server->client->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0; + server->client->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0; + + /* We're airborne Set socket buffersize */ + rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100); return 0; + /* Yargs. It didn't work out. */ +out_no_root: + dprintk("nfs_sb_init: get root inode failed: errno %d\n", -no_root_error); + if (!IS_ERR(root_inode)) + iput(root_inode); + return no_root_error; } /* - * Initialise the common bits of the superblock + * Initialise the timeout values for a connection */ -static inline void nfs_initialise_sb(struct super_block *sb) +static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans) { - struct nfs_server *server = NFS_SB(sb); - - sb->s_magic = NFS_SUPER_MAGIC; + to->to_initval = timeo * HZ / 10; + to->to_retries = retrans; + if (!to->to_retries) + to->to_retries = 2; + + switch (proto) { + case IPPROTO_TCP: + if (!to->to_initval) + to->to_initval = 60 * HZ; + if (to->to_initval > NFS_MAX_TCP_TIMEOUT) + to->to_initval = NFS_MAX_TCP_TIMEOUT; + to->to_increment = to->to_initval; + to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); + to->to_exponential = 0; + break; + case IPPROTO_UDP: + default: + if (!to->to_initval) + to->to_initval = 11 * HZ / 10; + if (to->to_initval > NFS_MAX_UDP_TIMEOUT) + to->to_initval = NFS_MAX_UDP_TIMEOUT; + to->to_maxval = NFS_MAX_UDP_TIMEOUT; + to->to_exponential = 1; + break; + } +} - /* We probably want something more informative here */ - snprintf(sb->s_id, sizeof(sb->s_id), - "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev)); +/* + * Create an RPC client handle. + */ +static struct rpc_clnt * +nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) +{ + struct rpc_timeout timeparms; + struct rpc_xprt *xprt = NULL; + struct rpc_clnt *clnt = NULL; + int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; + + nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans); + + server->retrans_timeo = timeparms.to_initval; + server->retrans_count = timeparms.to_retries; + + /* create transport and client */ + xprt = xprt_create_proto(proto, &server->addr, &timeparms); + if (IS_ERR(xprt)) { + dprintk("%s: cannot create RPC transport. Error = %ld\n", + __FUNCTION__, PTR_ERR(xprt)); + return (struct rpc_clnt *)xprt; + } + clnt = rpc_create_client(xprt, server->hostname, &nfs_program, + server->rpc_ops->version, data->pseudoflavor); + if (IS_ERR(clnt)) { + dprintk("%s: cannot create RPC client. Error = %ld\n", + __FUNCTION__, PTR_ERR(xprt)); + goto out_fail; + } - if (sb->s_blocksize == 0) - sb->s_blocksize = nfs_block_bits(server->wsize, - &sb->s_blocksize_bits); + clnt->cl_intr = 1; + clnt->cl_softrtry = 1; - if (server->flags & NFS_MOUNT_NOAC) - sb->s_flags |= MS_SYNCHRONOUS; + return clnt; - nfs_super_set_maxbytes(sb, server->maxfilesize); +out_fail: + return clnt; } /* - * Finish setting up an NFS2/3 superblock + * Clone a server record */ -static void nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data) +static struct nfs_server *nfs_clone_server(struct super_block *sb, struct nfs_clone_mount *data) { struct nfs_server *server = NFS_SB(sb); + struct nfs_server *parent = NFS_SB(data->sb); + struct inode *root_inode; + struct nfs_fsinfo fsinfo; + void *err = ERR_PTR(-ENOMEM); + + sb->s_op = data->sb->s_op; + sb->s_blocksize = data->sb->s_blocksize; + sb->s_blocksize_bits = data->sb->s_blocksize_bits; + sb->s_maxbytes = data->sb->s_maxbytes; + + server->client_sys = server->client_acl = ERR_PTR(-EINVAL); + server->io_stats = nfs_alloc_iostats(); + if (server->io_stats == NULL) + goto out; + + server->client = rpc_clone_client(parent->client); + if (IS_ERR((err = server->client))) + goto out; + + if (!IS_ERR(parent->client_sys)) { + server->client_sys = rpc_clone_client(parent->client_sys); + if (IS_ERR((err = server->client_sys))) + goto out; + } + if (!IS_ERR(parent->client_acl)) { + server->client_acl = rpc_clone_client(parent->client_acl); + if (IS_ERR((err = server->client_acl))) + goto out; + } + root_inode = nfs_fhget(sb, data->fh, data->fattr); + if (!root_inode) + goto out; + sb->s_root = d_alloc_root(root_inode); + if (!sb->s_root) + goto out_put_root; + fsinfo.fattr = data->fattr; + if (NFS_PROTO(root_inode)->fsinfo(server, data->fh, &fsinfo) == 0) + nfs_super_set_maxbytes(sb, fsinfo.maxfilesize); + sb->s_root->d_op = server->rpc_ops->dentry_ops; + sb->s_flags |= MS_ACTIVE; + return server; +out_put_root: + iput(root_inode); +out: + return err; +} - sb->s_blocksize_bits = 0; - sb->s_blocksize = 0; - if (data->bsize) - sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); - - if (server->flags & NFS_MOUNT_VER3) { - /* The VFS shouldn't apply the umask to mode bits. We will do - * so ourselves when necessary. - */ - sb->s_flags |= MS_POSIXACL; - sb->s_time_gran = 1; +/* + * Copy an existing superblock and attach revised data + */ +static int nfs_clone_generic_sb(struct nfs_clone_mount *data, + struct super_block *(*fill_sb)(struct nfs_server *, struct nfs_clone_mount *), + struct nfs_server *(*fill_server)(struct super_block *, struct nfs_clone_mount *), + struct vfsmount *mnt) +{ + struct nfs_server *server; + struct nfs_server *parent = NFS_SB(data->sb); + struct super_block *sb = ERR_PTR(-EINVAL); + char *hostname; + int error = -ENOMEM; + int len; + + server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); + if (server == NULL) + goto out_err; + memcpy(server, parent, sizeof(*server)); + hostname = (data->hostname != NULL) ? data->hostname : parent->hostname; + len = strlen(hostname) + 1; + server->hostname = kmalloc(len, GFP_KERNEL); + if (server->hostname == NULL) + goto free_server; + memcpy(server->hostname, hostname, len); + error = rpciod_up(); + if (error != 0) + goto free_hostname; + + sb = fill_sb(server, data); + if (IS_ERR(sb)) { + error = PTR_ERR(sb); + goto kill_rpciod; } + + if (sb->s_root) + goto out_rpciod_down; - sb->s_op = &nfs_sops; - nfs_initialise_sb(sb); + server = fill_server(sb, data); + if (IS_ERR(server)) { + error = PTR_ERR(server); + goto out_deactivate; + } + return simple_set_mnt(mnt, sb); +out_deactivate: + up_write(&sb->s_umount); + deactivate_super(sb); + return error; +out_rpciod_down: + rpciod_down(); + kfree(server->hostname); + kfree(server); + return simple_set_mnt(mnt, sb); +kill_rpciod: + rpciod_down(); +free_hostname: + kfree(server->hostname); +free_server: + kfree(server); +out_err: + return error; } /* - * Finish setting up a cloned NFS2/3 superblock + * Set up an NFS2/3 superblock + * + * The way this works is that the mount process passes a structure + * in the data argument which contains the server's IP address + * and the root file handle obtained from the server's mount + * daemon. We stash these away in the private superblock fields. */ -static void nfs_clone_super(struct super_block *sb, - const struct super_block *old_sb) +static int +nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent) { - struct nfs_server *server = NFS_SB(sb); + struct nfs_server *server; + rpc_authflavor_t authflavor; - sb->s_blocksize_bits = old_sb->s_blocksize_bits; - sb->s_blocksize = old_sb->s_blocksize; - sb->s_maxbytes = old_sb->s_maxbytes; + server = NFS_SB(sb); + sb->s_blocksize_bits = 0; + sb->s_blocksize = 0; + if (data->bsize) + sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); + if (data->rsize) + server->rsize = nfs_block_size(data->rsize, NULL); + if (data->wsize) + server->wsize = nfs_block_size(data->wsize, NULL); + server->flags = data->flags & NFS_MOUNT_FLAGMASK; + + server->acregmin = data->acregmin*HZ; + server->acregmax = data->acregmax*HZ; + server->acdirmin = data->acdirmin*HZ; + server->acdirmax = data->acdirmax*HZ; + + /* Start lockd here, before we might error out */ + if (!(server->flags & NFS_MOUNT_NONLM)) + lockd_up(); + + server->namelen = data->namlen; + server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL); + if (!server->hostname) + return -ENOMEM; + strcpy(server->hostname, data->hostname); + + /* Check NFS protocol revision and initialize RPC op vector + * and file handle pool. */ +#ifdef CONFIG_NFS_V3 + if (server->flags & NFS_MOUNT_VER3) { + server->rpc_ops = &nfs_v3_clientops; + server->caps |= NFS_CAP_READDIRPLUS; + } else { + server->rpc_ops = &nfs_v2_clientops; + } +#else + server->rpc_ops = &nfs_v2_clientops; +#endif + /* Fill in pseudoflavor for mount version < 5 */ + if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) + data->pseudoflavor = RPC_AUTH_UNIX; + authflavor = data->pseudoflavor; /* save for sb_init() */ + /* XXX maybe we want to add a server->pseudoflavor field */ + + /* Create RPC client handles */ + server->client = nfs_create_client(server, data); + if (IS_ERR(server->client)) + return PTR_ERR(server->client); + /* RFC 2623, sec 2.3.2 */ + if (authflavor != RPC_AUTH_UNIX) { + struct rpc_auth *auth; + + server->client_sys = rpc_clone_client(server->client); + if (IS_ERR(server->client_sys)) + return PTR_ERR(server->client_sys); + auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys); + if (IS_ERR(auth)) + return PTR_ERR(auth); + } else { + atomic_inc(&server->client->cl_count); + server->client_sys = server->client; + } if (server->flags & NFS_MOUNT_VER3) { - /* The VFS shouldn't apply the umask to mode bits. We will do - * so ourselves when necessary. +#ifdef CONFIG_NFS_V3_ACL + if (!(server->flags & NFS_MOUNT_NOACL)) { + server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); + /* No errors! Assume that Sun nfsacls are supported */ + if (!IS_ERR(server->client_acl)) + server->caps |= NFS_CAP_ACLS; + } +#else + server->flags &= ~NFS_MOUNT_NOACL; +#endif /* CONFIG_NFS_V3_ACL */ + /* + * The VFS shouldn't apply the umask to mode bits. We will + * do so ourselves when necessary. */ sb->s_flags |= MS_POSIXACL; + if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) + server->namelen = NFS3_MAXNAMLEN; sb->s_time_gran = 1; + } else { + if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) + server->namelen = NFS2_MAXNAMLEN; } - sb->s_op = old_sb->s_op; - nfs_initialise_sb(sb); + sb->s_op = &nfs_sops; + return nfs_sb_init(sb, authflavor); } -static int nfs_set_super(struct super_block *s, void *_server) +static int nfs_set_super(struct super_block *s, void *data) { - struct nfs_server *server = _server; - int ret; - - s->s_fs_info = server; - ret = set_anon_super(s, server); - if (ret == 0) - server->s_dev = s->s_dev; - return ret; + s->s_fs_info = data; + return set_anon_super(s, data); } static int nfs_compare_super(struct super_block *sb, void *data) { - struct nfs_server *server = data, *old = NFS_SB(sb); + struct nfs_server *server = data; + struct nfs_server *old = NFS_SB(sb); - if (old->nfs_client != server->nfs_client) + if (old->addr.sin_addr.s_addr != server->addr.sin_addr.s_addr) return 0; - if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0) + if (old->addr.sin_port != server->addr.sin_port) return 0; - return 1; + return !nfs_compare_fh(&old->fh, &server->fh); } static int nfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) { + int error; struct nfs_server *server = NULL; struct super_block *s; - struct nfs_fh mntfh; + struct nfs_fh *root; struct nfs_mount_data *data = raw_data; - struct dentry *mntroot; - int error; - /* Validate the mount data */ - error = nfs_validate_mount_data(data, &mntfh); - if (error < 0) - return error; + error = -EINVAL; + if (data == NULL) { + dprintk("%s: missing data argument\n", __FUNCTION__); + goto out_err_noserver; + } + if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { + dprintk("%s: bad mount version\n", __FUNCTION__); + goto out_err_noserver; + } + switch (data->version) { + case 1: + data->namlen = 0; + case 2: + data->bsize = 0; + case 3: + if (data->flags & NFS_MOUNT_VER3) { + dprintk("%s: mount structure version %d does not support NFSv3\n", + __FUNCTION__, + data->version); + goto out_err_noserver; + } + data->root.size = NFS2_FHSIZE; + memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); + case 4: + if (data->flags & NFS_MOUNT_SECFLAVOUR) { + dprintk("%s: mount structure version %d does not support strong security\n", + __FUNCTION__, + data->version); + goto out_err_noserver; + } + case 5: + memset(data->context, 0, sizeof(data->context)); + } +#ifndef CONFIG_NFS_V3 + /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ + error = -EPROTONOSUPPORT; + if (data->flags & NFS_MOUNT_VER3) { + dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); + goto out_err_noserver; + } +#endif /* CONFIG_NFS_V3 */ - /* Get a volume representation */ - server = nfs_create_server(data, &mntfh); - if (IS_ERR(server)) { - error = PTR_ERR(server); + error = -ENOMEM; + server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); + if (!server) goto out_err_noserver; + /* Zero out the NFS state stuff */ + init_nfsv4_state(server); + server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); + + root = &server->fh; + if (data->flags & NFS_MOUNT_VER3) + root->size = data->root.size; + else + root->size = NFS2_FHSIZE; + error = -EINVAL; + if (root->size > sizeof(root->data)) { + dprintk("%s: invalid root filehandle\n", __FUNCTION__); + goto out_err; + } + memcpy(root->data, data->root.data, root->size); + + /* We now require that the mount process passes the remote address */ + memcpy(&server->addr, &data->addr, sizeof(server->addr)); + if (server->addr.sin_addr.s_addr == INADDR_ANY) { + dprintk("%s: mount program didn't pass remote address!\n", + __FUNCTION__); + goto out_err; + } + + /* Fire up rpciod if not yet running */ + error = rpciod_up(); + if (error < 0) { + dprintk("%s: couldn't start rpciod! Error = %d\n", + __FUNCTION__, error); + goto out_err; } - /* Get a superblock - note that we may end up sharing one that already exists */ s = sget(fs_type, nfs_compare_super, nfs_set_super, server); if (IS_ERR(s)) { error = PTR_ERR(s); - goto out_err_nosb; + goto out_err_rpciod; } - if (s->s_fs_info != server) { - nfs_free_server(server); - server = NULL; - } + if (s->s_root) + goto out_rpciod_down; - if (!s->s_root) { - /* initial superblock/root creation */ - s->s_flags = flags; - nfs_fill_super(s, data); - } + s->s_flags = flags; - mntroot = nfs_get_root(s, &mntfh); - if (IS_ERR(mntroot)) { - error = PTR_ERR(mntroot); - goto error_splat_super; + error = nfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0); + if (error) { + up_write(&s->s_umount); + deactivate_super(s); + return error; } - s->s_flags |= MS_ACTIVE; - mnt->mnt_sb = s; - mnt->mnt_root = mntroot; - return 0; + return simple_set_mnt(mnt, s); -out_err_nosb: - nfs_free_server(server); -out_err_noserver: - return error; +out_rpciod_down: + rpciod_down(); + kfree(server); + return simple_set_mnt(mnt, s); -error_splat_super: - up_write(&s->s_umount); - deactivate_super(s); +out_err_rpciod: + rpciod_down(); +out_err: + kfree(server); +out_err_noserver: return error; } -/* - * Destroy an NFS2/3 superblock - */ static void nfs_kill_super(struct super_block *s) { struct nfs_server *server = NFS_SB(s); kill_anon_super(s); - nfs_free_server(server); + + if (!IS_ERR(server->client)) + rpc_shutdown_client(server->client); + if (!IS_ERR(server->client_sys)) + rpc_shutdown_client(server->client_sys); + if (!IS_ERR(server->client_acl)) + rpc_shutdown_client(server->client_acl); + + if (!(server->flags & NFS_MOUNT_NONLM)) + lockd_down(); /* release rpc.lockd */ + + rpciod_down(); /* release rpciod */ + + nfs_free_iostats(server->io_stats); + kfree(server->hostname); + kfree(server); + nfs_release_automount_timer(); } -/* - * Clone an NFS2/3 server record on xdev traversal (FSID-change) - */ -static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *raw_data, - struct vfsmount *mnt) +static struct super_block *nfs_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data) { - struct nfs_clone_mount *data = raw_data; - struct super_block *s; - struct nfs_server *server; - struct dentry *mntroot; - int error; - - dprintk("--> nfs_xdev_get_sb()\n"); + struct super_block *sb; + + server->fsid = data->fattr->fsid; + nfs_copy_fh(&server->fh, data->fh); + sb = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); + if (!IS_ERR(sb) && sb->s_root == NULL && !(server->flags & NFS_MOUNT_NONLM)) + lockd_up(); + return sb; +} - /* create a new volume representation */ - server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); - if (IS_ERR(server)) { - error = PTR_ERR(server); - goto out_err_noserver; - } +static int nfs_clone_nfs_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) +{ + struct nfs_clone_mount *data = raw_data; + return nfs_clone_generic_sb(data, nfs_clone_sb, nfs_clone_server, mnt); +} - /* Get a superblock - note that we may end up sharing one that already exists */ - s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); - if (IS_ERR(s)) { - error = PTR_ERR(s); - goto out_err_nosb; +#ifdef CONFIG_NFS_V4 +static struct rpc_clnt *nfs4_create_client(struct nfs_server *server, + struct rpc_timeout *timeparms, int proto, rpc_authflavor_t flavor) +{ + struct nfs4_client *clp; + struct rpc_xprt *xprt = NULL; + struct rpc_clnt *clnt = NULL; + int err = -EIO; + + clp = nfs4_get_client(&server->addr.sin_addr); + if (!clp) { + dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__); + return ERR_PTR(err); } - if (s->s_fs_info != server) { - nfs_free_server(server); - server = NULL; + /* Now create transport and client */ + down_write(&clp->cl_sem); + if (IS_ERR(clp->cl_rpcclient)) { + xprt = xprt_create_proto(proto, &server->addr, timeparms); + if (IS_ERR(xprt)) { + up_write(&clp->cl_sem); + err = PTR_ERR(xprt); + dprintk("%s: cannot create RPC transport. Error = %d\n", + __FUNCTION__, err); + goto out_fail; + } + /* Bind to a reserved port! */ + xprt->resvport = 1; + clnt = rpc_create_client(xprt, server->hostname, &nfs_program, + server->rpc_ops->version, flavor); + if (IS_ERR(clnt)) { + up_write(&clp->cl_sem); + err = PTR_ERR(clnt); + dprintk("%s: cannot create RPC client. Error = %d\n", + __FUNCTION__, err); + goto out_fail; + } + clnt->cl_intr = 1; + clnt->cl_softrtry = 1; + clp->cl_rpcclient = clnt; + memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr)); + nfs_idmap_new(clp); } - - if (!s->s_root) { - /* initial superblock/root creation */ - s->s_flags = flags; - nfs_clone_super(s, data->sb); + list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks); + clnt = rpc_clone_client(clp->cl_rpcclient); + if (!IS_ERR(clnt)) + server->nfs4_state = clp; + up_write(&clp->cl_sem); + clp = NULL; + + if (IS_ERR(clnt)) { + dprintk("%s: cannot create RPC client. Error = %d\n", + __FUNCTION__, err); + return clnt; } - mntroot = nfs_get_root(s, data->fh); - if (IS_ERR(mntroot)) { - error = PTR_ERR(mntroot); - goto error_splat_super; + if (server->nfs4_state->cl_idmap == NULL) { + dprintk("%s: failed to create idmapper.\n", __FUNCTION__); + return ERR_PTR(-ENOMEM); } - s->s_flags |= MS_ACTIVE; - mnt->mnt_sb = s; - mnt->mnt_root = mntroot; + if (clnt->cl_auth->au_flavor != flavor) { + struct rpc_auth *auth; - dprintk("<-- nfs_xdev_get_sb() = 0\n"); - return 0; - -out_err_nosb: - nfs_free_server(server); -out_err_noserver: - dprintk("<-- nfs_xdev_get_sb() = %d [error]\n", error); - return error; + auth = rpcauth_create(flavor, clnt); + if (IS_ERR(auth)) { + dprintk("%s: couldn't create credcache!\n", __FUNCTION__); + return (struct rpc_clnt *)auth; + } + } + return clnt; -error_splat_super: - up_write(&s->s_umount); - deactivate_super(s); - dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error); - return error; + out_fail: + if (clp) + nfs4_put_client(clp); + return ERR_PTR(err); } -#ifdef CONFIG_NFS_V4 - /* - * Finish setting up a cloned NFS4 superblock + * Set up an NFS4 superblock */ -static void nfs4_clone_super(struct super_block *sb, - const struct super_block *old_sb) +static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent) { - sb->s_blocksize_bits = old_sb->s_blocksize_bits; - sb->s_blocksize = old_sb->s_blocksize; - sb->s_maxbytes = old_sb->s_maxbytes; + struct nfs_server *server; + struct rpc_timeout timeparms; + rpc_authflavor_t authflavour; + int err = -EIO; + + sb->s_blocksize_bits = 0; + sb->s_blocksize = 0; + server = NFS_SB(sb); + if (data->rsize != 0) + server->rsize = nfs_block_size(data->rsize, NULL); + if (data->wsize != 0) + server->wsize = nfs_block_size(data->wsize, NULL); + server->flags = data->flags & NFS_MOUNT_FLAGMASK; + server->caps = NFS_CAP_ATOMIC_OPEN; + + server->acregmin = data->acregmin*HZ; + server->acregmax = data->acregmax*HZ; + server->acdirmin = data->acdirmin*HZ; + server->acdirmax = data->acdirmax*HZ; + + server->rpc_ops = &nfs_v4_clientops; + + nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans); + + server->retrans_timeo = timeparms.to_initval; + server->retrans_count = timeparms.to_retries; + + /* Now create transport and client */ + authflavour = RPC_AUTH_UNIX; + if (data->auth_flavourlen != 0) { + if (data->auth_flavourlen != 1) { + dprintk("%s: Invalid number of RPC auth flavours %d.\n", + __FUNCTION__, data->auth_flavourlen); + err = -EINVAL; + goto out_fail; + } + if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) { + err = -EFAULT; + goto out_fail; + } + } + + server->client = nfs4_create_client(server, &timeparms, data->proto, authflavour); + if (IS_ERR(server->client)) { + err = PTR_ERR(server->client); + dprintk("%s: cannot create RPC client. Error = %d\n", + __FUNCTION__, err); + goto out_fail; + } + sb->s_time_gran = 1; - sb->s_op = old_sb->s_op; - nfs_initialise_sb(sb); + + sb->s_op = &nfs4_sops; + err = nfs_sb_init(sb, authflavour); + + out_fail: + return err; } -/* - * Set up an NFS4 superblock - */ -static void nfs4_fill_super(struct super_block *sb) +static int nfs4_compare_super(struct super_block *sb, void *data) { - sb->s_time_gran = 1; - sb->s_op = &nfs4_sops; - nfs_initialise_sb(sb); + struct nfs_server *server = data; + struct nfs_server *old = NFS_SB(sb); + + if (strcmp(server->hostname, old->hostname) != 0) + return 0; + if (strcmp(server->mnt_path, old->mnt_path) != 0) + return 0; + return 1; } -static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) +static void * +nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) { void *p = NULL; @@ -793,22 +1297,14 @@ static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) return dst; } -/* - * Get the superblock for an NFS4 mountpoint - */ static int nfs4_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) { - struct nfs4_mount_data *data = raw_data; - struct super_block *s; + int error; struct nfs_server *server; - struct sockaddr_in addr; - rpc_authflavor_t authflavour; - struct nfs_fh mntfh; - struct dentry *mntroot; - char *mntpath = NULL, *hostname = NULL, ip_addr[16]; + struct super_block *s; + struct nfs4_mount_data *data = raw_data; void *p; - int error; if (data == NULL) { dprintk("%s: missing data argument\n", __FUNCTION__); @@ -819,112 +1315,84 @@ static int nfs4_get_sb(struct file_system_type *fs_type, return -EINVAL; } - /* We now require that the mount process passes the remote address */ - if (data->host_addrlen != sizeof(addr)) - return -EINVAL; - - if (copy_from_user(&addr, data->host_addr, sizeof(addr))) - return -EFAULT; - - if (addr.sin_family != AF_INET || - addr.sin_addr.s_addr == INADDR_ANY - ) { - dprintk("%s: mount program didn't pass remote IP address!\n", - __FUNCTION__); - return -EINVAL; - } - /* RFC3530: The default port for NFS is 2049 */ - if (addr.sin_port == 0) - addr.sin_port = NFS_PORT; - - /* Grab the authentication type */ - authflavour = RPC_AUTH_UNIX; - if (data->auth_flavourlen != 0) { - if (data->auth_flavourlen != 1) { - dprintk("%s: Invalid number of RPC auth flavours %d.\n", - __FUNCTION__, data->auth_flavourlen); - error = -EINVAL; - goto out_err_noserver; - } - - if (copy_from_user(&authflavour, data->auth_flavours, - sizeof(authflavour))) { - error = -EFAULT; - goto out_err_noserver; - } - } + server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); + if (!server) + return -ENOMEM; + /* Zero out the NFS state stuff */ + init_nfsv4_state(server); + server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); p = nfs_copy_user_string(NULL, &data->hostname, 256); if (IS_ERR(p)) goto out_err; - hostname = p; + server->hostname = p; p = nfs_copy_user_string(NULL, &data->mnt_path, 1024); if (IS_ERR(p)) goto out_err; - mntpath = p; - - dprintk("MNTPATH: %s\n", mntpath); + server->mnt_path = p; - p = nfs_copy_user_string(ip_addr, &data->client_addr, - sizeof(ip_addr) - 1); + p = nfs_copy_user_string(server->ip_addr, &data->client_addr, + sizeof(server->ip_addr) - 1); if (IS_ERR(p)) goto out_err; - /* Get a volume representation */ - server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr, - authflavour, &mntfh); - if (IS_ERR(server)) { - error = PTR_ERR(server); - goto out_err_noserver; + /* We now require that the mount process passes the remote address */ + if (data->host_addrlen != sizeof(server->addr)) { + error = -EINVAL; + goto out_free; + } + if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { + error = -EFAULT; + goto out_free; + } + if (server->addr.sin_family != AF_INET || + server->addr.sin_addr.s_addr == INADDR_ANY) { + dprintk("%s: mount program didn't pass remote IP address!\n", + __FUNCTION__); + error = -EINVAL; + goto out_free; } - /* Get a superblock - note that we may end up sharing one that already exists */ - s = sget(fs_type, nfs_compare_super, nfs_set_super, server); + /* Fire up rpciod if not yet running */ + error = rpciod_up(); + if (error < 0) { + dprintk("%s: couldn't start rpciod! Error = %d\n", + __FUNCTION__, error); + goto out_free; + } + + s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); + if (IS_ERR(s)) { error = PTR_ERR(s); goto out_free; } - if (s->s_fs_info != server) { - nfs_free_server(server); - server = NULL; + if (s->s_root) { + kfree(server->mnt_path); + kfree(server->hostname); + kfree(server); + return simple_set_mnt(mnt, s); } - if (!s->s_root) { - /* initial superblock/root creation */ - s->s_flags = flags; - nfs4_fill_super(s); - } + s->s_flags = flags; - mntroot = nfs4_get_root(s, &mntfh); - if (IS_ERR(mntroot)) { - error = PTR_ERR(mntroot); - goto error_splat_super; + error = nfs4_fill_super(s, data, flags & MS_SILENT ? 1 : 0); + if (error) { + up_write(&s->s_umount); + deactivate_super(s); + return error; } - s->s_flags |= MS_ACTIVE; - mnt->mnt_sb = s; - mnt->mnt_root = mntroot; - kfree(mntpath); - kfree(hostname); - return 0; - + return simple_set_mnt(mnt, s); out_err: error = PTR_ERR(p); - goto out_err_noserver; - out_free: - nfs_free_server(server); -out_err_noserver: - kfree(mntpath); - kfree(hostname); + kfree(server->mnt_path); + kfree(server->hostname); + kfree(server); return error; - -error_splat_super: - up_write(&s->s_umount); - deactivate_super(s); - goto out_err_noserver; } static void nfs4_kill_super(struct super_block *sb) @@ -935,140 +1403,135 @@ static void nfs4_kill_super(struct super_block *sb) kill_anon_super(sb); nfs4_renewd_prepare_shutdown(server); - nfs_free_server(server); -} - -/* - * Clone an NFS4 server record on xdev traversal (FSID-change) - */ -static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *raw_data, - struct vfsmount *mnt) -{ - struct nfs_clone_mount *data = raw_data; - struct super_block *s; - struct nfs_server *server; - struct dentry *mntroot; - int error; - - dprintk("--> nfs4_xdev_get_sb()\n"); - - /* create a new volume representation */ - server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); - if (IS_ERR(server)) { - error = PTR_ERR(server); - goto out_err_noserver; - } - - /* Get a superblock - note that we may end up sharing one that already exists */ - s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); - if (IS_ERR(s)) { - error = PTR_ERR(s); - goto out_err_nosb; - } - if (s->s_fs_info != server) { - nfs_free_server(server); - server = NULL; - } + if (server->client != NULL && !IS_ERR(server->client)) + rpc_shutdown_client(server->client); - if (!s->s_root) { - /* initial superblock/root creation */ - s->s_flags = flags; - nfs4_clone_super(s, data->sb); - } - - mntroot = nfs4_get_root(s, data->fh); - if (IS_ERR(mntroot)) { - error = PTR_ERR(mntroot); - goto error_splat_super; - } + destroy_nfsv4_state(server); - s->s_flags |= MS_ACTIVE; - mnt->mnt_sb = s; - mnt->mnt_root = mntroot; - - dprintk("<-- nfs4_xdev_get_sb() = 0\n"); - return 0; - -out_err_nosb: - nfs_free_server(server); -out_err_noserver: - dprintk("<-- nfs4_xdev_get_sb() = %d [error]\n", error); - return error; + rpciod_down(); -error_splat_super: - up_write(&s->s_umount); - deactivate_super(s); - dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error); - return error; + nfs_free_iostats(server->io_stats); + kfree(server->hostname); + kfree(server); + nfs_release_automount_timer(); } /* - * Create an NFS4 server record on referral traversal + * Constructs the SERVER-side path */ -static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *raw_data, - struct vfsmount *mnt) +static inline char *nfs4_dup_path(const struct dentry *dentry) { - struct nfs_clone_mount *data = raw_data; - struct super_block *s; - struct nfs_server *server; - struct dentry *mntroot; - struct nfs_fh mntfh; - int error; - - dprintk("--> nfs4_referral_get_sb()\n"); + char *page = (char *) __get_free_page(GFP_USER); + char *path; - /* create a new volume representation */ - server = nfs4_create_referral_server(data, &mntfh); - if (IS_ERR(server)) { - error = PTR_ERR(server); - goto out_err_noserver; - } - - /* Get a superblock - note that we may end up sharing one that already exists */ - s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); - if (IS_ERR(s)) { - error = PTR_ERR(s); - goto out_err_nosb; - } + path = nfs4_path(dentry, page, PAGE_SIZE); + if (!IS_ERR(path)) { + int len = PAGE_SIZE + page - path; + char *tmp = path; - if (s->s_fs_info != server) { - nfs_free_server(server); - server = NULL; + path = kmalloc(len, GFP_KERNEL); + if (path) + memcpy(path, tmp, len); + else + path = ERR_PTR(-ENOMEM); } + free_page((unsigned long)page); + return path; +} - if (!s->s_root) { - /* initial superblock/root creation */ - s->s_flags = flags; - nfs4_fill_super(s); +static struct super_block *nfs4_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data) +{ + const struct dentry *dentry = data->dentry; + struct nfs4_client *clp = server->nfs4_state; + struct super_block *sb; + + server->fsid = data->fattr->fsid; + nfs_copy_fh(&server->fh, data->fh); + server->mnt_path = nfs4_dup_path(dentry); + if (IS_ERR(server->mnt_path)) { + sb = (struct super_block *)server->mnt_path; + goto err; } + sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server); + if (IS_ERR(sb) || sb->s_root) + goto free_path; + nfs4_server_capabilities(server, &server->fh); + + down_write(&clp->cl_sem); + atomic_inc(&clp->cl_count); + list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks); + up_write(&clp->cl_sem); + return sb; +free_path: + kfree(server->mnt_path); +err: + server->mnt_path = NULL; + return sb; +} - mntroot = nfs4_get_root(s, data->fh); - if (IS_ERR(mntroot)) { - error = PTR_ERR(mntroot); - goto error_splat_super; - } +static int nfs_clone_nfs4_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) +{ + struct nfs_clone_mount *data = raw_data; + return nfs_clone_generic_sb(data, nfs4_clone_sb, nfs_clone_server, mnt); +} - s->s_flags |= MS_ACTIVE; - mnt->mnt_sb = s; - mnt->mnt_root = mntroot; +static struct super_block *nfs4_referral_sb(struct nfs_server *server, struct nfs_clone_mount *data) +{ + struct super_block *sb = ERR_PTR(-ENOMEM); + int len; + + len = strlen(data->mnt_path) + 1; + server->mnt_path = kmalloc(len, GFP_KERNEL); + if (server->mnt_path == NULL) + goto err; + memcpy(server->mnt_path, data->mnt_path, len); + memcpy(&server->addr, data->addr, sizeof(struct sockaddr_in)); + + sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server); + if (IS_ERR(sb) || sb->s_root) + goto free_path; + return sb; +free_path: + kfree(server->mnt_path); +err: + server->mnt_path = NULL; + return sb; +} - dprintk("<-- nfs4_referral_get_sb() = 0\n"); - return 0; +static struct nfs_server *nfs4_referral_server(struct super_block *sb, struct nfs_clone_mount *data) +{ + struct nfs_server *server = NFS_SB(sb); + struct rpc_timeout timeparms; + int proto, timeo, retrans; + void *err; + + proto = IPPROTO_TCP; + /* Since we are following a referral and there may be alternatives, + set the timeouts and retries to low values */ + timeo = 2; + retrans = 1; + nfs_init_timeout_values(&timeparms, proto, timeo, retrans); + + server->client = nfs4_create_client(server, &timeparms, proto, data->authflavor); + if (IS_ERR((err = server->client))) + goto out_err; -out_err_nosb: - nfs_free_server(server); -out_err_noserver: - dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error); - return error; + sb->s_time_gran = 1; + sb->s_op = &nfs4_sops; + err = ERR_PTR(nfs_sb_init(sb, data->authflavor)); + if (!IS_ERR(err)) + return server; +out_err: + return (struct nfs_server *)err; +} -error_splat_super: - up_write(&s->s_umount); - deactivate_super(s); - dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error); - return error; +static int nfs_referral_nfs4_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) +{ + struct nfs_clone_mount *data = raw_data; + return nfs_clone_generic_sb(data, nfs4_referral_sb, nfs4_referral_server, mnt); } -#endif /* CONFIG_NFS_V4 */ +#endif diff --git a/trunk/fs/nfs/write.c b/trunk/fs/nfs/write.c index c12effb46fe5..86bac6a5008e 100644 --- a/trunk/fs/nfs/write.c +++ b/trunk/fs/nfs/write.c @@ -90,13 +90,22 @@ static mempool_t *nfs_commit_mempool; static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion); -struct nfs_write_data *nfs_commit_alloc(void) +struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount) { struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS); if (p) { memset(p, 0, sizeof(*p)); INIT_LIST_HEAD(&p->pages); + if (pagecount <= ARRAY_SIZE(p->page_array)) + p->pagevec = p->page_array; + else { + p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS); + if (!p->pagevec) { + mempool_free(p, nfs_commit_mempool); + p = NULL; + } + } } return p; } @@ -108,15 +117,13 @@ void nfs_commit_free(struct nfs_write_data *p) mempool_free(p, nfs_commit_mempool); } -struct nfs_write_data *nfs_writedata_alloc(size_t len) +struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) { - unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; struct nfs_write_data *p = mempool_alloc(nfs_wdata_mempool, SLAB_NOFS); if (p) { memset(p, 0, sizeof(*p)); INIT_LIST_HEAD(&p->pages); - p->npages = pagecount; if (pagecount <= ARRAY_SIZE(p->page_array)) p->pagevec = p->page_array; else { @@ -130,7 +137,7 @@ struct nfs_write_data *nfs_writedata_alloc(size_t len) return p; } -static void nfs_writedata_free(struct nfs_write_data *p) +void nfs_writedata_free(struct nfs_write_data *p) { if (p && (p->pagevec != &p->page_array[0])) kfree(p->pagevec); @@ -201,7 +208,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode, int result, written = 0; struct nfs_write_data *wdata; - wdata = nfs_writedata_alloc(wsize); + wdata = nfs_writedata_alloc(1); if (!wdata) return -ENOMEM; @@ -396,7 +403,6 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) out: clear_bit(BDI_write_congested, &bdi->state); wake_up_all(&nfs_write_congestion); - writeback_congestion_end(); return err; } @@ -591,8 +597,8 @@ static void nfs_cancel_commit_list(struct list_head *head) req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_inode_remove_request(req); - dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); nfs_clear_page_writeback(req); + dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); } } @@ -993,24 +999,24 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, int how) struct nfs_page *req = nfs_list_entry(head->next); struct page *page = req->wb_page; struct nfs_write_data *data; - size_t wsize = NFS_SERVER(inode)->wsize, nbytes; - unsigned int offset; + unsigned int wsize = NFS_SERVER(inode)->wsize; + unsigned int nbytes, offset; int requests = 0; LIST_HEAD(list); nfs_list_remove_request(req); nbytes = req->wb_bytes; - do { - size_t len = min(nbytes, wsize); - - data = nfs_writedata_alloc(len); + for (;;) { + data = nfs_writedata_alloc(1); if (!data) goto out_bad; list_add(&data->pages, &list); requests++; - nbytes -= len; - } while (nbytes != 0); + if (nbytes <= wsize) + break; + nbytes -= wsize; + } atomic_set(&req->wb_complete, requests); ClearPageError(page); @@ -1064,7 +1070,7 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, int how) struct nfs_write_data *data; unsigned int count; - data = nfs_writedata_alloc(NFS_SERVER(inode)->wsize); + data = nfs_writedata_alloc(NFS_SERVER(inode)->wpages); if (!data) goto out_bad; @@ -1253,13 +1259,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) dprintk("NFS: %4d nfs_writeback_done (status %d)\n", task->tk_pid, task->tk_status); - /* - * ->write_done will attempt to use post-op attributes to detect - * conflicting writes by other clients. A strict interpretation - * of close-to-open would allow us to continue caching even if - * another writer had changed the file, but some applications - * depend on tighter cache coherency when writing. - */ + /* Call the NFS version-specific code */ status = NFS_PROTO(data->inode)->write_done(task, data); if (status != 0) return status; @@ -1280,7 +1280,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) if (time_before(complain, jiffies)) { dprintk("NFS: faulty NFS server %s:" " (committed = %d) != (stable = %d)\n", - NFS_SERVER(data->inode)->nfs_client->cl_hostname, + NFS_SERVER(data->inode)->hostname, resp->verf->committed, argp->stable); complain = jiffies + 300 * HZ; } @@ -1378,7 +1378,7 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) struct nfs_write_data *data; struct nfs_page *req; - data = nfs_commit_alloc(); + data = nfs_commit_alloc(NFS_SERVER(inode)->wpages); if (!data) goto out_bad; @@ -1393,8 +1393,8 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_mark_request_commit(req); - dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); nfs_clear_page_writeback(req); + dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); } return -ENOMEM; } diff --git a/trunk/fs/nfsd/nfs4callback.c b/trunk/fs/nfsd/nfs4callback.c index 8583d99ee740..54b37b1d2e3a 100644 --- a/trunk/fs/nfsd/nfs4callback.c +++ b/trunk/fs/nfsd/nfs4callback.c @@ -375,28 +375,16 @@ nfsd4_probe_callback(struct nfs4_client *clp) { struct sockaddr_in addr; struct nfs4_callback *cb = &clp->cl_callback; - struct rpc_timeout timeparms = { - .to_initval = (NFSD_LEASE_TIME/4) * HZ, - .to_retries = 5, - .to_maxval = (NFSD_LEASE_TIME/2) * HZ, - .to_exponential = 1, - }; + struct rpc_timeout timeparms; + struct rpc_xprt * xprt; struct rpc_program * program = &cb->cb_program; - struct rpc_create_args args = { - .protocol = IPPROTO_TCP, - .address = (struct sockaddr *)&addr, - .addrsize = sizeof(addr), - .timeout = &timeparms, - .servername = clp->cl_name.data, - .program = program, - .version = nfs_cb_version[1]->number, - .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ - .flags = (RPC_CLNT_CREATE_NOPING), - }; + struct rpc_stat * stat = &cb->cb_stat; + struct rpc_clnt * clnt; struct rpc_message msg = { .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], .rpc_argp = clp, }; + char hostname[32]; int status; if (atomic_read(&cb->cb_set)) @@ -408,27 +396,51 @@ nfsd4_probe_callback(struct nfs4_client *clp) addr.sin_port = htons(cb->cb_port); addr.sin_addr.s_addr = htonl(cb->cb_addr); + /* Initialize timeout */ + timeparms.to_initval = (NFSD_LEASE_TIME/4) * HZ; + timeparms.to_retries = 0; + timeparms.to_maxval = (NFSD_LEASE_TIME/2) * HZ; + timeparms.to_exponential = 1; + + /* Create RPC transport */ + xprt = xprt_create_proto(IPPROTO_TCP, &addr, &timeparms); + if (IS_ERR(xprt)) { + dprintk("NFSD: couldn't create callback transport!\n"); + goto out_err; + } + /* Initialize rpc_program */ program->name = "nfs4_cb"; program->number = cb->cb_prog; program->nrvers = ARRAY_SIZE(nfs_cb_version); program->version = nfs_cb_version; - program->stats = &cb->cb_stat; + program->stats = stat; /* Initialize rpc_stat */ - memset(program->stats, 0, sizeof(cb->cb_stat)); - program->stats->program = program; - - /* Create RPC client */ - cb->cb_client = rpc_create(&args); - if (!cb->cb_client) { + memset(stat, 0, sizeof(struct rpc_stat)); + stat->program = program; + + /* Create RPC client + * + * XXX AUTH_UNIX only - need AUTH_GSS.... + */ + sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr)); + clnt = rpc_new_client(xprt, hostname, program, 1, RPC_AUTH_UNIX); + if (IS_ERR(clnt)) { dprintk("NFSD: couldn't create callback client\n"); goto out_err; } + clnt->cl_intr = 0; + clnt->cl_softrtry = 1; /* Kick rpciod, put the call on the wire. */ - if (rpciod_up() != 0) + + if (rpciod_up() != 0) { + dprintk("nfsd: couldn't start rpciod for callbacks!\n"); goto out_clnt; + } + + cb->cb_client = clnt; /* the task holds a reference to the nfs4_client struct */ atomic_inc(&clp->cl_count); @@ -436,7 +448,7 @@ nfsd4_probe_callback(struct nfs4_client *clp) msg.rpc_cred = nfsd4_lookupcred(clp,0); if (IS_ERR(msg.rpc_cred)) goto out_rpciod; - status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL); + status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL); put_rpccred(msg.rpc_cred); if (status != 0) { @@ -450,7 +462,7 @@ nfsd4_probe_callback(struct nfs4_client *clp) rpciod_down(); cb->cb_client = NULL; out_clnt: - rpc_shutdown_client(cb->cb_client); + rpc_shutdown_client(clnt); out_err: dprintk("NFSD: warning: no callback path to client %.*s\n", (int)clp->cl_name.len, clp->cl_name.data); diff --git a/trunk/fs/nfsd/nfs4recover.c b/trunk/fs/nfsd/nfs4recover.c index e35d7e52fdeb..06da7506363c 100644 --- a/trunk/fs/nfsd/nfs4recover.c +++ b/trunk/fs/nfsd/nfs4recover.c @@ -33,7 +33,7 @@ * */ -#include + #include #include #include @@ -87,35 +87,34 @@ int nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) { struct xdr_netobj cksum; - struct hash_desc desc; + struct crypto_tfm *tfm; struct scatterlist sg[1]; int status = nfserr_resource; dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", clname->len, clname->data); - desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; - desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(desc.tfm)) - goto out_no_tfm; - cksum.len = crypto_hash_digestsize(desc.tfm); + tfm = crypto_alloc_tfm("md5", CRYPTO_TFM_REQ_MAY_SLEEP); + if (tfm == NULL) + goto out; + cksum.len = crypto_tfm_alg_digestsize(tfm); cksum.data = kmalloc(cksum.len, GFP_KERNEL); if (cksum.data == NULL) goto out; + crypto_digest_init(tfm); sg[0].page = virt_to_page(clname->data); sg[0].offset = offset_in_page(clname->data); sg[0].length = clname->len; - if (crypto_hash_digest(&desc, sg, sg->length, cksum.data)) - goto out; + crypto_digest_update(tfm, sg, 1); + crypto_digest_final(tfm, cksum.data); md5_to_hex(dname, cksum.data); kfree(cksum.data); status = nfs_ok; out: - crypto_free_hash(desc.tfm); -out_no_tfm: + crypto_free_tfm(tfm); return status; } diff --git a/trunk/fs/nfsd/nfsfh.c b/trunk/fs/nfsd/nfsfh.c index 501d83884530..ecc439d2565f 100644 --- a/trunk/fs/nfsd/nfsfh.c +++ b/trunk/fs/nfsd/nfsfh.c @@ -187,11 +187,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) goto out; } - /* Set user creds for this exportpoint */ - error = nfserrno(nfsd_setuser(rqstp, exp)); - if (error) - goto out; - /* * Look up the dentry using the NFS file handle. */ @@ -246,17 +241,16 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access) dprintk("nfsd: fh_verify - just checking\n"); dentry = fhp->fh_dentry; exp = fhp->fh_export; - /* Set user creds for this exportpoint; necessary even - * in the "just checking" case because this may be a - * filehandle that was created by fh_compose, and that - * is about to be used in another nfsv4 compound - * operation */ - error = nfserrno(nfsd_setuser(rqstp, exp)); - if (error) - goto out; } cache_get(&exp->h); + /* Set user creds for this exportpoint; necessary even in the "just + * checking" case because this may be a filehandle that was created by + * fh_compose, and that is about to be used in another nfsv4 compound + * operation */ + error = nfserrno(nfsd_setuser(rqstp, exp)); + if (error) + goto out; error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type); if (error) diff --git a/trunk/fs/ocfs2/Makefile b/trunk/fs/ocfs2/Makefile index 9fb8132f19b0..7d3be845a614 100644 --- a/trunk/fs/ocfs2/Makefile +++ b/trunk/fs/ocfs2/Makefile @@ -16,7 +16,6 @@ ocfs2-objs := \ file.o \ heartbeat.o \ inode.o \ - ioctl.o \ journal.o \ localalloc.o \ mmap.o \ diff --git a/trunk/fs/ocfs2/alloc.c b/trunk/fs/ocfs2/alloc.c index f43bc5f18a35..edaab05a93e0 100644 --- a/trunk/fs/ocfs2/alloc.c +++ b/trunk/fs/ocfs2/alloc.c @@ -1717,29 +1717,17 @@ static int ocfs2_do_truncate(struct ocfs2_super *osb, ocfs2_remove_from_cache(inode, eb_bh); + BUG_ON(eb->h_suballoc_slot); BUG_ON(el->l_recs[0].e_clusters); BUG_ON(el->l_recs[0].e_cpos); BUG_ON(el->l_recs[0].e_blkno); - if (eb->h_suballoc_slot == 0) { - /* - * This code only understands how to - * lock the suballocator in slot 0, - * which is fine because allocation is - * only ever done out of that - * suballocator too. A future version - * might change that however, so avoid - * a free if we don't know how to - * handle it. This way an fs incompat - * bit will not be necessary. - */ - status = ocfs2_free_extent_block(handle, - tc->tc_ext_alloc_inode, - tc->tc_ext_alloc_bh, - eb); - if (status < 0) { - mlog_errno(status); - goto bail; - } + status = ocfs2_free_extent_block(handle, + tc->tc_ext_alloc_inode, + tc->tc_ext_alloc_bh, + eb); + if (status < 0) { + mlog_errno(status); + goto bail; } } brelse(eb_bh); diff --git a/trunk/fs/ocfs2/aops.c b/trunk/fs/ocfs2/aops.c index 3d7c082a8f58..f1d1c342ce01 100644 --- a/trunk/fs/ocfs2/aops.c +++ b/trunk/fs/ocfs2/aops.c @@ -391,28 +391,31 @@ struct ocfs2_journal_handle *ocfs2_start_walk_page_trans(struct inode *inode, static int ocfs2_commit_write(struct file *file, struct page *page, unsigned from, unsigned to) { - int ret; + int ret, extending = 0, locklevel = 0; + loff_t new_i_size; struct buffer_head *di_bh = NULL; struct inode *inode = page->mapping->host; struct ocfs2_journal_handle *handle = NULL; - struct ocfs2_dinode *di; mlog_entry("(0x%p, 0x%p, %u, %u)\n", file, page, from, to); /* NOTE: ocfs2_file_aio_write has ensured that it's safe for - * us to continue here without rechecking the I/O against - * changed inode values. + * us to sample inode->i_size here without the metadata lock: * * 1) We're currently holding the inode alloc lock, so no * nodes can change it underneath us. * * 2) We've had to take the metadata lock at least once - * already to check for extending writes, suid removal, etc. - * The meta data update code then ensures that we don't get a - * stale inode allocation image (i_size, i_clusters, etc). + * already to check for extending writes, hence insuring + * that our current copy is also up to date. */ + new_i_size = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; + if (new_i_size > i_size_read(inode)) { + extending = 1; + locklevel = 1; + } - ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, 1, page); + ret = ocfs2_meta_lock_with_page(inode, NULL, &di_bh, locklevel, page); if (ret != 0) { mlog_errno(ret); goto out; @@ -424,20 +427,23 @@ static int ocfs2_commit_write(struct file *file, struct page *page, goto out_unlock_meta; } - handle = ocfs2_start_walk_page_trans(inode, page, from, to); - if (IS_ERR(handle)) { - ret = PTR_ERR(handle); - goto out_unlock_data; - } + if (extending) { + handle = ocfs2_start_walk_page_trans(inode, page, from, to); + if (IS_ERR(handle)) { + ret = PTR_ERR(handle); + handle = NULL; + goto out_unlock_data; + } - /* Mark our buffer early. We'd rather catch this error up here - * as opposed to after a successful commit_write which would - * require us to set back inode->i_size. */ - ret = ocfs2_journal_access(handle, inode, di_bh, - OCFS2_JOURNAL_ACCESS_WRITE); - if (ret < 0) { - mlog_errno(ret); - goto out_commit; + /* Mark our buffer early. We'd rather catch this error up here + * as opposed to after a successful commit_write which would + * require us to set back inode->i_size. */ + ret = ocfs2_journal_access(handle, inode, di_bh, + OCFS2_JOURNAL_ACCESS_WRITE); + if (ret < 0) { + mlog_errno(ret); + goto out_commit; + } } /* might update i_size */ @@ -447,28 +453,37 @@ static int ocfs2_commit_write(struct file *file, struct page *page, goto out_commit; } - di = (struct ocfs2_dinode *)di_bh->b_data; + if (extending) { + loff_t size = (u64) i_size_read(inode); + struct ocfs2_dinode *di = + (struct ocfs2_dinode *)di_bh->b_data; - /* ocfs2_mark_inode_dirty() is too heavy to use here. */ - inode->i_mtime = inode->i_ctime = CURRENT_TIME; - di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec); - di->i_mtime_nsec = di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); + /* ocfs2_mark_inode_dirty is too heavy to use here. */ + inode->i_blocks = ocfs2_align_bytes_to_sectors(size); + inode->i_ctime = inode->i_mtime = CURRENT_TIME; - inode->i_blocks = ocfs2_align_bytes_to_sectors((u64)(i_size_read(inode))); - di->i_size = cpu_to_le64((u64)i_size_read(inode)); + di->i_size = cpu_to_le64(size); + di->i_ctime = di->i_mtime = + cpu_to_le64(inode->i_mtime.tv_sec); + di->i_ctime_nsec = di->i_mtime_nsec = + cpu_to_le32(inode->i_mtime.tv_nsec); - ret = ocfs2_journal_dirty(handle, di_bh); - if (ret < 0) { - mlog_errno(ret); - goto out_commit; + ret = ocfs2_journal_dirty(handle, di_bh); + if (ret < 0) { + mlog_errno(ret); + goto out_commit; + } } + BUG_ON(extending && (i_size_read(inode) != new_i_size)); + out_commit: - ocfs2_commit_trans(handle); + if (handle) + ocfs2_commit_trans(handle); out_unlock_data: ocfs2_data_unlock(inode, 1); out_unlock_meta: - ocfs2_meta_unlock(inode, 1); + ocfs2_meta_unlock(inode, locklevel); out: if (di_bh) brelse(di_bh); diff --git a/trunk/fs/ocfs2/buffer_head_io.c b/trunk/fs/ocfs2/buffer_head_io.c index c9037414f4f6..9a24adf9be6e 100644 --- a/trunk/fs/ocfs2/buffer_head_io.c +++ b/trunk/fs/ocfs2/buffer_head_io.c @@ -100,9 +100,6 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, mlog_entry("(block=(%llu), nr=(%d), flags=%d, inode=%p)\n", (unsigned long long)block, nr, flags, inode); - BUG_ON((flags & OCFS2_BH_READAHEAD) && - (!inode || !(flags & OCFS2_BH_CACHED))); - if (osb == NULL || osb->sb == NULL || bhs == NULL) { status = -EINVAL; mlog_errno(status); @@ -143,30 +140,6 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, bh = bhs[i]; ignore_cache = 0; - /* There are three read-ahead cases here which we need to - * be concerned with. All three assume a buffer has - * previously been submitted with OCFS2_BH_READAHEAD - * and it hasn't yet completed I/O. - * - * 1) The current request is sync to disk. This rarely - * happens these days, and never when performance - * matters - the code can just wait on the buffer - * lock and re-submit. - * - * 2) The current request is cached, but not - * readahead. ocfs2_buffer_uptodate() will return - * false anyway, so we'll wind up waiting on the - * buffer lock to do I/O. We re-check the request - * with after getting the lock to avoid a re-submit. - * - * 3) The current request is readahead (and so must - * also be a caching one). We short circuit if the - * buffer is locked (under I/O) and if it's in the - * uptodate cache. The re-check from #2 catches the - * case that the previous read-ahead completes just - * before our is-it-in-flight check. - */ - if (flags & OCFS2_BH_CACHED && !ocfs2_buffer_uptodate(inode, bh)) { mlog(ML_UPTODATE, @@ -196,14 +169,6 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, continue; } - /* A read-ahead request was made - if the - * buffer is already under read-ahead from a - * previously submitted request than we are - * done here. */ - if ((flags & OCFS2_BH_READAHEAD) - && ocfs2_buffer_read_ahead(inode, bh)) - continue; - lock_buffer(bh); if (buffer_jbd(bh)) { #ifdef CATCH_BH_JBD_RACES @@ -216,22 +181,13 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, continue; #endif } - - /* Re-check ocfs2_buffer_uptodate() as a - * previously read-ahead buffer may have - * completed I/O while we were waiting for the - * buffer lock. */ - if ((flags & OCFS2_BH_CACHED) - && !(flags & OCFS2_BH_READAHEAD) - && ocfs2_buffer_uptodate(inode, bh)) { - unlock_buffer(bh); - continue; - } - clear_buffer_uptodate(bh); get_bh(bh); /* for end_buffer_read_sync() */ bh->b_end_io = end_buffer_read_sync; - submit_bh(READ, bh); + if (flags & OCFS2_BH_READAHEAD) + submit_bh(READA, bh); + else + submit_bh(READ, bh); continue; } } @@ -241,39 +197,34 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, u64 block, int nr, for (i = (nr - 1); i >= 0; i--) { bh = bhs[i]; - if (!(flags & OCFS2_BH_READAHEAD)) { - /* We know this can't have changed as we hold the - * inode sem. Avoid doing any work on the bh if the - * journal has it. */ - if (!buffer_jbd(bh)) - wait_on_buffer(bh); - - if (!buffer_uptodate(bh)) { - /* Status won't be cleared from here on out, - * so we can safely record this and loop back - * to cleanup the other buffers. Don't need to - * remove the clustered uptodate information - * for this bh as it's not marked locally - * uptodate. */ - status = -EIO; - brelse(bh); - bhs[i] = NULL; - continue; - } + /* We know this can't have changed as we hold the + * inode sem. Avoid doing any work on the bh if the + * journal has it. */ + if (!buffer_jbd(bh)) + wait_on_buffer(bh); + + if (!buffer_uptodate(bh)) { + /* Status won't be cleared from here on out, + * so we can safely record this and loop back + * to cleanup the other buffers. Don't need to + * remove the clustered uptodate information + * for this bh as it's not marked locally + * uptodate. */ + status = -EIO; + brelse(bh); + bhs[i] = NULL; + continue; } - /* Always set the buffer in the cache, even if it was - * a forced read, or read-ahead which hasn't yet - * completed. */ if (inode) ocfs2_set_buffer_uptodate(inode, bh); } if (inode) mutex_unlock(&OCFS2_I(inode)->ip_io_mutex); - mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s, flags=0x%x\n", + mlog(ML_BH_IO, "block=(%llu), nr=(%d), cached=%s\n", (unsigned long long)block, nr, - (!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes", flags); + (!(flags & OCFS2_BH_CACHED) || ignore_cache) ? "no" : "yes"); bail: diff --git a/trunk/fs/ocfs2/buffer_head_io.h b/trunk/fs/ocfs2/buffer_head_io.h index 6cc20930fac3..6ecb90937b68 100644 --- a/trunk/fs/ocfs2/buffer_head_io.h +++ b/trunk/fs/ocfs2/buffer_head_io.h @@ -49,7 +49,7 @@ int ocfs2_read_blocks(struct ocfs2_super *osb, #define OCFS2_BH_CACHED 1 -#define OCFS2_BH_READAHEAD 8 +#define OCFS2_BH_READAHEAD 8 /* use this to pass READA down to submit_bh */ static inline int ocfs2_read_block(struct ocfs2_super * osb, u64 off, struct buffer_head **bh, int flags, diff --git a/trunk/fs/ocfs2/cluster/heartbeat.c b/trunk/fs/ocfs2/cluster/heartbeat.c index 305cba3681fe..504595d6cf65 100644 --- a/trunk/fs/ocfs2/cluster/heartbeat.c +++ b/trunk/fs/ocfs2/cluster/heartbeat.c @@ -320,12 +320,8 @@ static int compute_max_sectors(struct block_device *bdev) max_pages = q->max_hw_segments; max_pages--; /* Handle I/Os that straddle a page */ - if (max_pages) { - max_sectors = max_pages << (PAGE_SHIFT - 9); - } else { - /* If BIO contains 1 or less than 1 page. */ - max_sectors = q->max_sectors; - } + max_sectors = max_pages << (PAGE_SHIFT - 9); + /* Why is fls() 1-based???? */ pow_two_sectors = 1 << (fls(max_sectors) - 1); diff --git a/trunk/fs/ocfs2/dir.c b/trunk/fs/ocfs2/dir.c index 04e01915b86e..3d494d1a5f36 100644 --- a/trunk/fs/ocfs2/dir.c +++ b/trunk/fs/ocfs2/dir.c @@ -74,14 +74,14 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb, int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) { int error = 0; - unsigned long offset, blk, last_ra_blk = 0; - int i, stored; + unsigned long offset, blk; + int i, num, stored; struct buffer_head * bh, * tmp; struct ocfs2_dir_entry * de; int err; struct inode *inode = filp->f_dentry->d_inode; struct super_block * sb = inode->i_sb; - unsigned int ra_sectors = 16; + int have_disk_lock = 0; mlog_entry("dirino=%llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); @@ -95,8 +95,9 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) mlog_errno(error); /* we haven't got any yet, so propagate the error. */ stored = error; - goto bail_nolock; + goto bail; } + have_disk_lock = 1; offset = filp->f_pos & (sb->s_blocksize - 1); @@ -112,21 +113,16 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) continue; } - /* The idea here is to begin with 8k read-ahead and to stay - * 4k ahead of our current position. - * - * TODO: Use the pagecache for this. We just need to - * make sure it's cluster-safe... */ - if (!last_ra_blk - || (((last_ra_blk - blk) << 9) <= (ra_sectors / 2))) { - for (i = ra_sectors >> (sb->s_blocksize_bits - 9); + /* + * Do the readahead (8k) + */ + if (!offset) { + for (i = 16 >> (sb->s_blocksize_bits - 9), num = 0; i > 0; i--) { tmp = ocfs2_bread(inode, ++blk, &err, 1); if (tmp) brelse(tmp); } - last_ra_blk = blk; - ra_sectors = 8; } revalidate: @@ -198,9 +194,9 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) stored = 0; bail: - ocfs2_meta_unlock(inode, 0); + if (have_disk_lock) + ocfs2_meta_unlock(inode, 0); -bail_nolock: mlog_exit(stored); return stored; diff --git a/trunk/fs/ocfs2/dlm/dlmast.c b/trunk/fs/ocfs2/dlm/dlmast.c index f13a4bac41f0..42775e2bbe2c 100644 --- a/trunk/fs/ocfs2/dlm/dlmast.c +++ b/trunk/fs/ocfs2/dlm/dlmast.c @@ -367,10 +367,12 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data) goto do_ast; } - mlog(0, "got %sast for unknown lock! cookie=%u:%llu, " - "name=%.*s, namelen=%u\n", past->type == DLM_AST ? "" : "b", - dlm_get_lock_cookie_node(cookie), dlm_get_lock_cookie_seq(cookie), - locklen, name, locklen); + mlog(ML_ERROR, "got %sast for unknown lock! cookie=%u:%llu, " + "name=%.*s, namelen=%u\n", + past->type == DLM_AST ? "" : "b", + dlm_get_lock_cookie_node(cookie), + dlm_get_lock_cookie_seq(cookie), + locklen, name, locklen); ret = DLM_NORMAL; unlock_out: diff --git a/trunk/fs/ocfs2/dlm/dlmmaster.c b/trunk/fs/ocfs2/dlm/dlmmaster.c index 9503240ef0e5..1b8346dd0572 100644 --- a/trunk/fs/ocfs2/dlm/dlmmaster.c +++ b/trunk/fs/ocfs2/dlm/dlmmaster.c @@ -2375,6 +2375,7 @@ int dlm_migrate_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, mlog(0, "returning %d\n", ret); return ret; } +EXPORT_SYMBOL_GPL(dlm_migrate_lockres); int dlm_lock_basts_flushed(struct dlm_ctxt *dlm, struct dlm_lock *lock) { diff --git a/trunk/fs/ocfs2/dlm/dlmunlock.c b/trunk/fs/ocfs2/dlm/dlmunlock.c index 37be4b2e0d4a..b0c3134f4f70 100644 --- a/trunk/fs/ocfs2/dlm/dlmunlock.c +++ b/trunk/fs/ocfs2/dlm/dlmunlock.c @@ -155,7 +155,7 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm, else status = dlm_get_unlock_actions(dlm, res, lock, lksb, &actions); - if (status != DLM_NORMAL && (status != DLM_CANCELGRANT || !master_node)) + if (status != DLM_NORMAL) goto leave; /* By now this has been masked out of cancel requests. */ @@ -183,7 +183,8 @@ static enum dlm_status dlmunlock_common(struct dlm_ctxt *dlm, spin_lock(&lock->spinlock); /* if the master told us the lock was already granted, * let the ast handle all of these actions */ - if (status == DLM_CANCELGRANT) { + if (status == DLM_NORMAL && + lksb->status == DLM_CANCELGRANT) { actions &= ~(DLM_UNLOCK_REMOVE_LOCK| DLM_UNLOCK_REGRANT_LOCK| DLM_UNLOCK_CLEAR_CONVERT_TYPE); @@ -348,9 +349,14 @@ static enum dlm_status dlm_send_remote_unlock_request(struct dlm_ctxt *dlm, vec, veclen, owner, &status); if (tmpret >= 0) { // successfully sent and received - if (status == DLM_FORWARD) + if (status == DLM_CANCELGRANT) + ret = DLM_NORMAL; + else if (status == DLM_FORWARD) { mlog(0, "master was in-progress. retry\n"); - ret = status; + ret = DLM_FORWARD; + } else + ret = status; + lksb->status = status; } else { mlog_errno(tmpret); if (dlm_is_host_down(tmpret)) { @@ -366,6 +372,7 @@ static enum dlm_status dlm_send_remote_unlock_request(struct dlm_ctxt *dlm, /* something bad. this will BUG in ocfs2 */ ret = dlm_err_to_dlm_status(tmpret); } + lksb->status = ret; } return ret; @@ -476,10 +483,6 @@ int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data) /* lock was found on queue */ lksb = lock->lksb; - if (flags & (LKM_VALBLK|LKM_PUT_LVB) && - lock->ml.type != LKM_EXMODE) - flags &= ~(LKM_VALBLK|LKM_PUT_LVB); - /* unlockast only called on originating node */ if (flags & LKM_PUT_LVB) { lksb->flags |= DLM_LKSB_PUT_LVB; @@ -504,8 +507,11 @@ int dlm_unlock_lock_handler(struct o2net_msg *msg, u32 len, void *data) "cookie=%u:%llu\n", dlm_get_lock_cookie_node(unlock->cookie), dlm_get_lock_cookie_seq(unlock->cookie)); - else + else { + /* send the lksb->status back to the other node */ + status = lksb->status; dlm_lock_put(lock); + } leave: if (res) @@ -527,22 +533,26 @@ static enum dlm_status dlm_get_cancel_actions(struct dlm_ctxt *dlm, if (dlm_lock_on_list(&res->blocked, lock)) { /* cancel this outright */ + lksb->status = DLM_NORMAL; status = DLM_NORMAL; *actions = (DLM_UNLOCK_CALL_AST | DLM_UNLOCK_REMOVE_LOCK); } else if (dlm_lock_on_list(&res->converting, lock)) { /* cancel the request, put back on granted */ + lksb->status = DLM_NORMAL; status = DLM_NORMAL; *actions = (DLM_UNLOCK_CALL_AST | DLM_UNLOCK_REMOVE_LOCK | DLM_UNLOCK_REGRANT_LOCK | DLM_UNLOCK_CLEAR_CONVERT_TYPE); } else if (dlm_lock_on_list(&res->granted, lock)) { - /* too late, already granted. */ - status = DLM_CANCELGRANT; + /* too late, already granted. DLM_CANCELGRANT */ + lksb->status = DLM_CANCELGRANT; + status = DLM_NORMAL; *actions = DLM_UNLOCK_CALL_AST; } else { mlog(ML_ERROR, "lock to cancel is not on any list!\n"); + lksb->status = DLM_IVLOCKID; status = DLM_IVLOCKID; *actions = 0; } @@ -559,11 +569,13 @@ static enum dlm_status dlm_get_unlock_actions(struct dlm_ctxt *dlm, /* unlock request */ if (!dlm_lock_on_list(&res->granted, lock)) { + lksb->status = DLM_DENIED; status = DLM_DENIED; dlm_error(status); *actions = 0; } else { /* unlock granted lock */ + lksb->status = DLM_NORMAL; status = DLM_NORMAL; *actions = (DLM_UNLOCK_FREE_LOCK | DLM_UNLOCK_CALL_AST | @@ -620,8 +632,6 @@ enum dlm_status dlmunlock(struct dlm_ctxt *dlm, struct dlm_lockstatus *lksb, spin_lock(&res->spinlock); is_master = (res->owner == dlm->node_num); - if (flags & LKM_VALBLK && lock->ml.type != LKM_EXMODE) - flags &= ~LKM_VALBLK; spin_unlock(&res->spinlock); if (is_master) { @@ -655,7 +665,7 @@ enum dlm_status dlmunlock(struct dlm_ctxt *dlm, struct dlm_lockstatus *lksb, } if (call_ast) { - mlog(0, "calling unlockast(%p, %d)\n", data, status); + mlog(0, "calling unlockast(%p, %d)\n", data, lksb->status); if (is_master) { /* it is possible that there is one last bast * pending. make sure it is flushed, then @@ -667,12 +677,9 @@ enum dlm_status dlmunlock(struct dlm_ctxt *dlm, struct dlm_lockstatus *lksb, wait_event(dlm->ast_wq, dlm_lock_basts_flushed(dlm, lock)); } - (*unlockast)(data, status); + (*unlockast)(data, lksb->status); } - if (status == DLM_CANCELGRANT) - status = DLM_NORMAL; - if (status == DLM_NORMAL) { mlog(0, "kicking the thread\n"); dlm_kick_thread(dlm, res); diff --git a/trunk/fs/ocfs2/dlmglue.c b/trunk/fs/ocfs2/dlmglue.c index 151b41781eab..762eb1fbb34d 100644 --- a/trunk/fs/ocfs2/dlmglue.c +++ b/trunk/fs/ocfs2/dlmglue.c @@ -1330,7 +1330,6 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime)); lvb->lvb_imtime_packed = cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime)); - lvb->lvb_iattr = cpu_to_be32(oi->ip_attr); mlog_meta_lvb(0, lockres); @@ -1361,9 +1360,6 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode) oi->ip_clusters = be32_to_cpu(lvb->lvb_iclusters); i_size_write(inode, be64_to_cpu(lvb->lvb_isize)); - oi->ip_attr = be32_to_cpu(lvb->lvb_iattr); - ocfs2_set_inode_flags(inode); - /* fast-symlinks are a special case */ if (S_ISLNK(inode->i_mode) && !oi->ip_clusters) inode->i_blocks = 0; @@ -2903,9 +2899,8 @@ void ocfs2_dump_meta_lvb_info(u64 level, be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid), be16_to_cpu(lvb->lvb_imode)); mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, " - "mtime_packed 0x%llx iattr 0x%x\n", be16_to_cpu(lvb->lvb_inlink), + "mtime_packed 0x%llx\n", be16_to_cpu(lvb->lvb_inlink), (long long)be64_to_cpu(lvb->lvb_iatime_packed), (long long)be64_to_cpu(lvb->lvb_ictime_packed), - (long long)be64_to_cpu(lvb->lvb_imtime_packed), - be32_to_cpu(lvb->lvb_iattr)); + (long long)be64_to_cpu(lvb->lvb_imtime_packed)); } diff --git a/trunk/fs/ocfs2/dlmglue.h b/trunk/fs/ocfs2/dlmglue.h index 243ae862ece5..8f2d1db2d9ea 100644 --- a/trunk/fs/ocfs2/dlmglue.h +++ b/trunk/fs/ocfs2/dlmglue.h @@ -27,7 +27,7 @@ #ifndef DLMGLUE_H #define DLMGLUE_H -#define OCFS2_LVB_VERSION 3 +#define OCFS2_LVB_VERSION 2 struct ocfs2_meta_lvb { __be32 lvb_version; @@ -40,8 +40,7 @@ struct ocfs2_meta_lvb { __be64 lvb_isize; __be16 lvb_imode; __be16 lvb_inlink; - __be32 lvb_iattr; - __be32 lvb_reserved[2]; + __be32 lvb_reserved[3]; }; /* ocfs2_meta_lock_full() and ocfs2_data_lock_full() 'arg_flags' flags */ diff --git a/trunk/fs/ocfs2/file.c b/trunk/fs/ocfs2/file.c index 2bbfa17090cf..a9559c874530 100644 --- a/trunk/fs/ocfs2/file.c +++ b/trunk/fs/ocfs2/file.c @@ -44,7 +44,6 @@ #include "file.h" #include "sysfile.h" #include "inode.h" -#include "ioctl.h" #include "journal.h" #include "mmap.h" #include "suballoc.h" @@ -1228,12 +1227,10 @@ const struct file_operations ocfs2_fops = { .open = ocfs2_file_open, .aio_read = ocfs2_file_aio_read, .aio_write = ocfs2_file_aio_write, - .ioctl = ocfs2_ioctl, }; const struct file_operations ocfs2_dops = { .read = generic_read_dir, .readdir = ocfs2_readdir, .fsync = ocfs2_sync_file, - .ioctl = ocfs2_ioctl, }; diff --git a/trunk/fs/ocfs2/inode.c b/trunk/fs/ocfs2/inode.c index 7bcf69154592..327a5b7b86ed 100644 --- a/trunk/fs/ocfs2/inode.c +++ b/trunk/fs/ocfs2/inode.c @@ -71,26 +71,6 @@ static int ocfs2_truncate_for_delete(struct ocfs2_super *osb, struct inode *inode, struct buffer_head *fe_bh); -void ocfs2_set_inode_flags(struct inode *inode) -{ - unsigned int flags = OCFS2_I(inode)->ip_attr; - - inode->i_flags &= ~(S_IMMUTABLE | - S_SYNC | S_APPEND | S_NOATIME | S_DIRSYNC); - - if (flags & OCFS2_IMMUTABLE_FL) - inode->i_flags |= S_IMMUTABLE; - - if (flags & OCFS2_SYNC_FL) - inode->i_flags |= S_SYNC; - if (flags & OCFS2_APPEND_FL) - inode->i_flags |= S_APPEND; - if (flags & OCFS2_NOATIME_FL) - inode->i_flags |= S_NOATIME; - if (flags & OCFS2_DIRSYNC_FL) - inode->i_flags |= S_DIRSYNC; -} - struct inode *ocfs2_ilookup_for_vote(struct ocfs2_super *osb, u64 blkno, int delete_vote) @@ -280,6 +260,7 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, inode->i_blocks = ocfs2_align_bytes_to_sectors(le64_to_cpu(fe->i_size)); inode->i_mapping->a_ops = &ocfs2_aops; + inode->i_flags |= S_NOATIME; inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime); inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec); inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime); @@ -295,7 +276,6 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); OCFS2_I(inode)->ip_orphaned_slot = OCFS2_INVALID_SLOT; - OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); if (create_ino) inode->i_ino = ino_from_blkno(inode->i_sb, @@ -350,9 +330,6 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe, ocfs2_inode_lock_res_init(&OCFS2_I(inode)->ip_data_lockres, OCFS2_LOCK_TYPE_DATA, inode); - ocfs2_set_inode_flags(inode); - inode->i_flags |= S_NOATIME; - status = 0; bail: mlog_exit(status); @@ -1050,8 +1027,12 @@ struct buffer_head *ocfs2_bread(struct inode *inode, u64 p_blkno; int readflags = OCFS2_BH_CACHED; +#if 0 + /* only turn this on if we know we can deal with read_block + * returning nothing */ if (reada) readflags |= OCFS2_BH_READAHEAD; +#endif if (((u64)block << inode->i_sb->s_blocksize_bits) >= i_size_read(inode)) { @@ -1150,7 +1131,6 @@ int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle, spin_lock(&OCFS2_I(inode)->ip_lock); fe->i_clusters = cpu_to_le32(OCFS2_I(inode)->ip_clusters); - fe->i_attr = cpu_to_le32(OCFS2_I(inode)->ip_attr); spin_unlock(&OCFS2_I(inode)->ip_lock); fe->i_size = cpu_to_le64(i_size_read(inode)); @@ -1189,8 +1169,6 @@ void ocfs2_refresh_inode(struct inode *inode, spin_lock(&OCFS2_I(inode)->ip_lock); OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters); - OCFS2_I(inode)->ip_attr = le32_to_cpu(fe->i_attr); - ocfs2_set_inode_flags(inode); i_size_write(inode, le64_to_cpu(fe->i_size)); inode->i_nlink = le16_to_cpu(fe->i_links_count); inode->i_uid = le32_to_cpu(fe->i_uid); diff --git a/trunk/fs/ocfs2/inode.h b/trunk/fs/ocfs2/inode.h index 4d1e53992566..35140f6cf840 100644 --- a/trunk/fs/ocfs2/inode.h +++ b/trunk/fs/ocfs2/inode.h @@ -56,7 +56,6 @@ struct ocfs2_inode_info struct ocfs2_journal_handle *ip_handle; u32 ip_flags; /* see below */ - u32 ip_attr; /* inode attributes */ /* protected by recovery_lock. */ struct inode *ip_next_orphan; @@ -143,6 +142,4 @@ int ocfs2_mark_inode_dirty(struct ocfs2_journal_handle *handle, int ocfs2_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb); int ocfs2_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb); -void ocfs2_set_inode_flags(struct inode *inode); - #endif /* OCFS2_INODE_H */ diff --git a/trunk/fs/ocfs2/ioctl.c b/trunk/fs/ocfs2/ioctl.c deleted file mode 100644 index 3663cef80689..000000000000 --- a/trunk/fs/ocfs2/ioctl.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * linux/fs/ocfs2/ioctl.c - * - * Copyright (C) 2006 Herbert Poetzl - * adapted from Remy Card's ext2/ioctl.c - */ - -#include -#include - -#define MLOG_MASK_PREFIX ML_INODE -#include - -#include "ocfs2.h" -#include "alloc.h" -#include "dlmglue.h" -#include "inode.h" -#include "journal.h" - -#include "ocfs2_fs.h" -#include "ioctl.h" - -#include - -static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags) -{ - int status; - - status = ocfs2_meta_lock(inode, NULL, NULL, 0); - if (status < 0) { - mlog_errno(status); - return status; - } - *flags = OCFS2_I(inode)->ip_attr; - ocfs2_meta_unlock(inode, 0); - - mlog_exit(status); - return status; -} - -static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags, - unsigned mask) -{ - struct ocfs2_inode_info *ocfs2_inode = OCFS2_I(inode); - struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); - struct ocfs2_journal_handle *handle = NULL; - struct buffer_head *bh = NULL; - unsigned oldflags; - int status; - - mutex_lock(&inode->i_mutex); - - status = ocfs2_meta_lock(inode, NULL, &bh, 1); - if (status < 0) { - mlog_errno(status); - goto bail; - } - - status = -EROFS; - if (IS_RDONLY(inode)) - goto bail_unlock; - - status = -EACCES; - if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) - goto bail_unlock; - - if (!S_ISDIR(inode->i_mode)) - flags &= ~OCFS2_DIRSYNC_FL; - - handle = ocfs2_start_trans(osb, NULL, OCFS2_INODE_UPDATE_CREDITS); - if (IS_ERR(handle)) { - status = PTR_ERR(handle); - mlog_errno(status); - goto bail_unlock; - } - - oldflags = ocfs2_inode->ip_attr; - flags = flags & mask; - flags |= oldflags & ~mask; - - /* - * The IMMUTABLE and APPEND_ONLY flags can only be changed by - * the relevant capability. - */ - status = -EPERM; - if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) & - (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) { - if (!capable(CAP_LINUX_IMMUTABLE)) - goto bail_unlock; - } - - ocfs2_inode->ip_attr = flags; - ocfs2_set_inode_flags(inode); - - status = ocfs2_mark_inode_dirty(handle, inode, bh); - if (status < 0) - mlog_errno(status); - - ocfs2_commit_trans(handle); -bail_unlock: - ocfs2_meta_unlock(inode, 1); -bail: - mutex_unlock(&inode->i_mutex); - - if (bh) - brelse(bh); - - mlog_exit(status); - return status; -} - -int ocfs2_ioctl(struct inode * inode, struct file * filp, - unsigned int cmd, unsigned long arg) -{ - unsigned int flags; - int status; - - switch (cmd) { - case OCFS2_IOC_GETFLAGS: - status = ocfs2_get_inode_attr(inode, &flags); - if (status < 0) - return status; - - flags &= OCFS2_FL_VISIBLE; - return put_user(flags, (int __user *) arg); - case OCFS2_IOC_SETFLAGS: - if (get_user(flags, (int __user *) arg)) - return -EFAULT; - - return ocfs2_set_inode_attr(inode, flags, - OCFS2_FL_MODIFIABLE); - default: - return -ENOTTY; - } -} - diff --git a/trunk/fs/ocfs2/ioctl.h b/trunk/fs/ocfs2/ioctl.h deleted file mode 100644 index 4a7c82931dba..000000000000 --- a/trunk/fs/ocfs2/ioctl.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * ioctl.h - * - * Function prototypes - * - * Copyright (C) 2006 Herbert Poetzl - * - */ - -#ifndef OCFS2_IOCTL_H -#define OCFS2_IOCTL_H - -int ocfs2_ioctl(struct inode * inode, struct file * filp, - unsigned int cmd, unsigned long arg); - -#endif /* OCFS2_IOCTL_H */ diff --git a/trunk/fs/ocfs2/localalloc.c b/trunk/fs/ocfs2/localalloc.c index 1f17a4d08287..0d1973ea32b0 100644 --- a/trunk/fs/ocfs2/localalloc.c +++ b/trunk/fs/ocfs2/localalloc.c @@ -840,12 +840,6 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb, mlog(0, "Allocating %u clusters for a new window.\n", ocfs2_local_alloc_window_bits(osb)); - - /* Instruct the allocation code to try the most recently used - * cluster group. We'll re-record the group used this pass - * below. */ - ac->ac_last_group = osb->la_last_gd; - /* we used the generic suballoc reserve function, but we set * everything up nicely, so there's no reason why we can't use * the more specific cluster api to claim bits. */ @@ -858,8 +852,6 @@ static int ocfs2_local_alloc_new_window(struct ocfs2_super *osb, goto bail; } - osb->la_last_gd = ac->ac_last_group; - la->la_bm_off = cpu_to_le32(cluster_off); alloc->id1.bitmap1.i_total = cpu_to_le32(cluster_count); /* just in case... In the future when we find space ourselves, diff --git a/trunk/fs/ocfs2/namei.c b/trunk/fs/ocfs2/namei.c index 0d3e939b1f56..0673862c8bdd 100644 --- a/trunk/fs/ocfs2/namei.c +++ b/trunk/fs/ocfs2/namei.c @@ -56,7 +56,6 @@ #include "journal.h" #include "namei.h" #include "suballoc.h" -#include "super.h" #include "symlink.h" #include "sysfile.h" #include "uptodate.h" @@ -311,6 +310,13 @@ static int ocfs2_mknod(struct inode *dir, /* get our super block */ osb = OCFS2_SB(dir->i_sb); + if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) { + mlog(ML_ERROR, "inode %llu has i_nlink of %u\n", + (unsigned long long)OCFS2_I(dir)->ip_blkno, dir->i_nlink); + status = -EMLINK; + goto leave; + } + handle = ocfs2_alloc_handle(osb); if (handle == NULL) { status = -ENOMEM; @@ -325,11 +331,6 @@ static int ocfs2_mknod(struct inode *dir, goto leave; } - if (S_ISDIR(mode) && (dir->i_nlink >= OCFS2_LINK_MAX)) { - status = -EMLINK; - goto leave; - } - dirfe = (struct ocfs2_dinode *) parent_fe_bh->b_data; if (!dirfe->i_links_count) { /* can't make a file in a deleted directory. */ @@ -642,6 +643,11 @@ static int ocfs2_link(struct dentry *old_dentry, goto bail; } + if (inode->i_nlink >= OCFS2_LINK_MAX) { + err = -EMLINK; + goto bail; + } + handle = ocfs2_alloc_handle(osb); if (handle == NULL) { err = -ENOMEM; @@ -655,11 +661,6 @@ static int ocfs2_link(struct dentry *old_dentry, goto bail; } - if (!dir->i_nlink) { - err = -ENOENT; - goto bail; - } - err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, dentry->d_name.len); if (err) @@ -1963,8 +1964,13 @@ struct buffer_head *ocfs2_find_entry(const char *name, int namelen, } num++; + /* XXX: questionable readahead stuff here */ bh = ocfs2_bread(dir, b++, &err, 1); bh_use[ra_max] = bh; +#if 0 // ??? + if (bh) + ll_rw_block(READ, 1, &bh); +#endif } } if ((bh = bh_use[ra_ptr++]) == NULL) @@ -1972,10 +1978,6 @@ struct buffer_head *ocfs2_find_entry(const char *name, int namelen, wait_on_buffer(bh); if (!buffer_uptodate(bh)) { /* read error, skip block & hope for the best */ - ocfs2_error(dir->i_sb, "reading directory %llu, " - "offset %lu\n", - (unsigned long long)OCFS2_I(dir)->ip_blkno, - block); brelse(bh); goto next; } diff --git a/trunk/fs/ocfs2/ocfs2.h b/trunk/fs/ocfs2/ocfs2.h index 0462a7f4e21b..cd4a6f253d13 100644 --- a/trunk/fs/ocfs2/ocfs2.h +++ b/trunk/fs/ocfs2/ocfs2.h @@ -197,6 +197,7 @@ struct ocfs2_super struct ocfs2_node_map recovery_map; struct ocfs2_node_map umount_map; + u32 num_clusters; u64 root_blkno; u64 system_dir_blkno; u64 bitmap_blkno; @@ -236,7 +237,6 @@ struct ocfs2_super enum ocfs2_local_alloc_state local_alloc_state; struct buffer_head *local_alloc_bh; - u64 la_last_gd; /* Next two fields are for local node slot recovery during * mount. */ diff --git a/trunk/fs/ocfs2/ocfs2_fs.h b/trunk/fs/ocfs2/ocfs2_fs.h index 3330a5dc6be2..c5b1ac547c15 100644 --- a/trunk/fs/ocfs2/ocfs2_fs.h +++ b/trunk/fs/ocfs2/ocfs2_fs.h @@ -114,26 +114,6 @@ #define OCFS2_CHAIN_FL (0x00000400) /* Chain allocator */ #define OCFS2_DEALLOC_FL (0x00000800) /* Truncate log */ -/* Inode attributes, keep in sync with EXT2 */ -#define OCFS2_SECRM_FL (0x00000001) /* Secure deletion */ -#define OCFS2_UNRM_FL (0x00000002) /* Undelete */ -#define OCFS2_COMPR_FL (0x00000004) /* Compress file */ -#define OCFS2_SYNC_FL (0x00000008) /* Synchronous updates */ -#define OCFS2_IMMUTABLE_FL (0x00000010) /* Immutable file */ -#define OCFS2_APPEND_FL (0x00000020) /* writes to file may only append */ -#define OCFS2_NODUMP_FL (0x00000040) /* do not dump file */ -#define OCFS2_NOATIME_FL (0x00000080) /* do not update atime */ -#define OCFS2_DIRSYNC_FL (0x00010000) /* dirsync behaviour (directories only) */ - -#define OCFS2_FL_VISIBLE (0x000100FF) /* User visible flags */ -#define OCFS2_FL_MODIFIABLE (0x000100FF) /* User modifiable flags */ - -/* - * ioctl commands - */ -#define OCFS2_IOC_GETFLAGS _IOR('f', 1, long) -#define OCFS2_IOC_SETFLAGS _IOW('f', 2, long) - /* * Journal Flags (ocfs2_dinode.id1.journal1.i_flags) */ @@ -419,9 +399,7 @@ struct ocfs2_dinode { __le32 i_atime_nsec; __le32 i_ctime_nsec; __le32 i_mtime_nsec; - __le32 i_attr; - __le32 i_reserved1; -/*70*/ __le64 i_reserved2[8]; +/*70*/ __le64 i_reserved1[9]; /*B8*/ union { __le64 i_pad1; /* Generic way to refer to this 64bit union */ diff --git a/trunk/fs/ocfs2/suballoc.c b/trunk/fs/ocfs2/suballoc.c index 9d91e66f51a9..195523090c87 100644 --- a/trunk/fs/ocfs2/suballoc.c +++ b/trunk/fs/ocfs2/suballoc.c @@ -70,6 +70,12 @@ static int ocfs2_block_group_search(struct inode *inode, struct buffer_head *group_bh, u32 bits_wanted, u32 min_bits, u16 *bit_off, u16 *bits_found); +static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, + u32 bits_wanted, + u32 min_bits, + u16 *bit_off, + unsigned int *num_bits, + u64 *bg_blkno); static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, struct ocfs2_alloc_context *ac, u32 bits_wanted, @@ -79,6 +85,11 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, u64 *bg_blkno); static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh, int nr); +static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb, + struct buffer_head *bg_bh, + unsigned int bits_wanted, + u16 *bit_off, + u16 *bits_found); static inline int ocfs2_block_group_set_bits(struct ocfs2_journal_handle *handle, struct inode *alloc_inode, struct ocfs2_group_desc *bg, @@ -132,64 +143,6 @@ static u32 ocfs2_bits_per_group(struct ocfs2_chain_list *cl) return (u32)le16_to_cpu(cl->cl_cpg) * (u32)le16_to_cpu(cl->cl_bpc); } -/* somewhat more expensive than our other checks, so use sparingly. */ -static int ocfs2_check_group_descriptor(struct super_block *sb, - struct ocfs2_dinode *di, - struct ocfs2_group_desc *gd) -{ - unsigned int max_bits; - - if (!OCFS2_IS_VALID_GROUP_DESC(gd)) { - OCFS2_RO_ON_INVALID_GROUP_DESC(sb, gd); - return -EIO; - } - - if (di->i_blkno != gd->bg_parent_dinode) { - ocfs2_error(sb, "Group descriptor # %llu has bad parent " - "pointer (%llu, expected %llu)", - (unsigned long long)le64_to_cpu(gd->bg_blkno), - (unsigned long long)le64_to_cpu(gd->bg_parent_dinode), - (unsigned long long)le64_to_cpu(di->i_blkno)); - return -EIO; - } - - max_bits = le16_to_cpu(di->id2.i_chain.cl_cpg) * le16_to_cpu(di->id2.i_chain.cl_bpc); - if (le16_to_cpu(gd->bg_bits) > max_bits) { - ocfs2_error(sb, "Group descriptor # %llu has bit count of %u", - (unsigned long long)le64_to_cpu(gd->bg_blkno), - le16_to_cpu(gd->bg_bits)); - return -EIO; - } - - if (le16_to_cpu(gd->bg_chain) >= - le16_to_cpu(di->id2.i_chain.cl_next_free_rec)) { - ocfs2_error(sb, "Group descriptor # %llu has bad chain %u", - (unsigned long long)le64_to_cpu(gd->bg_blkno), - le16_to_cpu(gd->bg_chain)); - return -EIO; - } - - if (le16_to_cpu(gd->bg_free_bits_count) > le16_to_cpu(gd->bg_bits)) { - ocfs2_error(sb, "Group descriptor # %llu has bit count %u but " - "claims that %u are free", - (unsigned long long)le64_to_cpu(gd->bg_blkno), - le16_to_cpu(gd->bg_bits), - le16_to_cpu(gd->bg_free_bits_count)); - return -EIO; - } - - if (le16_to_cpu(gd->bg_bits) > (8 * le16_to_cpu(gd->bg_size))) { - ocfs2_error(sb, "Group descriptor # %llu has bit count %u but " - "max bitmap bits of %u", - (unsigned long long)le64_to_cpu(gd->bg_blkno), - le16_to_cpu(gd->bg_bits), - 8 * le16_to_cpu(gd->bg_size)); - return -EIO; - } - - return 0; -} - static int ocfs2_block_group_fill(struct ocfs2_journal_handle *handle, struct inode *alloc_inode, struct buffer_head *bg_bh, @@ -710,7 +663,6 @@ static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh, static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb, struct buffer_head *bg_bh, unsigned int bits_wanted, - unsigned int total_bits, u16 *bit_off, u16 *bits_found) { @@ -727,8 +679,10 @@ static int ocfs2_block_group_find_clear_bits(struct ocfs2_super *osb, found = start = best_offset = best_size = 0; bitmap = bg->bg_bitmap; - while((offset = ocfs2_find_next_zero_bit(bitmap, total_bits, start)) != -1) { - if (offset == total_bits) + while((offset = ocfs2_find_next_zero_bit(bitmap, + le16_to_cpu(bg->bg_bits), + start)) != -1) { + if (offset == le16_to_cpu(bg->bg_bits)) break; if (!ocfs2_test_bg_bit_allocatable(bg_bh, offset)) { @@ -957,35 +911,14 @@ static int ocfs2_cluster_group_search(struct inode *inode, { int search = -ENOSPC; int ret; - struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *) group_bh->b_data; + struct ocfs2_group_desc *bg = (struct ocfs2_group_desc *) group_bh->b_data; u16 tmp_off, tmp_found; - unsigned int max_bits, gd_cluster_off; BUG_ON(!ocfs2_is_cluster_bitmap(inode)); - if (gd->bg_free_bits_count) { - max_bits = le16_to_cpu(gd->bg_bits); - - /* Tail groups in cluster bitmaps which aren't cpg - * aligned are prone to partial extention by a failed - * fs resize. If the file system resize never got to - * update the dinode cluster count, then we don't want - * to trust any clusters past it, regardless of what - * the group descriptor says. */ - gd_cluster_off = ocfs2_blocks_to_clusters(inode->i_sb, - le64_to_cpu(gd->bg_blkno)); - if ((gd_cluster_off + max_bits) > - OCFS2_I(inode)->ip_clusters) { - max_bits = OCFS2_I(inode)->ip_clusters - gd_cluster_off; - mlog(0, "Desc %llu, bg_bits %u, clusters %u, use %u\n", - (unsigned long long)le64_to_cpu(gd->bg_blkno), - le16_to_cpu(gd->bg_bits), - OCFS2_I(inode)->ip_clusters, max_bits); - } - + if (bg->bg_free_bits_count) { ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb), group_bh, bits_wanted, - max_bits, &tmp_off, &tmp_found); if (ret) return ret; @@ -1018,109 +951,17 @@ static int ocfs2_block_group_search(struct inode *inode, if (bg->bg_free_bits_count) ret = ocfs2_block_group_find_clear_bits(OCFS2_SB(inode->i_sb), group_bh, bits_wanted, - le16_to_cpu(bg->bg_bits), bit_off, bits_found); return ret; } -static int ocfs2_alloc_dinode_update_counts(struct inode *inode, - struct ocfs2_journal_handle *handle, - struct buffer_head *di_bh, - u32 num_bits, - u16 chain) -{ - int ret; - u32 tmp_used; - struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data; - struct ocfs2_chain_list *cl = (struct ocfs2_chain_list *) &di->id2.i_chain; - - ret = ocfs2_journal_access(handle, inode, di_bh, - OCFS2_JOURNAL_ACCESS_WRITE); - if (ret < 0) { - mlog_errno(ret); - goto out; - } - - tmp_used = le32_to_cpu(di->id1.bitmap1.i_used); - di->id1.bitmap1.i_used = cpu_to_le32(num_bits + tmp_used); - le32_add_cpu(&cl->cl_recs[chain].c_free, -num_bits); - - ret = ocfs2_journal_dirty(handle, di_bh); - if (ret < 0) - mlog_errno(ret); - -out: - return ret; -} - -static int ocfs2_search_one_group(struct ocfs2_alloc_context *ac, - u32 bits_wanted, - u32 min_bits, - u16 *bit_off, - unsigned int *num_bits, - u64 gd_blkno, - u16 *bits_left) -{ - int ret; - u16 found; - struct buffer_head *group_bh = NULL; - struct ocfs2_group_desc *gd; - struct inode *alloc_inode = ac->ac_inode; - struct ocfs2_journal_handle *handle = ac->ac_handle; - - ret = ocfs2_read_block(OCFS2_SB(alloc_inode->i_sb), gd_blkno, - &group_bh, OCFS2_BH_CACHED, alloc_inode); - if (ret < 0) { - mlog_errno(ret); - return ret; - } - - gd = (struct ocfs2_group_desc *) group_bh->b_data; - if (!OCFS2_IS_VALID_GROUP_DESC(gd)) { - OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, gd); - ret = -EIO; - goto out; - } - - ret = ac->ac_group_search(alloc_inode, group_bh, bits_wanted, min_bits, - bit_off, &found); - if (ret < 0) { - if (ret != -ENOSPC) - mlog_errno(ret); - goto out; - } - - *num_bits = found; - - ret = ocfs2_alloc_dinode_update_counts(alloc_inode, handle, ac->ac_bh, - *num_bits, - le16_to_cpu(gd->bg_chain)); - if (ret < 0) { - mlog_errno(ret); - goto out; - } - - ret = ocfs2_block_group_set_bits(handle, alloc_inode, gd, group_bh, - *bit_off, *num_bits); - if (ret < 0) - mlog_errno(ret); - - *bits_left = le16_to_cpu(gd->bg_free_bits_count); - -out: - brelse(group_bh); - - return ret; -} - static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, u32 bits_wanted, u32 min_bits, u16 *bit_off, unsigned int *num_bits, - u64 *bg_blkno, - u16 *bits_left) + u64 *bg_blkno) { int status; u16 chain, tmp_bits; @@ -1147,9 +988,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, goto bail; } bg = (struct ocfs2_group_desc *) group_bh->b_data; - status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg); - if (status) { - mlog_errno(status); + if (!OCFS2_IS_VALID_GROUP_DESC(bg)) { + OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg); + status = -EIO; goto bail; } @@ -1177,9 +1018,9 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, goto bail; } bg = (struct ocfs2_group_desc *) group_bh->b_data; - status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, bg); - if (status) { - mlog_errno(status); + if (!OCFS2_IS_VALID_GROUP_DESC(bg)) { + OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, bg); + status = -EIO; goto bail; } } @@ -1258,7 +1099,6 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, (unsigned long long)fe->i_blkno); *bg_blkno = le64_to_cpu(bg->bg_blkno); - *bits_left = le16_to_cpu(bg->bg_free_bits_count); bail: if (group_bh) brelse(group_bh); @@ -1280,8 +1120,6 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, { int status; u16 victim, i; - u16 bits_left = 0; - u64 hint_blkno = ac->ac_last_group; struct ocfs2_chain_list *cl; struct ocfs2_dinode *fe; @@ -1308,28 +1146,6 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, goto bail; } - if (hint_blkno) { - /* Attempt to short-circuit the usual search mechanism - * by jumping straight to the most recently used - * allocation group. This helps us mantain some - * contiguousness across allocations. */ - status = ocfs2_search_one_group(ac, bits_wanted, min_bits, - bit_off, num_bits, - hint_blkno, &bits_left); - if (!status) { - /* Be careful to update *bg_blkno here as the - * caller is expecting it to be filled in, and - * ocfs2_search_one_group() won't do that for - * us. */ - *bg_blkno = hint_blkno; - goto set_hint; - } - if (status < 0 && status != -ENOSPC) { - mlog_errno(status); - goto bail; - } - } - cl = (struct ocfs2_chain_list *) &fe->id2.i_chain; victim = ocfs2_find_victim_chain(cl); @@ -1337,9 +1153,9 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, ac->ac_allow_chain_relink = 1; status = ocfs2_search_chain(ac, bits_wanted, min_bits, bit_off, - num_bits, bg_blkno, &bits_left); + num_bits, bg_blkno); if (!status) - goto set_hint; + goto bail; if (status < 0 && status != -ENOSPC) { mlog_errno(status); goto bail; @@ -1361,8 +1177,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, ac->ac_chain = i; status = ocfs2_search_chain(ac, bits_wanted, min_bits, - bit_off, num_bits, bg_blkno, - &bits_left); + bit_off, num_bits, + bg_blkno); if (!status) break; if (status < 0 && status != -ENOSPC) { @@ -1370,19 +1186,8 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_super *osb, goto bail; } } - -set_hint: - if (status != -ENOSPC) { - /* If the next search of this group is not likely to - * yield a suitable extent, then we reset the last - * group hint so as to not waste a disk read */ - if (bits_left < min_bits) - ac->ac_last_group = 0; - else - ac->ac_last_group = *bg_blkno; - } - bail: + mlog_exit(status); return status; } @@ -1536,7 +1341,7 @@ int ocfs2_claim_clusters(struct ocfs2_super *osb, { int status; unsigned int bits_wanted = ac->ac_bits_wanted - ac->ac_bits_given; - u64 bg_blkno = 0; + u64 bg_blkno; u16 bg_bit_off; mlog_entry_void(); @@ -1689,9 +1494,9 @@ static int ocfs2_free_suballoc_bits(struct ocfs2_journal_handle *handle, } group = (struct ocfs2_group_desc *) group_bh->b_data; - status = ocfs2_check_group_descriptor(alloc_inode->i_sb, fe, group); - if (status) { - mlog_errno(status); + if (!OCFS2_IS_VALID_GROUP_DESC(group)) { + OCFS2_RO_ON_INVALID_GROUP_DESC(alloc_inode->i_sb, group); + status = -EIO; goto bail; } BUG_ON((count + start_bit) > le16_to_cpu(group->bg_bits)); diff --git a/trunk/fs/ocfs2/suballoc.h b/trunk/fs/ocfs2/suballoc.h index c787838d1052..a76c82a7ceac 100644 --- a/trunk/fs/ocfs2/suballoc.h +++ b/trunk/fs/ocfs2/suballoc.h @@ -49,8 +49,6 @@ struct ocfs2_alloc_context { u16 ac_chain; int ac_allow_chain_relink; group_search_t *ac_group_search; - - u64 ac_last_group; }; void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac); diff --git a/trunk/fs/ocfs2/super.c b/trunk/fs/ocfs2/super.c index d17e33e66a1e..382706a67ffd 100644 --- a/trunk/fs/ocfs2/super.c +++ b/trunk/fs/ocfs2/super.c @@ -1442,13 +1442,8 @@ static int ocfs2_initialize_super(struct super_block *sb, osb->bitmap_blkno = OCFS2_I(inode)->ip_blkno; - /* We don't have a cluster lock on the bitmap here because - * we're only interested in static information and the extra - * complexity at mount time isn't worht it. Don't pass the - * inode in to the read function though as we don't want it to - * be put in the cache. */ status = ocfs2_read_block(osb, osb->bitmap_blkno, &bitmap_bh, 0, - NULL); + inode); iput(inode); if (status < 0) { mlog_errno(status); @@ -1457,6 +1452,7 @@ static int ocfs2_initialize_super(struct super_block *sb, di = (struct ocfs2_dinode *) bitmap_bh->b_data; osb->bitmap_cpg = le16_to_cpu(di->id2.i_chain.cl_cpg); + osb->num_clusters = le32_to_cpu(di->id1.bitmap1.i_total); brelse(bitmap_bh); mlog(0, "cluster bitmap inode: %llu, clusters per group: %u\n", (unsigned long long)osb->bitmap_blkno, osb->bitmap_cpg); diff --git a/trunk/fs/ocfs2/uptodate.c b/trunk/fs/ocfs2/uptodate.c index 9707ed7a3206..b8a00a793326 100644 --- a/trunk/fs/ocfs2/uptodate.c +++ b/trunk/fs/ocfs2/uptodate.c @@ -206,10 +206,7 @@ static int ocfs2_buffer_cached(struct ocfs2_inode_info *oi, } /* Warning: even if it returns true, this does *not* guarantee that - * the block is stored in our inode metadata cache. - * - * This can be called under lock_buffer() - */ + * the block is stored in our inode metadata cache. */ int ocfs2_buffer_uptodate(struct inode *inode, struct buffer_head *bh) { @@ -229,16 +226,6 @@ int ocfs2_buffer_uptodate(struct inode *inode, return ocfs2_buffer_cached(OCFS2_I(inode), bh); } -/* - * Determine whether a buffer is currently out on a read-ahead request. - * ip_io_sem should be held to serialize submitters with the logic here. - */ -int ocfs2_buffer_read_ahead(struct inode *inode, - struct buffer_head *bh) -{ - return buffer_locked(bh) && ocfs2_buffer_cached(OCFS2_I(inode), bh); -} - /* Requires ip_lock */ static void ocfs2_append_cache_array(struct ocfs2_caching_info *ci, sector_t block) @@ -416,11 +403,7 @@ static void __ocfs2_set_buffer_uptodate(struct ocfs2_inode_info *oi, * * Note that this function may actually fail to insert the block if * memory cannot be allocated. This is not fatal however (but may - * result in a performance penalty) - * - * Readahead buffers can be passed in here before the I/O request is - * completed. - */ + * result in a performance penalty) */ void ocfs2_set_buffer_uptodate(struct inode *inode, struct buffer_head *bh) { diff --git a/trunk/fs/ocfs2/uptodate.h b/trunk/fs/ocfs2/uptodate.h index 2e73206059a8..01cd32d26b06 100644 --- a/trunk/fs/ocfs2/uptodate.h +++ b/trunk/fs/ocfs2/uptodate.h @@ -40,7 +40,5 @@ void ocfs2_set_new_buffer_uptodate(struct inode *inode, struct buffer_head *bh); void ocfs2_remove_from_cache(struct inode *inode, struct buffer_head *bh); -int ocfs2_buffer_read_ahead(struct inode *inode, - struct buffer_head *bh); #endif /* OCFS2_UPTODATE_H */ diff --git a/trunk/fs/partitions/Kconfig b/trunk/fs/partitions/Kconfig index e478f1941831..c9a478099281 100644 --- a/trunk/fs/partitions/Kconfig +++ b/trunk/fs/partitions/Kconfig @@ -99,7 +99,7 @@ config IBM_PARTITION config MAC_PARTITION bool "Macintosh partition map support" if PARTITION_ADVANCED - default y if (MAC || PPC_PMAC) + default y if MAC help Say Y here if you would like to use hard disks under Linux which were partitioned on a Macintosh. diff --git a/trunk/fs/partitions/sun.c b/trunk/fs/partitions/sun.c index 0a5927c806ca..abe91ca03edf 100644 --- a/trunk/fs/partitions/sun.c +++ b/trunk/fs/partitions/sun.c @@ -74,7 +74,7 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev) spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect); for (i = 0; i < 8; i++, p++) { unsigned long st_sector; - unsigned int num_sectors; + int num_sectors; st_sector = be32_to_cpu(p->start_cylinder) * spc; num_sectors = be32_to_cpu(p->num_sectors); diff --git a/trunk/fs/proc/proc_misc.c b/trunk/fs/proc/proc_misc.c index 942156225447..9f2cfc30f9cf 100644 --- a/trunk/fs/proc/proc_misc.c +++ b/trunk/fs/proc/proc_misc.c @@ -169,7 +169,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off, "Mapped: %8lu kB\n" "Slab: %8lu kB\n" "PageTables: %8lu kB\n" - "NFS_Unstable: %8lu kB\n" + "NFS Unstable: %8lu kB\n" "Bounce: %8lu kB\n" "CommitLimit: %8lu kB\n" "Committed_AS: %8lu kB\n" diff --git a/trunk/fs/reiserfs/file.c b/trunk/fs/reiserfs/file.c index 1627edd50810..f318b58510fd 100644 --- a/trunk/fs/reiserfs/file.c +++ b/trunk/fs/reiserfs/file.c @@ -48,8 +48,8 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp) return 0; } - mutex_lock(&inode->i_mutex); reiserfs_write_lock(inode->i_sb); + mutex_lock(&inode->i_mutex); /* freeing preallocation only involves relogging blocks that * are already in the current transaction. preallocation gets * freed at the end of each transaction, so it is impossible for diff --git a/trunk/fs/reiserfs/inode.c b/trunk/fs/reiserfs/inode.c index 52f1e2136546..12dfdcfbee3d 100644 --- a/trunk/fs/reiserfs/inode.c +++ b/trunk/fs/reiserfs/inode.c @@ -39,10 +39,14 @@ void reiserfs_delete_inode(struct inode *inode) /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */ if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */ + mutex_lock(&inode->i_mutex); + reiserfs_delete_xattrs(inode); - if (journal_begin(&th, inode->i_sb, jbegin_count)) + if (journal_begin(&th, inode->i_sb, jbegin_count)) { + mutex_unlock(&inode->i_mutex); goto out; + } reiserfs_update_inode_transaction(inode); err = reiserfs_delete_object(&th, inode); @@ -53,8 +57,12 @@ void reiserfs_delete_inode(struct inode *inode) if (!err) DQUOT_FREE_INODE(inode); - if (journal_end(&th, inode->i_sb, jbegin_count)) + if (journal_end(&th, inode->i_sb, jbegin_count)) { + mutex_unlock(&inode->i_mutex); goto out; + } + + mutex_unlock(&inode->i_mutex); /* check return value from reiserfs_delete_object after * ending the transaction @@ -2340,7 +2348,6 @@ static int reiserfs_write_full_page(struct page *page, unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT; int error = 0; unsigned long block; - sector_t last_block; struct buffer_head *head, *bh; int partial = 0; int nr = 0; @@ -2388,19 +2395,10 @@ static int reiserfs_write_full_page(struct page *page, } bh = head; block = page->index << (PAGE_CACHE_SHIFT - s->s_blocksize_bits); - last_block = (i_size_read(inode) - 1) >> inode->i_blkbits; /* first map all the buffers, logging any direct items we find */ do { - if (block > last_block) { - /* - * This can happen when the block size is less than - * the page size. The corresponding bytes in the page - * were zero filled above - */ - clear_buffer_dirty(bh); - set_buffer_uptodate(bh); - } else if ((checked || buffer_dirty(bh)) && - (!buffer_mapped(bh) || (buffer_mapped(bh) + if ((checked || buffer_dirty(bh)) && (!buffer_mapped(bh) || + (buffer_mapped(bh) && bh->b_blocknr == 0))) { /* not mapped yet, or it points to a direct item, search diff --git a/trunk/fs/reiserfs/ioctl.c b/trunk/fs/reiserfs/ioctl.c index a986b5e1e288..745c88100895 100644 --- a/trunk/fs/reiserfs/ioctl.c +++ b/trunk/fs/reiserfs/ioctl.c @@ -116,12 +116,12 @@ static int reiserfs_unpack(struct inode *inode, struct file *filp) if (REISERFS_I(inode)->i_flags & i_nopack_mask) { return 0; } + reiserfs_write_lock(inode->i_sb); /* we need to make sure nobody is changing the file size beneath ** us */ mutex_lock(&inode->i_mutex); - reiserfs_write_lock(inode->i_sb); write_from = inode->i_size & (blocksize - 1); /* if we are on a block boundary, we are already unpacked. */ diff --git a/trunk/fs/reiserfs/xattr.c b/trunk/fs/reiserfs/xattr.c index d935fb9394e3..39fedaa88a0c 100644 --- a/trunk/fs/reiserfs/xattr.c +++ b/trunk/fs/reiserfs/xattr.c @@ -424,7 +424,7 @@ int xattr_readdir(struct file *file, filldir_t filler, void *buf) int res = -ENOTDIR; if (!file->f_op || !file->f_op->readdir) goto out; - mutex_lock_nested(&inode->i_mutex, I_MUTEX_XATTR); + mutex_lock(&inode->i_mutex); // down(&inode->i_zombie); res = -ENOENT; if (!IS_DEADDIR(inode)) { diff --git a/trunk/fs/super.c b/trunk/fs/super.c index 5c4c94d5495e..6d4e8174b6db 100644 --- a/trunk/fs/super.c +++ b/trunk/fs/super.c @@ -49,7 +49,6 @@ DEFINE_SPINLOCK(sb_lock); /** * alloc_super - create new superblock - * @type: filesystem type superblock should belong to * * Allocates and initializes a new &struct super_block. alloc_super() * returns a pointer new superblock or %NULL if allocation had failed. diff --git a/trunk/fs/udf/ialloc.c b/trunk/fs/udf/ialloc.c index 33323473e3c4..3873c672cb4c 100644 --- a/trunk/fs/udf/ialloc.c +++ b/trunk/fs/udf/ialloc.c @@ -75,12 +75,6 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err) } *err = -ENOSPC; - UDF_I_UNIQUE(inode) = 0; - UDF_I_LENEXTENTS(inode) = 0; - UDF_I_NEXT_ALLOC_BLOCK(inode) = 0; - UDF_I_NEXT_ALLOC_GOAL(inode) = 0; - UDF_I_STRAT4096(inode) = 0; - block = udf_new_block(dir->i_sb, NULL, UDF_I_LOCATION(dir).partitionReferenceNum, start, err); if (*err) @@ -90,6 +84,11 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err) } mutex_lock(&sbi->s_alloc_mutex); + UDF_I_UNIQUE(inode) = 0; + UDF_I_LENEXTENTS(inode) = 0; + UDF_I_NEXT_ALLOC_BLOCK(inode) = 0; + UDF_I_NEXT_ALLOC_GOAL(inode) = 0; + UDF_I_STRAT4096(inode) = 0; if (UDF_SB_LVIDBH(sb)) { struct logicalVolHeaderDesc *lvhd; diff --git a/trunk/fs/udf/super.c b/trunk/fs/udf/super.c index fcce1a21a51b..4df822c881b6 100644 --- a/trunk/fs/udf/super.c +++ b/trunk/fs/udf/super.c @@ -115,13 +115,6 @@ static struct inode *udf_alloc_inode(struct super_block *sb) ei = (struct udf_inode_info *)kmem_cache_alloc(udf_inode_cachep, SLAB_KERNEL); if (!ei) return NULL; - - ei->i_unique = 0; - ei->i_lenExtents = 0; - ei->i_next_alloc_block = 0; - ei->i_next_alloc_goal = 0; - ei->i_strat4096 = 0; - return &ei->vfs_inode; } @@ -1659,7 +1652,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) iput(inode); goto error_out; } - sb->s_maxbytes = 1<<30; + sb->s_maxbytes = MAX_LFS_FILESIZE; return 0; error_out: diff --git a/trunk/fs/udf/truncate.c b/trunk/fs/udf/truncate.c index 0abd66ce36ea..e1b0e8cfecb4 100644 --- a/trunk/fs/udf/truncate.c +++ b/trunk/fs/udf/truncate.c @@ -239,51 +239,37 @@ void udf_truncate_extents(struct inode * inode) { if (offset) { - /* - * OK, there is not extent covering inode->i_size and - * no extent above inode->i_size => truncate is - * extending the file by 'offset'. - */ - if ((!bh && extoffset == udf_file_entry_alloc_offset(inode)) || - (bh && extoffset == sizeof(struct allocExtDesc))) { - /* File has no extents at all! */ - memset(&eloc, 0x00, sizeof(kernel_lb_addr)); - elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset; - udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1); + extoffset -= adsize; + etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1); + if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) + { + extoffset -= adsize; + elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset); + udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0); } - else { + else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) + { + kernel_lb_addr neloc = { 0, 0 }; extoffset -= adsize; - etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1); - if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) - { - extoffset -= adsize; - elen = EXT_NOT_RECORDED_NOT_ALLOCATED | (elen + offset); - udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 0); - } - else if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) + nelen = EXT_NOT_RECORDED_NOT_ALLOCATED | + ((elen + offset + inode->i_sb->s_blocksize - 1) & + ~(inode->i_sb->s_blocksize - 1)); + udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1); + udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1); + } + else + { + if (elen & (inode->i_sb->s_blocksize - 1)) { - kernel_lb_addr neloc = { 0, 0 }; extoffset -= adsize; - nelen = EXT_NOT_RECORDED_NOT_ALLOCATED | - ((elen + offset + inode->i_sb->s_blocksize - 1) & + elen = EXT_RECORDED_ALLOCATED | + ((elen + inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize - 1)); - udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1); - udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1); - } - else - { - if (elen & (inode->i_sb->s_blocksize - 1)) - { - extoffset -= adsize; - elen = EXT_RECORDED_ALLOCATED | - ((elen + inode->i_sb->s_blocksize - 1) & - ~(inode->i_sb->s_blocksize - 1)); - udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1); - } - memset(&eloc, 0x00, sizeof(kernel_lb_addr)); - elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset; - udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1); + udf_write_aext(inode, bloc, &extoffset, eloc, elen, bh, 1); } + memset(&eloc, 0x00, sizeof(kernel_lb_addr)); + elen = EXT_NOT_RECORDED_NOT_ALLOCATED | offset; + udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1); } } } diff --git a/trunk/fs/ufs/balloc.c b/trunk/fs/ufs/balloc.c index b82381475779..b01804baa120 100644 --- a/trunk/fs/ufs/balloc.c +++ b/trunk/fs/ufs/balloc.c @@ -248,7 +248,7 @@ static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk, if (likely(cur_index != index)) { page = ufs_get_locked_page(mapping, index); - if (!page || IS_ERR(page)) /* it was truncated or EIO */ + if (IS_ERR(page)) continue; } else page = locked_page; diff --git a/trunk/fs/ufs/inode.c b/trunk/fs/ufs/inode.c index 30c6e8a9446c..e7c8615beb65 100644 --- a/trunk/fs/ufs/inode.c +++ b/trunk/fs/ufs/inode.c @@ -169,20 +169,18 @@ static void ufs_clear_frag(struct inode *inode, struct buffer_head *bh) static struct buffer_head * ufs_clear_frags(struct inode *inode, sector_t beg, - unsigned int n, sector_t want) + unsigned int n) { - struct buffer_head *res = NULL, *bh; + struct buffer_head *res, *bh; sector_t end = beg + n; - for (; beg < end; ++beg) { + res = sb_getblk(inode->i_sb, beg); + ufs_clear_frag(inode, res); + for (++beg; beg < end; ++beg) { bh = sb_getblk(inode->i_sb, beg); ufs_clear_frag(inode, bh); - if (want != beg) - brelse(bh); - else - res = bh; + brelse(bh); } - BUG_ON(!res); return res; } @@ -267,9 +265,7 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment, lastfrag = ufsi->i_lastfrag; } - tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]); - if (tmp) - goal = tmp + uspi->s_fpb; + goal = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]) + uspi->s_fpb; tmp = ufs_new_fragments (inode, p, fragment - blockoff, goal, required + blockoff, err, locked_page); @@ -281,15 +277,13 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment, tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff), fs32_to_cpu(sb, *p), required + (blockoff - lastblockoff), err, locked_page); - } else /* (lastblock > block) */ { + } /* * We will allocate new block before last allocated block */ - if (block) { - tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[block-1]); - if (tmp) - goal = tmp + uspi->s_fpb; - } + else /* (lastblock > block) */ { + if (lastblock && (tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock-1]))) + goal = tmp + uspi->s_fpb; tmp = ufs_new_fragments(inode, p, fragment - blockoff, goal, uspi->s_fpb, err, locked_page); } @@ -302,7 +296,7 @@ ufs_inode_getfrag(struct inode *inode, unsigned int fragment, } if (!phys) { - result = ufs_clear_frags(inode, tmp, required, tmp + blockoff); + result = ufs_clear_frags(inode, tmp + blockoff, required); } else { *phys = tmp + blockoff; result = NULL; @@ -389,7 +383,7 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, } } - if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1]))) + if (block && (tmp = fs32_to_cpu(sb, ((__fs32*)bh->b_data)[block-1]) + uspi->s_fpb)) goal = tmp + uspi->s_fpb; else goal = bh->b_blocknr + uspi->s_fpb; @@ -403,8 +397,7 @@ ufs_inode_getblock(struct inode *inode, struct buffer_head *bh, if (!phys) { - result = ufs_clear_frags(inode, tmp, uspi->s_fpb, - tmp + blockoff); + result = ufs_clear_frags(inode, tmp + blockoff, uspi->s_fpb); } else { *phys = tmp + blockoff; *new = 1; diff --git a/trunk/fs/ufs/namei.c b/trunk/fs/ufs/namei.c index d344b411e261..abd5f23a426d 100644 --- a/trunk/fs/ufs/namei.c +++ b/trunk/fs/ufs/namei.c @@ -129,7 +129,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry, struct inode * inode; if (l > sb->s_blocksize) - goto out_notlocked; + goto out; lock_kernel(); inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO); @@ -155,7 +155,6 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry, err = ufs_add_nondir(dentry, inode); out: unlock_kernel(); -out_notlocked: return err; out_fail: diff --git a/trunk/fs/ufs/truncate.c b/trunk/fs/ufs/truncate.c index ea11d04c41a0..c9b55872079b 100644 --- a/trunk/fs/ufs/truncate.c +++ b/trunk/fs/ufs/truncate.c @@ -375,15 +375,17 @@ static int ufs_alloc_lastblock(struct inode *inode) int err = 0; struct address_space *mapping = inode->i_mapping; struct ufs_sb_private_info *uspi = UFS_SB(inode->i_sb)->s_uspi; + struct ufs_inode_info *ufsi = UFS_I(inode); unsigned lastfrag, i, end; struct page *lastpage; struct buffer_head *bh; lastfrag = (i_size_read(inode) + uspi->s_fsize - 1) >> uspi->s_fshift; - if (!lastfrag) + if (!lastfrag) { + ufsi->i_lastfrag = 0; goto out; - + } lastfrag--; lastpage = ufs_get_locked_page(mapping, lastfrag >> @@ -398,25 +400,25 @@ static int ufs_alloc_lastblock(struct inode *inode) for (i = 0; i < end; ++i) bh = bh->b_this_page; - - err = ufs_getfrag_block(inode, lastfrag, bh, 1); - - if (unlikely(err)) - goto out_unlock; - - if (buffer_new(bh)) { - clear_buffer_new(bh); - unmap_underlying_metadata(bh->b_bdev, - bh->b_blocknr); - /* - * we do not zeroize fragment, because of - * if it maped to hole, it already contains zeroes - */ - set_buffer_uptodate(bh); - mark_buffer_dirty(bh); - set_page_dirty(lastpage); + if (!buffer_mapped(bh)) { + err = ufs_getfrag_block(inode, lastfrag, bh, 1); + + if (unlikely(err)) + goto out_unlock; + + if (buffer_new(bh)) { + clear_buffer_new(bh); + unmap_underlying_metadata(bh->b_bdev, + bh->b_blocknr); + /* + * we do not zeroize fragment, because of + * if it maped to hole, it already contains zeroes + */ + set_buffer_uptodate(bh); + mark_buffer_dirty(bh); + set_page_dirty(lastpage); + } } - out_unlock: ufs_put_locked_page(lastpage); out: @@ -438,11 +440,23 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) return -EPERM; - err = ufs_alloc_lastblock(inode); + if (inode->i_size > old_i_size) { + /* + * if we expand file we should care about + * allocation of block for last byte first of all + */ + err = ufs_alloc_lastblock(inode); - if (err) { - i_size_write(inode, old_i_size); - goto out; + if (err) { + i_size_write(inode, old_i_size); + goto out; + } + /* + * go away, because of we expand file, and we do not + * need free blocks, and zeroizes page + */ + lock_kernel(); + goto almost_end; } block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block); @@ -463,8 +477,21 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size) yield(); } + if (inode->i_size < old_i_size) { + /* + * now we should have enough space + * to allocate block for last byte + */ + err = ufs_alloc_lastblock(inode); + if (err) + /* + * looks like all the same - we have no space, + * but we truncate file already + */ + inode->i_size = (ufsi->i_lastfrag - 1) * uspi->s_fsize; + } +almost_end: inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; - ufsi->i_lastfrag = DIRECT_FRAGMENT; unlock_kernel(); mark_inode_dirty(inode); out: diff --git a/trunk/fs/ufs/util.c b/trunk/fs/ufs/util.c index 22f820a9b15c..337cf2c46d10 100644 --- a/trunk/fs/ufs/util.c +++ b/trunk/fs/ufs/util.c @@ -251,12 +251,12 @@ struct page *ufs_get_locked_page(struct address_space *mapping, { struct page *page; +try_again: page = find_lock_page(mapping, index); if (!page) { page = read_cache_page(mapping, index, (filler_t*)mapping->a_ops->readpage, NULL); - if (IS_ERR(page)) { printk(KERN_ERR "ufs_change_blocknr: " "read_cache_page error: ino %lu, index: %lu\n", @@ -266,14 +266,6 @@ struct page *ufs_get_locked_page(struct address_space *mapping, lock_page(page); - if (unlikely(page->mapping == NULL)) { - /* Truncate got there first */ - unlock_page(page); - page_cache_release(page); - page = NULL; - goto out; - } - if (!PageUptodate(page) || PageError(page)) { unlock_page(page); page_cache_release(page); @@ -283,8 +275,15 @@ struct page *ufs_get_locked_page(struct address_space *mapping, mapping->host->i_ino, index); page = ERR_PTR(-EIO); + goto out; } } + + if (unlikely(!page->mapping || !page_has_buffers(page))) { + unlock_page(page); + page_cache_release(page); + goto try_again;/*we really need these buffers*/ + } out: return page; } diff --git a/trunk/fs/xfs/linux-2.6/xfs_aops.c b/trunk/fs/xfs/linux-2.6/xfs_aops.c index 34dcb43a7837..c40f81ba9b13 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_aops.c +++ b/trunk/fs/xfs/linux-2.6/xfs_aops.c @@ -1390,19 +1390,11 @@ xfs_vm_direct_IO( iocb->private = xfs_alloc_ioend(inode, IOMAP_UNWRITTEN); - if (rw == WRITE) { - ret = blockdev_direct_IO_own_locking(rw, iocb, inode, - iomap.iomap_target->bt_bdev, - iov, offset, nr_segs, - xfs_get_blocks_direct, - xfs_end_io_direct); - } else { - ret = blockdev_direct_IO_no_locking(rw, iocb, inode, - iomap.iomap_target->bt_bdev, - iov, offset, nr_segs, - xfs_get_blocks_direct, - xfs_end_io_direct); - } + ret = blockdev_direct_IO_own_locking(rw, iocb, inode, + iomap.iomap_target->bt_bdev, + iov, offset, nr_segs, + xfs_get_blocks_direct, + xfs_end_io_direct); if (unlikely(ret <= 0 && iocb->private)) xfs_destroy_ioend(iocb->private); diff --git a/trunk/fs/xfs/linux-2.6/xfs_buf.h b/trunk/fs/xfs/linux-2.6/xfs_buf.h index 7858703ed84c..ceda3a2859d2 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_buf.h +++ b/trunk/fs/xfs/linux-2.6/xfs_buf.h @@ -246,8 +246,8 @@ extern void xfs_buf_trace(xfs_buf_t *, char *, void *, void *); #define BUF_BUSY XBF_DONT_BLOCK #define XFS_BUF_BFLAGS(bp) ((bp)->b_flags) -#define XFS_BUF_ZEROFLAGS(bp) ((bp)->b_flags &= \ - ~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI|XBF_ORDERED)) +#define XFS_BUF_ZEROFLAGS(bp) \ + ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC|XBF_DELWRI)) #define XFS_BUF_STALE(bp) ((bp)->b_flags |= XFS_B_STALE) #define XFS_BUF_UNSTALE(bp) ((bp)->b_flags &= ~XFS_B_STALE) diff --git a/trunk/fs/xfs/linux-2.6/xfs_lrw.c b/trunk/fs/xfs/linux-2.6/xfs_lrw.c index ee788b1cb364..5d9cfd91ad08 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_lrw.c +++ b/trunk/fs/xfs/linux-2.6/xfs_lrw.c @@ -264,9 +264,7 @@ xfs_read( dmflags, &locktype); if (ret) { xfs_iunlock(ip, XFS_IOLOCK_SHARED); - if (unlikely(ioflags & IO_ISDIRECT)) - mutex_unlock(&inode->i_mutex); - return ret; + goto unlock_mutex; } } @@ -274,9 +272,6 @@ xfs_read( bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)), -1, FI_REMAPF_LOCKED); - if (unlikely(ioflags & IO_ISDIRECT)) - mutex_unlock(&inode->i_mutex); - xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore, (void *)iovp, segs, *offset, ioflags); ret = __generic_file_aio_read(iocb, iovp, segs, offset); @@ -286,6 +281,10 @@ xfs_read( XFS_STATS_ADD(xs_read_bytes, ret); xfs_iunlock(ip, XFS_IOLOCK_SHARED); + +unlock_mutex: + if (unlikely(ioflags & IO_ISDIRECT)) + mutex_unlock(&inode->i_mutex); return ret; } @@ -391,8 +390,6 @@ xfs_splice_write( xfs_inode_t *ip = XFS_BHVTOI(bdp); xfs_mount_t *mp = ip->i_mount; ssize_t ret; - struct inode *inode = outfilp->f_mapping->host; - xfs_fsize_t isize; XFS_STATS_INC(xs_write_calls); if (XFS_FORCED_SHUTDOWN(ip->i_mount)) @@ -419,20 +416,6 @@ xfs_splice_write( if (ret > 0) XFS_STATS_ADD(xs_write_bytes, ret); - isize = i_size_read(inode); - if (unlikely(ret < 0 && ret != -EFAULT && *ppos > isize)) - *ppos = isize; - - if (*ppos > ip->i_d.di_size) { - xfs_ilock(ip, XFS_ILOCK_EXCL); - if (*ppos > ip->i_d.di_size) { - ip->i_d.di_size = *ppos; - i_size_write(inode, *ppos); - ip->i_update_core = 1; - ip->i_update_size = 1; - } - xfs_iunlock(ip, XFS_ILOCK_EXCL); - } xfs_iunlock(ip, XFS_IOLOCK_EXCL); return ret; } diff --git a/trunk/fs/xfs/linux-2.6/xfs_super.c b/trunk/fs/xfs/linux-2.6/xfs_super.c index 4754f342a5d3..9bdef9d51900 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_super.c +++ b/trunk/fs/xfs/linux-2.6/xfs_super.c @@ -314,13 +314,6 @@ xfs_mountfs_check_barriers(xfs_mount_t *mp) return; } - if (xfs_readonly_buftarg(mp->m_ddev_targp)) { - xfs_fs_cmn_err(CE_NOTE, mp, - "Disabling barriers, underlying device is readonly"); - mp->m_flags &= ~XFS_MOUNT_BARRIER; - return; - } - error = xfs_barrier_test(mp); if (error) { xfs_fs_cmn_err(CE_NOTE, mp, diff --git a/trunk/fs/xfs/quota/xfs_qm_bhv.c b/trunk/fs/xfs/quota/xfs_qm_bhv.c index db8872be8c87..e95e99f7168f 100644 --- a/trunk/fs/xfs/quota/xfs_qm_bhv.c +++ b/trunk/fs/xfs/quota/xfs_qm_bhv.c @@ -203,7 +203,7 @@ xfs_qm_statvfs( if (error || !vnode) return error; - mp = xfs_vfstom(bhvtovfs(bhv)); + mp = XFS_BHVTOM(bhv); ip = xfs_vtoi(vnode); if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)) @@ -217,24 +217,17 @@ xfs_qm_statvfs( return 0; dp = &dqp->q_core; - limit = dp->d_blk_softlimit ? - be64_to_cpu(dp->d_blk_softlimit) : - be64_to_cpu(dp->d_blk_hardlimit); + limit = dp->d_blk_softlimit ? dp->d_blk_softlimit : dp->d_blk_hardlimit; if (limit && statp->f_blocks > limit) { statp->f_blocks = limit; - statp->f_bfree = - (statp->f_blocks > be64_to_cpu(dp->d_bcount)) ? - (statp->f_blocks - be64_to_cpu(dp->d_bcount)) : 0; + statp->f_bfree = (statp->f_blocks > dp->d_bcount) ? + (statp->f_blocks - dp->d_bcount) : 0; } - - limit = dp->d_ino_softlimit ? - be64_to_cpu(dp->d_ino_softlimit) : - be64_to_cpu(dp->d_ino_hardlimit); + limit = dp->d_ino_softlimit ? dp->d_ino_softlimit : dp->d_ino_hardlimit; if (limit && statp->f_files > limit) { statp->f_files = limit; - statp->f_ffree = - (statp->f_files > be64_to_cpu(dp->d_icount)) ? - (statp->f_ffree - be64_to_cpu(dp->d_icount)) : 0; + statp->f_ffree = (statp->f_files > dp->d_icount) ? + (statp->f_ffree - dp->d_icount) : 0; } xfs_qm_dqput(dqp); diff --git a/trunk/fs/xfs/xfs_alloc.c b/trunk/fs/xfs/xfs_alloc.c index d2bbcd882a69..eef6763f3a67 100644 --- a/trunk/fs/xfs/xfs_alloc.c +++ b/trunk/fs/xfs/xfs_alloc.c @@ -1835,47 +1835,40 @@ xfs_alloc_fix_freelist( &agbp))) return error; if (!pag->pagf_init) { - ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK); - ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); args->agbp = NULL; return 0; } } else agbp = NULL; - /* - * If this is a metadata preferred pag and we are user data + /* If this is a metadata preferred pag and we are user data * then try somewhere else if we are not being asked to * try harder at this point */ - if (pag->pagf_metadata && args->userdata && - (flags & XFS_ALLOC_FLAG_TRYLOCK)) { - ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); + if (pag->pagf_metadata && args->userdata && flags) { args->agbp = NULL; return 0; } - if (!(flags & XFS_ALLOC_FLAG_FREEING)) { - need = XFS_MIN_FREELIST_PAG(pag, mp); - delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0; - /* - * If it looks like there isn't a long enough extent, or enough - * total blocks, reject it. - */ - longest = (pag->pagf_longest > delta) ? - (pag->pagf_longest - delta) : - (pag->pagf_flcount > 0 || pag->pagf_longest > 0); - if ((args->minlen + args->alignment + args->minalignslop - 1) > - longest || - ((int)(pag->pagf_freeblks + pag->pagf_flcount - - need - args->total) < (int)args->minleft)) { - if (agbp) - xfs_trans_brelse(tp, agbp); - args->agbp = NULL; - return 0; - } + need = XFS_MIN_FREELIST_PAG(pag, mp); + delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0; + /* + * If it looks like there isn't a long enough extent, or enough + * total blocks, reject it. + */ + longest = (pag->pagf_longest > delta) ? + (pag->pagf_longest - delta) : + (pag->pagf_flcount > 0 || pag->pagf_longest > 0); + if (args->minlen + args->alignment + args->minalignslop - 1 > longest || + (!(flags & XFS_ALLOC_FLAG_FREEING) && + (int)(pag->pagf_freeblks + pag->pagf_flcount - + need - args->total) < + (int)args->minleft)) { + if (agbp) + xfs_trans_brelse(tp, agbp); + args->agbp = NULL; + return 0; } - /* * Get the a.g. freespace buffer. * Can fail if we're not blocking on locks, and it's held. @@ -1885,8 +1878,6 @@ xfs_alloc_fix_freelist( &agbp))) return error; if (agbp == NULL) { - ASSERT(flags & XFS_ALLOC_FLAG_TRYLOCK); - ASSERT(!(flags & XFS_ALLOC_FLAG_FREEING)); args->agbp = NULL; return 0; } @@ -1896,24 +1887,22 @@ xfs_alloc_fix_freelist( */ agf = XFS_BUF_TO_AGF(agbp); need = XFS_MIN_FREELIST(agf, mp); + delta = need > be32_to_cpu(agf->agf_flcount) ? + (need - be32_to_cpu(agf->agf_flcount)) : 0; /* * If there isn't enough total or single-extent, reject it. */ - if (!(flags & XFS_ALLOC_FLAG_FREEING)) { - delta = need > be32_to_cpu(agf->agf_flcount) ? - (need - be32_to_cpu(agf->agf_flcount)) : 0; - longest = be32_to_cpu(agf->agf_longest); - longest = (longest > delta) ? (longest - delta) : - (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0); - if ((args->minlen + args->alignment + args->minalignslop - 1) > - longest || - ((int)(be32_to_cpu(agf->agf_freeblks) + - be32_to_cpu(agf->agf_flcount) - need - args->total) < - (int)args->minleft)) { - xfs_trans_brelse(tp, agbp); - args->agbp = NULL; - return 0; - } + longest = be32_to_cpu(agf->agf_longest); + longest = (longest > delta) ? (longest - delta) : + (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0); + if (args->minlen + args->alignment + args->minalignslop - 1 > longest || + (!(flags & XFS_ALLOC_FLAG_FREEING) && + (int)(be32_to_cpu(agf->agf_freeblks) + + be32_to_cpu(agf->agf_flcount) - need - args->total) < + (int)args->minleft)) { + xfs_trans_brelse(tp, agbp); + args->agbp = NULL; + return 0; } /* * Make the freelist shorter if it's too long. @@ -1961,11 +1950,12 @@ xfs_alloc_fix_freelist( * on a completely full ag. */ if (targs.agbno == NULLAGBLOCK) { - if (flags & XFS_ALLOC_FLAG_FREEING) - break; - xfs_trans_brelse(tp, agflbp); - args->agbp = NULL; - return 0; + if (!(flags & XFS_ALLOC_FLAG_FREEING)) { + xfs_trans_brelse(tp, agflbp); + args->agbp = NULL; + return 0; + } + break; } /* * Put each allocated block on the list. @@ -2452,26 +2442,31 @@ xfs_free_extent( xfs_fsblock_t bno, /* starting block number of extent */ xfs_extlen_t len) /* length of extent */ { - xfs_alloc_arg_t args; +#ifdef DEBUG + xfs_agf_t *agf; /* a.g. freespace header */ +#endif + xfs_alloc_arg_t args; /* allocation argument structure */ int error; ASSERT(len != 0); - memset(&args, 0, sizeof(xfs_alloc_arg_t)); args.tp = tp; args.mp = tp->t_mountp; args.agno = XFS_FSB_TO_AGNO(args.mp, bno); ASSERT(args.agno < args.mp->m_sb.sb_agcount); args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno); + args.alignment = 1; + args.minlen = args.minleft = args.minalignslop = 0; down_read(&args.mp->m_peraglock); args.pag = &args.mp->m_perag[args.agno]; if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING))) goto error0; #ifdef DEBUG ASSERT(args.agbp != NULL); - ASSERT((args.agbno + len) <= - be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)); + agf = XFS_BUF_TO_AGF(args.agbp); + ASSERT(args.agbno + len <= be32_to_cpu(agf->agf_length)); #endif - error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); + error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, + len, 0); error0: up_read(&args.mp->m_peraglock); return error; diff --git a/trunk/fs/xfs/xfs_alloc.h b/trunk/fs/xfs/xfs_alloc.h index 5a4256120ccc..650591f999ae 100644 --- a/trunk/fs/xfs/xfs_alloc.h +++ b/trunk/fs/xfs/xfs_alloc.h @@ -43,26 +43,6 @@ typedef enum xfs_alloctype #define XFS_ALLOC_FLAG_TRYLOCK 0x00000001 /* use trylock for buffer locking */ #define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/ -/* - * In order to avoid ENOSPC-related deadlock caused by - * out-of-order locking of AGF buffer (PV 947395), we place - * constraints on the relationship among actual allocations for - * data blocks, freelist blocks, and potential file data bmap - * btree blocks. However, these restrictions may result in no - * actual space allocated for a delayed extent, for example, a data - * block in a certain AG is allocated but there is no additional - * block for the additional bmap btree block due to a split of the - * bmap btree of the file. The result of this may lead to an - * infinite loop in xfssyncd when the file gets flushed to disk and - * all delayed extents need to be actually allocated. To get around - * this, we explicitly set aside a few blocks which will not be - * reserved in delayed allocation. Considering the minimum number of - * needed freelist blocks is 4 fsbs _per AG_, a potential split of file's bmap - * btree requires 1 fsb, so we set the number of set-aside blocks - * to 4 + 4*agcount. - */ -#define XFS_ALLOC_SET_ASIDE(mp) (4 + ((mp)->m_sb.sb_agcount * 4)) - /* * Argument structure for xfs_alloc routines. * This is turned into a structure to avoid having 20 arguments passed diff --git a/trunk/fs/xfs/xfs_bmap.c b/trunk/fs/xfs/xfs_bmap.c index bf46fae303af..3a6137539064 100644 --- a/trunk/fs/xfs/xfs_bmap.c +++ b/trunk/fs/xfs/xfs_bmap.c @@ -4993,7 +4993,7 @@ xfs_bmapi( bma.firstblock = *firstblock; bma.alen = alen; bma.off = aoff; - bma.conv = !!(flags & XFS_BMAPI_CONVERT); + bma.conv = (flags & XFS_BMAPI_CONVERT); bma.wasdel = wasdelay; bma.minlen = minlen; bma.low = flist->xbf_low; diff --git a/trunk/fs/xfs/xfs_fsops.c b/trunk/fs/xfs/xfs_fsops.c index c064e72ada9e..077629bab532 100644 --- a/trunk/fs/xfs/xfs_fsops.c +++ b/trunk/fs/xfs/xfs_fsops.c @@ -462,7 +462,7 @@ xfs_fs_counts( xfs_icsb_sync_counters_lazy(mp); s = XFS_SB_LOCK(mp); - cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); + cnt->freedata = mp->m_sb.sb_fdblocks; cnt->freertx = mp->m_sb.sb_frextents; cnt->freeino = mp->m_sb.sb_ifree; cnt->allocino = mp->m_sb.sb_icount; @@ -519,19 +519,15 @@ xfs_reserve_blocks( } mp->m_resblks = request; } else { - __int64_t free; - - free = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); delta = request - mp->m_resblks; - lcounter = free - delta; + lcounter = mp->m_sb.sb_fdblocks - delta; if (lcounter < 0) { /* We can't satisfy the request, just get what we can */ - mp->m_resblks += free; - mp->m_resblks_avail += free; - mp->m_sb.sb_fdblocks = XFS_ALLOC_SET_ASIDE(mp); + mp->m_resblks += mp->m_sb.sb_fdblocks; + mp->m_resblks_avail += mp->m_sb.sb_fdblocks; + mp->m_sb.sb_fdblocks = 0; } else { - mp->m_sb.sb_fdblocks = - lcounter + XFS_ALLOC_SET_ASIDE(mp); + mp->m_sb.sb_fdblocks = lcounter; mp->m_resblks = request; mp->m_resblks_avail += delta; } diff --git a/trunk/fs/xfs/xfs_inode.c b/trunk/fs/xfs/xfs_inode.c index 1f8ecff8553a..86c1bf0bba9e 100644 --- a/trunk/fs/xfs/xfs_inode.c +++ b/trunk/fs/xfs/xfs_inode.c @@ -334,9 +334,10 @@ xfs_itobp( #if !defined(__KERNEL__) ni = 0; #elif defined(DEBUG) - ni = BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog; + ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : + (BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog); #else /* usual case */ - ni = 1; + ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1; #endif for (i = 0; i < ni; i++) { @@ -347,15 +348,11 @@ xfs_itobp( (i << mp->m_sb.sb_inodelog)); di_ok = INT_GET(dip->di_core.di_magic, ARCH_CONVERT) == XFS_DINODE_MAGIC && XFS_DINODE_GOOD_VERSION(INT_GET(dip->di_core.di_version, ARCH_CONVERT)); - if (unlikely(XFS_TEST_ERROR(!di_ok, mp, - XFS_ERRTAG_ITOBP_INOTOBP, - XFS_RANDOM_ITOBP_INOTOBP))) { - if (imap_flags & XFS_IMAP_BULKSTAT) { - xfs_trans_brelse(tp, bp); - return XFS_ERROR(EINVAL); - } + if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, + XFS_RANDOM_ITOBP_INOTOBP))) { #ifdef DEBUG - cmn_err(CE_ALERT, + if (!(imap_flags & XFS_IMAP_BULKSTAT)) + cmn_err(CE_ALERT, "Device %s - bad inode magic/vsn " "daddr %lld #%d (magic=%x)", XFS_BUFTARG_NAME(mp->m_ddev_targp), diff --git a/trunk/fs/xfs/xfs_log.c b/trunk/fs/xfs/xfs_log.c index 21ac1a67e3e0..e730328636c3 100644 --- a/trunk/fs/xfs/xfs_log.c +++ b/trunk/fs/xfs/xfs_log.c @@ -1413,7 +1413,7 @@ xlog_sync(xlog_t *log, ops = iclog->ic_header.h_num_logops; INT_SET(iclog->ic_header.h_num_logops, ARCH_CONVERT, ops); - bp = iclog->ic_bp; + bp = iclog->ic_bp; ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1); XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2); XFS_BUF_SET_ADDR(bp, BLOCK_LSN(INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT))); @@ -1430,14 +1430,15 @@ xlog_sync(xlog_t *log, } XFS_BUF_SET_PTR(bp, (xfs_caddr_t) &(iclog->ic_header), count); XFS_BUF_SET_FSPRIVATE(bp, iclog); /* save for later */ - XFS_BUF_ZEROFLAGS(bp); XFS_BUF_BUSY(bp); XFS_BUF_ASYNC(bp); /* * Do an ordered write for the log block. - * Its unnecessary to flush the first split block in the log wrap case. + * + * It may not be needed to flush the first split block in the log wrap + * case, but do it anyways to be safe -AK */ - if (!split && (log->l_mp->m_flags & XFS_MOUNT_BARRIER)) + if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) XFS_BUF_ORDERED(bp); ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); @@ -1459,7 +1460,7 @@ xlog_sync(xlog_t *log, return error; } if (split) { - bp = iclog->ic_log->l_xbuf; + bp = iclog->ic_log->l_xbuf; ASSERT(XFS_BUF_FSPRIVATE2(bp, unsigned long) == (unsigned long)1); XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)2); @@ -1467,7 +1468,6 @@ xlog_sync(xlog_t *log, XFS_BUF_SET_PTR(bp, (xfs_caddr_t)((__psint_t)&(iclog->ic_header)+ (__psint_t)count), split); XFS_BUF_SET_FSPRIVATE(bp, iclog); - XFS_BUF_ZEROFLAGS(bp); XFS_BUF_BUSY(bp); XFS_BUF_ASYNC(bp); if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) diff --git a/trunk/fs/xfs/xfs_mount.c b/trunk/fs/xfs/xfs_mount.c index 9dfae18d995f..4be5c0b2d296 100644 --- a/trunk/fs/xfs/xfs_mount.c +++ b/trunk/fs/xfs/xfs_mount.c @@ -1243,6 +1243,24 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields) xfs_trans_log_buf(tp, bp, first, last); } +/* + * In order to avoid ENOSPC-related deadlock caused by + * out-of-order locking of AGF buffer (PV 947395), we place + * constraints on the relationship among actual allocations for + * data blocks, freelist blocks, and potential file data bmap + * btree blocks. However, these restrictions may result in no + * actual space allocated for a delayed extent, for example, a data + * block in a certain AG is allocated but there is no additional + * block for the additional bmap btree block due to a split of the + * bmap btree of the file. The result of this may lead to an + * infinite loop in xfssyncd when the file gets flushed to disk and + * all delayed extents need to be actually allocated. To get around + * this, we explicitly set aside a few blocks which will not be + * reserved in delayed allocation. Considering the minimum number of + * needed freelist blocks is 4 fsbs, a potential split of file's bmap + * btree requires 1 fsb, so we set the number of set-aside blocks to 8. +*/ +#define SET_ASIDE_BLOCKS 8 /* * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply @@ -1288,8 +1306,7 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, return 0; case XFS_SBS_FDBLOCKS: - lcounter = (long long) - mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); + lcounter = (long long)mp->m_sb.sb_fdblocks - SET_ASIDE_BLOCKS; res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); if (delta > 0) { /* Putting blocks back */ @@ -1323,7 +1340,7 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, } } - mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp); + mp->m_sb.sb_fdblocks = lcounter + SET_ASIDE_BLOCKS; return 0; case XFS_SBS_FREXTENTS: lcounter = (long long)mp->m_sb.sb_frextents; @@ -2004,8 +2021,7 @@ xfs_icsb_sync_counters_lazy( * when we get near ENOSPC. */ #define XFS_ICSB_INO_CNTR_REENABLE 64 -#define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \ - (512 + XFS_ALLOC_SET_ASIDE(mp)) +#define XFS_ICSB_FDBLK_CNTR_REENABLE 512 STATIC void xfs_icsb_balance_counter( xfs_mount_t *mp, @@ -2039,7 +2055,7 @@ xfs_icsb_balance_counter( case XFS_SBS_FDBLOCKS: count = mp->m_sb.sb_fdblocks; resid = do_div(count, weight); - if (count < XFS_ICSB_FDBLK_CNTR_REENABLE(mp)) + if (count < XFS_ICSB_FDBLK_CNTR_REENABLE) goto out; break; default: @@ -2094,11 +2110,11 @@ xfs_icsb_modify_counters_int( case XFS_SBS_FDBLOCKS: BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0); - lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); + lcounter = icsbp->icsb_fdblocks; lcounter += delta; if (unlikely(lcounter < 0)) goto slow_path; - icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp); + icsbp->icsb_fdblocks = lcounter; break; default: BUG(); diff --git a/trunk/fs/xfs/xfs_vfsops.c b/trunk/fs/xfs/xfs_vfsops.c index a34796e57afb..6c96391f3f1a 100644 --- a/trunk/fs/xfs/xfs_vfsops.c +++ b/trunk/fs/xfs/xfs_vfsops.c @@ -515,7 +515,7 @@ xfs_mount( if (error) goto error2; - if (mp->m_flags & XFS_MOUNT_BARRIER) + if ((mp->m_flags & XFS_MOUNT_BARRIER) && !(vfsp->vfs_flag & VFS_RDONLY)) xfs_mountfs_check_barriers(mp); error = XFS_IOINIT(vfsp, args, flags); @@ -811,8 +811,7 @@ xfs_statvfs( statp->f_bsize = sbp->sb_blocksize; lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0; statp->f_blocks = sbp->sb_dblocks - lsize; - statp->f_bfree = statp->f_bavail = - sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); + statp->f_bfree = statp->f_bavail = sbp->sb_fdblocks; fakeinos = statp->f_bfree << sbp->sb_inopblog; #if XFS_BIG_INUMS fakeinos += mp->m_inoadd; diff --git a/trunk/include/Kbuild b/trunk/include/Kbuild index 2d03f995865f..cb2534800b19 100644 --- a/trunk/include/Kbuild +++ b/trunk/include/Kbuild @@ -1,9 +1,2 @@ -header-y += asm-generic/ -header-y += linux/ -header-y += scsi/ -header-y += sound/ -header-y += mtd/ -header-y += rdma/ -header-y += video/ - -header-y += asm-$(ARCH)/ +header-y += asm-generic/ linux/ scsi/ sound/ mtd/ rdma/ video/ +header-y += asm-$(ARCH)/ diff --git a/trunk/include/asm-alpha/Kbuild b/trunk/include/asm-alpha/Kbuild index b7c8f188b313..e57fd57538b8 100644 --- a/trunk/include/asm-alpha/Kbuild +++ b/trunk/include/asm-alpha/Kbuild @@ -1,11 +1,5 @@ include include/asm-generic/Kbuild.asm -header-y += gentrap.h -header-y += regdef.h -header-y += pal.h -header-y += reg.h +unifdef-y += console.h fpu.h sysinfo.h -unifdef-y += console.h -unifdef-y += fpu.h -unifdef-y += sysinfo.h -unifdef-y += compiler.h +header-y += gentrap.h regdef.h pal.h reg.h diff --git a/trunk/include/asm-alpha/compiler.h b/trunk/include/asm-alpha/compiler.h index d2768cc3d7a4..00c6f57ad9a7 100644 --- a/trunk/include/asm-alpha/compiler.h +++ b/trunk/include/asm-alpha/compiler.h @@ -90,7 +90,6 @@ __asm__("stw %1,%0" : "=m"(mem) : "r"(val)) #endif -#ifdef __KERNEL__ /* Some idiots over in thought inline should imply always_inline. This breaks stuff. We'll include this file whenever we run into such problems. */ @@ -102,6 +101,4 @@ #undef __always_inline #define __always_inline inline __attribute__((always_inline)) -#endif /* __KERNEL__ */ - #endif /* __ALPHA_COMPILER_H */ diff --git a/trunk/include/asm-alpha/page.h b/trunk/include/asm-alpha/page.h index d2bed3cb33ff..8c7cd50d4eae 100644 --- a/trunk/include/asm-alpha/page.h +++ b/trunk/include/asm-alpha/page.h @@ -1,8 +1,6 @@ #ifndef _ALPHA_PAGE_H #define _ALPHA_PAGE_H -#ifdef __KERNEL__ - #include /* PAGE_SHIFT determines the page size */ @@ -10,6 +8,8 @@ #define PAGE_SIZE (1UL << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) +#ifdef __KERNEL__ + #ifndef __ASSEMBLY__ #define STRICT_MM_TYPECHECKS @@ -92,9 +92,9 @@ typedef unsigned long pgprot_t; #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) +#endif /* __KERNEL__ */ #include #include -#endif /* __KERNEL__ */ #endif /* _ALPHA_PAGE_H */ diff --git a/trunk/include/asm-arm/arch-iop3xx/iop331-irqs.h b/trunk/include/asm-arm/arch-iop3xx/iop331-irqs.h index 7135ad7e335e..8ff73d487222 100644 --- a/trunk/include/asm-arm/arch-iop3xx/iop331-irqs.h +++ b/trunk/include/asm-arm/arch-iop3xx/iop331-irqs.h @@ -91,6 +91,7 @@ #define NR_IRQS NR_IOP331_IRQS +#if defined(CONFIG_ARCH_IQ80331) /* * Interrupts available on the IQ80331 board */ @@ -110,6 +111,7 @@ #define IRQ_IQ80331_INTC IRQ_IOP331_XINT2 #define IRQ_IQ80331_INTD IRQ_IOP331_XINT3 +#elif defined(CONFIG_MACH_IQ80332) /* * Interrupts available on the IQ80332 board */ @@ -129,4 +131,6 @@ #define IRQ_IQ80332_INTC IRQ_IOP331_XINT2 #define IRQ_IQ80332_INTD IRQ_IOP331_XINT3 +#endif + #endif // _IOP331_IRQ_H_ diff --git a/trunk/include/asm-arm/arch-omap/clock.h b/trunk/include/asm-arm/arch-omap/clock.h index f83003f5287b..3c4eb9fbe48a 100644 --- a/trunk/include/asm-arm/arch-omap/clock.h +++ b/trunk/include/asm-arm/arch-omap/clock.h @@ -48,6 +48,8 @@ struct clk_functions { }; extern unsigned int mpurate; +extern struct list_head clocks; +extern spinlock_t clockfw_lock; extern int clk_init(struct clk_functions * custom_clocks); extern int clk_register(struct clk *clk); diff --git a/trunk/include/asm-arm/arch-pxa/ssp.h b/trunk/include/asm-arm/arch-pxa/ssp.h index ea200551a75f..949878c0d908 100644 --- a/trunk/include/asm-arm/arch-pxa/ssp.h +++ b/trunk/include/asm-arm/arch-pxa/ssp.h @@ -40,8 +40,8 @@ struct ssp_dev { }; int ssp_write_word(struct ssp_dev *dev, u32 data); -int ssp_read_word(struct ssp_dev *dev, u32 *data); -int ssp_flush(struct ssp_dev *dev); +int ssp_read_word(struct ssp_dev *dev); +void ssp_flush(struct ssp_dev *dev); void ssp_enable(struct ssp_dev *dev); void ssp_disable(struct ssp_dev *dev); void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp); diff --git a/trunk/include/asm-arm/arch-s3c2410/anubis-cpld.h b/trunk/include/asm-arm/arch-s3c2410/anubis-cpld.h index 40e8e270d337..5675b1796b55 100644 --- a/trunk/include/asm-arm/arch-s3c2410/anubis-cpld.h +++ b/trunk/include/asm-arm/arch-s3c2410/anubis-cpld.h @@ -9,6 +9,9 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * */ #ifndef __ASM_ARCH_ANUBISCPLD_H diff --git a/trunk/include/asm-arm/arch-s3c2410/anubis-irq.h b/trunk/include/asm-arm/arch-s3c2410/anubis-irq.h index 4b5f423779df..82f15dbd97e8 100644 --- a/trunk/include/asm-arm/arch-s3c2410/anubis-irq.h +++ b/trunk/include/asm-arm/arch-s3c2410/anubis-irq.h @@ -9,7 +9,9 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. -*/ + * + * Changelog: + */ #ifndef __ASM_ARCH_ANUBISIRQ_H #define __ASM_ARCH_ANUBISIRQ_H diff --git a/trunk/include/asm-arm/arch-s3c2410/anubis-map.h b/trunk/include/asm-arm/arch-s3c2410/anubis-map.h index 058a2104b035..d529ffda8599 100644 --- a/trunk/include/asm-arm/arch-s3c2410/anubis-map.h +++ b/trunk/include/asm-arm/arch-s3c2410/anubis-map.h @@ -9,6 +9,8 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: */ /* needs arch/map.h including with this */ diff --git a/trunk/include/asm-arm/arch-s3c2410/audio.h b/trunk/include/asm-arm/arch-s3c2410/audio.h index 7e0222276c98..0d276e67f2fb 100644 --- a/trunk/include/asm-arm/arch-s3c2410/audio.h +++ b/trunk/include/asm-arm/arch-s3c2410/audio.h @@ -9,6 +9,10 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 20-Nov-2004 BJD Created file + * 07-Mar-2005 BJD Added suspend/resume calls */ #ifndef __ASM_ARCH_AUDIO_H diff --git a/trunk/include/asm-arm/arch-s3c2410/bast-cpld.h b/trunk/include/asm-arm/arch-s3c2410/bast-cpld.h index 8969cffe83fa..e28ca51a4975 100644 --- a/trunk/include/asm-arm/arch-s3c2410/bast-cpld.h +++ b/trunk/include/asm-arm/arch-s3c2410/bast-cpld.h @@ -8,6 +8,11 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 25-May-2003 BJD Created file, added CTRL1 registers + * 30-Aug-2004 BJD Updated definitions from 2.4.26 port + * 30-Aug-2004 BJD Added CTRL3 and CTRL4 definitions */ #ifndef __ASM_ARCH_BASTCPLD_H diff --git a/trunk/include/asm-arm/arch-s3c2410/bast-irq.h b/trunk/include/asm-arm/arch-s3c2410/bast-irq.h index 15ffa66f5011..b79b47f0d126 100644 --- a/trunk/include/asm-arm/arch-s3c2410/bast-irq.h +++ b/trunk/include/asm-arm/arch-s3c2410/bast-irq.h @@ -8,7 +8,11 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. -*/ + * + * Changelog: + * 14-Sep-2004 BJD Fixed IRQ_USBOC definition + * 06-Jan-2003 BJD Linux 2.6.0 version + */ #ifndef __ASM_ARCH_BASTIRQ_H #define __ASM_ARCH_BASTIRQ_H diff --git a/trunk/include/asm-arm/arch-s3c2410/bast-map.h b/trunk/include/asm-arm/arch-s3c2410/bast-map.h index 727cef84c70e..29c07e302b04 100644 --- a/trunk/include/asm-arm/arch-s3c2410/bast-map.h +++ b/trunk/include/asm-arm/arch-s3c2410/bast-map.h @@ -8,6 +8,10 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 06-Jan-2003 BJD Linux 2.6.0 version, moved bast specifics from arch/map.h + * 12-Mar-2004 BJD Fixed header include protection */ /* needs arch/map.h including with this */ diff --git a/trunk/include/asm-arm/arch-s3c2410/bast-pmu.h b/trunk/include/asm-arm/arch-s3c2410/bast-pmu.h index 82836027f00f..758c5c59d4bf 100644 --- a/trunk/include/asm-arm/arch-s3c2410/bast-pmu.h +++ b/trunk/include/asm-arm/arch-s3c2410/bast-pmu.h @@ -9,6 +9,9 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 08-Oct-2003 BJD Initial creation */ #ifndef __ASM_ARCH_BASTPMU_H diff --git a/trunk/include/asm-arm/arch-s3c2410/debug-macro.S b/trunk/include/asm-arm/arch-s3c2410/debug-macro.S index 93064860e0e5..b7d15d125458 100644 --- a/trunk/include/asm-arm/arch-s3c2410/debug-macro.S +++ b/trunk/include/asm-arm/arch-s3c2410/debug-macro.S @@ -10,6 +10,9 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Modifications: + * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA */ #include diff --git a/trunk/include/asm-arm/arch-s3c2410/dma.h b/trunk/include/asm-arm/arch-s3c2410/dma.h index 3661e465b0a5..72964f9b8414 100644 --- a/trunk/include/asm-arm/arch-s3c2410/dma.h +++ b/trunk/include/asm-arm/arch-s3c2410/dma.h @@ -1,13 +1,18 @@ -/* linux/include/asm-arm/arch-s3c2410/dma.h +/* linux/include/asm-arm/arch-bast/dma.h * - * Copyright (C) 2003,2004,2006 Simtec Electronics + * Copyright (C) 2003,2004 Simtec Electronics * Ben Dooks * - * Samsung S3C241XX DMA support + * Samsung S3C2410X DMA support * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * ??-May-2003 BJD Created file + * ??-Jun-2003 BJD Added more dma functionality to go with arch + * 10-Nov-2004 BJD Added sys_device support */ #ifndef __ASM_ARCH_DMA_H @@ -16,26 +21,28 @@ #include #include "hardware.h" + /* * This is the maximum DMA address(physical address) that can be DMAd to. * */ -#define MAX_DMA_ADDRESS 0x40000000 +#define MAX_DMA_ADDRESS 0x20000000 #define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */ + /* we have 4 dma channels */ #define S3C2410_DMA_CHANNELS (4) /* types */ -enum s3c2410_dma_state { +typedef enum { S3C2410_DMA_IDLE, S3C2410_DMA_RUNNING, S3C2410_DMA_PAUSED -}; +} s3c2410_dma_state_t; -/* enum s3c2410_dma_loadst +/* s3c2410_dma_loadst_t * * This represents the state of the DMA engine, wrt to the loaded / running * transfers. Since we don't have any way of knowing exactly the state of @@ -63,40 +70,44 @@ enum s3c2410_dma_state { * currently running. */ -enum s3c2410_dma_loadst { +typedef enum { S3C2410_DMALOAD_NONE, S3C2410_DMALOAD_1LOADED, S3C2410_DMALOAD_1RUNNING, S3C2410_DMALOAD_1LOADED_1RUNNING, -}; +} s3c2410_dma_loadst_t; -enum s3c2410_dma_buffresult { +typedef enum { S3C2410_RES_OK, S3C2410_RES_ERR, S3C2410_RES_ABORT -}; +} s3c2410_dma_buffresult_t; -enum s3c2410_dmasrc { - S3C2410_DMASRC_HW, /* source is memory */ - S3C2410_DMASRC_MEM /* source is hardware */ + +typedef enum s3c2410_dmasrc_e s3c2410_dmasrc_t; + +enum s3c2410_dmasrc_e { + S3C2410_DMASRC_HW, /* source is memory */ + S3C2410_DMASRC_MEM /* source is hardware */ }; -/* enum s3c2410_chan_op +/* enum s3c2410_chan_op_e * * operation codes passed to the DMA code by the user, and also used * to inform the current channel owner of any changes to the system state */ -enum s3c2410_chan_op { +enum s3c2410_chan_op_e { S3C2410_DMAOP_START, S3C2410_DMAOP_STOP, S3C2410_DMAOP_PAUSE, S3C2410_DMAOP_RESUME, S3C2410_DMAOP_FLUSH, - S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */ - S3C2410_DMAOP_STARTED, /* indicate channel started */ + S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */ }; +typedef enum s3c2410_chan_op_e s3c2410_chan_op_t; + /* flags */ #define S3C2410_DMAF_SLOW (1<<0) /* slow, so don't worry about @@ -105,100 +116,104 @@ enum s3c2410_chan_op { /* dma buffer */ +typedef struct s3c2410_dma_buf_s s3c2410_dma_buf_t; + struct s3c2410_dma_client { char *name; }; +typedef struct s3c2410_dma_client s3c2410_dma_client_t; + /* s3c2410_dma_buf_s * * internally used buffer structure to describe a queued or running * buffer. */ -struct s3c2410_dma_buf; -struct s3c2410_dma_buf { - struct s3c2410_dma_buf *next; - int magic; /* magic */ - int size; /* buffer size in bytes */ - dma_addr_t data; /* start of DMA data */ - dma_addr_t ptr; /* where the DMA got to [1] */ - void *id; /* client's id */ +struct s3c2410_dma_buf_s { + s3c2410_dma_buf_t *next; + int magic; /* magic */ + int size; /* buffer size in bytes */ + dma_addr_t data; /* start of DMA data */ + dma_addr_t ptr; /* where the DMA got to [1] */ + void *id; /* client's id */ }; /* [1] is this updated for both recv/send modes? */ -struct s3c2410_dma_chan; +typedef struct s3c2410_dma_chan_s s3c2410_dma_chan_t; /* s3c2410_dma_cbfn_t * * buffer callback routine type */ -typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *, - void *buf, int size, - enum s3c2410_dma_buffresult result); +typedef void (*s3c2410_dma_cbfn_t)(s3c2410_dma_chan_t *, void *buf, int size, + s3c2410_dma_buffresult_t result); -typedef int (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *, - enum s3c2410_chan_op ); +typedef int (*s3c2410_dma_opfn_t)(s3c2410_dma_chan_t *, + s3c2410_chan_op_t ); -struct s3c2410_dma_stats { - unsigned long loads; - unsigned long timeout_longest; - unsigned long timeout_shortest; - unsigned long timeout_avg; - unsigned long timeout_failed; +struct s3c2410_dma_stats_s { + unsigned long loads; + unsigned long timeout_longest; + unsigned long timeout_shortest; + unsigned long timeout_avg; + unsigned long timeout_failed; }; -/* struct s3c2410_dma_chan +typedef struct s3c2410_dma_stats_s s3c2410_dma_stats_t; + +/* struct s3c2410_dma_chan_s * * full state information for each DMA channel */ -struct s3c2410_dma_chan { +struct s3c2410_dma_chan_s { /* channel state flags and information */ - unsigned char number; /* number of this dma channel */ - unsigned char in_use; /* channel allocated */ - unsigned char irq_claimed; /* irq claimed for channel */ - unsigned char irq_enabled; /* irq enabled for channel */ - unsigned char xfer_unit; /* size of an transfer */ + unsigned char number; /* number of this dma channel */ + unsigned char in_use; /* channel allocated */ + unsigned char irq_claimed; /* irq claimed for channel */ + unsigned char irq_enabled; /* irq enabled for channel */ + unsigned char xfer_unit; /* size of an transfer */ /* channel state */ - enum s3c2410_dma_state state; - enum s3c2410_dma_loadst load_state; - struct s3c2410_dma_client *client; + s3c2410_dma_state_t state; + s3c2410_dma_loadst_t load_state; + s3c2410_dma_client_t *client; /* channel configuration */ - enum s3c2410_dmasrc source; - unsigned long dev_addr; - unsigned long load_timeout; - unsigned int flags; /* channel flags */ + s3c2410_dmasrc_t source; + unsigned long dev_addr; + unsigned long load_timeout; + unsigned int flags; /* channel flags */ /* channel's hardware position and configuration */ - void __iomem *regs; /* channels registers */ - void __iomem *addr_reg; /* data address register */ - unsigned int irq; /* channel irq */ - unsigned long dcon; /* default value of DCON */ + void __iomem *regs; /* channels registers */ + void __iomem *addr_reg; /* data address register */ + unsigned int irq; /* channel irq */ + unsigned long dcon; /* default value of DCON */ /* driver handles */ - s3c2410_dma_cbfn_t callback_fn; /* buffer done callback */ - s3c2410_dma_opfn_t op_fn; /* channel op callback */ + s3c2410_dma_cbfn_t callback_fn; /* buffer done callback */ + s3c2410_dma_opfn_t op_fn; /* channel operation callback */ /* stats gathering */ - struct s3c2410_dma_stats *stats; - struct s3c2410_dma_stats stats_store; + s3c2410_dma_stats_t *stats; + s3c2410_dma_stats_t stats_store; /* buffer list and information */ - struct s3c2410_dma_buf *curr; /* current dma buffer */ - struct s3c2410_dma_buf *next; /* next buffer to load */ - struct s3c2410_dma_buf *end; /* end of queue */ + s3c2410_dma_buf_t *curr; /* current dma buffer */ + s3c2410_dma_buf_t *next; /* next buffer to load */ + s3c2410_dma_buf_t *end; /* end of queue */ /* system device */ struct sys_device dev; }; /* the currently allocated channel information */ -extern struct s3c2410_dma_chan s3c2410_chans[]; +extern s3c2410_dma_chan_t s3c2410_chans[]; /* note, we don't really use dma_device_t at the moment */ typedef unsigned long dma_device_t; @@ -211,7 +226,7 @@ typedef unsigned long dma_device_t; */ extern int s3c2410_dma_request(dmach_t channel, - struct s3c2410_dma_client *, void *dev); + s3c2410_dma_client_t *, void *dev); /* s3c2410_dma_ctrl @@ -219,7 +234,7 @@ extern int s3c2410_dma_request(dmach_t channel, * change the state of the dma channel */ -extern int s3c2410_dma_ctrl(dmach_t channel, enum s3c2410_chan_op op); +extern int s3c2410_dma_ctrl(dmach_t channel, s3c2410_chan_op_t op); /* s3c2410_dma_setflags * @@ -234,7 +249,7 @@ extern int s3c2410_dma_setflags(dmach_t channel, * free the dma channel (will also abort any outstanding operations) */ -extern int s3c2410_dma_free(dmach_t channel, struct s3c2410_dma_client *); +extern int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *); /* s3c2410_dma_enqueue * @@ -258,7 +273,7 @@ extern int s3c2410_dma_config(dmach_t channel, int xferunit, int dcon); * configure the device we're talking to */ -extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source, +extern int s3c2410_dma_devconfig(int channel, s3c2410_dmasrc_t source, int hwcfg, unsigned long devaddr); /* s3c2410_dma_getposition diff --git a/trunk/include/asm-arm/arch-s3c2410/fb.h b/trunk/include/asm-arm/arch-s3c2410/fb.h index 71161797bc89..4790491ba9d0 100644 --- a/trunk/include/asm-arm/arch-s3c2410/fb.h +++ b/trunk/include/asm-arm/arch-s3c2410/fb.h @@ -7,6 +7,13 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * + * Changelog: + * 07-Sep-2004 RTP Created file + * 03-Nov-2004 BJD Updated and minor cleanups + * 03-Aug-2005 RTP Renamed to fb.h + * 26-Oct-2005 BJD Changed name of platdata init */ #ifndef __ASM_ARM_FB_H diff --git a/trunk/include/asm-arm/arch-s3c2410/hardware.h b/trunk/include/asm-arm/arch-s3c2410/hardware.h index 871f8af09b8b..a2330bf83695 100644 --- a/trunk/include/asm-arm/arch-s3c2410/hardware.h +++ b/trunk/include/asm-arm/arch-s3c2410/hardware.h @@ -8,6 +8,16 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 21-May-2003 BJD Created file + * 06-Jun-2003 BJD Added CPU frequency settings + * 03-Sep-2003 BJD Linux v2.6 support + * 12-Mar-2004 BJD Fixed include protection, fixed type of clock vars + * 14-Sep-2004 BJD Added misccr and getpin to gpio + * 01-Oct-2004 BJD Added the new gpio functions + * 16-Oct-2004 BJD Removed the clock variables + * 15-Jan-2006 LCVR Added s3c2400_gpio_getirq() */ #ifndef __ASM_ARCH_HARDWARE_H diff --git a/trunk/include/asm-arm/arch-s3c2410/idle.h b/trunk/include/asm-arm/arch-s3c2410/idle.h index eed450608f9c..749227c09576 100644 --- a/trunk/include/asm-arm/arch-s3c2410/idle.h +++ b/trunk/include/asm-arm/arch-s3c2410/idle.h @@ -8,6 +8,10 @@ * published by the Free Software Foundation. * * S3C2410 CPU Idle controls + * + * Changelog: + * 28-Oct-2004 BJD Initial version + * */ #ifndef __ASM_ARCH_IDLE_H diff --git a/trunk/include/asm-arm/arch-s3c2410/iic.h b/trunk/include/asm-arm/arch-s3c2410/iic.h index ed3d6c7bf6d7..518547f6d7a7 100644 --- a/trunk/include/asm-arm/arch-s3c2410/iic.h +++ b/trunk/include/asm-arm/arch-s3c2410/iic.h @@ -8,6 +8,10 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 05-Oct-2004 BJD Created file + * 19-Oct-2004 BJD Updated for s3c2440 */ #ifndef __ASM_ARCH_IIC_H diff --git a/trunk/include/asm-arm/arch-s3c2410/io.h b/trunk/include/asm-arm/arch-s3c2410/io.h index 6b35a4f2630e..16fbc8afffd9 100644 --- a/trunk/include/asm-arm/arch-s3c2410/io.h +++ b/trunk/include/asm-arm/arch-s3c2410/io.h @@ -4,7 +4,13 @@ * * Copyright (C) 1997 Russell King * (C) 2003 Simtec Electronics -*/ + * + * Modifications: + * 06-Dec-1997 RMK Created. + * 02-Sep-2003 BJD Modified for S3C2410 + * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA + * 13-Oct-2005 BJD Fixed problems with LDRH/STRH offset range + */ #ifndef __ASM_ARM_ARCH_IO_H #define __ASM_ARM_ARCH_IO_H diff --git a/trunk/include/asm-arm/arch-s3c2410/irqs.h b/trunk/include/asm-arm/arch-s3c2410/irqs.h index 39a69829d163..d9773d697268 100644 --- a/trunk/include/asm-arm/arch-s3c2410/irqs.h +++ b/trunk/include/asm-arm/arch-s3c2410/irqs.h @@ -6,7 +6,14 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. -*/ + * + * Changelog: + * 12-May-2003 BJD Created file + * 08-Jan-2003 BJD Linux 2.6.0 version, moved BAST bits out + * 12-Mar-2004 BJD Fixed bug in header protection + * 10-Feb-2005 BJD Added camera IRQ from guillaume.gourat@nexvision.tv + * 28-Feb-2005 BJD Updated s3c2440 IRQs + */ #ifndef __ASM_ARCH_IRQS_H diff --git a/trunk/include/asm-arm/arch-s3c2410/map.h b/trunk/include/asm-arm/arch-s3c2410/map.h index 27ba0ac3fdd5..fae2766ff32b 100644 --- a/trunk/include/asm-arm/arch-s3c2410/map.h +++ b/trunk/include/asm-arm/arch-s3c2410/map.h @@ -8,6 +8,13 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 12-May-2003 BJD Created file + * 06-Jan-2003 BJD Linux 2.6.0 version, moved bast specifics out + * 10-Feb-2005 BJD Added CAMIF definition from guillaume.gourat@nexvision.tv + * 10-Mar-2005 LCVR Added support to S3C2400, changed {VA,SZ} names + * 15-Jan-2006 LCVR Added S3C24XX_PA macros for common S3C24XX resources */ #ifndef __ASM_ARCH_MAP_H diff --git a/trunk/include/asm-arm/arch-s3c2410/memory.h b/trunk/include/asm-arm/arch-s3c2410/memory.h index 4be6a74c4303..6ab834a14c8e 100644 --- a/trunk/include/asm-arm/arch-s3c2410/memory.h +++ b/trunk/include/asm-arm/arch-s3c2410/memory.h @@ -1,4 +1,6 @@ -/* linux/include/asm-arm/arch-s3c2410/memory.h +/* + * linux/include/asm-arm/arch-s3c2410/memory.h + * * from linux/include/asm-arm/arch-rpc/memory.h * * Copyright (C) 1996,1997,1998 Russell King. @@ -6,6 +8,16 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 20-Oct-1996 RMK Created + * 31-Dec-1997 RMK Fixed definitions to reduce warnings + * 11-Jan-1998 RMK Uninlined to reduce hits on cache + * 08-Feb-1998 RMK Added __virt_to_bus and __bus_to_virt + * 21-Mar-1999 RMK Renamed to memory.h + * RMK Added TASK_SIZE and PAGE_OFFSET + * 05-Apr-2004 BJD Copied and altered for arch-s3c2410 + * 17-Mar-2005 LCVR Modified for S3C2400 */ #ifndef __ASM_ARCH_MEMORY_H diff --git a/trunk/include/asm-arm/arch-s3c2410/nand.h b/trunk/include/asm-arm/arch-s3c2410/nand.h index e350ae2acfc6..9148ac045b0d 100644 --- a/trunk/include/asm-arm/arch-s3c2410/nand.h +++ b/trunk/include/asm-arm/arch-s3c2410/nand.h @@ -8,6 +8,9 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 23-Sep-2004 BJD Created file */ /* struct s3c2410_nand_set diff --git a/trunk/include/asm-arm/arch-s3c2410/osiris-map.h b/trunk/include/asm-arm/arch-s3c2410/osiris-map.h index e2d406218ae5..7c4b0cd2d14d 100644 --- a/trunk/include/asm-arm/arch-s3c2410/osiris-map.h +++ b/trunk/include/asm-arm/arch-s3c2410/osiris-map.h @@ -9,6 +9,8 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: */ /* needs arch/map.h including with this */ diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-adc.h b/trunk/include/asm-arm/arch-s3c2410/regs-adc.h index c7b90b3ecc9e..15bfc2f5754e 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-adc.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-adc.h @@ -7,6 +7,9 @@ * published by the Free Software Foundation. * * S3C2410 ADC registers + * + * Changelog: + * 27-09-2004 SAH Created file */ #ifndef __ASM_ARCH_REGS_ADC_H diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-clock.h b/trunk/include/asm-arm/arch-s3c2410/regs-clock.h index b2f4690c0791..a7c61feb8433 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-clock.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-clock.h @@ -8,6 +8,18 @@ * published by the Free Software Foundation. * * S3C2410 clock register definitions + * + * Changelog: + * 18-Aug-2004 Ben Dooks Added 2440 definitions + * 08-Aug-2004 Herbert Pötzl Added CLKCON definitions + * 19-06-2003 Ben Dooks Created file + * 12-03-2004 Ben Dooks Updated include protection + * 29-Sep-2004 Ben Dooks Fixed usage for assembly inclusion + * 10-Feb-2005 Ben Dooks Fixed CAMDIVN address (Guillaume Gourat) + * 10-Mar-2005 Lucas Villa Real Changed S3C2410_VA to S3C24XX_VA + * 27-Aug-2005 Ben Dooks Add clock-slow info + * 20-Oct-2005 Ben Dooks Fixed overflow in PLL (Guillaume Gourat) + * 20-Oct-2005 Ben Dooks Add masks for DCLK (Guillaume Gourat) */ #ifndef __ASM_ARM_REGS_CLOCK diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-gpio.h b/trunk/include/asm-arm/arch-s3c2410/regs-gpio.h index 93c49432db95..6dd17f0f84e0 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-gpio.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-gpio.h @@ -8,6 +8,21 @@ * published by the Free Software Foundation. * * S3C2410 GPIO register definitions + * + * Changelog: + * 19-06-2003 BJD Created file + * 23-06-2003 BJD Updated GSTATUS registers + * 12-03-2004 BJD Updated include protection + * 20-07-2004 BJD Added GPIO pin numbers, added Port A definitions + * 04-10-2004 BJD Fixed number of bugs, added EXT IRQ filter defs + * 17-10-2004 BJD Added GSTATUS1 register definitions + * 18-11-2004 BJD Fixed definitions of GPE3, GPE4, GPE5 and GPE6 + * 18-11-2004 BJD Added S3C2440 AC97 controls + * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA + * 28-Mar-2005 LCVR Fixed definition of GPB10 + * 26-Oct-2005 BJD Added generic configuration types + * 27-Nov-2005 LCVR Added definitions to S3C2400 registers + * 15-Jan-2006 LCVR Written S3C24XX_GPIO_BASE() macro */ diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-gpioj.h b/trunk/include/asm-arm/arch-s3c2410/regs-gpioj.h index 91cefa260497..18edae50d0b8 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-gpioj.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-gpioj.h @@ -8,6 +8,10 @@ * published by the Free Software Foundation. * * S3C2440 GPIO J register definitions + * + * Changelog: + * 11-Aug-2004 BJD Created file + * 10-Feb-2005 BJD Fix GPJ12 definition (Guillaume Gourat) */ diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-iic.h b/trunk/include/asm-arm/arch-s3c2410/regs-iic.h index 2ae29522f253..fed3288e2046 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-iic.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-iic.h @@ -8,6 +8,10 @@ * published by the Free Software Foundation. * * S3C2410 I2C Controller + * + * Changelog: + * 03-Oct-2004 BJD Initial include for Linux + * 08-Nov-2004 BJD Added S3C2440 filter register */ #ifndef __ASM_ARCH_REGS_IIC_H diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-iis.h b/trunk/include/asm-arm/arch-s3c2410/regs-iis.h index 72cd2509822e..7fdde9b91cb4 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-iis.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-iis.h @@ -8,7 +8,17 @@ * published by the Free Software Foundation. * * S3C2410 IIS register definition -*/ + * + * Changelog: + * 19-06-2003 BJD Created file + * 26-06-2003 BJD Finished off definitions for register addresses + * 12-03-2004 BJD Updated include protection + * 07-03-2005 BJD Added FIFO size flags and S3C2440 MPLL + * 05-04-2005 LCVR Added IISFCON definitions for the S3C2400 + * 18-07-2005 DA Change IISCON_MPLL to IISMOD_MPLL + * Correct IISMOD_256FS and IISMOD_384FS + * Add IISCON_PSCEN + */ #ifndef __ASM_ARCH_REGS_IIS_H #define __ASM_ARCH_REGS_IIS_H diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-irq.h b/trunk/include/asm-arm/arch-s3c2410/regs-irq.h index 29fb8ef670f0..572fca5d9acf 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-irq.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-irq.h @@ -6,7 +6,14 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. -*/ + * + * + * + * Changelog: + * 19-06-2003 BJD Created file + * 12-03-2004 BJD Updated include protection + * 10-03-2005 LCVR Changed S3C2410_VA to S3C24XX_VA + */ #ifndef ___ASM_ARCH_REGS_IRQ_H diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-lcd.h b/trunk/include/asm-arm/arch-s3c2410/regs-lcd.h index b306d6e3135d..b6b1b4e8bbeb 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-lcd.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-lcd.h @@ -6,6 +6,14 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * + * + * Changelog: + * 12-06-2003 BJD Created file + * 26-06-2003 BJD Updated LCDCON register definitions + * 12-03-2004 BJD Updated include protection + * 10-03-2005 LCVR Changed S3C2410_VA to S3C24XX_VA */ diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-mem.h b/trunk/include/asm-arm/arch-s3c2410/regs-mem.h index 375dca50364e..a2d7d0cec042 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-mem.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-mem.h @@ -8,6 +8,12 @@ * published by the Free Software Foundation. * * S3C2410 Memory Control register definitions + * + * Changelog: + * 29-Sep-2004 BJD Initial include for Linux + * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA + * 04-Apr-2005 LCVR Added S3C2400 DRAM/BANKSIZE_MASK definitions + * */ #ifndef __ASM_ARM_MEMREGS_H diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-nand.h b/trunk/include/asm-arm/arch-s3c2410/regs-nand.h index b824d371ae0b..c1470c695c33 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-nand.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-nand.h @@ -8,6 +8,10 @@ * published by the Free Software Foundation. * * S3C2410 NAND register definitions + * + * Changelog: + * 18-Aug-2004 BJD Copied file from 2.4 and updated + * 01-May-2005 BJD Added definitions for s3c2440 controller */ #ifndef __ASM_ARM_REGS_NAND diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-power.h b/trunk/include/asm-arm/arch-s3c2410/regs-power.h deleted file mode 100644 index 6c319ea2afac..000000000000 --- a/trunk/include/asm-arm/arch-s3c2410/regs-power.h +++ /dev/null @@ -1,34 +0,0 @@ -/* linux/include/asm/arch-s3c2410/regs-power.h - * - * Copyright (c) 2003,2004,2005,2006 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * S3C24XX power control register definitions -*/ - -#ifndef __ASM_ARM_REGS_PWR -#define __ASM_ARM_REGS_PWR __FILE__ - -#define S3C24XX_PWRREG(x) ((x) + S3C24XX_VA_CLKPWR) - -#define S3C2412_PWRMODECON S3C24XX_PWRREG(0x20) -#define S3C2412_PWRCFG S3C24XX_PWRREG(0x24) - -#define S3C2412_PWRCFG_BATF_IGNORE (0<<0) -#define S3C2412_PWRCFG_BATF_SLEEP (3<<0) -#define S3C2412_PWRCFG_BATF_MASK (3<<0) - -#define S3C2412_PWRCFG_STANDBYWFI_IGNORE (0<<6) -#define S3C2412_PWRCFG_STANDBYWFI_IDLE (1<<6) -#define S3C2412_PWRCFG_STANDBYWFI_STOP (2<<6) -#define S3C2412_PWRCFG_STANDBYWFI_SLEEP (3<<6) -#define S3C2412_PWRCFG_STANDBYWFI_MASK (3<<6) - -#define S3C2412_PWRCFG_RTC_MASKIRQ (1<<8) -#define S3C2412_PWRCFG_NAND_NORST (1<<9) - -#endif /* __ASM_ARM_REGS_PWR */ diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-rtc.h b/trunk/include/asm-arm/arch-s3c2410/regs-rtc.h index cd88fd634d12..228983f89bc8 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-rtc.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-rtc.h @@ -8,12 +8,17 @@ * published by the Free Software Foundation. * * S3C2410 Internal RTC register definition + * + * Changelog: + * 19-06-2003 BJD Created file + * 12-03-2004 BJD Updated include protection + * 15-01-2005 LCVR Changed S3C2410_VA to S3C24XX_VA (s3c2400 support) */ #ifndef __ASM_ARCH_REGS_RTC_H #define __ASM_ARCH_REGS_RTC_H __FILE__ -#define S3C2410_RTCREG(x) (x) +#define S3C2410_RTCREG(x) ((x) + S3C24XX_VA_RTC) #define S3C2410_RTCCON S3C2410_RTCREG(0x40) #define S3C2410_RTCCON_RTCEN (1<<0) diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-sdi.h b/trunk/include/asm-arm/arch-s3c2410/regs-sdi.h index 06e716e5b46d..ca9a26fbecec 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-sdi.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-sdi.h @@ -8,6 +8,11 @@ * published by the Free Software Foundation. * * S3C2410 MMC/SDIO register definitions + * + * Changelog: + * 18-Aug-2004 Ben Dooks Created initial file + * 29-Nov-2004 Koen Martens Added some missing defines, fixed duplicates + * 29-Nov-2004 Ben Dooks Updated Koen's patch */ #ifndef __ASM_ARM_REGS_SDI diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-serial.h b/trunk/include/asm-arm/arch-s3c2410/regs-serial.h index 19c77da9c3fe..93f651ae2967 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-serial.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-serial.h @@ -27,7 +27,10 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ + * + * Modifications: + * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA (s3c2400 support) + */ #ifndef __ASM_ARM_REGS_SERIAL_H #define __ASM_ARM_REGS_SERIAL_H diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-spi.h b/trunk/include/asm-arm/arch-s3c2410/regs-spi.h index 3552280d1e8f..338217858c73 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-spi.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-spi.h @@ -7,7 +7,13 @@ * published by the Free Software Foundation. * * S3C2410 SPI register definition -*/ + * + * Changelog: + * 20-04-2004 KF Created file + * 04-10-2004 BJD Removed VA address (no longer mapped) + * tidied file for submission + * 03-04-2005 LCVR Added S3C2400_SPPIN_nCS definition + */ #ifndef __ASM_ARCH_REGS_SPI_H #define __ASM_ARCH_REGS_SPI_H diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-timer.h b/trunk/include/asm-arm/arch-s3c2410/regs-timer.h index 731918e77831..169064e27520 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-timer.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-timer.h @@ -8,6 +8,13 @@ * published by the Free Software Foundation. * * S3C2410 Timer configuration + * + * Changelog: + * 05-06-2003 BJD Created file + * 26-06-2003 BJD Added more timer definitions to mux / control + * 12-03-2004 BJD Updated include protection + * 10-02-2005 BJD Added S3C2410_TCFG1_MUX4_SHIFT (Guillaume Gourat) + * 10-03-2005 LCVR Changed S3C2410_VA to S3C24XX_VA */ diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-udc.h b/trunk/include/asm-arm/arch-s3c2410/regs-udc.h index 3aa31a27da1a..bf315b763252 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-udc.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-udc.h @@ -6,7 +6,13 @@ * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. -*/ + * + * Changelog: + * 01-08-2004 Initial creation + * 12-09-2004 Cleanup for submission + * 24-10-2004 Fixed S3C2410_UDC_MAXP_REG definition + * 10-03-2005 Changed S3C2410_VA to S3C24XX_VA + */ #ifndef __ASM_ARCH_REGS_UDC_H #define __ASM_ARCH_REGS_UDC_H diff --git a/trunk/include/asm-arm/arch-s3c2410/regs-watchdog.h b/trunk/include/asm-arm/arch-s3c2410/regs-watchdog.h index f4fff448c7bd..d199ca6aff22 100644 --- a/trunk/include/asm-arm/arch-s3c2410/regs-watchdog.h +++ b/trunk/include/asm-arm/arch-s3c2410/regs-watchdog.h @@ -1,4 +1,4 @@ -/* linux/include/asm/arch-s3c2410/regs-watchdog.h +/* linux/include/asm/arch-s3c2410/regs0watchdog.h * * Copyright (c) 2003 Simtec Electronics * http://www.simtec.co.uk/products/SWLINUX/ @@ -8,6 +8,11 @@ * published by the Free Software Foundation. * * S3C2410 Watchdog timer control + * + * Changelog: + * 21-06-2003 BJD Created file + * 12-03-2004 BJD Updated include protection + * 10-03-2005 LCVR Changed S3C2410_VA to S3C24XX_VA */ diff --git a/trunk/include/asm-arm/arch-s3c2410/system.h b/trunk/include/asm-arm/arch-s3c2410/system.h index 718246d85952..9b0d85024cb4 100644 --- a/trunk/include/asm-arm/arch-s3c2410/system.h +++ b/trunk/include/asm-arm/arch-s3c2410/system.h @@ -8,7 +8,14 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. -*/ + * + * Changelog: + * 12-May-2003 BJD Created file + * 14-May-2003 BJD Removed idle to aid debugging + * 12-Jun-2003 BJD Added reset via watchdog + * 04-Sep-2003 BJD Moved to v2.6 + * 28-Oct-2004 BJD Added over-ride for idle, and fixed reset panic() + */ #include #include diff --git a/trunk/include/asm-arm/arch-s3c2410/timex.h b/trunk/include/asm-arm/arch-s3c2410/timex.h index 703c337c5617..3558a3a750bf 100644 --- a/trunk/include/asm-arm/arch-s3c2410/timex.h +++ b/trunk/include/asm-arm/arch-s3c2410/timex.h @@ -8,6 +8,12 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 02-Sep-2003 BJD Created file + * 05-Jan-2004 BJD Updated for Linux 2.6.0 + * 22-Nov-2004 BJD Fixed CLOCK_TICK_RATE + * 10-Jan-2004 BJD Removed s3c2410_clock_tick_rate */ #ifndef __ASM_ARCH_TIMEX_H diff --git a/trunk/include/asm-arm/arch-s3c2410/uncompress.h b/trunk/include/asm-arm/arch-s3c2410/uncompress.h index 81b3e91c56ab..8e152a05e533 100644 --- a/trunk/include/asm-arm/arch-s3c2410/uncompress.h +++ b/trunk/include/asm-arm/arch-s3c2410/uncompress.h @@ -8,6 +8,15 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 22-May-2003 BJD Created + * 08-Sep-2003 BJD Moved to linux v2.6 + * 12-Mar-2004 BJD Updated header protection + * 12-Oct-2004 BJD Take account of debug uart configuration + * 15-Nov-2004 BJD Fixed uart configuration + * 22-Feb-2005 BJD Added watchdog to uncompress + * 04-Apr-2005 LCVR Added support to S3C2400 (no cpuid at GSTATUS1) */ #ifndef __ASM_ARCH_UNCOMPRESS_H diff --git a/trunk/include/asm-arm/arch-s3c2410/usb-control.h b/trunk/include/asm-arm/arch-s3c2410/usb-control.h index 35723569a17a..bd43b566db3e 100644 --- a/trunk/include/asm-arm/arch-s3c2410/usb-control.h +++ b/trunk/include/asm-arm/arch-s3c2410/usb-control.h @@ -8,6 +8,11 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 11-Sep-2004 BJD Created file + * 21-Sep-2004 BJD Updated port info + * 09-Aug-2005 BJD Renamed s3c2410_report_oc s3c2410_usb_report_oc */ #ifndef __ASM_ARCH_USBCONTROL_H diff --git a/trunk/include/asm-arm/arch-s3c2410/vmalloc.h b/trunk/include/asm-arm/arch-s3c2410/vmalloc.h index 0ae3bdb7e03b..33963cd5461b 100644 --- a/trunk/include/asm-arm/arch-s3c2410/vmalloc.h +++ b/trunk/include/asm-arm/arch-s3c2410/vmalloc.h @@ -10,7 +10,11 @@ * published by the Free Software Foundation. * * S3C2410 vmalloc definition -*/ + * + * Changelog: + * 12-Mar-2004 BJD Fixed header, added include protection + * 12=Mar-2004 BJD Fixed VMALLOC_END definitions + */ #ifndef __ASM_ARCH_VMALLOC_H #define __ASM_ARCH_VMALLOC_H diff --git a/trunk/include/asm-arm/arch-s3c2410/vr1000-cpld.h b/trunk/include/asm-arm/arch-s3c2410/vr1000-cpld.h index a341b1e1bd98..0ee373ac60d4 100644 --- a/trunk/include/asm-arm/arch-s3c2410/vr1000-cpld.h +++ b/trunk/include/asm-arm/arch-s3c2410/vr1000-cpld.h @@ -8,6 +8,10 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 25-May-2003 BJD Created file, added CTRL1 registers + * 19-Mar-2004 BJD Added VR1000 CPLD definitions */ #ifndef __ASM_ARCH_VR1000CPLD_H diff --git a/trunk/include/asm-arm/arch-s3c2410/vr1000-irq.h b/trunk/include/asm-arm/arch-s3c2410/vr1000-irq.h index c39a0ffa670d..694f7715d2da 100644 --- a/trunk/include/asm-arm/arch-s3c2410/vr1000-irq.h +++ b/trunk/include/asm-arm/arch-s3c2410/vr1000-irq.h @@ -8,7 +8,11 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. -*/ + * + * Changelog: + * 06-Jan-2003 BJD Linux 2.6.0 version + * 19-Mar-2004 BJD Updates for VR1000 + */ #ifndef __ASM_ARCH_VR1000IRQ_H #define __ASM_ARCH_VR1000IRQ_H diff --git a/trunk/include/asm-arm/arch-s3c2410/vr1000-map.h b/trunk/include/asm-arm/arch-s3c2410/vr1000-map.h index 1fe4db36c834..867c9355fd39 100644 --- a/trunk/include/asm-arm/arch-s3c2410/vr1000-map.h +++ b/trunk/include/asm-arm/arch-s3c2410/vr1000-map.h @@ -8,6 +8,12 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * Changelog: + * 06-Jan-2003 BJD Linux 2.6.0 version, split specifics from arch/map.h + * 12-Mar-2004 BJD Fixed header include protection + * 19-Mar-2004 BJD Copied to VR1000 machine headers. + * 19-Jan-2005 BJD Updated map definitions */ /* needs arch/map.h including with this */ diff --git a/trunk/include/asm-arm/cacheflush.h b/trunk/include/asm-arm/cacheflush.h index e4a2569c636c..fe0c744e0266 100644 --- a/trunk/include/asm-arm/cacheflush.h +++ b/trunk/include/asm-arm/cacheflush.h @@ -247,12 +247,14 @@ extern void dmac_flush_range(unsigned long, unsigned long); */ #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ do { \ + flush_cache_page(vma, vaddr, page_to_pfn(page));\ memcpy(dst, src, len); \ - flush_ptrace_access(vma, page, vaddr, dst, len, 1);\ + flush_dcache_page(page); \ } while (0) #define copy_from_user_page(vma, page, vaddr, dst, src, len) \ do { \ + flush_cache_page(vma, vaddr, page_to_pfn(page));\ memcpy(dst, src, len); \ } while (0) @@ -283,24 +285,10 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned l __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); } } - -static inline void -flush_ptrace_access(struct vm_area_struct *vma, struct page *page, - unsigned long uaddr, void *kaddr, - unsigned long len, int write) -{ - if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) { - unsigned long addr = (unsigned long)kaddr; - __cpuc_coherent_kern_range(addr, addr + len); - } -} #else extern void flush_cache_mm(struct mm_struct *mm); extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn); -extern void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, - unsigned long uaddr, void *kaddr, - unsigned long len, int write); #endif /* diff --git a/trunk/include/asm-arm/elf.h b/trunk/include/asm-arm/elf.h index ae7baa6c73f7..71061ca5c5d0 100644 --- a/trunk/include/asm-arm/elf.h +++ b/trunk/include/asm-arm/elf.h @@ -8,9 +8,7 @@ #include #include -#ifdef __KERNEL #include -#endif typedef unsigned long elf_greg_t; typedef unsigned long elf_freg_t[3]; diff --git a/trunk/include/asm-arm/hardware/ssp.h b/trunk/include/asm-arm/hardware/ssp.h index 3b42e181997c..28aa11b769cd 100644 --- a/trunk/include/asm-arm/hardware/ssp.h +++ b/trunk/include/asm-arm/hardware/ssp.h @@ -16,8 +16,8 @@ struct ssp_state { }; int ssp_write_word(u16 data); -int ssp_read_word(u16 *data); -int ssp_flush(void); +int ssp_read_word(void); +void ssp_flush(void); void ssp_enable(void); void ssp_disable(void); void ssp_save_state(struct ssp_state *ssp); diff --git a/trunk/include/asm-arm/io.h b/trunk/include/asm-arm/io.h index bf7b9dea30f1..b3479fc1cc8f 100644 --- a/trunk/include/asm-arm/io.h +++ b/trunk/include/asm-arm/io.h @@ -291,12 +291,5 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr); */ #define xlate_dev_kmem_ptr(p) p -/* - * Register ISA memory and port locations for glibc iopl/inb/outb - * emulation. - */ -extern void register_isa_ports(unsigned int mmio, unsigned int io, - unsigned int io_shift); - #endif /* __KERNEL__ */ #endif /* __ASM_ARM_IO_H */ diff --git a/trunk/include/asm-arm/page.h b/trunk/include/asm-arm/page.h index b721270b9986..63d12f0244c5 100644 --- a/trunk/include/asm-arm/page.h +++ b/trunk/include/asm-arm/page.h @@ -193,8 +193,8 @@ extern pmd_t *top_pmd; #define ARCH_SLAB_MINALIGN 8 #endif -#include - #endif /* __KERNEL__ */ +#include + #endif diff --git a/trunk/include/asm-arm/procinfo.h b/trunk/include/asm-arm/procinfo.h index 91a31adfa8a8..edb7b6502fcf 100644 --- a/trunk/include/asm-arm/procinfo.h +++ b/trunk/include/asm-arm/procinfo.h @@ -55,6 +55,5 @@ extern unsigned int elf_hwcap; #define HWCAP_VFP 64 #define HWCAP_EDSP 128 #define HWCAP_JAVA 256 -#define HWCAP_IWMMXT 512 #endif diff --git a/trunk/include/asm-arm/spinlock.h b/trunk/include/asm-arm/spinlock.h index 01b7c26a3038..406ca97a8ab2 100644 --- a/trunk/include/asm-arm/spinlock.h +++ b/trunk/include/asm-arm/spinlock.h @@ -199,21 +199,7 @@ static inline void __raw_read_unlock(raw_rwlock_t *rw) : "cc"); } -static inline int __raw_read_trylock(raw_rwlock_t *rw) -{ - unsigned long tmp, tmp2 = 1; - - __asm__ __volatile__( -"1: ldrex %0, [%2]\n" -" adds %0, %0, #1\n" -" strexpl %1, %0, [%2]\n" - : "=&r" (tmp), "+r" (tmp2) - : "r" (&rw->lock) - : "cc"); - - smp_mb(); - return tmp2 == 0; -} +#define __raw_read_trylock(lock) generic__raw_read_trylock(lock) /* read_can_lock - would read_trylock() succeed? */ #define __raw_read_can_lock(x) ((x)->lock < 0x80000000) diff --git a/trunk/include/asm-generic/Kbuild b/trunk/include/asm-generic/Kbuild index 3c06be381701..70594b275a6e 100644 --- a/trunk/include/asm-generic/Kbuild +++ b/trunk/include/asm-generic/Kbuild @@ -1,12 +1,3 @@ -header-y += atomic.h -header-y += errno-base.h -header-y += errno.h -header-y += fcntl.h -header-y += ioctl.h -header-y += ipc.h -header-y += mman.h -header-y += signal.h -header-y += statfs.h - -unifdef-y += resource.h -unifdef-y += siginfo.h +header-y += atomic.h errno-base.h errno.h fcntl.h ioctl.h ipc.h mman.h \ + signal.h statfs.h +unifdef-y := resource.h siginfo.h diff --git a/trunk/include/asm-generic/Kbuild.asm b/trunk/include/asm-generic/Kbuild.asm index a84c3d88a189..6b16dda18115 100644 --- a/trunk/include/asm-generic/Kbuild.asm +++ b/trunk/include/asm-generic/Kbuild.asm @@ -1,34 +1,8 @@ -unifdef-y += a.out.h -unifdef-y += auxvec.h -unifdef-y += byteorder.h -unifdef-y += errno.h -unifdef-y += fcntl.h -unifdef-y += ioctl.h -unifdef-y += ioctls.h -unifdef-y += ipcbuf.h -unifdef-y += mman.h -unifdef-y += msgbuf.h -unifdef-y += param.h -unifdef-y += poll.h -unifdef-y += posix_types.h -unifdef-y += ptrace.h -unifdef-y += resource.h -unifdef-y += sembuf.h -unifdef-y += shmbuf.h -unifdef-y += sigcontext.h -unifdef-y += siginfo.h -unifdef-y += signal.h -unifdef-y += socket.h -unifdef-y += sockios.h -unifdef-y += stat.h -unifdef-y += statfs.h -unifdef-y += termbits.h -unifdef-y += termios.h -unifdef-y += types.h -unifdef-y += unistd.h -unifdef-y += user.h +unifdef-y += a.out.h auxvec.h byteorder.h errno.h fcntl.h ioctl.h \ + ioctls.h ipcbuf.h mman.h msgbuf.h param.h poll.h \ + posix_types.h ptrace.h resource.h sembuf.h shmbuf.h shmparam.h \ + sigcontext.h siginfo.h signal.h socket.h sockios.h stat.h \ + statfs.h termbits.h termios.h timex.h types.h unistd.h user.h # These probably shouldn't be exported -unifdef-y += shmparam.h -unifdef-y += elf.h -unifdef-y += page.h +unifdef-y += elf.h page.h diff --git a/trunk/include/asm-generic/audit_change_attr.h b/trunk/include/asm-generic/audit_change_attr.h index 50764550a60c..cb05bf69745a 100644 --- a/trunk/include/asm-generic/audit_change_attr.h +++ b/trunk/include/asm-generic/audit_change_attr.h @@ -1,20 +1,16 @@ __NR_chmod, __NR_fchmod, -#ifdef __NR_chown __NR_chown, __NR_fchown, __NR_lchown, -#endif __NR_setxattr, __NR_lsetxattr, __NR_fsetxattr, __NR_removexattr, __NR_lremovexattr, __NR_fremovexattr, -#ifdef __NR_fchownat __NR_fchownat, __NR_fchmodat, -#endif #ifdef __NR_chown32 __NR_chown32, __NR_fchown32, diff --git a/trunk/include/asm-generic/audit_dir_write.h b/trunk/include/asm-generic/audit_dir_write.h index 6621bd82cbe8..161a7a58fbab 100644 --- a/trunk/include/asm-generic/audit_dir_write.h +++ b/trunk/include/asm-generic/audit_dir_write.h @@ -1,18 +1,14 @@ __NR_rename, __NR_mkdir, __NR_rmdir, -#ifdef __NR_creat __NR_creat, -#endif __NR_link, __NR_unlink, __NR_symlink, __NR_mknod, -#ifdef __NR_mkdirat __NR_mkdirat, __NR_mknodat, __NR_unlinkat, __NR_renameat, __NR_linkat, __NR_symlinkat, -#endif diff --git a/trunk/include/asm-generic/audit_read.h b/trunk/include/asm-generic/audit_read.h deleted file mode 100644 index 0e87464d9847..000000000000 --- a/trunk/include/asm-generic/audit_read.h +++ /dev/null @@ -1,8 +0,0 @@ -__NR_readlink, -__NR_quotactl, -__NR_listxattr, -__NR_llistxattr, -__NR_flistxattr, -__NR_getxattr, -__NR_lgetxattr, -__NR_fgetxattr, diff --git a/trunk/include/asm-generic/audit_write.h b/trunk/include/asm-generic/audit_write.h deleted file mode 100644 index f10d367fb2a5..000000000000 --- a/trunk/include/asm-generic/audit_write.h +++ /dev/null @@ -1,11 +0,0 @@ -#include -__NR_acct, -__NR_swapon, -__NR_quotactl, -__NR_truncate, -#ifdef __NR_truncate64 -__NR_truncate64, -#endif -#ifdef __NR_bind -__NR_bind, /* bind can affect fs object only in one way... */ -#endif diff --git a/trunk/include/asm-i386/Kbuild b/trunk/include/asm-i386/Kbuild index b75a348d0c1c..c064a8e9170f 100644 --- a/trunk/include/asm-i386/Kbuild +++ b/trunk/include/asm-i386/Kbuild @@ -1,10 +1,5 @@ include include/asm-generic/Kbuild.asm -header-y += boot.h -header-y += debugreg.h -header-y += ldt.h -header-y += ucontext.h +header-y += boot.h cpufeature.h debugreg.h ldt.h setup.h ucontext.h -unifdef-y += mtrr.h -unifdef-y += setup.h -unifdef-y += vm86.h +unifdef-y += mtrr.h vm86.h diff --git a/trunk/include/asm-i386/alternative.h b/trunk/include/asm-i386/alternative.h index b01a7ec409ce..96adbabec740 100644 --- a/trunk/include/asm-i386/alternative.h +++ b/trunk/include/asm-i386/alternative.h @@ -88,6 +88,9 @@ static inline void alternatives_smp_switch(int smp) {} /* * Alternative inline assembly for SMP. * + * alternative_smp() takes two versions (SMP first, UP second) and is + * for more complex stuff such as spinlocks. + * * The LOCK_PREFIX macro defined here replaces the LOCK and * LOCK_PREFIX macros used everywhere in the source tree. * @@ -107,6 +110,21 @@ static inline void alternatives_smp_switch(int smp) {} */ #ifdef CONFIG_SMP +#define alternative_smp(smpinstr, upinstr, args...) \ + asm volatile ("661:\n\t" smpinstr "\n662:\n" \ + ".section .smp_altinstructions,\"a\"\n" \ + " .align 4\n" \ + " .long 661b\n" /* label */ \ + " .long 663f\n" /* new instruction */ \ + " .byte 0x68\n" /* X86_FEATURE_UP */ \ + " .byte 662b-661b\n" /* sourcelen */ \ + " .byte 664f-663f\n" /* replacementlen */ \ + ".previous\n" \ + ".section .smp_altinstr_replacement,\"awx\"\n" \ + "663:\n\t" upinstr "\n" /* replacement */ \ + "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \ + ".previous" : args) + #define LOCK_PREFIX \ ".section .smp_locks,\"a\"\n" \ " .align 4\n" \ @@ -115,6 +133,8 @@ static inline void alternatives_smp_switch(int smp) {} "661:\n\tlock; " #else /* ! CONFIG_SMP */ +#define alternative_smp(smpinstr, upinstr, args...) \ + asm volatile (upinstr : args) #define LOCK_PREFIX "" #endif diff --git a/trunk/include/asm-i386/elf.h b/trunk/include/asm-i386/elf.h index db4344d9f73f..1eac92cb5b16 100644 --- a/trunk/include/asm-i386/elf.h +++ b/trunk/include/asm-i386/elf.h @@ -7,7 +7,10 @@ #include #include +#include +#include /* for savesegment */ #include +#include #include @@ -45,12 +48,6 @@ typedef struct user_fxsr_struct elf_fpxregset_t; #define ELF_DATA ELFDATA2LSB #define ELF_ARCH EM_386 -#ifdef __KERNEL__ - -#include -#include /* for savesegment */ -#include - /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program starts %edx contains a pointer to a function which might be registered using `atexit'. This provides a mean for the dynamic linker to call DT_FINI functions for @@ -114,6 +111,7 @@ typedef struct user_fxsr_struct elf_fpxregset_t; #define ELF_PLATFORM (system_utsname.machine) +#ifdef __KERNEL__ #define SET_PERSONALITY(ex, ibcs2) do { } while (0) /* diff --git a/trunk/include/asm-i386/kprobes.h b/trunk/include/asm-i386/kprobes.h index 8774d06689da..0730a20f6db8 100644 --- a/trunk/include/asm-i386/kprobes.h +++ b/trunk/include/asm-i386/kprobes.h @@ -45,7 +45,6 @@ typedef u8 kprobe_opcode_t; #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry #define ARCH_SUPPORTS_KRETPROBES #define ARCH_INACTIVE_KPROBE_COUNT 0 -#define flush_insn_slot(p) do { } while (0) void arch_remove_kprobe(struct kprobe *p); void kretprobe_trampoline(void); diff --git a/trunk/include/asm-i386/mach-default/mach_mpspec.h b/trunk/include/asm-i386/mach-default/mach_mpspec.h index 51c9a9775932..6b5dadcf1d0e 100644 --- a/trunk/include/asm-i386/mach-default/mach_mpspec.h +++ b/trunk/include/asm-i386/mach-default/mach_mpspec.h @@ -3,10 +3,6 @@ #define MAX_IRQ_SOURCES 256 -#if CONFIG_BASE_SMALL == 0 -#define MAX_MP_BUSSES 256 -#else #define MAX_MP_BUSSES 32 -#endif #endif /* __ASM_MACH_MPSPEC_H */ diff --git a/trunk/include/asm-i386/mmzone.h b/trunk/include/asm-i386/mmzone.h index 22cb07cc8f32..e33e9f9e4c66 100644 --- a/trunk/include/asm-i386/mmzone.h +++ b/trunk/include/asm-i386/mmzone.h @@ -14,7 +14,7 @@ extern struct pglist_data *node_data[]; #ifdef CONFIG_X86_NUMAQ #include -#elif defined(CONFIG_ACPI_SRAT)/* summit or generic arch */ +#else /* summit or generic arch */ #include #endif diff --git a/trunk/include/asm-i386/rwlock.h b/trunk/include/asm-i386/rwlock.h index 87c069ccba08..96b0bef2ea56 100644 --- a/trunk/include/asm-i386/rwlock.h +++ b/trunk/include/asm-i386/rwlock.h @@ -21,21 +21,23 @@ #define RW_LOCK_BIAS_STR "0x01000000" #define __build_read_lock_ptr(rw, helper) \ - asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t" \ + alternative_smp("lock; subl $1,(%0)\n\t" \ "jns 1f\n" \ "call " helper "\n\t" \ - "1:\n" \ - ::"a" (rw) : "memory") + "1:\n", \ + "subl $1,(%0)\n\t", \ + :"a" (rw) : "memory") #define __build_read_lock_const(rw, helper) \ - asm volatile(LOCK_PREFIX " subl $1,%0\n\t" \ + alternative_smp("lock; subl $1,%0\n\t" \ "jns 1f\n" \ "pushl %%eax\n\t" \ "leal %0,%%eax\n\t" \ "call " helper "\n\t" \ "popl %%eax\n\t" \ - "1:\n" \ - :"+m" (*(volatile int *)rw) : : "memory") + "1:\n", \ + "subl $1,%0\n\t", \ + "+m" (*(volatile int *)rw) : : "memory") #define __build_read_lock(rw, helper) do { \ if (__builtin_constant_p(rw)) \ @@ -45,21 +47,23 @@ } while (0) #define __build_write_lock_ptr(rw, helper) \ - asm volatile(LOCK_PREFIX " subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ + alternative_smp("lock; subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ "jz 1f\n" \ "call " helper "\n\t" \ - "1:\n" \ - ::"a" (rw) : "memory") + "1:\n", \ + "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t", \ + :"a" (rw) : "memory") #define __build_write_lock_const(rw, helper) \ - asm volatile(LOCK_PREFIX " subl $" RW_LOCK_BIAS_STR ",%0\n\t" \ + alternative_smp("lock; subl $" RW_LOCK_BIAS_STR ",%0\n\t" \ "jz 1f\n" \ "pushl %%eax\n\t" \ "leal %0,%%eax\n\t" \ "call " helper "\n\t" \ "popl %%eax\n\t" \ - "1:\n" \ - :"+m" (*(volatile int *)rw) : : "memory") + "1:\n", \ + "subl $" RW_LOCK_BIAS_STR ",%0\n\t", \ + "+m" (*(volatile int *)rw) : : "memory") #define __build_write_lock(rw, helper) do { \ if (__builtin_constant_p(rw)) \ diff --git a/trunk/include/asm-i386/setup.h b/trunk/include/asm-i386/setup.h index 2734909eff84..f737e423029e 100644 --- a/trunk/include/asm-i386/setup.h +++ b/trunk/include/asm-i386/setup.h @@ -6,7 +6,6 @@ #ifndef _i386_SETUP_H #define _i386_SETUP_H -#ifdef __KERNEL__ #include /* @@ -14,7 +13,6 @@ */ #define MAXMEM_PFN PFN_DOWN(MAXMEM) #define MAX_NONPAE_PFN (1 << 20) -#endif #define PARAM_SIZE 4096 #define COMMAND_LINE_SIZE 256 diff --git a/trunk/include/asm-i386/signal.h b/trunk/include/asm-i386/signal.h index c3e8adec5918..3824a502351f 100644 --- a/trunk/include/asm-i386/signal.h +++ b/trunk/include/asm-i386/signal.h @@ -2,6 +2,7 @@ #define _ASMi386_SIGNAL_H #include +#include #include #include @@ -9,9 +10,6 @@ struct siginfo; #ifdef __KERNEL__ - -#include - /* Most things should be clean enough to redefine this at will, if care is taken to make libc match. */ diff --git a/trunk/include/asm-i386/spinlock.h b/trunk/include/asm-i386/spinlock.h index d1020363c41a..d816c62a7a1d 100644 --- a/trunk/include/asm-i386/spinlock.h +++ b/trunk/include/asm-i386/spinlock.h @@ -22,7 +22,7 @@ #define __raw_spin_lock_string \ "\n1:\t" \ - LOCK_PREFIX " ; decb %0\n\t" \ + "lock ; decb %0\n\t" \ "jns 3f\n" \ "2:\t" \ "rep;nop\n\t" \ @@ -38,7 +38,7 @@ */ #define __raw_spin_lock_string_flags \ "\n1:\t" \ - LOCK_PREFIX " ; decb %0\n\t" \ + "lock ; decb %0\n\t" \ "jns 5f\n" \ "2:\t" \ "testl $0x200, %1\n\t" \ @@ -57,9 +57,15 @@ "jmp 4b\n" \ "5:\n\t" +#define __raw_spin_lock_string_up \ + "\n\tdecb %0" + static inline void __raw_spin_lock(raw_spinlock_t *lock) { - asm(__raw_spin_lock_string : "+m" (lock->slock) : : "memory"); + alternative_smp( + __raw_spin_lock_string, + __raw_spin_lock_string_up, + "+m" (lock->slock) : : "memory"); } /* @@ -70,7 +76,10 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock) #ifndef CONFIG_PROVE_LOCKING static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags) { - asm(__raw_spin_lock_string_flags : "+m" (lock->slock) : "r" (flags) : "memory"); + alternative_smp( + __raw_spin_lock_string_flags, + __raw_spin_lock_string_up, + "+m" (lock->slock) : "r" (flags) : "memory"); } #endif diff --git a/trunk/include/asm-i386/system.h b/trunk/include/asm-i386/system.h index 098bcee94e38..49928eb33f8b 100644 --- a/trunk/include/asm-i386/system.h +++ b/trunk/include/asm-i386/system.h @@ -11,14 +11,9 @@ struct task_struct; /* one of the stranger aspects of C forward declarations.. */ extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next)); -/* - * Saving eflags is important. It switches not only IOPL between tasks, - * it also protects other tasks from NT leaking through sysenter etc. - */ #define switch_to(prev,next,last) do { \ unsigned long esi,edi; \ - asm volatile("pushfl\n\t" /* Save flags */ \ - "pushl %%ebp\n\t" \ + asm volatile("pushl %%ebp\n\t" \ "movl %%esp,%0\n\t" /* save ESP */ \ "movl %5,%%esp\n\t" /* restore ESP */ \ "movl $1f,%1\n\t" /* save EIP */ \ @@ -26,7 +21,6 @@ extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struc "jmp __switch_to\n" \ "1:\t" \ "popl %%ebp\n\t" \ - "popfl" \ :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \ "=a" (last),"=S" (esi),"=D" (edi) \ :"m" (next->thread.esp),"m" (next->thread.eip), \ diff --git a/trunk/include/asm-i386/unwind.h b/trunk/include/asm-i386/unwind.h index 4c1a0b968569..69f0f1df6722 100644 --- a/trunk/include/asm-i386/unwind.h +++ b/trunk/include/asm-i386/unwind.h @@ -87,7 +87,6 @@ static inline int arch_unw_user_mode(const struct unwind_frame_info *info) #else #define UNW_PC(frame) ((void)(frame), 0) -#define UNW_SP(frame) ((void)(frame), 0) static inline int arch_unw_user_mode(const void *info) { diff --git a/trunk/include/asm-ia64/Kbuild b/trunk/include/asm-ia64/Kbuild index 15818a18bc52..85d6f8005eb4 100644 --- a/trunk/include/asm-ia64/Kbuild +++ b/trunk/include/asm-ia64/Kbuild @@ -1,17 +1,7 @@ include include/asm-generic/Kbuild.asm -header-y += break.h -header-y += fpu.h -header-y += fpswa.h -header-y += gcc_intrin.h -header-y += ia64regs.h -header-y += intel_intrin.h -header-y += intrinsics.h -header-y += perfmon_default_smpl.h -header-y += ptrace_offsets.h -header-y += rse.h -header-y += setup.h -header-y += ucontext.h +header-y += break.h fpu.h fpswa.h gcc_intrin.h ia64regs.h \ + intel_intrin.h intrinsics.h perfmon_default_smpl.h \ + ptrace_offsets.h rse.h setup.h ucontext.h unifdef-y += perfmon.h -unifdef-y += ustack.h diff --git a/trunk/include/asm-ia64/kprobes.h b/trunk/include/asm-ia64/kprobes.h index 938904910115..2418a787c405 100644 --- a/trunk/include/asm-ia64/kprobes.h +++ b/trunk/include/asm-ia64/kprobes.h @@ -125,6 +125,5 @@ static inline void jprobe_return(void) } extern void invalidate_stacked_regs(void); extern void flush_register_stack(void); -extern void flush_insn_slot(struct kprobe *p); #endif /* _ASM_KPROBES_H */ diff --git a/trunk/include/asm-ia64/meminit.h b/trunk/include/asm-ia64/meminit.h index 6a33a07b3f1d..894bc4d89dc0 100644 --- a/trunk/include/asm-ia64/meminit.h +++ b/trunk/include/asm-ia64/meminit.h @@ -56,11 +56,6 @@ extern void efi_memmap_init(unsigned long *, unsigned long *); extern struct page *vmem_map; extern int find_largest_hole (u64 start, u64 end, void *arg); extern int create_mem_map_page_table (u64 start, u64 end, void *arg); - extern int vmemmap_find_next_valid_pfn(int, int); -#else -static inline int vmemmap_find_next_valid_pfn(int node, int i) -{ - return i + 1; -} #endif + #endif /* meminit_h */ diff --git a/trunk/include/asm-ia64/mman.h b/trunk/include/asm-ia64/mman.h index c73b87832a1e..6ba179f12718 100644 --- a/trunk/include/asm-ia64/mman.h +++ b/trunk/include/asm-ia64/mman.h @@ -22,12 +22,4 @@ #define MCL_CURRENT 1 /* lock all current mappings */ #define MCL_FUTURE 2 /* lock all future mappings */ -#ifdef __KERNEL__ -#ifndef __ASSEMBLY__ -#define arch_mmap_check ia64_mmap_check -int ia64_mmap_check(unsigned long addr, unsigned long len, - unsigned long flags); -#endif -#endif - #endif /* _ASM_IA64_MMAN_H */ diff --git a/trunk/include/asm-ia64/page.h b/trunk/include/asm-ia64/page.h index 947cb72b520e..f5a949ec6e1e 100644 --- a/trunk/include/asm-ia64/page.h +++ b/trunk/include/asm-ia64/page.h @@ -7,7 +7,6 @@ * David Mosberger-Tang */ -# ifdef __KERNEL__ #include #include @@ -65,6 +64,7 @@ # define __pa(x) ((x) - PAGE_OFFSET) # define __va(x) ((x) + PAGE_OFFSET) #else /* !__ASSEMBLY */ +# ifdef __KERNEL__ # define STRICT_MM_TYPECHECKS extern void clear_page (void *page); @@ -174,6 +174,7 @@ get_order (unsigned long size) return order; } +# endif /* __KERNEL__ */ #endif /* !__ASSEMBLY__ */ #ifdef STRICT_MM_TYPECHECKS @@ -227,5 +228,4 @@ get_order (unsigned long size) (((current->personality & READ_IMPLIES_EXEC) != 0) \ ? VM_EXEC : 0)) -# endif /* __KERNEL__ */ #endif /* _ASM_IA64_PAGE_H */ diff --git a/trunk/include/asm-ia64/pal.h b/trunk/include/asm-ia64/pal.h index 20a8d618c845..37e52a2836b0 100644 --- a/trunk/include/asm-ia64/pal.h +++ b/trunk/include/asm-ia64/pal.h @@ -1433,12 +1433,7 @@ typedef union pal_version_u { } pal_version_u_t; -/* - * Return PAL version information. While the documentation states that - * PAL_VERSION can be called in either physical or virtual mode, some - * implementations only allow physical calls. We don't call it very often, - * so the overhead isn't worth eliminating. - */ +/* Return PAL version information */ static inline s64 ia64_pal_version (pal_version_u_t *pal_min_version, pal_version_u_t *pal_cur_version) { diff --git a/trunk/include/asm-ia64/ptrace.h b/trunk/include/asm-ia64/ptrace.h index 1414316efd40..415abb23b210 100644 --- a/trunk/include/asm-ia64/ptrace.h +++ b/trunk/include/asm-ia64/ptrace.h @@ -56,8 +56,6 @@ #include - -#ifdef __KERNEL__ #ifndef ASM_OFFSETS_C #include #endif @@ -81,10 +79,11 @@ #define KERNEL_STACK_SIZE IA64_STK_OFFSET -#endif /* __KERNEL__ */ - #ifndef __ASSEMBLY__ +#include +#include + /* * This struct defines the way the registers are saved on system * calls. @@ -230,9 +229,6 @@ struct switch_stack { #ifdef __KERNEL__ -#include -#include - #define __ARCH_SYS_PTRACE 1 /* diff --git a/trunk/include/asm-ia64/sn/sn_sal.h b/trunk/include/asm-ia64/sn/sn_sal.h index ba826b3f75bb..bd4452bda357 100644 --- a/trunk/include/asm-ia64/sn/sn_sal.h +++ b/trunk/include/asm-ia64/sn/sn_sal.h @@ -706,9 +706,12 @@ static inline int sn_change_memprotect(u64 paddr, u64 len, u64 perms, u64 *nasid_array) { struct ia64_sal_retval ret_stuff; + unsigned long irq_flags; + local_irq_save(irq_flags); ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_MEMPROTECT, paddr, len, (u64)nasid_array, perms, 0, 0, 0); + local_irq_restore(irq_flags); return ret_stuff.status; } #define SN_MEMPROT_ACCESS_CLASS_0 0x14a080 @@ -1140,9 +1143,12 @@ static inline int sn_inject_error(u64 paddr, u64 *data, u64 *ecc) { struct ia64_sal_retval ret_stuff; + unsigned long irq_flags; + local_irq_save(irq_flags); ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_INJECT_ERROR, paddr, (u64)data, (u64)ecc, 0, 0, 0, 0); + local_irq_restore(irq_flags); return ret_stuff.status; } diff --git a/trunk/include/asm-ia64/sn/xp.h b/trunk/include/asm-ia64/sn/xp.h index 6f807e0193b7..9bd2f9bf329b 100644 --- a/trunk/include/asm-ia64/sn/xp.h +++ b/trunk/include/asm-ia64/sn/xp.h @@ -60,37 +60,23 @@ * the bte_copy() once in the hope that the failure was due to a temporary * aberration (i.e., the link going down temporarily). * - * src - physical address of the source of the transfer. - * vdst - virtual address of the destination of the transfer. - * len - number of bytes to transfer from source to destination. - * mode - see bte_copy() for definition. - * notification - see bte_copy() for definition. + * See bte_copy for definition of the input parameters. * * Note: xp_bte_copy() should never be called while holding a spinlock. */ static inline bte_result_t -xp_bte_copy(u64 src, u64 vdst, u64 len, u64 mode, void *notification) +xp_bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) { bte_result_t ret; - u64 pdst = ia64_tpa(vdst); - /* - * Ensure that the physically mapped memory is contiguous. - * - * We do this by ensuring that the memory is from region 7 only. - * If the need should arise to use memory from one of the other - * regions, then modify the BUG_ON() statement to ensure that the - * memory from that region is always physically contiguous. - */ - BUG_ON(REGION_NUMBER(vdst) != RGN_KERNEL); + ret = bte_copy(src, dest, len, mode, notification); - ret = bte_copy(src, pdst, len, mode, notification); if (ret != BTE_SUCCESS) { if (!in_interrupt()) { cond_resched(); } - ret = bte_copy(src, pdst, len, mode, notification); + ret = bte_copy(src, dest, len, mode, notification); } return ret; diff --git a/trunk/include/asm-ia64/sn/xpc.h b/trunk/include/asm-ia64/sn/xpc.h index 35e1386f37ab..8406f1ef4caf 100644 --- a/trunk/include/asm-ia64/sn/xpc.h +++ b/trunk/include/asm-ia64/sn/xpc.h @@ -683,9 +683,7 @@ extern struct xpc_vars *xpc_vars; extern struct xpc_rsvd_page *xpc_rsvd_page; extern struct xpc_vars_part *xpc_vars_part; extern struct xpc_partition xpc_partitions[XP_MAX_PARTITIONS + 1]; -extern char *xpc_remote_copy_buffer; -extern void *xpc_remote_copy_buffer_base; -extern void *xpc_kmalloc_cacheline_aligned(size_t, gfp_t, void **); +extern char xpc_remote_copy_buffer[]; extern struct xpc_rsvd_page *xpc_rsvd_page_init(void); extern void xpc_allow_IPI_ops(void); extern void xpc_restrict_IPI_ops(void); @@ -1126,8 +1124,8 @@ xpc_notify_IRQ_send_local(struct xpc_channel *ch, u8 ipi_flag, #define XPC_GET_IPI_FLAGS(_amo, _c) ((u8) (((_amo) >> ((_c) * 8)) & 0xff)) #define XPC_SET_IPI_FLAGS(_amo, _c, _f) (_amo) |= ((u64) (_f) << ((_c) * 8)) -#define XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & __IA64_UL_CONST(0x0f0f0f0f0f0f0f0f)) -#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo) ((_amo) & __IA64_UL_CONST(0x1010101010101010)) +#define XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(_amo) ((_amo) & 0x0f0f0f0f0f0f0f0f) +#define XPC_ANY_MSG_IPI_FLAGS_SET(_amo) ((_amo) & 0x1010101010101010) static inline void diff --git a/trunk/include/asm-ia64/system.h b/trunk/include/asm-ia64/system.h index 384fbf7f2a0f..fc9677bc87ee 100644 --- a/trunk/include/asm-ia64/system.h +++ b/trunk/include/asm-ia64/system.h @@ -24,7 +24,7 @@ * 0xa000000000000000+2*PERCPU_PAGE_SIZE * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page) */ -#define KERNEL_START (GATE_ADDR+__IA64_UL_CONST(0x100000000)) +#define KERNEL_START (GATE_ADDR+0x100000000) #define PERCPU_ADDR (-PERCPU_PAGE_SIZE) #ifndef __ASSEMBLY__ diff --git a/trunk/include/asm-ia64/unistd.h b/trunk/include/asm-ia64/unistd.h index f581662c5ab8..bb0eb727dcd0 100644 --- a/trunk/include/asm-ia64/unistd.h +++ b/trunk/include/asm-ia64/unistd.h @@ -286,7 +286,8 @@ /* 1294, 1295 reserved for pselect/ppoll */ #define __NR_unshare 1296 #define __NR_splice 1297 -/* 1298, 1299 reserved for set_robust_list/get_robust_list */ +#define __NR_set_robust_list 1298 +#define __NR_get_robust_list 1299 #define __NR_sync_file_range 1300 #define __NR_tee 1301 #define __NR_vmsplice 1302 diff --git a/trunk/include/asm-ia64/ustack.h b/trunk/include/asm-ia64/ustack.h index a349467913ea..da55c91246e3 100644 --- a/trunk/include/asm-ia64/ustack.h +++ b/trunk/include/asm-ia64/ustack.h @@ -5,15 +5,12 @@ * Constants for the user stack size */ -#ifdef __KERNEL__ #include /* The absolute hard limit for stack size is 1/2 of the mappable space in the region */ #define MAX_USER_STACK_SIZE (RGN_MAP_LIMIT/2) -#define STACK_TOP (0x6000000000000000UL + RGN_MAP_LIMIT) -#endif - -/* Make a default stack size of 2GiB */ +/* Make a default stack size of 2GB */ #define DEFAULT_USER_STACK_SIZE (1UL << 31) +#define STACK_TOP (0x6000000000000000UL + RGN_MAP_LIMIT) #endif /* _ASM_IA64_USTACK_H */ diff --git a/trunk/include/asm-m68k/page.h b/trunk/include/asm-m68k/page.h index fcc165ddd09e..db017f838c29 100644 --- a/trunk/include/asm-m68k/page.h +++ b/trunk/include/asm-m68k/page.h @@ -2,8 +2,6 @@ #define _M68K_PAGE_H -#ifdef __KERNEL__ - /* PAGE_SHIFT determines the page size */ #ifndef CONFIG_SUN3 #define PAGE_SHIFT (12) @@ -17,6 +15,8 @@ #endif #define PAGE_MASK (~(PAGE_SIZE-1)) +#ifdef __KERNEL__ + #include #if PAGE_SHIFT < 13 @@ -175,8 +175,8 @@ static inline void *__va(unsigned long x) #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) -#include - #endif /* __KERNEL__ */ +#include + #endif /* _M68K_PAGE_H */ diff --git a/trunk/include/asm-mips/page.h b/trunk/include/asm-mips/page.h index 219d359861f3..6ed1151a05a3 100644 --- a/trunk/include/asm-mips/page.h +++ b/trunk/include/asm-mips/page.h @@ -14,6 +14,8 @@ #include +#endif + /* * PAGE_SHIFT determines the page size */ @@ -32,6 +34,8 @@ #define PAGE_SIZE (1UL << PAGE_SHIFT) #define PAGE_MASK (~((1 << PAGE_SHIFT) - 1)) + +#ifdef __KERNEL__ #ifndef __ASSEMBLY__ extern void clear_page(void * page); @@ -164,6 +168,8 @@ typedef struct { unsigned long pgprot; } pgprot_t; #define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE) #define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET) +#endif /* defined (__KERNEL__) */ + #ifdef CONFIG_LIMITED_DMA #define WANT_PAGE_VIRTUAL #endif @@ -171,6 +177,4 @@ typedef struct { unsigned long pgprot; } pgprot_t; #include #include -#endif /* defined (__KERNEL__) */ - #endif /* _ASM_PAGE_H */ diff --git a/trunk/include/asm-parisc/page.h b/trunk/include/asm-parisc/page.h index 57d6d82756dd..0695bc958d56 100644 --- a/trunk/include/asm-parisc/page.h +++ b/trunk/include/asm-parisc/page.h @@ -1,14 +1,22 @@ #ifndef _PARISC_PAGE_H #define _PARISC_PAGE_H +#if !defined(__KERNEL__) +/* this is for userspace applications (4k page size) */ +# define PAGE_SHIFT 12 /* 4k */ +# define PAGE_SIZE (1UL << PAGE_SHIFT) +# define PAGE_MASK (~(PAGE_SIZE-1)) +#endif + + #ifdef __KERNEL__ #if defined(CONFIG_PARISC_PAGE_SIZE_4KB) -# define PAGE_SHIFT 12 +# define PAGE_SHIFT 12 /* 4k */ #elif defined(CONFIG_PARISC_PAGE_SIZE_16KB) -# define PAGE_SHIFT 14 +# define PAGE_SHIFT 14 /* 16k */ #elif defined(CONFIG_PARISC_PAGE_SIZE_64KB) -# define PAGE_SHIFT 16 +# define PAGE_SHIFT 16 /* 64k */ #else # error "unknown default kernel page size" #endif @@ -180,9 +188,9 @@ extern int npmem_ranges; #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) +#endif /* __KERNEL__ */ + #include #include -#endif /* __KERNEL__ */ - #endif /* _PARISC_PAGE_H */ diff --git a/trunk/include/asm-powerpc/Kbuild b/trunk/include/asm-powerpc/Kbuild index 9827849953a3..ac61d7eb6021 100644 --- a/trunk/include/asm-powerpc/Kbuild +++ b/trunk/include/asm-powerpc/Kbuild @@ -1,41 +1,10 @@ include include/asm-generic/Kbuild.asm -header-y += auxvec.h -header-y += ioctls.h -header-y += mman.h -header-y += sembuf.h -header-y += siginfo.h -header-y += stat.h -header-y += errno.h -header-y += ipcbuf.h -header-y += msgbuf.h -header-y += shmbuf.h -header-y += socket.h -header-y += termbits.h -header-y += fcntl.h -header-y += ipc.h -header-y += poll.h -header-y += shmparam.h -header-y += sockios.h -header-y += ucontext.h -header-y += ioctl.h -header-y += linkage.h -header-y += resource.h -header-y += sigcontext.h -header-y += statfs.h +unifdef-y += a.out.h asm-compat.h bootx.h byteorder.h cputable.h elf.h \ + nvram.h param.h posix_types.h ptrace.h seccomp.h signal.h \ + termios.h types.h unistd.h -unifdef-y += a.out.h -unifdef-y += asm-compat.h -unifdef-y += bootx.h -unifdef-y += byteorder.h -unifdef-y += cputable.h -unifdef-y += elf.h -unifdef-y += nvram.h -unifdef-y += param.h -unifdef-y += posix_types.h -unifdef-y += ptrace.h -unifdef-y += seccomp.h -unifdef-y += signal.h -unifdef-y += termios.h -unifdef-y += types.h -unifdef-y += unistd.h +header-y += auxvec.h ioctls.h mman.h sembuf.h siginfo.h stat.h errno.h \ + ipcbuf.h msgbuf.h shmbuf.h socket.h termbits.h fcntl.h ipc.h \ + poll.h shmparam.h sockios.h ucontext.h ioctl.h linkage.h \ + resource.h sigcontext.h statfs.h diff --git a/trunk/include/asm-powerpc/backlight.h b/trunk/include/asm-powerpc/backlight.h index 8cf5c37c3817..58d4b6f8d827 100644 --- a/trunk/include/asm-powerpc/backlight.h +++ b/trunk/include/asm-powerpc/backlight.h @@ -30,12 +30,8 @@ static inline void pmac_backlight_key_down(void) pmac_backlight_key(1); } -extern void pmac_backlight_set_legacy_brightness_pmu(int brightness); extern int pmac_backlight_set_legacy_brightness(int brightness); extern int pmac_backlight_get_legacy_brightness(void); -extern void pmac_backlight_enable(void); -extern void pmac_backlight_disable(void); - #endif /* __KERNEL__ */ #endif diff --git a/trunk/include/asm-powerpc/cputable.h b/trunk/include/asm-powerpc/cputable.h index 12707ab9dc98..1ba3c9983614 100644 --- a/trunk/include/asm-powerpc/cputable.h +++ b/trunk/include/asm-powerpc/cputable.h @@ -23,7 +23,6 @@ #define PPC_FEATURE_SMT 0x00004000 #define PPC_FEATURE_ICACHE_SNOOP 0x00002000 #define PPC_FEATURE_ARCH_2_05 0x00001000 -#define PPC_FEATURE_PA6T 0x00000800 #define PPC_FEATURE_TRUE_LE 0x00000002 #define PPC_FEATURE_PPC_LE 0x00000001 @@ -37,7 +36,6 @@ struct cpu_spec; typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); -typedef void (*cpu_restore_t)(void); enum powerpc_oprofile_type { PPC_OPROFILE_INVALID = 0, @@ -67,8 +65,6 @@ struct cpu_spec { * BHT, SPD, etc... from head.S before branching to identify_machine */ cpu_setup_t cpu_setup; - /* Used to restore cpu setup on secondary processors and at resume */ - cpu_restore_t cpu_restore; /* Used by oprofile userspace to select the right counters */ char *oprofile_cpu_type; @@ -149,7 +145,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTR_PPCAS_ARCH_V2_BASE (CPU_FTR_SLB | \ CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ - CPU_FTR_NODSISRALIGN) + CPU_FTR_NODSISRALIGN | CPU_FTR_CTRL) /* iSeries doesn't support large pages */ #ifdef CONFIG_PPC_ISERIES @@ -314,29 +310,24 @@ extern void do_cpu_ftr_fixups(unsigned long offset); CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \ CPU_FTR_MMCRA | CPU_FTR_CTRL) #define CPU_FTRS_POWER4 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ - CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ - CPU_FTR_MMCRA) + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_MMCRA) #define CPU_FTRS_PPC970 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ - CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA) #define CPU_FTRS_POWER5 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ - CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ CPU_FTR_PURR) #define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ - CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ + CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_REAL_LE) #define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ - CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ - CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ - CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE) -#define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ - CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \ - CPU_FTR_PURR | CPU_FTR_REAL_LE) + CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ + CPU_FTR_CTRL | CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE) #define CPU_FTRS_COMPATIBLE (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2) #endif @@ -345,7 +336,7 @@ extern void do_cpu_ftr_fixups(unsigned long offset); #define CPU_FTRS_POSSIBLE \ (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | \ CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 | \ - CPU_FTRS_CELL | CPU_FTRS_PA6T) + CPU_FTRS_CELL | CPU_FTR_CI_LARGE_PAGE) #else enum { CPU_FTRS_POSSIBLE = @@ -384,7 +375,7 @@ enum { #define CPU_FTRS_ALWAYS \ (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 & \ CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_POWER6 & \ - CPU_FTRS_CELL & CPU_FTRS_PA6T & CPU_FTRS_POSSIBLE) + CPU_FTRS_CELL & CPU_FTRS_POSSIBLE) #else enum { CPU_FTRS_ALWAYS = diff --git a/trunk/include/asm-powerpc/eeh.h b/trunk/include/asm-powerpc/eeh.h index 6a784396660b..4df3e80118f4 100644 --- a/trunk/include/asm-powerpc/eeh.h +++ b/trunk/include/asm-powerpc/eeh.h @@ -205,7 +205,6 @@ static inline void eeh_memset_io(volatile void __iomem *addr, int c, lc |= lc << 8; lc |= lc << 16; - __asm__ __volatile__ ("sync" : : : "memory"); while(n && !EEH_CHECK_ALIGN(p, 4)) { *((volatile u8 *)p) = c; p++; @@ -230,7 +229,6 @@ static inline void eeh_memcpy_fromio(void *dest, const volatile void __iomem *sr void *destsave = dest; unsigned long nsave = n; - __asm__ __volatile__ ("sync" : : : "memory"); while(n && (!EEH_CHECK_ALIGN(vsrc, 4) || !EEH_CHECK_ALIGN(dest, 4))) { *((u8 *)dest) = *((volatile u8 *)vsrc); __asm__ __volatile__ ("eieio" : : : "memory"); @@ -268,7 +266,6 @@ static inline void eeh_memcpy_toio(volatile void __iomem *dest, const void *src, { void *vdest = (void __force *) dest; - __asm__ __volatile__ ("sync" : : : "memory"); while(n && (!EEH_CHECK_ALIGN(vdest, 4) || !EEH_CHECK_ALIGN(src, 4))) { *((volatile u8 *)vdest) = *((u8 *)src); src++; diff --git a/trunk/include/asm-powerpc/futex.h b/trunk/include/asm-powerpc/futex.h index 936422e54891..f1b3c00bc1ce 100644 --- a/trunk/include/asm-powerpc/futex.h +++ b/trunk/include/asm-powerpc/futex.h @@ -84,33 +84,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) { - int prev; - - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) - return -EFAULT; - - __asm__ __volatile__ ( - LWSYNC_ON_SMP -"1: lwarx %0,0,%2 # futex_atomic_cmpxchg_inatomic\n\ - cmpw 0,%0,%3\n\ - bne- 3f\n" - PPC405_ERR77(0,%2) -"2: stwcx. %4,0,%2\n\ - bne- 1b\n" - ISYNC_ON_SMP -"3: .section .fixup,\"ax\"\n\ -4: li %0,%5\n\ - b 3b\n\ - .previous\n\ - .section __ex_table,\"a\"\n\ - .align 3\n\ - " PPC_LONG "1b,4b,2b,4b\n\ - .previous" \ - : "=&r" (prev), "+m" (*uaddr) - : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT) - : "cc", "memory"); - - return prev; + return -ENOSYS; } #endif /* __KERNEL__ */ diff --git a/trunk/include/asm-powerpc/hvcall.h b/trunk/include/asm-powerpc/hvcall.h index 257d1cecb8c9..0d3c4e85711a 100644 --- a/trunk/include/asm-powerpc/hvcall.h +++ b/trunk/include/asm-powerpc/hvcall.h @@ -164,15 +164,9 @@ #define H_VIO_SIGNAL 0x104 #define H_SEND_CRQ 0x108 #define H_COPY_RDMA 0x110 -#define H_REGISTER_LOGICAL_LAN 0x114 -#define H_FREE_LOGICAL_LAN 0x118 -#define H_ADD_LOGICAL_LAN_BUFFER 0x11C -#define H_SEND_LOGICAL_LAN 0x120 -#define H_MULTICAST_CTRL 0x130 #define H_SET_XDABR 0x134 #define H_STUFF_TCE 0x138 #define H_PUT_TCE_INDIRECT 0x13C -#define H_CHANGE_LOGICAL_LAN_MAC 0x14C #define H_VTERM_PARTNER_INFO 0x150 #define H_REGISTER_VTERM 0x154 #define H_FREE_VTERM 0x158 @@ -202,59 +196,102 @@ #define H_GET_HCA_INFO 0x1B8 #define H_GET_PERF_COUNT 0x1BC #define H_MANAGE_TRACE 0x1C0 -#define H_FREE_LOGICAL_LAN_BUFFER 0x1D4 #define H_QUERY_INT_STATE 0x1E4 #define H_POLL_PENDING 0x1D8 #define H_JOIN 0x298 #define H_VASI_STATE 0x2A4 #define H_ENABLE_CRQ 0x2B0 -#define MAX_HCALL_OPCODE H_ENABLE_CRQ #ifndef __ASSEMBLY__ -/** - * plpar_hcall_norets: - Make a pseries hypervisor call with no return arguments - * @opcode: The hypervisor call to make. +/* plpar_hcall() -- Generic call interface using above opcodes * - * This call supports up to 7 arguments and only returns the status of - * the hcall. Use this version where possible, its slightly faster than - * the other plpar_hcalls. + * The actual call interface is a hypervisor call instruction with + * the opcode in R3 and input args in R4-R7. + * Status is returned in R3 with variable output values in R4-R11. + * Only H_PTE_READ with H_READ_4 uses R6-R11 so we ignore it for now + * and return only two out args which MUST ALWAYS BE PROVIDED. + */ +long plpar_hcall(unsigned long opcode, + unsigned long arg1, + unsigned long arg2, + unsigned long arg3, + unsigned long arg4, + unsigned long *out1, + unsigned long *out2, + unsigned long *out3); + +/* Same as plpar_hcall but for those opcodes that return no values + * other than status. Slightly more efficient. */ long plpar_hcall_norets(unsigned long opcode, ...); -/** - * plpar_hcall: - Make a pseries hypervisor call - * @opcode: The hypervisor call to make. - * @retbuf: Buffer to store up to 4 return arguments in. - * - * This call supports up to 6 arguments and 4 return arguments. Use - * PLPAR_HCALL_BUFSIZE to size the return argument buffer. - * - * Used for all but the craziest of phyp interfaces (see plpar_hcall9) +/* + * Special hcall interface for ibmveth support. + * Takes 8 input parms. Returns a rc and stores the + * R4 return value in *out1. */ -#define PLPAR_HCALL_BUFSIZE 4 -long plpar_hcall(unsigned long opcode, unsigned long *retbuf, ...); +long plpar_hcall_8arg_2ret(unsigned long opcode, + unsigned long arg1, + unsigned long arg2, + unsigned long arg3, + unsigned long arg4, + unsigned long arg5, + unsigned long arg6, + unsigned long arg7, + unsigned long arg8, + unsigned long *out1); -/** - * plpar_hcall9: - Make a pseries hypervisor call with up to 9 return arguments - * @opcode: The hypervisor call to make. - * @retbuf: Buffer to store up to 9 return arguments in. +/* plpar_hcall_4out() + * + * same as plpar_hcall except with 4 output arguments. * - * This call supports up to 9 arguments and 9 return arguments. Use - * PLPAR_HCALL9_BUFSIZE to size the return argument buffer. */ -#define PLPAR_HCALL9_BUFSIZE 9 -long plpar_hcall9(unsigned long opcode, unsigned long *retbuf, ...); +long plpar_hcall_4out(unsigned long opcode, + unsigned long arg1, + unsigned long arg2, + unsigned long arg3, + unsigned long arg4, + unsigned long *out1, + unsigned long *out2, + unsigned long *out3, + unsigned long *out4); + +long plpar_hcall_7arg_7ret(unsigned long opcode, + unsigned long arg1, + unsigned long arg2, + unsigned long arg3, + unsigned long arg4, + unsigned long arg5, + unsigned long arg6, + unsigned long arg7, + unsigned long *out1, + unsigned long *out2, + unsigned long *out3, + unsigned long *out4, + unsigned long *out5, + unsigned long *out6, + unsigned long *out7); -/* For hcall instrumentation. One structure per-hcall, per-CPU */ -struct hcall_stats { - unsigned long num_calls; /* number of calls (on this CPU) */ - unsigned long tb_total; /* total wall time (mftb) of calls. */ - unsigned long purr_total; /* total cpu time (PURR) of calls. */ -}; -void update_hcall_stats(unsigned long opcode, unsigned long tb_delta, - unsigned long purr_delta); -#define HCALL_STAT_ARRAY_SIZE ((MAX_HCALL_OPCODE >> 2) + 1) +long plpar_hcall_9arg_9ret(unsigned long opcode, + unsigned long arg1, + unsigned long arg2, + unsigned long arg3, + unsigned long arg4, + unsigned long arg5, + unsigned long arg6, + unsigned long arg7, + unsigned long arg8, + unsigned long arg9, + unsigned long *out1, + unsigned long *out2, + unsigned long *out3, + unsigned long *out4, + unsigned long *out5, + unsigned long *out6, + unsigned long *out7, + unsigned long *out8, + unsigned long *out9); #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/trunk/include/asm-powerpc/ibmebus.h b/trunk/include/asm-powerpc/ibmebus.h index 7ab195a27888..7a42723d107c 100644 --- a/trunk/include/asm-powerpc/ibmebus.h +++ b/trunk/include/asm-powerpc/ibmebus.h @@ -48,7 +48,7 @@ extern struct dma_mapping_ops ibmebus_dma_ops; extern struct bus_type ibmebus_bus_type; struct ibmebus_dev { - const char *name; + char *name; struct of_device ofdev; }; diff --git a/trunk/include/asm-powerpc/ide.h b/trunk/include/asm-powerpc/ide.h index c8390f9485de..b09b42af6a1e 100644 --- a/trunk/include/asm-powerpc/ide.h +++ b/trunk/include/asm-powerpc/ide.h @@ -12,7 +12,6 @@ #include #include #endif -#include #ifndef MAX_HWIFS #ifdef __powerpc64__ @@ -22,14 +21,15 @@ #endif #endif -#define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 __iomem *)(p), (a), (c)) -#define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 __iomem *)(p), (a), (c)) -#define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 __iomem *)(p), (a), (c)) -#define __ide_mm_outsl(p, a, c) _outsl_ns((volatile u32 __iomem *)(p), (a), (c)) - #ifndef __powerpc64__ #include #include +#include + +extern void __ide_mm_insw(void __iomem *port, void *addr, u32 count); +extern void __ide_mm_outsw(void __iomem *port, void *addr, u32 count); +extern void __ide_mm_insl(void __iomem *port, void *addr, u32 count); +extern void __ide_mm_outsl(void __iomem *port, void *addr, u32 count); struct ide_machdep_calls { int (*default_irq)(unsigned long base); diff --git a/trunk/include/asm-powerpc/io.h b/trunk/include/asm-powerpc/io.h index 46bae1cf385b..a9496f34b048 100644 --- a/trunk/include/asm-powerpc/io.h +++ b/trunk/include/asm-powerpc/io.h @@ -19,12 +19,20 @@ extern int check_legacy_ioport(unsigned long base_port); #include #include #include -#include +#ifdef CONFIG_PPC_ISERIES +#include +#endif #include #include #include +#define __ide_mm_insw(p, a, c) _insw_ns((volatile u16 __iomem *)(p), (a), (c)) +#define __ide_mm_insl(p, a, c) _insl_ns((volatile u32 __iomem *)(p), (a), (c)) +#define __ide_mm_outsw(p, a, c) _outsw_ns((volatile u16 __iomem *)(p), (a), (c)) +#define __ide_mm_outsl(p, a, c) _outsl_ns((volatile u32 __iomem *)(p), (a), (c)) + + #define SIO_CONFIG_RA 0x398 #define SIO_CONFIG_RD 0x399 @@ -34,53 +42,39 @@ extern unsigned long isa_io_base; extern unsigned long pci_io_base; #ifdef CONFIG_PPC_ISERIES - -extern int in_8(const volatile unsigned char __iomem *addr); -extern void out_8(volatile unsigned char __iomem *addr, int val); -extern int in_le16(const volatile unsigned short __iomem *addr); -extern int in_be16(const volatile unsigned short __iomem *addr); -extern void out_le16(volatile unsigned short __iomem *addr, int val); -extern void out_be16(volatile unsigned short __iomem *addr, int val); -extern unsigned in_le32(const volatile unsigned __iomem *addr); -extern unsigned in_be32(const volatile unsigned __iomem *addr); -extern void out_le32(volatile unsigned __iomem *addr, int val); -extern void out_be32(volatile unsigned __iomem *addr, int val); -extern unsigned long in_le64(const volatile unsigned long __iomem *addr); -extern unsigned long in_be64(const volatile unsigned long __iomem *addr); -extern void out_le64(volatile unsigned long __iomem *addr, unsigned long val); -extern void out_be64(volatile unsigned long __iomem *addr, unsigned long val); - -extern unsigned char __raw_readb(const volatile void __iomem *addr); -extern unsigned short __raw_readw(const volatile void __iomem *addr); -extern unsigned int __raw_readl(const volatile void __iomem *addr); -extern unsigned long __raw_readq(const volatile void __iomem *addr); -extern void __raw_writeb(unsigned char v, volatile void __iomem *addr); -extern void __raw_writew(unsigned short v, volatile void __iomem *addr); -extern void __raw_writel(unsigned int v, volatile void __iomem *addr); -extern void __raw_writeq(unsigned long v, volatile void __iomem *addr); - -extern void memset_io(volatile void __iomem *addr, int c, unsigned long n); -extern void memcpy_fromio(void *dest, const volatile void __iomem *src, - unsigned long n); -extern void memcpy_toio(volatile void __iomem *dest, const void *src, - unsigned long n); - -#else /* CONFIG_PPC_ISERIES */ - -#define in_8(addr) __in_8((addr)) -#define out_8(addr, val) __out_8((addr), (val)) -#define in_le16(addr) __in_le16((addr)) -#define in_be16(addr) __in_be16((addr)) -#define out_le16(addr, val) __out_le16((addr), (val)) -#define out_be16(addr, val) __out_be16((addr), (val)) -#define in_le32(addr) __in_le32((addr)) -#define in_be32(addr) __in_be32((addr)) -#define out_le32(addr, val) __out_le32((addr), (val)) -#define out_be32(addr, val) __out_be32((addr), (val)) -#define in_le64(addr) __in_le64((addr)) -#define in_be64(addr) __in_be64((addr)) -#define out_le64(addr, val) __out_le64((addr), (val)) -#define out_be64(addr, val) __out_be64((addr), (val)) +/* __raw_* accessors aren't supported on iSeries */ +#define __raw_readb(addr) { BUG(); 0; } +#define __raw_readw(addr) { BUG(); 0; } +#define __raw_readl(addr) { BUG(); 0; } +#define __raw_readq(addr) { BUG(); 0; } +#define __raw_writeb(v, addr) { BUG(); 0; } +#define __raw_writew(v, addr) { BUG(); 0; } +#define __raw_writel(v, addr) { BUG(); 0; } +#define __raw_writeq(v, addr) { BUG(); 0; } +#define readb(addr) iSeries_Read_Byte(addr) +#define readw(addr) iSeries_Read_Word(addr) +#define readl(addr) iSeries_Read_Long(addr) +#define writeb(data, addr) iSeries_Write_Byte((data),(addr)) +#define writew(data, addr) iSeries_Write_Word((data),(addr)) +#define writel(data, addr) iSeries_Write_Long((data),(addr)) +#define memset_io(a,b,c) iSeries_memset_io((a),(b),(c)) +#define memcpy_fromio(a,b,c) iSeries_memcpy_fromio((a), (b), (c)) +#define memcpy_toio(a,b,c) iSeries_memcpy_toio((a), (b), (c)) + +#define inb(addr) readb(((void __iomem *)(long)(addr))) +#define inw(addr) readw(((void __iomem *)(long)(addr))) +#define inl(addr) readl(((void __iomem *)(long)(addr))) +#define outb(data,addr) writeb(data,((void __iomem *)(long)(addr))) +#define outw(data,addr) writew(data,((void __iomem *)(long)(addr))) +#define outl(data,addr) writel(data,((void __iomem *)(long)(addr))) +/* + * The *_ns versions below don't do byte-swapping. + * Neither do the standard versions now, these are just here + * for older code. + */ +#define insw_ns(port, buf, ns) _insw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns)) +#define insl_ns(port, buf, nl) _insl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl)) +#else static inline unsigned char __raw_readb(const volatile void __iomem *addr) { @@ -114,11 +108,23 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) { *(volatile unsigned long __force *)addr = v; } +#define readb(addr) eeh_readb(addr) +#define readw(addr) eeh_readw(addr) +#define readl(addr) eeh_readl(addr) +#define readq(addr) eeh_readq(addr) +#define writeb(data, addr) eeh_writeb((data), (addr)) +#define writew(data, addr) eeh_writew((data), (addr)) +#define writel(data, addr) eeh_writel((data), (addr)) +#define writeq(data, addr) eeh_writeq((data), (addr)) #define memset_io(a,b,c) eeh_memset_io((a),(b),(c)) #define memcpy_fromio(a,b,c) eeh_memcpy_fromio((a),(b),(c)) #define memcpy_toio(a,b,c) eeh_memcpy_toio((a),(b),(c)) - -#endif /* CONFIG_PPC_ISERIES */ +#define inb(port) eeh_inb((unsigned long)port) +#define outb(val, port) eeh_outb(val, (unsigned long)port) +#define inw(port) eeh_inw((unsigned long)port) +#define outw(val, port) eeh_outw(val, (unsigned long)port) +#define inl(port) eeh_inl((unsigned long)port) +#define outl(val, port) eeh_outl(val, (unsigned long)port) /* * The insw/outsw/insl/outsl macros don't do byte-swapping. @@ -128,43 +134,32 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) #define insb(port, buf, ns) eeh_insb((port), (buf), (ns)) #define insw(port, buf, ns) eeh_insw_ns((port), (buf), (ns)) #define insl(port, buf, nl) eeh_insl_ns((port), (buf), (nl)) +#define insw_ns(port, buf, ns) eeh_insw_ns((port), (buf), (ns)) +#define insl_ns(port, buf, nl) eeh_insl_ns((port), (buf), (nl)) #define outsb(port, buf, ns) _outsb((u8 __iomem *)((port)+pci_io_base), (buf), (ns)) #define outsw(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns)) #define outsl(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl)) -#define readb(addr) eeh_readb(addr) -#define readw(addr) eeh_readw(addr) -#define readl(addr) eeh_readl(addr) -#define readq(addr) eeh_readq(addr) -#define writeb(data, addr) eeh_writeb((data), (addr)) -#define writew(data, addr) eeh_writew((data), (addr)) -#define writel(data, addr) eeh_writel((data), (addr)) -#define writeq(data, addr) eeh_writeq((data), (addr)) -#define inb(port) eeh_inb((unsigned long)port) -#define outb(val, port) eeh_outb(val, (unsigned long)port) -#define inw(port) eeh_inw((unsigned long)port) -#define outw(val, port) eeh_outw(val, (unsigned long)port) -#define inl(port) eeh_inl((unsigned long)port) -#define outl(val, port) eeh_outl(val, (unsigned long)port) +#endif #define readb_relaxed(addr) readb(addr) #define readw_relaxed(addr) readw(addr) #define readl_relaxed(addr) readl(addr) #define readq_relaxed(addr) readq(addr) -extern void _insb(volatile u8 __iomem *port, void *buf, long count); -extern void _outsb(volatile u8 __iomem *port, const void *buf, long count); -extern void _insw_ns(volatile u16 __iomem *port, void *buf, long count); -extern void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count); -extern void _insl_ns(volatile u32 __iomem *port, void *buf, long count); -extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count); +extern void _insb(volatile u8 __iomem *port, void *buf, int ns); +extern void _outsb(volatile u8 __iomem *port, const void *buf, int ns); +extern void _insw(volatile u16 __iomem *port, void *buf, int ns); +extern void _outsw(volatile u16 __iomem *port, const void *buf, int ns); +extern void _insl(volatile u32 __iomem *port, void *buf, int nl); +extern void _outsl(volatile u32 __iomem *port, const void *buf, int nl); +extern void _insw_ns(volatile u16 __iomem *port, void *buf, int ns); +extern void _outsw_ns(volatile u16 __iomem *port, const void *buf, int ns); +extern void _insl_ns(volatile u32 __iomem *port, void *buf, int nl); +extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, int nl); -static inline void mmiowb(void) -{ - __asm__ __volatile__ ("sync" : : : "memory"); - get_paca()->io_sync = 0; -} +#define mmiowb() /* * output pause versions need a delay at least for the @@ -177,6 +172,14 @@ static inline void mmiowb(void) #define inl_p(port) inl(port) #define outl_p(val, port) (udelay(1), outl((val), (port))) +/* + * The *_ns versions below don't do byte-swapping. + * Neither do the standard versions now, these are just here + * for older code. + */ +#define outsw_ns(port, buf, ns) _outsw_ns((u16 __iomem *)((port)+pci_io_base), (buf), (ns)) +#define outsl_ns(port, buf, nl) _outsl_ns((u32 __iomem *)((port)+pci_io_base), (buf), (nl)) + #define IO_SPACE_LIMIT ~(0UL) @@ -268,92 +271,86 @@ static inline void iosync(void) * and should not be used directly by device drivers. Use inb/readb * instead. */ -static inline int __in_8(const volatile unsigned char __iomem *addr) +static inline int in_8(const volatile unsigned char __iomem *addr) { int ret; - __asm__ __volatile__("sync; lbz%U1%X1 %0,%1; twi 0,%0,0; isync" + __asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync" : "=r" (ret) : "m" (*addr)); return ret; } -static inline void __out_8(volatile unsigned char __iomem *addr, int val) +static inline void out_8(volatile unsigned char __iomem *addr, int val) { - __asm__ __volatile__("sync; stb%U0%X0 %1,%0" + __asm__ __volatile__("stb%U0%X0 %1,%0; sync" : "=m" (*addr) : "r" (val)); - get_paca()->io_sync = 1; } -static inline int __in_le16(const volatile unsigned short __iomem *addr) +static inline int in_le16(const volatile unsigned short __iomem *addr) { int ret; - __asm__ __volatile__("sync; lhbrx %0,0,%1; twi 0,%0,0; isync" + __asm__ __volatile__("lhbrx %0,0,%1; twi 0,%0,0; isync" : "=r" (ret) : "r" (addr), "m" (*addr)); return ret; } -static inline int __in_be16(const volatile unsigned short __iomem *addr) +static inline int in_be16(const volatile unsigned short __iomem *addr) { int ret; - __asm__ __volatile__("sync; lhz%U1%X1 %0,%1; twi 0,%0,0; isync" + __asm__ __volatile__("lhz%U1%X1 %0,%1; twi 0,%0,0; isync" : "=r" (ret) : "m" (*addr)); return ret; } -static inline void __out_le16(volatile unsigned short __iomem *addr, int val) +static inline void out_le16(volatile unsigned short __iomem *addr, int val) { - __asm__ __volatile__("sync; sthbrx %1,0,%2" + __asm__ __volatile__("sthbrx %1,0,%2; sync" : "=m" (*addr) : "r" (val), "r" (addr)); - get_paca()->io_sync = 1; } -static inline void __out_be16(volatile unsigned short __iomem *addr, int val) +static inline void out_be16(volatile unsigned short __iomem *addr, int val) { - __asm__ __volatile__("sync; sth%U0%X0 %1,%0" + __asm__ __volatile__("sth%U0%X0 %1,%0; sync" : "=m" (*addr) : "r" (val)); - get_paca()->io_sync = 1; } -static inline unsigned __in_le32(const volatile unsigned __iomem *addr) +static inline unsigned in_le32(const volatile unsigned __iomem *addr) { unsigned ret; - __asm__ __volatile__("sync; lwbrx %0,0,%1; twi 0,%0,0; isync" + __asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync" : "=r" (ret) : "r" (addr), "m" (*addr)); return ret; } -static inline unsigned __in_be32(const volatile unsigned __iomem *addr) +static inline unsigned in_be32(const volatile unsigned __iomem *addr) { unsigned ret; - __asm__ __volatile__("sync; lwz%U1%X1 %0,%1; twi 0,%0,0; isync" + __asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync" : "=r" (ret) : "m" (*addr)); return ret; } -static inline void __out_le32(volatile unsigned __iomem *addr, int val) +static inline void out_le32(volatile unsigned __iomem *addr, int val) { - __asm__ __volatile__("sync; stwbrx %1,0,%2" : "=m" (*addr) + __asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr) : "r" (val), "r" (addr)); - get_paca()->io_sync = 1; } -static inline void __out_be32(volatile unsigned __iomem *addr, int val) +static inline void out_be32(volatile unsigned __iomem *addr, int val) { - __asm__ __volatile__("sync; stw%U0%X0 %1,%0" + __asm__ __volatile__("stw%U0%X0 %1,%0; sync" : "=m" (*addr) : "r" (val)); - get_paca()->io_sync = 1; } -static inline unsigned long __in_le64(const volatile unsigned long __iomem *addr) +static inline unsigned long in_le64(const volatile unsigned long __iomem *addr) { unsigned long tmp, ret; __asm__ __volatile__( - "sync\n" "ld %1,0(%2)\n" "twi 0,%1,0\n" "isync\n" @@ -368,16 +365,16 @@ static inline unsigned long __in_le64(const volatile unsigned long __iomem *addr return ret; } -static inline unsigned long __in_be64(const volatile unsigned long __iomem *addr) +static inline unsigned long in_be64(const volatile unsigned long __iomem *addr) { unsigned long ret; - __asm__ __volatile__("sync; ld%U1%X1 %0,%1; twi 0,%0,0; isync" + __asm__ __volatile__("ld%U1%X1 %0,%1; twi 0,%0,0; isync" : "=r" (ret) : "m" (*addr)); return ret; } -static inline void __out_le64(volatile unsigned long __iomem *addr, unsigned long val) +static inline void out_le64(volatile unsigned long __iomem *addr, unsigned long val) { unsigned long tmp; @@ -389,19 +386,19 @@ static inline void __out_le64(volatile unsigned long __iomem *addr, unsigned lon "rldicl %1,%1,32,0\n" "rlwimi %0,%1,8,8,31\n" "rlwimi %0,%1,24,16,23\n" - "sync\n" - "std %0,0(%3)" + "std %0,0(%3)\n" + "sync" : "=&r" (tmp) , "=&r" (val) : "1" (val) , "b" (addr) , "m" (*addr)); - get_paca()->io_sync = 1; } -static inline void __out_be64(volatile unsigned long __iomem *addr, unsigned long val) +static inline void out_be64(volatile unsigned long __iomem *addr, unsigned long val) { - __asm__ __volatile__("sync; std%U0%X0 %1,%0" : "=m" (*addr) : "r" (val)); - get_paca()->io_sync = 1; + __asm__ __volatile__("std%U0%X0 %1,%0; sync" : "=m" (*addr) : "r" (val)); } +#ifndef CONFIG_PPC_ISERIES #include +#endif /** * check_signature - find BIOS signatures @@ -417,6 +414,7 @@ static inline int check_signature(const volatile void __iomem * io_addr, const unsigned char *signature, int length) { int retval = 0; +#ifndef CONFIG_PPC_ISERIES do { if (readb(io_addr) != *signature) goto out; @@ -426,6 +424,7 @@ static inline int check_signature(const volatile void __iomem * io_addr, } while (length); retval = 1; out: +#endif return retval; } diff --git a/trunk/include/asm-powerpc/ipic.h b/trunk/include/asm-powerpc/ipic.h index 53079ec3a515..0fe396a2b666 100644 --- a/trunk/include/asm-powerpc/ipic.h +++ b/trunk/include/asm-powerpc/ipic.h @@ -69,6 +69,9 @@ enum ipic_mcp_irq { IPIC_MCP_MU = 7, }; +extern void ipic_init(phys_addr_t phys_addr, unsigned int flags, + unsigned int irq_offset, + unsigned char *senses, unsigned int senses_count); extern int ipic_set_priority(unsigned int irq, unsigned int priority); extern void ipic_set_highest_priority(unsigned int irq); extern void ipic_set_default_priority(void); @@ -76,16 +79,7 @@ extern void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq); extern void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq); extern u32 ipic_get_mcp_status(void); extern void ipic_clear_mcp_status(u32 mask); - -#ifdef CONFIG_PPC_MERGE -extern void ipic_init(struct device_node *node, unsigned int flags); -extern unsigned int ipic_get_irq(struct pt_regs *regs); -#else -extern void ipic_init(phys_addr_t phys_addr, unsigned int flags, - unsigned int irq_offset, - unsigned char *senses, unsigned int senses_count); extern int ipic_get_irq(struct pt_regs *regs); -#endif #endif /* __ASM_IPIC_H__ */ #endif /* __KERNEL__ */ diff --git a/trunk/include/asm-powerpc/irq.h b/trunk/include/asm-powerpc/irq.h index 4da41efb1319..d903a62959da 100644 --- a/trunk/include/asm-powerpc/irq.h +++ b/trunk/include/asm-powerpc/irq.h @@ -137,7 +137,7 @@ struct irq_map_entry { extern struct irq_map_entry irq_map[NR_IRQS]; -/** +/*** * irq_alloc_host - Allocate a new irq_host data structure * @node: device-tree node of the interrupt controller * @revmap_type: type of reverse mapping to use @@ -159,14 +159,14 @@ extern struct irq_host *irq_alloc_host(unsigned int revmap_type, irq_hw_number_t inval_irq); -/** +/*** * irq_find_host - Locates a host for a given device node * @node: device-tree node of the interrupt controller */ extern struct irq_host *irq_find_host(struct device_node *node); -/** +/*** * irq_set_default_host - Set a "default" host * @host: default host pointer * @@ -178,7 +178,7 @@ extern struct irq_host *irq_find_host(struct device_node *node); extern void irq_set_default_host(struct irq_host *host); -/** +/*** * irq_set_virq_count - Set the maximum number of virt irqs * @count: number of linux virtual irqs, capped with NR_IRQS * @@ -188,7 +188,7 @@ extern void irq_set_default_host(struct irq_host *host); extern void irq_set_virq_count(unsigned int count); -/** +/*** * irq_create_mapping - Map a hardware interrupt into linux virq space * @host: host owning this hardware interrupt or NULL for default host * @hwirq: hardware irq number in that host space @@ -202,13 +202,13 @@ extern unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq); -/** +/*** * irq_dispose_mapping - Unmap an interrupt * @virq: linux virq number of the interrupt to unmap */ extern void irq_dispose_mapping(unsigned int virq); -/** +/*** * irq_find_mapping - Find a linux virq from an hw irq number. * @host: host owning this hardware interrupt * @hwirq: hardware irq number in that host space @@ -221,7 +221,7 @@ extern unsigned int irq_find_mapping(struct irq_host *host, irq_hw_number_t hwirq); -/** +/*** * irq_radix_revmap - Find a linux virq from a hw irq number. * @host: host owning this hardware interrupt * @hwirq: hardware irq number in that host space @@ -232,7 +232,7 @@ extern unsigned int irq_find_mapping(struct irq_host *host, extern unsigned int irq_radix_revmap(struct irq_host *host, irq_hw_number_t hwirq); -/** +/*** * irq_linear_revmap - Find a linux virq from a hw irq number. * @host: host owning this hardware interrupt * @hwirq: hardware irq number in that host space @@ -247,7 +247,7 @@ extern unsigned int irq_linear_revmap(struct irq_host *host, -/** +/*** * irq_alloc_virt - Allocate virtual irq numbers * @host: host owning these new virtual irqs * @count: number of consecutive numbers to allocate @@ -261,7 +261,7 @@ extern unsigned int irq_alloc_virt(struct irq_host *host, unsigned int count, unsigned int hint); -/** +/*** * irq_free_virt - Free virtual irq numbers * @virq: virtual irq number of the first interrupt to free * @count: number of interrupts to free @@ -300,7 +300,7 @@ extern unsigned int irq_of_parse_and_map(struct device_node *dev, int index); /* -- End OF helpers -- */ -/** +/*** * irq_early_init - Init irq remapping subsystem */ extern void irq_early_init(void); diff --git a/trunk/include/asm-powerpc/iseries/hv_call_xm.h b/trunk/include/asm-powerpc/iseries/hv_call_xm.h index 392ac3f54df0..ca9202cb01ed 100644 --- a/trunk/include/asm-powerpc/iseries/hv_call_xm.h +++ b/trunk/include/asm-powerpc/iseries/hv_call_xm.h @@ -16,6 +16,23 @@ #define HvCallXmSetTce HvCallXm + 11 #define HvCallXmSetTces HvCallXm + 13 +/* + * Structure passed to HvCallXm_getTceTableParms + */ +struct iommu_table_cb { + unsigned long itc_busno; /* Bus number for this tce table */ + unsigned long itc_start; /* Will be NULL for secondary */ + unsigned long itc_totalsize; /* Size (in pages) of whole table */ + unsigned long itc_offset; /* Index into real tce table of the + start of our section */ + unsigned long itc_size; /* Size (in pages) of our section */ + unsigned long itc_index; /* Index of this tce table */ + unsigned short itc_maxtables; /* Max num of tables for partition */ + unsigned char itc_virtbus; /* Flag to indicate virtual bus */ + unsigned char itc_slotno; /* IOA Tce Slot Index */ + unsigned char itc_rsvd[4]; +}; + static inline void HvCallXm_getTceTableParms(u64 cb) { HvCall1(HvCallXmGetTceTableParms, cb); diff --git a/trunk/include/asm-powerpc/iseries/hv_lp_config.h b/trunk/include/asm-powerpc/iseries/hv_lp_config.h index a006fd1e4a2c..df8b20739719 100644 --- a/trunk/include/asm-powerpc/iseries/hv_lp_config.h +++ b/trunk/include/asm-powerpc/iseries/hv_lp_config.h @@ -25,6 +25,7 @@ #include #include +#include enum { HvCallCfg_Cur = 0, @@ -43,8 +44,16 @@ enum { #define HvCallCfgGetHostingLpIndex HvCallCfg + 32 extern HvLpIndex HvLpConfig_getLpIndex_outline(void); -extern HvLpIndex HvLpConfig_getLpIndex(void); -extern HvLpIndex HvLpConfig_getPrimaryLpIndex(void); + +static inline HvLpIndex HvLpConfig_getLpIndex(void) +{ + return itLpNaca.xLpIndex; +} + +static inline HvLpIndex HvLpConfig_getPrimaryLpIndex(void) +{ + return itLpNaca.xPrimaryLpIndex; +} static inline u64 HvLpConfig_getMsChunks(void) { diff --git a/trunk/include/asm-powerpc/iseries/iseries_io.h b/trunk/include/asm-powerpc/iseries/iseries_io.h new file mode 100644 index 000000000000..f29009bd63c9 --- /dev/null +++ b/trunk/include/asm-powerpc/iseries/iseries_io.h @@ -0,0 +1,60 @@ +#ifndef _ASM_POWERPC_ISERIES_ISERIES_IO_H +#define _ASM_POWERPC_ISERIES_ISERIES_IO_H + + +#ifdef CONFIG_PPC_ISERIES +#include +/* + * Created by Allan Trautman on Thu Dec 28 2000. + * + * Remaps the io.h for the iSeries Io + * Copyright (C) 2000 Allan H Trautman, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + * + * Change Activity: + * Created December 28, 2000 + * End Change Activity + */ + +#ifdef CONFIG_PCI +extern u8 iSeries_Read_Byte(const volatile void __iomem * IoAddress); +extern u16 iSeries_Read_Word(const volatile void __iomem * IoAddress); +extern u32 iSeries_Read_Long(const volatile void __iomem * IoAddress); +extern void iSeries_Write_Byte(u8 IoData, volatile void __iomem * IoAddress); +extern void iSeries_Write_Word(u16 IoData, volatile void __iomem * IoAddress); +extern void iSeries_Write_Long(u32 IoData, volatile void __iomem * IoAddress); + +extern void iSeries_memset_io(volatile void __iomem *dest, char x, size_t n); +extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, + size_t n); +extern void iSeries_memcpy_fromio(void *dest, + const volatile void __iomem *source, size_t n); +#else +static inline u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress) +{ + return 0xff; +} + +static inline void iSeries_Write_Byte(u8 IoData, + volatile void __iomem *IoAddress) +{ +} +#endif /* CONFIG_PCI */ + +#endif /* CONFIG_PPC_ISERIES */ +#endif /* _ASM_POWERPC_ISERIES_ISERIES_IO_H */ diff --git a/trunk/arch/powerpc/platforms/iseries/it_exp_vpd_panel.h b/trunk/include/asm-powerpc/iseries/it_exp_vpd_panel.h similarity index 89% rename from trunk/arch/powerpc/platforms/iseries/it_exp_vpd_panel.h rename to trunk/include/asm-powerpc/iseries/it_exp_vpd_panel.h index 6de9097b7f57..304a609ae21a 100644 --- a/trunk/arch/powerpc/platforms/iseries/it_exp_vpd_panel.h +++ b/trunk/include/asm-powerpc/iseries/it_exp_vpd_panel.h @@ -15,8 +15,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _PLATFORMS_ISERIES_IT_EXT_VPD_PANEL_H -#define _PLATFORMS_ISERIES_IT_EXT_VPD_PANEL_H +#ifndef _ASM_POWERPC_ISERIES_IT_EXT_VPD_PANEL_H +#define _ASM_POWERPC_ISERIES_IT_EXT_VPD_PANEL_H /* * This struct maps the panel information @@ -48,4 +48,4 @@ struct ItExtVpdPanel { extern struct ItExtVpdPanel xItExtVpdPanel; -#endif /* _PLATFORMS_ISERIES_IT_EXT_VPD_PANEL_H */ +#endif /* _ASM_POWERPC_ISERIES_IT_EXT_VPD_PANEL_H */ diff --git a/trunk/arch/powerpc/platforms/iseries/it_lp_naca.h b/trunk/include/asm-powerpc/iseries/it_lp_naca.h similarity index 96% rename from trunk/arch/powerpc/platforms/iseries/it_lp_naca.h rename to trunk/include/asm-powerpc/iseries/it_lp_naca.h index 9bbf58986819..4fdcf052927f 100644 --- a/trunk/arch/powerpc/platforms/iseries/it_lp_naca.h +++ b/trunk/include/asm-powerpc/iseries/it_lp_naca.h @@ -15,8 +15,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef _PLATFORMS_ISERIES_IT_LP_NACA_H -#define _PLATFORMS_ISERIES_IT_LP_NACA_H +#ifndef _ASM_POWERPC_ISERIES_IT_LP_NACA_H +#define _ASM_POWERPC_ISERIES_IT_LP_NACA_H #include @@ -77,4 +77,4 @@ extern struct ItLpNaca itLpNaca; #define ITLPNACA_HWSYNCEDTBS 0x20 /* Hardware synced TBs */ #define ITLPNACA_HMTINT 0x10 /* Utilize MHT for interrupts */ -#endif /* _PLATFORMS_ISERIES_IT_LP_NACA_H */ +#endif /* _ASM_POWERPC_ISERIES_IT_LP_NACA_H */ diff --git a/trunk/include/asm-powerpc/iseries/it_lp_queue.h b/trunk/include/asm-powerpc/iseries/it_lp_queue.h index 3f6814769295..284c5a7db3ac 100644 --- a/trunk/include/asm-powerpc/iseries/it_lp_queue.h +++ b/trunk/include/asm-powerpc/iseries/it_lp_queue.h @@ -27,6 +27,8 @@ #include #include +struct HvLpEvent; + #define IT_LP_MAX_QUEUES 8 #define IT_LP_NOT_USED 0 /* Queue will not be used by PLIC */ diff --git a/trunk/include/asm-powerpc/iseries/vio.h b/trunk/include/asm-powerpc/iseries/vio.h index 7a95d296abd1..72a97d37aac3 100644 --- a/trunk/include/asm-powerpc/iseries/vio.h +++ b/trunk/include/asm-powerpc/iseries/vio.h @@ -122,34 +122,6 @@ enum viorc { viorc_openRejected = 0x0301 }; -/* - * The structure of the events that flow between us and OS/400 for chario - * events. You can't mess with this unless the OS/400 side changes too. - */ -struct viocharlpevent { - struct HvLpEvent event; - u32 reserved; - u16 version; - u16 subtype_result_code; - u8 virtual_device; - u8 len; - u8 data[VIOCHAR_MAX_DATA]; -}; - -#define VIOCHAR_WINDOW 10 - -enum viocharsubtype { - viocharopen = 0x0001, - viocharclose = 0x0002, - viochardata = 0x0003, - viocharack = 0x0004, - viocharconfig = 0x0005 -}; - -enum viochar_rc { - viochar_rc_ebusy = 1 -}; - struct device; extern struct device *iSeries_vio_dev; diff --git a/trunk/include/asm-powerpc/kdump.h b/trunk/include/asm-powerpc/kdump.h index 10e8eb1e6f4f..dc1574c945f8 100644 --- a/trunk/include/asm-powerpc/kdump.h +++ b/trunk/include/asm-powerpc/kdump.h @@ -7,7 +7,7 @@ /* How many bytes to reserve at zero for kdump. The reserve limit should * be greater or equal to the trampoline's end address. * Reserve to the end of the FWNMI area, see head_64.S */ -#define KDUMP_RESERVE_LIMIT 0x10000 /* 64K */ +#define KDUMP_RESERVE_LIMIT 0x8000 #ifdef CONFIG_CRASH_DUMP diff --git a/trunk/include/asm-powerpc/kexec.h b/trunk/include/asm-powerpc/kexec.h index 11cbdf81fd2e..8f7fd5cfec34 100644 --- a/trunk/include/asm-powerpc/kexec.h +++ b/trunk/include/asm-powerpc/kexec.h @@ -32,7 +32,6 @@ #endif #ifndef __ASSEMBLY__ -#include #ifdef CONFIG_KEXEC @@ -110,6 +109,7 @@ static inline void crash_setup_regs(struct pt_regs *newregs, #define MAX_NOTE_BYTES 1024 +#ifdef __powerpc64__ extern void kexec_smp_wait(void); /* get and clear naca physid, wait for master to copy new code to 0 */ extern int crashing_cpu; @@ -119,6 +119,7 @@ static inline int kexec_sr_activated(int cpu) { return cpu_isset(cpu,cpus_in_sr); } +#endif /* __powerpc64 __ */ struct kimage; struct pt_regs; diff --git a/trunk/include/asm-powerpc/kprobes.h b/trunk/include/asm-powerpc/kprobes.h index 34e1f89a5fa0..2d0af52c823d 100644 --- a/trunk/include/asm-powerpc/kprobes.h +++ b/trunk/include/asm-powerpc/kprobes.h @@ -51,7 +51,6 @@ typedef unsigned int kprobe_opcode_t; #define ARCH_SUPPORTS_KRETPROBES #define ARCH_INACTIVE_KPROBE_COUNT 1 -#define flush_insn_slot(p) do { } while (0) void kretprobe_trampoline(void); extern void arch_remove_kprobe(struct kprobe *p); diff --git a/trunk/include/asm-powerpc/lppaca.h b/trunk/include/asm-powerpc/lppaca.h index 821ea0c512b4..4dc514aabfe7 100644 --- a/trunk/include/asm-powerpc/lppaca.h +++ b/trunk/include/asm-powerpc/lppaca.h @@ -27,9 +27,7 @@ // // //---------------------------------------------------------------------------- -#include #include -#include /* The Hypervisor barfs if the lppaca crosses a page boundary. A 1k * alignment is sufficient to prevent this */ @@ -116,7 +114,7 @@ struct lppaca { //============================================================================= -// CACHE_LINE_3 0x0100 - 0x017F: This line is shared with other processors +// CACHE_LINE_3 0x0100 - 0x007F: This line is shared with other processors //============================================================================= // This is the yield_count. An "odd" value (low bit on) means that // the processor is yielded (either because of an OS yield or a PLIC @@ -128,29 +126,12 @@ struct lppaca { u8 reserved6[124]; // Reserved x04-x7F //============================================================================= -// CACHE_LINE_4-5 0x0180 - 0x027F Contains PMC interrupt data +// CACHE_LINE_4-5 0x0100 - 0x01FF Contains PMC interrupt data //============================================================================= u8 pmc_save_area[256]; // PMC interrupt Area x00-xFF } __attribute__((__aligned__(0x400))); extern struct lppaca lppaca[]; -/* - * SLB shadow buffer structure as defined in the PAPR. The save_area - * contains adjacent ESID and VSID pairs for each shadowed SLB. The - * ESID is stored in the lower 64bits, then the VSID. - */ -struct slb_shadow { - u32 persistent; // Number of persistent SLBs x00-x03 - u32 buffer_length; // Total shadow buffer length x04-x07 - u64 reserved; // Alignment x08-x0f - struct { - u64 esid; - u64 vsid; - } save_area[SLB_NUM_BOLTED]; // x10-x40 -} ____cacheline_aligned; - -extern struct slb_shadow slb_shadow[]; - #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_LPPACA_H */ diff --git a/trunk/include/asm-powerpc/mpc86xx.h b/trunk/include/asm-powerpc/mpc86xx.h index b85df45b1a84..f260382739fa 100644 --- a/trunk/include/asm-powerpc/mpc86xx.h +++ b/trunk/include/asm-powerpc/mpc86xx.h @@ -23,6 +23,8 @@ #define _ISA_MEM_BASE isa_mem_base #ifdef CONFIG_PCI #define PCI_DRAM_OFFSET pci_dram_offset +#else +#define PCI_DRAM_OFFSET 0 #endif #define CPU0_BOOT_RELEASE 0x01000000 @@ -31,6 +33,7 @@ #define MCM_PORT_CONFIG_OFFSET 0x1010 /* Offset from CCSRBAR */ +#define MPC86xx_OPENPIC_OFFSET (0x40000) #define MPC86xx_MCM_OFFSET (0x00000) #define MPC86xx_MCM_SIZE (0x02000) diff --git a/trunk/include/asm-powerpc/mpic.h b/trunk/include/asm-powerpc/mpic.h index a9f9604b9eff..eb241c99c457 100644 --- a/trunk/include/asm-powerpc/mpic.h +++ b/trunk/include/asm-powerpc/mpic.h @@ -41,7 +41,6 @@ #define MPIC_GREG_IPI_VECTOR_PRI_1 0x000b0 #define MPIC_GREG_IPI_VECTOR_PRI_2 0x000c0 #define MPIC_GREG_IPI_VECTOR_PRI_3 0x000d0 -#define MPIC_GREG_IPI_STRIDE 0x10 #define MPIC_GREG_SPURIOUS 0x000e0 #define MPIC_GREG_TIMER_FREQ 0x000f0 @@ -69,7 +68,6 @@ #define MPIC_CPU_IPI_DISPATCH_1 0x00050 #define MPIC_CPU_IPI_DISPATCH_2 0x00060 #define MPIC_CPU_IPI_DISPATCH_3 0x00070 -#define MPIC_CPU_IPI_DISPATCH_STRIDE 0x00010 #define MPIC_CPU_CURRENT_TASK_PRI 0x00080 #define MPIC_CPU_TASKPRI_MASK 0x0000000f #define MPIC_CPU_WHOAMI 0x00090 @@ -116,103 +114,6 @@ #define MPIC_VEC_TIMER_1 248 #define MPIC_VEC_TIMER_0 247 -/* - * Tsi108 implementation of MPIC has many differences from the original one - */ - -/* - * Global registers - */ - -#define TSI108_GREG_BASE 0x00000 -#define TSI108_GREG_FEATURE_0 0x00000 -#define TSI108_GREG_GLOBAL_CONF_0 0x00004 -#define TSI108_GREG_VENDOR_ID 0x0000c -#define TSI108_GREG_IPI_VECTOR_PRI_0 0x00204 /* Doorbell 0 */ -#define TSI108_GREG_IPI_STRIDE 0x0c -#define TSI108_GREG_SPURIOUS 0x00010 -#define TSI108_GREG_TIMER_FREQ 0x00014 - -/* - * Timer registers - */ -#define TSI108_TIMER_BASE 0x0030 -#define TSI108_TIMER_STRIDE 0x10 -#define TSI108_TIMER_CURRENT_CNT 0x00000 -#define TSI108_TIMER_BASE_CNT 0x00004 -#define TSI108_TIMER_VECTOR_PRI 0x00008 -#define TSI108_TIMER_DESTINATION 0x0000c - -/* - * Per-Processor registers - */ -#define TSI108_CPU_BASE 0x00300 -#define TSI108_CPU_STRIDE 0x00040 -#define TSI108_CPU_IPI_DISPATCH_0 0x00200 -#define TSI108_CPU_IPI_DISPATCH_STRIDE 0x00000 -#define TSI108_CPU_CURRENT_TASK_PRI 0x00000 -#define TSI108_CPU_WHOAMI 0xffffffff -#define TSI108_CPU_INTACK 0x00004 -#define TSI108_CPU_EOI 0x00008 - -/* - * Per-source registers - */ -#define TSI108_IRQ_BASE 0x00100 -#define TSI108_IRQ_STRIDE 0x00008 -#define TSI108_IRQ_VECTOR_PRI 0x00000 -#define TSI108_VECPRI_VECTOR_MASK 0x000000ff -#define TSI108_VECPRI_POLARITY_POSITIVE 0x01000000 -#define TSI108_VECPRI_POLARITY_NEGATIVE 0x00000000 -#define TSI108_VECPRI_SENSE_LEVEL 0x02000000 -#define TSI108_VECPRI_SENSE_EDGE 0x00000000 -#define TSI108_VECPRI_POLARITY_MASK 0x01000000 -#define TSI108_VECPRI_SENSE_MASK 0x02000000 -#define TSI108_IRQ_DESTINATION 0x00004 - -/* weird mpic register indices and mask bits in the HW info array */ -enum { - MPIC_IDX_GREG_BASE = 0, - MPIC_IDX_GREG_FEATURE_0, - MPIC_IDX_GREG_GLOBAL_CONF_0, - MPIC_IDX_GREG_VENDOR_ID, - MPIC_IDX_GREG_IPI_VECTOR_PRI_0, - MPIC_IDX_GREG_IPI_STRIDE, - MPIC_IDX_GREG_SPURIOUS, - MPIC_IDX_GREG_TIMER_FREQ, - - MPIC_IDX_TIMER_BASE, - MPIC_IDX_TIMER_STRIDE, - MPIC_IDX_TIMER_CURRENT_CNT, - MPIC_IDX_TIMER_BASE_CNT, - MPIC_IDX_TIMER_VECTOR_PRI, - MPIC_IDX_TIMER_DESTINATION, - - MPIC_IDX_CPU_BASE, - MPIC_IDX_CPU_STRIDE, - MPIC_IDX_CPU_IPI_DISPATCH_0, - MPIC_IDX_CPU_IPI_DISPATCH_STRIDE, - MPIC_IDX_CPU_CURRENT_TASK_PRI, - MPIC_IDX_CPU_WHOAMI, - MPIC_IDX_CPU_INTACK, - MPIC_IDX_CPU_EOI, - - MPIC_IDX_IRQ_BASE, - MPIC_IDX_IRQ_STRIDE, - MPIC_IDX_IRQ_VECTOR_PRI, - - MPIC_IDX_VECPRI_VECTOR_MASK, - MPIC_IDX_VECPRI_POLARITY_POSITIVE, - MPIC_IDX_VECPRI_POLARITY_NEGATIVE, - MPIC_IDX_VECPRI_SENSE_LEVEL, - MPIC_IDX_VECPRI_SENSE_EDGE, - MPIC_IDX_VECPRI_POLARITY_MASK, - MPIC_IDX_VECPRI_SENSE_MASK, - MPIC_IDX_IRQ_DESTINATION, - MPIC_IDX_END -}; - - #ifdef CONFIG_MPIC_BROKEN_U3 /* Fixup table entry */ struct mpic_irq_fixup @@ -270,29 +171,15 @@ struct mpic volatile u32 __iomem *cpuregs[MPIC_MAX_CPUS]; volatile u32 __iomem *isus[MPIC_MAX_ISU]; -#ifdef CONFIG_MPIC_WEIRD - /* Pointer to HW info array */ - u32 *hw_set; -#endif - /* link */ struct mpic *next; }; -/* - * MPIC flags (passed to mpic_alloc) - * - * The top 4 bits contain an MPIC bhw id that is used to index the - * register offsets and some masks when CONFIG_MPIC_WEIRD is set. - * Note setting any ID (leaving those bits to 0) means standard MPIC - */ - /* This is the primary controller, only that one has IPIs and * has afinity control. A non-primary MPIC always uses CPU0 * registers only */ #define MPIC_PRIMARY 0x00000001 - /* Set this for a big-endian MPIC */ #define MPIC_BIG_ENDIAN 0x00000002 /* Broken U3 MPIC */ @@ -301,18 +188,6 @@ struct mpic #define MPIC_BROKEN_IPI 0x00000008 /* MPIC wants a reset */ #define MPIC_WANTS_RESET 0x00000010 -/* Spurious vector requires EOI */ -#define MPIC_SPV_EOI 0x00000020 -/* No passthrough disable */ -#define MPIC_NO_PTHROU_DIS 0x00000040 - -/* MPIC HW modification ID */ -#define MPIC_REGSET_MASK 0xf0000000 -#define MPIC_REGSET(val) (((val) & 0xf ) << 28) -#define MPIC_GET_REGSET(flags) (((flags) >> 28) & 0xf) - -#define MPIC_REGSET_STANDARD MPIC_REGSET(0) /* Original MPIC */ -#define MPIC_REGSET_TSI108 MPIC_REGSET(1) /* Tsi108/109 PIC */ /* Allocate the controller structure and setup the linux irq descs * for the range if interrupts passed in. No HW initialization is diff --git a/trunk/include/asm-powerpc/paca.h b/trunk/include/asm-powerpc/paca.h index 0a4e5c93e8e6..2d4585f06209 100644 --- a/trunk/include/asm-powerpc/paca.h +++ b/trunk/include/asm-powerpc/paca.h @@ -23,7 +23,6 @@ register struct paca_struct *local_paca asm("r13"); #define get_paca() local_paca #define get_lppaca() (get_paca()->lppaca_ptr) -#define get_slb_shadow() (get_paca()->slb_shadow_ptr) struct task_struct; @@ -94,14 +93,11 @@ struct paca_struct { u64 saved_r1; /* r1 save for RTAS calls */ u64 saved_msr; /* MSR saved here by enter_rtas */ u8 proc_enabled; /* irq soft-enable flag */ - u8 io_sync; /* writel() needs spin_unlock sync */ /* Stuff for accurate time accounting */ u64 user_time; /* accumulated usermode TB ticks */ u64 system_time; /* accumulated system TB ticks */ u64 startpurr; /* PURR/TB value snapshot */ - - struct slb_shadow *slb_shadow_ptr; }; extern struct paca_struct paca[]; diff --git a/trunk/include/asm-powerpc/page.h b/trunk/include/asm-powerpc/page.h index b4d38b0b15f8..fb597b37c2a2 100644 --- a/trunk/include/asm-powerpc/page.h +++ b/trunk/include/asm-powerpc/page.h @@ -55,6 +55,12 @@ #define PAGE_OFFSET ASM_CONST(CONFIG_KERNEL_START) #define KERNELBASE (PAGE_OFFSET + PHYSICAL_START) +#ifdef CONFIG_DISCONTIGMEM +#define page_to_pfn(page) discontigmem_page_to_pfn(page) +#define pfn_to_page(pfn) discontigmem_pfn_to_page(pfn) +#define pfn_valid(pfn) discontigmem_pfn_valid(pfn) +#endif + #ifdef CONFIG_FLATMEM #define pfn_valid(pfn) ((pfn) < max_mapnr) #endif diff --git a/trunk/include/asm-powerpc/pgalloc.h b/trunk/include/asm-powerpc/pgalloc.h index ae63db7b3e7d..9f0917c68659 100644 --- a/trunk/include/asm-powerpc/pgalloc.h +++ b/trunk/include/asm-powerpc/pgalloc.h @@ -117,7 +117,7 @@ static inline void pte_free(struct page *ptepage) pte_free_kernel(page_address(ptepage)); } -#define PGF_CACHENUM_MASK 0x3 +#define PGF_CACHENUM_MASK 0xf typedef struct pgtable_free { unsigned long val; diff --git a/trunk/include/asm-powerpc/ppc-pci.h b/trunk/include/asm-powerpc/ppc-pci.h index 1115756c79f9..cf79bc7ebb55 100644 --- a/trunk/include/asm-powerpc/ppc-pci.h +++ b/trunk/include/asm-powerpc/ppc-pci.h @@ -68,17 +68,6 @@ struct pci_dev *pci_get_device_by_addr(unsigned long addr); */ void eeh_slot_error_detail (struct pci_dn *pdn, int severity); -/** - * rtas_pci_enableo - enable IO transfers for this slot - * @pdn: pci device node - * @function: either EEH_THAW_MMIO or EEH_THAW_DMA - * - * Enable I/O transfers to this slot - */ -#define EEH_THAW_MMIO 2 -#define EEH_THAW_DMA 3 -int rtas_pci_enable(struct pci_dn *pdn, int function); - /** * rtas_set_slot_reset -- unfreeze a frozen slot * diff --git a/trunk/include/asm-powerpc/processor.h b/trunk/include/asm-powerpc/processor.h index 6cb6fb19e57f..22e54a2a6604 100644 --- a/trunk/include/asm-powerpc/processor.h +++ b/trunk/include/asm-powerpc/processor.h @@ -32,7 +32,6 @@ #define _CHRP_Motorola 0x04 /* motorola chrp, the cobra */ #define _CHRP_IBM 0x05 /* IBM chrp, the longtrail and longtrail 2 */ #define _CHRP_Pegasos 0x06 /* Genesi/bplan's Pegasos and Pegasos2 */ -#define _CHRP_briq 0x07 /* TotalImpact's briQ */ #if defined(__KERNEL__) && defined(CONFIG_PPC32) diff --git a/trunk/include/asm-powerpc/prom.h b/trunk/include/asm-powerpc/prom.h index 524629769336..b095a285c84b 100644 --- a/trunk/include/asm-powerpc/prom.h +++ b/trunk/include/asm-powerpc/prom.h @@ -72,8 +72,8 @@ struct property { }; struct device_node { - const char *name; - const char *type; + char *name; + char *type; phandle node; phandle linux_phandle; char *full_name; @@ -160,7 +160,7 @@ extern void unflatten_device_tree(void); extern void early_init_devtree(void *); extern int device_is_compatible(struct device_node *device, const char *); extern int machine_is_compatible(const char *compat); -extern const void *get_property(struct device_node *node, const char *name, +extern void *get_property(struct device_node *node, const char *name, int *lenp); extern void print_properties(struct device_node *node); extern int prom_n_addr_cells(struct device_node* np); @@ -197,8 +197,8 @@ extern int release_OF_resource(struct device_node* node, int index); */ -/* Helper to read a big number; size is in cells (not bytes) */ -static inline u64 of_read_number(const u32 *cell, int size) +/* Helper to read a big number */ +static inline u64 of_read_number(u32 *cell, int size) { u64 r = 0; while (size--) @@ -206,28 +206,18 @@ static inline u64 of_read_number(const u32 *cell, int size) return r; } -/* Like of_read_number, but we want an unsigned long result */ -#ifdef CONFIG_PPC32 -static inline unsigned long of_read_ulong(const u32 *cell, int size) -{ - return cell[size-1]; -} -#else -#define of_read_ulong(cell, size) of_read_number(cell, size) -#endif - /* Translate an OF address block into a CPU physical address */ #define OF_BAD_ADDR ((u64)-1) -extern u64 of_translate_address(struct device_node *np, const u32 *addr); +extern u64 of_translate_address(struct device_node *np, u32 *addr); /* Extract an address from a device, returns the region size and * the address space flags too. The PCI version uses a BAR number * instead of an absolute index */ -extern const u32 *of_get_address(struct device_node *dev, int index, +extern u32 *of_get_address(struct device_node *dev, int index, u64 *size, unsigned int *flags); -extern const u32 *of_get_pci_address(struct device_node *dev, int bar_no, +extern u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, unsigned int *flags); /* Get an address as a resource. Note that if your address is @@ -244,7 +234,7 @@ extern int of_pci_address_to_resource(struct device_node *dev, int bar, /* Parse the ibm,dma-window property of an OF node into the busno, phys and * size parameters. */ -void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop, +void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop, unsigned long *busno, unsigned long *phys, unsigned long *size); extern void kdump_move_device_tree(void); @@ -269,7 +259,7 @@ struct of_irq { u32 specifier[OF_MAX_IRQ_SPEC]; /* Specifier copy */ }; -/** +/*** * of_irq_map_init - Initialize the irq remapper * @flags: flags defining workarounds to enable * @@ -282,11 +272,10 @@ struct of_irq { extern void of_irq_map_init(unsigned int flags); -/** +/*** * of_irq_map_raw - Low level interrupt tree parsing * @parent: the device interrupt parent * @intspec: interrupt specifier ("interrupts" property of the device) - * @ointsize: size of the passed in interrupt specifier * @addr: address specifier (start of "reg" property of the device) * @out_irq: structure of_irq filled by this function * @@ -299,12 +288,11 @@ extern void of_irq_map_init(unsigned int flags); * */ -extern int of_irq_map_raw(struct device_node *parent, const u32 *intspec, - u32 ointsize, const u32 *addr, +extern int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr, struct of_irq *out_irq); -/** +/*** * of_irq_map_one - Resolve an interrupt for a device * @device: the device whose interrupt is to be resolved * @index: index of the interrupt to resolve @@ -317,7 +305,7 @@ extern int of_irq_map_raw(struct device_node *parent, const u32 *intspec, extern int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq); -/** +/*** * of_irq_map_pci - Resolve the interrupt for a PCI device * @pdev: the device whose interrupt is to be resolved * @out_irq: structure of_irq filled by this function diff --git a/trunk/include/asm-powerpc/ptrace.h b/trunk/include/asm-powerpc/ptrace.h index 4435efe85d0e..dc4cb9cc73a1 100644 --- a/trunk/include/asm-powerpc/ptrace.h +++ b/trunk/include/asm-powerpc/ptrace.h @@ -215,10 +215,12 @@ do { \ #define PTRACE_GETVRREGS 18 #define PTRACE_SETVRREGS 19 +#ifndef __powerpc64__ /* Get/set all the upper 32-bits of the SPE registers, accumulator, and * spefscr, in one go */ #define PTRACE_GETEVRREGS 20 #define PTRACE_SETEVRREGS 21 +#endif /* __powerpc64__ */ /* * Get or set a debug register. The first 16 are DABR registers and the @@ -233,6 +235,7 @@ do { \ #define PPC_PTRACE_GETFPREGS 0x97 /* Get FPRs 0 - 31 */ #define PPC_PTRACE_SETFPREGS 0x96 /* Set FPRs 0 - 31 */ +#ifdef __powerpc64__ /* Calls to trace a 64bit program from a 32bit program */ #define PPC_PTRACE_PEEKTEXT_3264 0x95 #define PPC_PTRACE_PEEKDATA_3264 0x94 @@ -240,5 +243,6 @@ do { \ #define PPC_PTRACE_POKEDATA_3264 0x92 #define PPC_PTRACE_PEEKUSR_3264 0x91 #define PPC_PTRACE_POKEUSR_3264 0x90 +#endif /* __powerpc64__ */ #endif /* _ASM_POWERPC_PTRACE_H */ diff --git a/trunk/include/asm-powerpc/reg.h b/trunk/include/asm-powerpc/reg.h index 3a9fcc15811b..cf73475a0c69 100644 --- a/trunk/include/asm-powerpc/reg.h +++ b/trunk/include/asm-powerpc/reg.h @@ -592,7 +592,6 @@ #define PV_630p 0x0041 #define PV_970MP 0x0044 #define PV_BE 0x0070 -#define PV_PA6T 0x0090 /* * Number of entries in the SLB. If this ever changes we should handle diff --git a/trunk/include/asm-powerpc/rtas.h b/trunk/include/asm-powerpc/rtas.h index d34f9e1f242c..a33c6acffa61 100644 --- a/trunk/include/asm-powerpc/rtas.h +++ b/trunk/include/asm-powerpc/rtas.h @@ -170,7 +170,6 @@ extern int rtas_get_sensor(int sensor, int index, int *state); extern int rtas_get_power_level(int powerdomain, int *level); extern int rtas_set_power_level(int powerdomain, int level, int *setlevel); extern int rtas_set_indicator(int indicator, int index, int new_value); -extern int rtas_set_indicator_fast(int indicator, int index, int new_value); extern void rtas_progress(char *s, unsigned short hex); extern void rtas_initialize(void); @@ -230,21 +229,5 @@ extern unsigned long rtas_rmo_buf; #define GLOBAL_INTERRUPT_QUEUE 9005 -/** - * rtas_config_addr - Format a busno, devfn and reg for RTAS. - * @busno: The bus number. - * @devfn: The device and function number as encoded by PCI_DEVFN(). - * @reg: The register number. - * - * This function encodes the given busno, devfn and register number as - * required for RTAS calls that take a "config_addr" parameter. - * See PAPR requirement 7.3.4-1 for more info. - */ -static inline u32 rtas_config_addr(int busno, int devfn, int reg) -{ - return ((reg & 0xf00) << 20) | ((busno & 0xff) << 16) | - (devfn << 8) | (reg & 0xff); -} - #endif /* __KERNEL__ */ #endif /* _POWERPC_RTAS_H */ diff --git a/trunk/include/asm-powerpc/smu.h b/trunk/include/asm-powerpc/smu.h index e49f644ca63a..51e65fc46a03 100644 --- a/trunk/include/asm-powerpc/smu.h +++ b/trunk/include/asm-powerpc/smu.h @@ -517,7 +517,7 @@ struct smu_sdbp_cpupiddata { * This returns the pointer to an SMU "sdb" partition data or NULL * if not found. The data format is described below */ -extern const struct smu_sdbp_header *smu_get_sdb_partition(int id, +extern struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size); /* Get "sdb" partition data from an SMU satellite */ diff --git a/trunk/include/asm-powerpc/spinlock.h b/trunk/include/asm-powerpc/spinlock.h index c31e4382a775..895cb6d3a42a 100644 --- a/trunk/include/asm-powerpc/spinlock.h +++ b/trunk/include/asm-powerpc/spinlock.h @@ -36,19 +36,6 @@ #define LOCK_TOKEN 1 #endif -#if defined(CONFIG_PPC64) && defined(CONFIG_SMP) -#define CLEAR_IO_SYNC (get_paca()->io_sync = 0) -#define SYNC_IO do { \ - if (unlikely(get_paca()->io_sync)) { \ - mb(); \ - get_paca()->io_sync = 0; \ - } \ - } while (0) -#else -#define CLEAR_IO_SYNC -#define SYNC_IO -#endif - /* * This returns the old value in the lock, so we succeeded * in getting the lock if the return value is 0. @@ -74,7 +61,6 @@ static __inline__ unsigned long __spin_trylock(raw_spinlock_t *lock) static int __inline__ __raw_spin_trylock(raw_spinlock_t *lock) { - CLEAR_IO_SYNC; return __spin_trylock(lock) == 0; } @@ -105,7 +91,6 @@ extern void __rw_yield(raw_rwlock_t *lock); static void __inline__ __raw_spin_lock(raw_spinlock_t *lock) { - CLEAR_IO_SYNC; while (1) { if (likely(__spin_trylock(lock) == 0)) break; @@ -122,7 +107,6 @@ static void __inline__ __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long { unsigned long flags_dis; - CLEAR_IO_SYNC; while (1) { if (likely(__spin_trylock(lock) == 0)) break; @@ -140,7 +124,6 @@ static void __inline__ __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long static __inline__ void __raw_spin_unlock(raw_spinlock_t *lock) { - SYNC_IO; __asm__ __volatile__("# __raw_spin_unlock\n\t" LWSYNC_ON_SMP: : :"memory"); lock->slock = 0; diff --git a/trunk/include/asm-powerpc/spu.h b/trunk/include/asm-powerpc/spu.h index b42b53c40f5d..c02d105d8294 100644 --- a/trunk/include/asm-powerpc/spu.h +++ b/trunk/include/asm-powerpc/spu.h @@ -106,7 +106,7 @@ struct spu_context; struct spu_runqueue; struct spu { - const char *name; + char *name; unsigned long local_store_phys; u8 *local_store; unsigned long problem_phys; diff --git a/trunk/include/asm-powerpc/system.h b/trunk/include/asm-powerpc/system.h index 4b41deaa8d8d..7307aa775671 100644 --- a/trunk/include/asm-powerpc/system.h +++ b/trunk/include/asm-powerpc/system.h @@ -53,15 +53,6 @@ #define smp_read_barrier_depends() do { } while(0) #endif /* CONFIG_SMP */ -/* - * This is a barrier which prevents following instructions from being - * started until the value of the argument x is known. For example, if - * x is a variable loaded from memory, this prevents following - * instructions from being executed until the load has been performed. - */ -#define data_barrier(x) \ - asm volatile("twi 0,%0,0; isync" : : "r" (x) : "memory"); - struct task_struct; struct pt_regs; @@ -177,6 +168,11 @@ extern u32 booke_wdt_enabled; extern u32 booke_wdt_period; #endif /* CONFIG_BOOKE_WDT */ +/* EBCDIC -> ASCII conversion for [0-9A-Z] on iSeries */ +extern unsigned char e2a(unsigned char); +extern unsigned char* strne2a(unsigned char *dest, + const unsigned char *src, size_t n); + struct device_node; extern void note_scsi_host(struct device_node *, void *); diff --git a/trunk/include/asm-powerpc/time.h b/trunk/include/asm-powerpc/time.h index 5785ac4737b5..dcde4410348d 100644 --- a/trunk/include/asm-powerpc/time.h +++ b/trunk/include/asm-powerpc/time.h @@ -30,6 +30,10 @@ extern unsigned long tb_ticks_per_usec; extern unsigned long tb_ticks_per_sec; extern u64 tb_to_xs; extern unsigned tb_to_us; +extern unsigned long tb_last_stamp; +extern u64 tb_last_jiffy; + +DECLARE_PER_CPU(unsigned long, last_jiffy); struct rtc_time; extern void to_tm(int tim, struct rtc_time * tm); diff --git a/trunk/include/asm-powerpc/tsi108.h b/trunk/include/asm-powerpc/tsi108.h index 2c702d35a7cf..c4c278d72f71 100644 --- a/trunk/include/asm-powerpc/tsi108.h +++ b/trunk/include/asm-powerpc/tsi108.h @@ -1,18 +1,16 @@ /* + * include/asm-ppc/tsi108.h + * * common routine and memory layout for Tundra TSI108(Grendel) host bridge * memory controller. * * Author: Jacob Pan (jacob.pan@freescale.com) * Alex Bounine (alexandreb@tundra.com) - * - * Copyright 2004-2006 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. + * 2004 (c) Freescale Semiconductor Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. */ - #ifndef __PPC_KERNEL_TSI108_H #define __PPC_KERNEL_TSI108_H diff --git a/trunk/include/asm-powerpc/tsi108_irq.h b/trunk/include/asm-powerpc/tsi108_irq.h deleted file mode 100644 index 3e4d04effa57..000000000000 --- a/trunk/include/asm-powerpc/tsi108_irq.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * (C) Copyright 2005 Tundra Semiconductor Corp. - * Alex Bounine, diff --git a/trunk/include/asm-ppc/io.h b/trunk/include/asm-ppc/io.h index 3d9a9e6f3321..89c6f1bc3aab 100644 --- a/trunk/include/asm-ppc/io.h +++ b/trunk/include/asm-ppc/io.h @@ -63,7 +63,7 @@ extern inline int in_8(const volatile unsigned char __iomem *addr) int ret; __asm__ __volatile__( - "sync; lbz%U1%X1 %0,%1;\n" + "lbz%U1%X1 %0,%1;\n" "twi 0,%0,0;\n" "isync" : "=r" (ret) : "m" (*addr)); return ret; @@ -78,7 +78,7 @@ extern inline int in_le16(const volatile unsigned short __iomem *addr) { int ret; - __asm__ __volatile__("sync; lhbrx %0,0,%1;\n" + __asm__ __volatile__("lhbrx %0,0,%1;\n" "twi 0,%0,0;\n" "isync" : "=r" (ret) : "r" (addr), "m" (*addr)); @@ -89,7 +89,7 @@ extern inline int in_be16(const volatile unsigned short __iomem *addr) { int ret; - __asm__ __volatile__("sync; lhz%U1%X1 %0,%1;\n" + __asm__ __volatile__("lhz%U1%X1 %0,%1;\n" "twi 0,%0,0;\n" "isync" : "=r" (ret) : "m" (*addr)); return ret; @@ -97,20 +97,20 @@ extern inline int in_be16(const volatile unsigned short __iomem *addr) extern inline void out_le16(volatile unsigned short __iomem *addr, int val) { - __asm__ __volatile__("sync; sthbrx %1,0,%2" : "=m" (*addr) : + __asm__ __volatile__("sthbrx %1,0,%2; eieio" : "=m" (*addr) : "r" (val), "r" (addr)); } extern inline void out_be16(volatile unsigned short __iomem *addr, int val) { - __asm__ __volatile__("sync; sth%U0%X0 %1,%0" : "=m" (*addr) : "r" (val)); + __asm__ __volatile__("sth%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); } extern inline unsigned in_le32(const volatile unsigned __iomem *addr) { unsigned ret; - __asm__ __volatile__("sync; lwbrx %0,0,%1;\n" + __asm__ __volatile__("lwbrx %0,0,%1;\n" "twi 0,%0,0;\n" "isync" : "=r" (ret) : "r" (addr), "m" (*addr)); @@ -121,7 +121,7 @@ extern inline unsigned in_be32(const volatile unsigned __iomem *addr) { unsigned ret; - __asm__ __volatile__("sync; lwz%U1%X1 %0,%1;\n" + __asm__ __volatile__("lwz%U1%X1 %0,%1;\n" "twi 0,%0,0;\n" "isync" : "=r" (ret) : "m" (*addr)); return ret; @@ -129,13 +129,13 @@ extern inline unsigned in_be32(const volatile unsigned __iomem *addr) extern inline void out_le32(volatile unsigned __iomem *addr, int val) { - __asm__ __volatile__("sync; stwbrx %1,0,%2" : "=m" (*addr) : + __asm__ __volatile__("stwbrx %1,0,%2; eieio" : "=m" (*addr) : "r" (val), "r" (addr)); } extern inline void out_be32(volatile unsigned __iomem *addr, int val) { - __asm__ __volatile__("sync; stw%U0%X0 %1,%0" : "=m" (*addr) : "r" (val)); + __asm__ __volatile__("stw%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); } #if defined (CONFIG_8260_PCI9) #define readb(addr) in_8((volatile u8 *)(addr)) @@ -259,7 +259,6 @@ extern __inline__ unsigned int name(unsigned int port) \ { \ unsigned int x; \ __asm__ __volatile__( \ - "sync\n" \ "0:" op " %0,0,%1\n" \ "1: twi 0,%0,0\n" \ "2: isync\n" \ @@ -285,7 +284,6 @@ extern __inline__ unsigned int name(unsigned int port) \ extern __inline__ void name(unsigned int val, unsigned int port) \ { \ __asm__ __volatile__( \ - "sync\n" \ "0:" op " %0,0,%1\n" \ "1: sync\n" \ "2:\n" \ @@ -327,12 +325,26 @@ __do_out_asm(outl, "stwbrx") #define inl_p(port) inl((port)) #define outl_p(val, port) outl((val), (port)) -extern void _insb(volatile u8 __iomem *port, void *buf, long count); -extern void _outsb(volatile u8 __iomem *port, const void *buf, long count); -extern void _insw_ns(volatile u16 __iomem *port, void *buf, long count); -extern void _outsw_ns(volatile u16 __iomem *port, const void *buf, long count); -extern void _insl_ns(volatile u32 __iomem *port, void *buf, long count); -extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, long count); +extern void _insb(volatile u8 __iomem *port, void *buf, int ns); +extern void _outsb(volatile u8 __iomem *port, const void *buf, int ns); +extern void _insw(volatile u16 __iomem *port, void *buf, int ns); +extern void _outsw(volatile u16 __iomem *port, const void *buf, int ns); +extern void _insl(volatile u32 __iomem *port, void *buf, int nl); +extern void _outsl(volatile u32 __iomem *port, const void *buf, int nl); +extern void _insw_ns(volatile u16 __iomem *port, void *buf, int ns); +extern void _outsw_ns(volatile u16 __iomem *port, const void *buf, int ns); +extern void _insl_ns(volatile u32 __iomem *port, void *buf, int nl); +extern void _outsl_ns(volatile u32 __iomem *port, const void *buf, int nl); + +/* + * The *_ns versions below don't do byte-swapping. + * Neither do the standard versions now, these are just here + * for older code. + */ +#define insw_ns(port, buf, ns) _insw_ns((port)+___IO_BASE, (buf), (ns)) +#define outsw_ns(port, buf, ns) _outsw_ns((port)+___IO_BASE, (buf), (ns)) +#define insl_ns(port, buf, nl) _insl_ns((port)+___IO_BASE, (buf), (nl)) +#define outsl_ns(port, buf, nl) _outsl_ns((port)+___IO_BASE, (buf), (nl)) #define IO_SPACE_LIMIT ~0 diff --git a/trunk/include/asm-ppc/mpc8260.h b/trunk/include/asm-ppc/mpc8260.h index 23579d4afae7..4b93481e7679 100644 --- a/trunk/include/asm-ppc/mpc8260.h +++ b/trunk/include/asm-ppc/mpc8260.h @@ -82,7 +82,6 @@ enum ppc_sys_devices { MPC82xx_CPM_SMC2, MPC82xx_CPM_USB, MPC82xx_SEC1, - MPC82xx_MDIO_BB, NUM_PPC_SYS_DEVS, }; diff --git a/trunk/include/asm-ppc/mpc8260_pci9.h b/trunk/include/asm-ppc/mpc8260_pci9.h index 9f7176881c56..26b3f6e787bc 100644 --- a/trunk/include/asm-ppc/mpc8260_pci9.h +++ b/trunk/include/asm-ppc/mpc8260_pci9.h @@ -30,6 +30,8 @@ #undef inb #undef inw #undef inl +#undef insw_ns +#undef insl_ns #undef memcpy_fromio extern int readb(volatile unsigned char *addr); @@ -41,6 +43,8 @@ extern void insl(unsigned port, void *buf, int nl); extern int inb(unsigned port); extern int inw(unsigned port); extern unsigned inl(unsigned port); +extern void insw_ns(unsigned port, void *buf, int ns); +extern void insl_ns(unsigned port, void *buf, int nl); extern void *memcpy_fromio(void *dest, unsigned long src, size_t count); #endif /* !__CONFIG_8260_PCI9_DEFS */ diff --git a/trunk/include/asm-ppc/mpc8xx.h b/trunk/include/asm-ppc/mpc8xx.h index d3a2f2fe230c..adcce33f20ae 100644 --- a/trunk/include/asm-ppc/mpc8xx.h +++ b/trunk/include/asm-ppc/mpc8xx.h @@ -110,7 +110,6 @@ enum ppc_sys_devices { MPC8xx_CPM_SMC1, MPC8xx_CPM_SMC2, MPC8xx_CPM_USB, - MPC8xx_MDIO_FEC, NUM_PPC_SYS_DEVS, }; diff --git a/trunk/include/asm-ppc/reg_booke.h b/trunk/include/asm-ppc/reg_booke.h index 602fbadeaf48..4944c0fb8bea 100644 --- a/trunk/include/asm-ppc/reg_booke.h +++ b/trunk/include/asm-ppc/reg_booke.h @@ -300,14 +300,14 @@ do { \ #define DBSR_IC 0x80000000 /* Instruction Completion */ #define DBSR_BT 0x40000000 /* Branch taken */ #define DBSR_TIE 0x10000000 /* Trap Instruction debug Event */ -#define DBSR_IAC1 0x04000000 /* Instruction Address Compare 1 Event */ -#define DBSR_IAC2 0x02000000 /* Instruction Address Compare 2 Event */ -#define DBSR_IAC3 0x00080000 /* Instruction Address Compare 3 Event */ -#define DBSR_IAC4 0x00040000 /* Instruction Address Compare 4 Event */ -#define DBSR_DAC1R 0x01000000 /* Data Address Compare 1 Read Event */ -#define DBSR_DAC1W 0x00800000 /* Data Address Compare 1 Write Event */ -#define DBSR_DAC2R 0x00400000 /* Data Address Compare 2 Read Event */ -#define DBSR_DAC2W 0x00200000 /* Data Address Compare 2 Write Event */ +#define DBSR_IAC1 0x00800000 /* Instruction Address Compare 1 Event */ +#define DBSR_IAC2 0x00400000 /* Instruction Address Compare 2 Event */ +#define DBSR_IAC3 0x00200000 /* Instruction Address Compare 3 Event */ +#define DBSR_IAC4 0x00100000 /* Instruction Address Compare 4 Event */ +#define DBSR_DAC1R 0x00080000 /* Data Address Compare 1 Read Event */ +#define DBSR_DAC1W 0x00040000 /* Data Address Compare 1 Write Event */ +#define DBSR_DAC2R 0x00020000 /* Data Address Compare 2 Read Event */ +#define DBSR_DAC2W 0x00010000 /* Data Address Compare 2 Write Event */ #endif /* Bit definitions related to the ESR. */ diff --git a/trunk/include/asm-s390/Kbuild b/trunk/include/asm-s390/Kbuild index 088969d55e72..ed8955f49e47 100644 --- a/trunk/include/asm-s390/Kbuild +++ b/trunk/include/asm-s390/Kbuild @@ -1,12 +1,4 @@ include include/asm-generic/Kbuild.asm -header-y += dasd.h -header-y += monwriter.h -header-y += qeth.h -header-y += tape390.h -header-y += ucontext.h -header-y += vtoc.h -header-y += z90crypt.h - -unifdef-y += cmb.h -unifdef-y += debug.h +unifdef-y += cmb.h debug.h +header-y += dasd.h qeth.h tape390.h ucontext.h vtoc.h z90crypt.h diff --git a/trunk/include/asm-s390/appldata.h b/trunk/include/asm-s390/appldata.h deleted file mode 100644 index b1770703b706..000000000000 --- a/trunk/include/asm-s390/appldata.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * include/asm-s390/appldata.h - * - * Copyright (C) IBM Corp. 2006 - * - * Author(s): Melissa Howland - */ - -#ifndef _ASM_S390_APPLDATA_H -#define _ASM_S390_APPLDATA_H - -#include - -#ifndef CONFIG_64BIT - -#define APPLDATA_START_INTERVAL_REC 0x00 /* Function codes for */ -#define APPLDATA_STOP_REC 0x01 /* DIAG 0xDC */ -#define APPLDATA_GEN_EVENT_REC 0x02 -#define APPLDATA_START_CONFIG_REC 0x03 - -/* - * Parameter list for DIAGNOSE X'DC' - */ -struct appldata_parameter_list { - u16 diag; /* The DIAGNOSE code X'00DC' */ - u8 function; /* The function code for the DIAGNOSE */ - u8 parlist_length; /* Length of the parameter list */ - u32 product_id_addr; /* Address of the 16-byte product ID */ - u16 reserved; - u16 buffer_length; /* Length of the application data buffer */ - u32 buffer_addr; /* Address of the application data buffer */ -} __attribute__ ((packed)); - -#else /* CONFIG_64BIT */ - -#define APPLDATA_START_INTERVAL_REC 0x80 -#define APPLDATA_STOP_REC 0x81 -#define APPLDATA_GEN_EVENT_REC 0x82 -#define APPLDATA_START_CONFIG_REC 0x83 - -/* - * Parameter list for DIAGNOSE X'DC' - */ -struct appldata_parameter_list { - u16 diag; - u8 function; - u8 parlist_length; - u32 unused01; - u16 reserved; - u16 buffer_length; - u32 unused02; - u64 product_id_addr; - u64 buffer_addr; -} __attribute__ ((packed)); - -#endif /* CONFIG_64BIT */ - -struct appldata_product_id { - char prod_nr[7]; /* product number */ - u16 prod_fn; /* product function */ - u8 record_nr; /* record number */ - u16 version_nr; /* version */ - u16 release_nr; /* release */ - u16 mod_lvl; /* modification level */ -} __attribute__ ((packed)); - -static inline int appldata_asm(struct appldata_product_id *id, - unsigned short fn, void *buffer, - unsigned short length) -{ - struct appldata_parameter_list parm_list; - int ry; - - if (!MACHINE_IS_VM) - return -ENOSYS; - parm_list.diag = 0xdc; - parm_list.function = fn; - parm_list.parlist_length = sizeof(parm_list); - parm_list.buffer_length = length; - parm_list.product_id_addr = (unsigned long) id; - parm_list.buffer_addr = virt_to_phys(buffer); - asm volatile( - "diag %1,%0,0xdc" - : "=d" (ry) - : "d" (&parm_list), "m" (parm_list), "m" (*id) - : "cc"); - return ry; -} - -#endif /* _ASM_S390_APPLDATA_H */ diff --git a/trunk/include/asm-s390/cio.h b/trunk/include/asm-s390/cio.h index da063cd5f0a0..28fdd6e2b8ba 100644 --- a/trunk/include/asm-s390/cio.h +++ b/trunk/include/asm-s390/cio.h @@ -270,11 +270,6 @@ struct diag210 { __u32 vrdccrft : 8; /* real device feature (output) */ } __attribute__ ((packed,aligned(4))); -struct ccw_dev_id { - u8 ssid; - u16 devno; -}; - extern int diag210(struct diag210 *addr); extern void wait_cons_dev(void); @@ -285,8 +280,6 @@ extern void cio_reset_channel_paths(void); extern void css_schedule_reprobe(void); -extern void reipl_ccw_dev(struct ccw_dev_id *id); - #endif #endif diff --git a/trunk/include/asm-s390/debug.h b/trunk/include/asm-s390/debug.h index c00dd2b3dc50..7f1ef99fd1e1 100644 --- a/trunk/include/asm-s390/debug.h +++ b/trunk/include/asm-s390/debug.h @@ -10,6 +10,7 @@ #define DEBUG_H #include +#include /* Note: * struct __debug_entry must be defined outside of #ifdef __KERNEL__ @@ -34,7 +35,6 @@ struct __debug_entry{ #define __DEBUG_FEATURE_VERSION 2 /* version of debug feature */ #ifdef __KERNEL__ -#include #include #include #include diff --git a/trunk/include/asm-s390/dma.h b/trunk/include/asm-s390/dma.h index 7425c6af6cd4..02720c449cd8 100644 --- a/trunk/include/asm-s390/dma.h +++ b/trunk/include/asm-s390/dma.h @@ -11,6 +11,6 @@ #define MAX_DMA_ADDRESS 0x80000000 -#define free_dma(x) do { } while (0) +#define free_dma(x) #endif /* _ASM_DMA_H */ diff --git a/trunk/include/asm-s390/elf.h b/trunk/include/asm-s390/elf.h index c0d629d61d3e..710646e64f7d 100644 --- a/trunk/include/asm-s390/elf.h +++ b/trunk/include/asm-s390/elf.h @@ -92,30 +92,29 @@ /* Keep this the last entry. */ #define R_390_NUM 61 -/* - * These are used to set parameters in the core dumps. - */ -#ifndef __s390x__ -#define ELF_CLASS ELFCLASS32 -#else /* __s390x__ */ -#define ELF_CLASS ELFCLASS64 -#endif /* __s390x__ */ -#define ELF_DATA ELFDATA2MSB -#define ELF_ARCH EM_S390 - /* * ELF register definitions.. */ +#include /* for task_struct */ #include #include +#include /* for save_access_regs */ + typedef s390_fp_regs elf_fpregset_t; typedef s390_regs elf_gregset_t; -#ifdef __KERNEL__ -#include /* for task_struct */ -#include /* for save_access_regs */ +/* + * These are used to set parameters in the core dumps. + */ +#ifndef __s390x__ +#define ELF_CLASS ELFCLASS32 +#else /* __s390x__ */ +#define ELF_CLASS ELFCLASS64 +#endif /* __s390x__ */ +#define ELF_DATA ELFDATA2MSB +#define ELF_ARCH EM_S390 /* * This is used to ensure we don't load something for the wrong architecture. @@ -199,6 +198,7 @@ static inline int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs) #define ELF_PLATFORM (NULL) +#ifdef __KERNEL__ #ifndef __s390x__ #define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) #else /* __s390x__ */ diff --git a/trunk/include/asm-s390/futex.h b/trunk/include/asm-s390/futex.h index 5e261e1de671..ffedf14f89f6 100644 --- a/trunk/include/asm-s390/futex.h +++ b/trunk/include/asm-s390/futex.h @@ -7,21 +7,75 @@ #include #include +#ifndef __s390x__ +#define __futex_atomic_fixup \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,4b,2b,4b,3b,4b\n" \ + ".previous" +#else /* __s390x__ */ +#define __futex_atomic_fixup \ + ".section __ex_table,\"a\"\n" \ + " .align 8\n" \ + " .quad 0b,4b,2b,4b,3b,4b\n" \ + ".previous" +#endif /* __s390x__ */ + +#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg) \ + asm volatile(" sacf 256\n" \ + "0: l %1,0(%6)\n" \ + "1: " insn \ + "2: cs %1,%2,0(%6)\n" \ + "3: jl 1b\n" \ + " lhi %0,0\n" \ + "4: sacf 0\n" \ + __futex_atomic_fixup \ + : "=d" (ret), "=&d" (oldval), "=&d" (newval), \ + "=m" (*uaddr) \ + : "0" (-EFAULT), "d" (oparg), "a" (uaddr), \ + "m" (*uaddr) : "cc" ); + static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) { int op = (encoded_op >> 28) & 7; int cmp = (encoded_op >> 24) & 15; int oparg = (encoded_op << 8) >> 20; int cmparg = (encoded_op << 20) >> 20; - int oldval, ret; - + int oldval = 0, newval, ret; if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - ret = uaccess.futex_atomic_op(op, uaddr, oparg, &oldval); + inc_preempt_count(); + + switch (op) { + case FUTEX_OP_SET: + __futex_atomic_op("lr %2,%5\n", + ret, oldval, newval, uaddr, oparg); + break; + case FUTEX_OP_ADD: + __futex_atomic_op("lr %2,%1\nar %2,%5\n", + ret, oldval, newval, uaddr, oparg); + break; + case FUTEX_OP_OR: + __futex_atomic_op("lr %2,%1\nor %2,%5\n", + ret, oldval, newval, uaddr, oparg); + break; + case FUTEX_OP_ANDN: + __futex_atomic_op("lr %2,%1\nnr %2,%5\n", + ret, oldval, newval, uaddr, oparg); + break; + case FUTEX_OP_XOR: + __futex_atomic_op("lr %2,%1\nxr %2,%5\n", + ret, oldval, newval, uaddr, oparg); + break; + default: + ret = -ENOSYS; + } + + dec_preempt_count(); if (!ret) { switch (cmp) { @@ -37,13 +91,32 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) return ret; } -static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, - int oldval, int newval) +static inline int +futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) { + int ret; + if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - - return uaccess.futex_atomic_cmpxchg(uaddr, oldval, newval); + asm volatile(" sacf 256\n" + " cs %1,%4,0(%5)\n" + "0: lr %0,%1\n" + "1: sacf 0\n" +#ifndef __s390x__ + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 0b,1b\n" + ".previous" +#else /* __s390x__ */ + ".section __ex_table,\"a\"\n" + " .align 8\n" + " .quad 0b,1b\n" + ".previous" +#endif /* __s390x__ */ + : "=d" (ret), "+d" (oldval), "=m" (*uaddr) + : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr) + : "cc", "memory" ); + return oldval; } #endif /* __KERNEL__ */ diff --git a/trunk/include/asm-s390/io.h b/trunk/include/asm-s390/io.h index a6cc27e77007..d4614b35f423 100644 --- a/trunk/include/asm-s390/io.h +++ b/trunk/include/asm-s390/io.h @@ -116,7 +116,7 @@ extern void iounmap(void *addr); #define outb(x,addr) ((void) writeb(x,addr)) #define outb_p(x,addr) outb(x,addr) -#define mmiowb() do { } while (0) +#define mmiowb() /* * Convert a physical pointer to a virtual kernel pointer for /dev/mem diff --git a/trunk/include/asm-s390/kdebug.h b/trunk/include/asm-s390/kdebug.h deleted file mode 100644 index 40cc68025e01..000000000000 --- a/trunk/include/asm-s390/kdebug.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _S390_KDEBUG_H -#define _S390_KDEBUG_H - -/* - * Feb 2006 Ported to s390 - */ -#include - -struct pt_regs; - -struct die_args { - struct pt_regs *regs; - const char *str; - long err; - int trapnr; - int signr; -}; - -/* Note - you should never unregister because that can race with NMIs. - * If you really want to do it first unregister - then synchronize_sched - * - then free. - */ -extern int register_die_notifier(struct notifier_block *); -extern int unregister_die_notifier(struct notifier_block *); -extern int register_page_fault_notifier(struct notifier_block *); -extern int unregister_page_fault_notifier(struct notifier_block *); -extern struct atomic_notifier_head s390die_chain; - - -enum die_val { - DIE_OOPS = 1, - DIE_BPT, - DIE_SSTEP, - DIE_PANIC, - DIE_NMI, - DIE_DIE, - DIE_NMIWATCHDOG, - DIE_KERNELDEBUG, - DIE_TRAP, - DIE_GPF, - DIE_CALL, - DIE_NMI_IPI, - DIE_PAGE_FAULT, -}; - -static inline int notify_die(enum die_val val, const char *str, - struct pt_regs *regs, long err, int trap, int sig) -{ - struct die_args args = { - .regs = regs, - .str = str, - .err = err, - .trapnr = trap, - .signr = sig - }; - return atomic_notifier_call_chain(&s390die_chain, val, &args); -} - -#endif diff --git a/trunk/include/asm-s390/kprobes.h b/trunk/include/asm-s390/kprobes.h deleted file mode 100644 index b847ff0ec3fa..000000000000 --- a/trunk/include/asm-s390/kprobes.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef _ASM_S390_KPROBES_H -#define _ASM_S390_KPROBES_H -/* - * Kernel Probes (KProbes) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * Copyright (C) IBM Corporation, 2002, 2006 - * - * 2002-Oct Created by Vamsi Krishna S Kernel - * Probes initial implementation ( includes suggestions from - * Rusty Russell). - * 2004-Nov Modified for PPC64 by Ananth N Mavinakayanahalli - * - * 2005-Dec Used as a template for s390 by Mike Grundy - * - */ -#include -#include -#include - -#define __ARCH_WANT_KPROBES_INSN_SLOT -struct pt_regs; -struct kprobe; - -typedef u16 kprobe_opcode_t; -#define BREAKPOINT_INSTRUCTION 0x0002 - -/* Maximum instruction size is 3 (16bit) halfwords: */ -#define MAX_INSN_SIZE 0x0003 -#define MAX_STACK_SIZE 64 -#define MIN_STACK_SIZE(ADDR) (((MAX_STACK_SIZE) < \ - (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) \ - ? (MAX_STACK_SIZE) \ - : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) - -#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)(pentry) - -#define ARCH_SUPPORTS_KRETPROBES -#define ARCH_INACTIVE_KPROBE_COUNT 0 - -#define KPROBE_SWAP_INST 0x10 - -#define FIXUP_PSW_NORMAL 0x08 -#define FIXUP_BRANCH_NOT_TAKEN 0x04 -#define FIXUP_RETURN_REGISTER 0x02 -#define FIXUP_NOT_REQUIRED 0x01 - -/* Architecture specific copy of original instruction */ -struct arch_specific_insn { - /* copy of original instruction */ - kprobe_opcode_t *insn; - int fixup; - int ilen; - int reg; -}; - -struct ins_replace_args { - kprobe_opcode_t *ptr; - kprobe_opcode_t old; - kprobe_opcode_t new; -}; -struct prev_kprobe { - struct kprobe *kp; - unsigned long status; - unsigned long saved_psw; - unsigned long kprobe_saved_imask; - unsigned long kprobe_saved_ctl[3]; -}; - -/* per-cpu kprobe control block */ -struct kprobe_ctlblk { - unsigned long kprobe_status; - unsigned long kprobe_saved_imask; - unsigned long kprobe_saved_ctl[3]; - struct pt_regs jprobe_saved_regs; - unsigned long jprobe_saved_r14; - unsigned long jprobe_saved_r15; - struct prev_kprobe prev_kprobe; - kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE]; -}; - -void arch_remove_kprobe(struct kprobe *p); -void kretprobe_trampoline(void); -int is_prohibited_opcode(kprobe_opcode_t *instruction); -void get_instruction_type(struct arch_specific_insn *ainsn); - -#define flush_insn_slot(p) do { } while (0) - -#endif /* _ASM_S390_KPROBES_H */ - -#ifdef CONFIG_KPROBES - -extern int kprobe_exceptions_notify(struct notifier_block *self, - unsigned long val, void *data); -#else /* !CONFIG_KPROBES */ -static inline int kprobe_exceptions_notify(struct notifier_block *self, - unsigned long val, void *data) -{ - return 0; -} -#endif diff --git a/trunk/include/asm-s390/lowcore.h b/trunk/include/asm-s390/lowcore.h index 18695d10dedf..596c8b172104 100644 --- a/trunk/include/asm-s390/lowcore.h +++ b/trunk/include/asm-s390/lowcore.h @@ -35,7 +35,6 @@ #define __LC_IO_NEW_PSW 0x01f0 #endif /* !__s390x__ */ -#define __LC_IPL_PARMBLOCK_PTR 0x014 #define __LC_EXT_PARAMS 0x080 #define __LC_CPU_ADDRESS 0x084 #define __LC_EXT_INT_CODE 0x086 @@ -48,7 +47,6 @@ #define __LC_PER_ATMID 0x096 #define __LC_PER_ADDRESS 0x098 #define __LC_PER_ACCESS_ID 0x0A1 -#define __LC_AR_MODE_ID 0x0A3 #define __LC_SUBCHANNEL_ID 0x0B8 #define __LC_SUBCHANNEL_NR 0x0BA @@ -108,28 +106,18 @@ #define __LC_INT_CLOCK 0xDE8 #endif /* __s390x__ */ +#define __LC_PANIC_MAGIC 0xE00 -#define __LC_PANIC_MAGIC 0xE00 #ifndef __s390x__ #define __LC_PFAULT_INTPARM 0x080 #define __LC_CPU_TIMER_SAVE_AREA 0x0D8 -#define __LC_CLOCK_COMP_SAVE_AREA 0x0E0 -#define __LC_PSW_SAVE_AREA 0x100 -#define __LC_PREFIX_SAVE_AREA 0x108 #define __LC_AREGS_SAVE_AREA 0x120 -#define __LC_FPREGS_SAVE_AREA 0x160 #define __LC_GPREGS_SAVE_AREA 0x180 #define __LC_CREGS_SAVE_AREA 0x1C0 #else /* __s390x__ */ #define __LC_PFAULT_INTPARM 0x11B8 -#define __LC_FPREGS_SAVE_AREA 0x1200 #define __LC_GPREGS_SAVE_AREA 0x1280 -#define __LC_PSW_SAVE_AREA 0x1300 -#define __LC_PREFIX_SAVE_AREA 0x1318 -#define __LC_FP_CREG_SAVE_AREA 0x131C -#define __LC_TODREG_SAVE_AREA 0x1324 #define __LC_CPU_TIMER_SAVE_AREA 0x1328 -#define __LC_CLOCK_COMP_SAVE_AREA 0x1331 #define __LC_AREGS_SAVE_AREA 0x1340 #define __LC_CREGS_SAVE_AREA 0x1380 #endif /* __s390x__ */ diff --git a/trunk/include/asm-s390/monwriter.h b/trunk/include/asm-s390/monwriter.h deleted file mode 100644 index f0cbf96c52e6..000000000000 --- a/trunk/include/asm-s390/monwriter.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * include/asm-s390/monwriter.h - * - * Copyright (C) IBM Corp. 2006 - * Character device driver for writing z/VM APPLDATA monitor records - * Version 1.0 - * Author(s): Melissa Howland - * - */ - -#ifndef _ASM_390_MONWRITER_H -#define _ASM_390_MONWRITER_H - -/* mon_function values */ -#define MONWRITE_START_INTERVAL 0x00 /* start interval recording */ -#define MONWRITE_STOP_INTERVAL 0x01 /* stop interval or config recording */ -#define MONWRITE_GEN_EVENT 0x02 /* generate event record */ -#define MONWRITE_START_CONFIG 0x03 /* start configuration recording */ - -/* the header the app uses in its write() data */ -struct monwrite_hdr { - unsigned char mon_function; - unsigned short applid; - unsigned char record_num; - unsigned short version; - unsigned short release; - unsigned short mod_level; - unsigned short datalen; - unsigned char hdrlen; - -} __attribute__((packed)); - -#endif /* _ASM_390_MONWRITER_H */ diff --git a/trunk/include/asm-s390/pgalloc.h b/trunk/include/asm-s390/pgalloc.h index 803bc7064418..a78e853e0dd5 100644 --- a/trunk/include/asm-s390/pgalloc.h +++ b/trunk/include/asm-s390/pgalloc.h @@ -21,16 +21,6 @@ extern void diag10(unsigned long addr); -/* - * Page allocation orders. - */ -#ifndef __s390x__ -# define PGD_ALLOC_ORDER 1 -#else /* __s390x__ */ -# define PMD_ALLOC_ORDER 2 -# define PGD_ALLOC_ORDER 2 -#endif /* __s390x__ */ - /* * Allocate and free page tables. The xxx_kernel() versions are * used to allocate a kernel page table - this turns on ASN bits @@ -39,23 +29,30 @@ extern void diag10(unsigned long addr); static inline pgd_t *pgd_alloc(struct mm_struct *mm) { - pgd_t *pgd = (pgd_t *) __get_free_pages(GFP_KERNEL, PGD_ALLOC_ORDER); + pgd_t *pgd; int i; - if (!pgd) - return NULL; - for (i = 0; i < PTRS_PER_PGD; i++) #ifndef __s390x__ - pmd_clear(pmd_offset(pgd + i, i*PGDIR_SIZE)); -#else - pgd_clear(pgd + i); -#endif + pgd = (pgd_t *) __get_free_pages(GFP_KERNEL,1); + if (pgd != NULL) + for (i = 0; i < USER_PTRS_PER_PGD; i++) + pmd_clear(pmd_offset(pgd + i, i*PGDIR_SIZE)); +#else /* __s390x__ */ + pgd = (pgd_t *) __get_free_pages(GFP_KERNEL,2); + if (pgd != NULL) + for (i = 0; i < PTRS_PER_PGD; i++) + pgd_clear(pgd + i); +#endif /* __s390x__ */ return pgd; } static inline void pgd_free(pgd_t *pgd) { - free_pages((unsigned long) pgd, PGD_ALLOC_ORDER); +#ifndef __s390x__ + free_pages((unsigned long) pgd, 1); +#else /* __s390x__ */ + free_pages((unsigned long) pgd, 2); +#endif /* __s390x__ */ } #ifndef __s390x__ @@ -71,19 +68,20 @@ static inline void pgd_free(pgd_t *pgd) #else /* __s390x__ */ static inline pmd_t * pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr) { - pmd_t *pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, PMD_ALLOC_ORDER); - int i; + pmd_t *pmd; + int i; - if (!pmd) - return NULL; - for (i=0; i < PTRS_PER_PMD; i++) - pmd_clear(pmd + i); + pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, 2); + if (pmd != NULL) { + for (i=0; i < PTRS_PER_PMD; i++) + pmd_clear(pmd+i); + } return pmd; } static inline void pmd_free (pmd_t *pmd) { - free_pages((unsigned long) pmd, PMD_ALLOC_ORDER); + free_pages((unsigned long) pmd, 2); } #define __pmd_free_tlb(tlb,pmd) \ @@ -125,14 +123,15 @@ pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page) static inline pte_t * pte_alloc_one_kernel(struct mm_struct *mm, unsigned long vmaddr) { - pte_t *pte = (pte_t *) __get_free_page(GFP_KERNEL|__GFP_REPEAT); - int i; - - if (!pte) - return NULL; - for (i=0; i < PTRS_PER_PTE; i++) { - pte_clear(mm, vmaddr, pte + i); - vmaddr += PAGE_SIZE; + pte_t *pte; + int i; + + pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT); + if (pte != NULL) { + for (i=0; i < PTRS_PER_PTE; i++) { + pte_clear(mm, vmaddr, pte+i); + vmaddr += PAGE_SIZE; + } } return pte; } diff --git a/trunk/include/asm-s390/pgtable.h b/trunk/include/asm-s390/pgtable.h index 1a07028d575e..24312387fa24 100644 --- a/trunk/include/asm-s390/pgtable.h +++ b/trunk/include/asm-s390/pgtable.h @@ -89,6 +89,19 @@ extern char empty_zero_page[PAGE_SIZE]; # define PTRS_PER_PGD 2048 #endif /* __s390x__ */ +/* + * pgd entries used up by user/kernel: + */ +#ifndef __s390x__ +# define USER_PTRS_PER_PGD 512 +# define USER_PGD_PTRS 512 +# define KERNEL_PGD_PTRS 512 +#else /* __s390x__ */ +# define USER_PTRS_PER_PGD 2048 +# define USER_PGD_PTRS 2048 +# define KERNEL_PGD_PTRS 2048 +#endif /* __s390x__ */ + #define FIRST_USER_ADDRESS 0 #define pte_ERROR(e) \ @@ -203,14 +216,12 @@ extern char empty_zero_page[PAGE_SIZE]; #define _PAGE_RO 0x200 /* HW read-only */ #define _PAGE_INVALID 0x400 /* HW invalid */ -/* Mask and six different types of pages. */ -#define _PAGE_TYPE_MASK 0x601 -#define _PAGE_TYPE_EMPTY 0x400 -#define _PAGE_TYPE_NONE 0x401 -#define _PAGE_TYPE_SWAP 0x600 -#define _PAGE_TYPE_FILE 0x601 -#define _PAGE_TYPE_RO 0x200 -#define _PAGE_TYPE_RW 0x000 +/* Mask and four different kinds of invalid pages. */ +#define _PAGE_INVALID_MASK 0x601 +#define _PAGE_INVALID_EMPTY 0x400 +#define _PAGE_INVALID_NONE 0x401 +#define _PAGE_INVALID_SWAP 0x600 +#define _PAGE_INVALID_FILE 0x601 #ifndef __s390x__ @@ -269,14 +280,15 @@ extern char empty_zero_page[PAGE_SIZE]; #endif /* __s390x__ */ /* - * Page protection definitions. + * No mapping available */ -#define PAGE_NONE __pgprot(_PAGE_TYPE_NONE) -#define PAGE_RO __pgprot(_PAGE_TYPE_RO) -#define PAGE_RW __pgprot(_PAGE_TYPE_RW) - -#define PAGE_KERNEL PAGE_RW -#define PAGE_COPY PAGE_RO +#define PAGE_NONE_SHARED __pgprot(_PAGE_INVALID_NONE) +#define PAGE_NONE_PRIVATE __pgprot(_PAGE_INVALID_NONE) +#define PAGE_RO_SHARED __pgprot(_PAGE_RO) +#define PAGE_RO_PRIVATE __pgprot(_PAGE_RO) +#define PAGE_COPY __pgprot(_PAGE_RO) +#define PAGE_SHARED __pgprot(0) +#define PAGE_KERNEL __pgprot(0) /* * The S390 can't do page protection for execute, and considers that the @@ -284,23 +296,23 @@ extern char empty_zero_page[PAGE_SIZE]; * the closest we can get.. */ /*xwr*/ -#define __P000 PAGE_NONE -#define __P001 PAGE_RO -#define __P010 PAGE_RO -#define __P011 PAGE_RO -#define __P100 PAGE_RO -#define __P101 PAGE_RO -#define __P110 PAGE_RO -#define __P111 PAGE_RO - -#define __S000 PAGE_NONE -#define __S001 PAGE_RO -#define __S010 PAGE_RW -#define __S011 PAGE_RW -#define __S100 PAGE_RO -#define __S101 PAGE_RO -#define __S110 PAGE_RW -#define __S111 PAGE_RW +#define __P000 PAGE_NONE_PRIVATE +#define __P001 PAGE_RO_PRIVATE +#define __P010 PAGE_COPY +#define __P011 PAGE_COPY +#define __P100 PAGE_RO_PRIVATE +#define __P101 PAGE_RO_PRIVATE +#define __P110 PAGE_COPY +#define __P111 PAGE_COPY + +#define __S000 PAGE_NONE_SHARED +#define __S001 PAGE_RO_SHARED +#define __S010 PAGE_SHARED +#define __S011 PAGE_SHARED +#define __S100 PAGE_RO_SHARED +#define __S101 PAGE_RO_SHARED +#define __S110 PAGE_SHARED +#define __S111 PAGE_SHARED /* * Certain architectures need to do special things when PTEs @@ -365,18 +377,18 @@ static inline int pmd_bad(pmd_t pmd) static inline int pte_none(pte_t pte) { - return (pte_val(pte) & _PAGE_TYPE_MASK) == _PAGE_TYPE_EMPTY; + return (pte_val(pte) & _PAGE_INVALID_MASK) == _PAGE_INVALID_EMPTY; } static inline int pte_present(pte_t pte) { return !(pte_val(pte) & _PAGE_INVALID) || - (pte_val(pte) & _PAGE_TYPE_MASK) == _PAGE_TYPE_NONE; + (pte_val(pte) & _PAGE_INVALID_MASK) == _PAGE_INVALID_NONE; } static inline int pte_file(pte_t pte) { - return (pte_val(pte) & _PAGE_TYPE_MASK) == _PAGE_TYPE_FILE; + return (pte_val(pte) & _PAGE_INVALID_MASK) == _PAGE_INVALID_FILE; } #define pte_same(a,b) (pte_val(a) == pte_val(b)) @@ -449,7 +461,7 @@ static inline void pmd_clear(pmd_t * pmdp) static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - pte_val(*ptep) = _PAGE_TYPE_EMPTY; + pte_val(*ptep) = _PAGE_INVALID_EMPTY; } /* @@ -465,7 +477,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) static inline pte_t pte_wrprotect(pte_t pte) { - /* Do not clobber _PAGE_TYPE_NONE pages! */ + /* Do not clobber _PAGE_INVALID_NONE pages! */ if (!(pte_val(pte) & _PAGE_INVALID)) pte_val(pte) |= _PAGE_RO; return pte; @@ -544,30 +556,26 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, return pte; } -static inline void __ptep_ipte(unsigned long address, pte_t *ptep) -{ - if (!(pte_val(*ptep) & _PAGE_INVALID)) { -#ifndef __s390x__ - /* S390 has 1mb segments, we are emulating 4MB segments */ - pte_t *pto = (pte_t *) (((unsigned long) ptep) & 0x7ffffc00); -#else - /* ipte in zarch mode can do the math */ - pte_t *pto = ptep; -#endif - asm volatile ("ipte %2,%3" - : "=m" (*ptep) : "m" (*ptep), - "a" (pto), "a" (address) ); - } - pte_val(*ptep) = _PAGE_TYPE_EMPTY; -} - static inline pte_t ptep_clear_flush(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) { pte_t pte = *ptep; - - __ptep_ipte(address, ptep); +#ifndef __s390x__ + if (!(pte_val(pte) & _PAGE_INVALID)) { + /* S390 has 1mb segments, we are emulating 4MB segments */ + pte_t *pto = (pte_t *) (((unsigned long) ptep) & 0x7ffffc00); + __asm__ __volatile__ ("ipte %2,%3" + : "=m" (*ptep) : "m" (*ptep), + "a" (pto), "a" (address) ); + } +#else /* __s390x__ */ + if (!(pte_val(pte) & _PAGE_INVALID)) + __asm__ __volatile__ ("ipte %2,%3" + : "=m" (*ptep) : "m" (*ptep), + "a" (ptep), "a" (address) ); +#endif /* __s390x__ */ + pte_val(*ptep) = _PAGE_INVALID_EMPTY; return pte; } @@ -747,7 +755,7 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) { pte_t pte; offset &= __SWP_OFFSET_MASK; - pte_val(pte) = _PAGE_TYPE_SWAP | ((type & 0x1f) << 2) | + pte_val(pte) = _PAGE_INVALID_SWAP | ((type & 0x1f) << 2) | ((offset & 1UL) << 7) | ((offset & ~1UL) << 11); return pte; } @@ -770,7 +778,7 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) #define pgoff_to_pte(__off) \ ((pte_t) { ((((__off) & 0x7f) << 1) + (((__off) >> 7) << 12)) \ - | _PAGE_TYPE_FILE }) + | _PAGE_INVALID_FILE }) #endif /* !__ASSEMBLY__ */ diff --git a/trunk/include/asm-s390/processor.h b/trunk/include/asm-s390/processor.h index a3a4e5fd30d7..5b71d3731723 100644 --- a/trunk/include/asm-s390/processor.h +++ b/trunk/include/asm-s390/processor.h @@ -339,21 +339,4 @@ int unregister_idle_notifier(struct notifier_block *nb); #endif -/* - * Helper macro for exception table entries - */ -#ifndef __s390x__ -#define EX_TABLE(_fault,_target) \ - ".section __ex_table,\"a\"\n" \ - " .align 4\n" \ - " .long " #_fault "," #_target "\n" \ - ".previous\n" -#else -#define EX_TABLE(_fault,_target) \ - ".section __ex_table,\"a\"\n" \ - " .align 8\n" \ - " .quad " #_fault "," #_target "\n" \ - ".previous\n" -#endif - #endif /* __ASM_S390_PROCESSOR_H */ diff --git a/trunk/include/asm-s390/setup.h b/trunk/include/asm-s390/setup.h index f1959732b6fd..19e31979309a 100644 --- a/trunk/include/asm-s390/setup.h +++ b/trunk/include/asm-s390/setup.h @@ -14,6 +14,8 @@ #define PARMAREA 0x10400 #define COMMAND_LINE_SIZE 896 +#define RAMDISK_ORIGIN 0x800000 +#define RAMDISK_SIZE 0x800000 #define MEMORY_CHUNKS 16 /* max 0x7fff */ #define IPL_PARMBLOCK_ORIGIN 0x2000 @@ -44,12 +46,10 @@ extern unsigned long machine_flags; #define MACHINE_HAS_IEEE (machine_flags & 2) #define MACHINE_HAS_CSP (machine_flags & 8) #define MACHINE_HAS_DIAG44 (1) -#define MACHINE_HAS_MVCOS (0) #else /* __s390x__ */ #define MACHINE_HAS_IEEE (1) #define MACHINE_HAS_CSP (1) #define MACHINE_HAS_DIAG44 (machine_flags & 32) -#define MACHINE_HAS_MVCOS (machine_flags & 512) #endif /* __s390x__ */ @@ -70,76 +70,52 @@ extern unsigned int console_irq; #define SET_CONSOLE_3215 do { console_mode = 2; } while (0) #define SET_CONSOLE_3270 do { console_mode = 3; } while (0) - -struct ipl_list_hdr { - u32 len; - u8 reserved1[3]; +struct ipl_list_header { + u32 length; + u8 reserved[3]; u8 version; - u32 blk0_len; - u8 pbt; - u8 flags; - u16 reserved2; } __attribute__((packed)); struct ipl_block_fcp { - u8 reserved1[313-1]; - u8 opt; - u8 reserved2[3]; - u16 reserved3; + u32 length; + u8 pbt; + u8 reserved1[322-1]; u16 devno; - u8 reserved4[4]; + u8 reserved2[4]; u64 wwpn; u64 lun; u32 bootprog; - u8 reserved5[12]; + u8 reserved3[12]; u64 br_lba; u32 scp_data_len; - u8 reserved6[260]; + u8 reserved4[260]; u8 scp_data[]; } __attribute__((packed)); -struct ipl_block_ccw { - u8 load_param[8]; - u8 reserved1[84]; - u8 reserved2[2]; - u16 devno; - u8 vm_flags; - u8 reserved3[3]; - u32 vm_parm_len; -} __attribute__((packed)); - struct ipl_parameter_block { - struct ipl_list_hdr hdr; union { - struct ipl_block_fcp fcp; - struct ipl_block_ccw ccw; - } ipl_info; + u32 length; + struct ipl_list_header header; + } hdr; + struct ipl_block_fcp fcp; } __attribute__((packed)); -#define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \ - sizeof(struct ipl_block_fcp)) - -#define IPL_PARM_BLK_CCW_LEN (sizeof(struct ipl_list_hdr) + \ - sizeof(struct ipl_block_ccw)) - #define IPL_MAX_SUPPORTED_VERSION (0) +#define IPL_TYPE_FCP (0) + /* * IPL validity flags and parameters as detected in head.S */ -extern u32 ipl_flags; +extern u32 ipl_parameter_flags; extern u16 ipl_devno; -void do_reipl(void); - -enum { - IPL_DEVNO_VALID = 1, - IPL_PARMBLOCK_VALID = 2, -}; +#define IPL_DEVNO_VALID (ipl_parameter_flags & 1) +#define IPL_PARMBLOCK_VALID (ipl_parameter_flags & 2) #define IPL_PARMBLOCK_START ((struct ipl_parameter_block *) \ IPL_PARMBLOCK_ORIGIN) -#define IPL_PARMBLOCK_SIZE (IPL_PARMBLOCK_START->hdr.len) +#define IPL_PARMBLOCK_SIZE (IPL_PARMBLOCK_START->hdr.length) #else /* __ASSEMBLY__ */ diff --git a/trunk/include/asm-s390/smp.h b/trunk/include/asm-s390/smp.h index 9fb02e9779c9..657646054c5e 100644 --- a/trunk/include/asm-s390/smp.h +++ b/trunk/include/asm-s390/smp.h @@ -104,7 +104,7 @@ smp_call_function_on(void (*func) (void *info), void *info, #define smp_cpu_not_running(cpu) 1 #define smp_get_cpu(cpu) ({ 0; }) #define smp_put_cpu(cpu) ({ 0; }) -#define smp_setup_cpu_possible_map() do { } while (0) +#define smp_setup_cpu_possible_map() #endif #endif diff --git a/trunk/include/asm-s390/uaccess.h b/trunk/include/asm-s390/uaccess.h index e2047b0c9092..0b7c0ca4c3d7 100644 --- a/trunk/include/asm-s390/uaccess.h +++ b/trunk/include/asm-s390/uaccess.h @@ -47,7 +47,7 @@ S390_lowcore.user_asce : S390_lowcore.kernel_asce; \ asm volatile ("lctlg 7,7,%0" : : "m" (__pto) ); \ }) -#else /* __s390x__ */ +#else #define set_fs(x) \ ({ \ unsigned long __pto; \ @@ -56,7 +56,7 @@ S390_lowcore.user_asce : S390_lowcore.kernel_asce; \ asm volatile ("lctl 7,7,%0" : : "m" (__pto) ); \ }) -#endif /* __s390x__ */ +#endif #define segment_eq(a,b) ((a).ar4 == (b).ar4) @@ -85,51 +85,76 @@ struct exception_table_entry unsigned long insn, fixup; }; -struct uaccess_ops { - size_t (*copy_from_user)(size_t, const void __user *, void *); - size_t (*copy_from_user_small)(size_t, const void __user *, void *); - size_t (*copy_to_user)(size_t, void __user *, const void *); - size_t (*copy_to_user_small)(size_t, void __user *, const void *); - size_t (*copy_in_user)(size_t, void __user *, const void __user *); - size_t (*clear_user)(size_t, void __user *); - size_t (*strnlen_user)(size_t, const char __user *); - size_t (*strncpy_from_user)(size_t, const char __user *, char *); - int (*futex_atomic_op)(int op, int __user *, int oparg, int *old); - int (*futex_atomic_cmpxchg)(int __user *, int old, int new); -}; - -extern struct uaccess_ops uaccess; -extern struct uaccess_ops uaccess_std; -extern struct uaccess_ops uaccess_mvcos; - -static inline int __put_user_fn(size_t size, void __user *ptr, void *x) -{ - size = uaccess.copy_to_user_small(size, ptr, x); - return size ? -EFAULT : size; -} - -static inline int __get_user_fn(size_t size, const void __user *ptr, void *x) -{ - size = uaccess.copy_from_user_small(size, ptr, x); - return size ? -EFAULT : size; -} +#ifndef __s390x__ +#define __uaccess_fixup \ + ".section .fixup,\"ax\"\n" \ + "2: lhi %0,%4\n" \ + " bras 1,3f\n" \ + " .long 1b\n" \ + "3: l 1,0(1)\n" \ + " br 1\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,2b\n" \ + ".previous" +#define __uaccess_clobber "cc", "1" +#else /* __s390x__ */ +#define __uaccess_fixup \ + ".section .fixup,\"ax\"\n" \ + "2: lghi %0,%4\n" \ + " jg 1b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 8\n" \ + " .quad 0b,2b\n" \ + ".previous" +#define __uaccess_clobber "cc" +#endif /* __s390x__ */ /* * These are the main single-value transfer routines. They automatically * use the right size if we just have the right pointer type. */ +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2) +#define __put_user_asm(x, ptr, err) \ +({ \ + err = 0; \ + asm volatile( \ + "0: mvcs 0(%1,%2),%3,%0\n" \ + "1:\n" \ + __uaccess_fixup \ + : "+&d" (err) \ + : "d" (sizeof(*(ptr))), "a" (ptr), "Q" (x), \ + "K" (-EFAULT) \ + : __uaccess_clobber ); \ +}) +#else +#define __put_user_asm(x, ptr, err) \ +({ \ + err = 0; \ + asm volatile( \ + "0: mvcs 0(%1,%2),0(%3),%0\n" \ + "1:\n" \ + __uaccess_fixup \ + : "+&d" (err) \ + : "d" (sizeof(*(ptr))), "a" (ptr), "a" (&(x)), \ + "K" (-EFAULT), "m" (x) \ + : __uaccess_clobber ); \ +}) +#endif + #define __put_user(x, ptr) \ ({ \ __typeof__(*(ptr)) __x = (x); \ - int __pu_err = -EFAULT; \ + int __pu_err; \ __chk_user_ptr(ptr); \ switch (sizeof (*(ptr))) { \ case 1: \ case 2: \ case 4: \ case 8: \ - __pu_err = __put_user_fn(sizeof (*(ptr)), \ - ptr, &__x); \ + __put_user_asm(__x, ptr, __pu_err); \ break; \ default: \ __put_user_bad(); \ @@ -147,36 +172,60 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x) extern int __put_user_bad(void) __attribute__((noreturn)); +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2) +#define __get_user_asm(x, ptr, err) \ +({ \ + err = 0; \ + asm volatile ( \ + "0: mvcp %O1(%2,%R1),0(%3),%0\n" \ + "1:\n" \ + __uaccess_fixup \ + : "+&d" (err), "=Q" (x) \ + : "d" (sizeof(*(ptr))), "a" (ptr), \ + "K" (-EFAULT) \ + : __uaccess_clobber ); \ +}) +#else +#define __get_user_asm(x, ptr, err) \ +({ \ + err = 0; \ + asm volatile ( \ + "0: mvcp 0(%2,%5),0(%3),%0\n" \ + "1:\n" \ + __uaccess_fixup \ + : "+&d" (err), "=m" (x) \ + : "d" (sizeof(*(ptr))), "a" (ptr), \ + "K" (-EFAULT), "a" (&(x)) \ + : __uaccess_clobber ); \ +}) +#endif + #define __get_user(x, ptr) \ ({ \ - int __gu_err = -EFAULT; \ - __chk_user_ptr(ptr); \ + int __gu_err; \ + __chk_user_ptr(ptr); \ switch (sizeof(*(ptr))) { \ case 1: { \ unsigned char __x; \ - __gu_err = __get_user_fn(sizeof (*(ptr)), \ - ptr, &__x); \ + __get_user_asm(__x, ptr, __gu_err); \ (x) = *(__force __typeof__(*(ptr)) *) &__x; \ break; \ }; \ case 2: { \ unsigned short __x; \ - __gu_err = __get_user_fn(sizeof (*(ptr)), \ - ptr, &__x); \ + __get_user_asm(__x, ptr, __gu_err); \ (x) = *(__force __typeof__(*(ptr)) *) &__x; \ break; \ }; \ case 4: { \ unsigned int __x; \ - __gu_err = __get_user_fn(sizeof (*(ptr)), \ - ptr, &__x); \ + __get_user_asm(__x, ptr, __gu_err); \ (x) = *(__force __typeof__(*(ptr)) *) &__x; \ break; \ }; \ case 8: { \ unsigned long long __x; \ - __gu_err = __get_user_fn(sizeof (*(ptr)), \ - ptr, &__x); \ + __get_user_asm(__x, ptr, __gu_err); \ (x) = *(__force __typeof__(*(ptr)) *) &__x; \ break; \ }; \ @@ -198,6 +247,8 @@ extern int __get_user_bad(void) __attribute__((noreturn)); #define __put_user_unaligned __put_user #define __get_user_unaligned __get_user +extern long __copy_to_user_asm(const void *from, long n, void __user *to); + /** * __copy_to_user: - Copy a block of data into user space, with less checking. * @to: Destination address, in user space. @@ -215,10 +266,7 @@ extern int __get_user_bad(void) __attribute__((noreturn)); static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n) { - if (__builtin_constant_p(n) && (n <= 256)) - return uaccess.copy_to_user_small(n, to, from); - else - return uaccess.copy_to_user(n, to, from); + return __copy_to_user_asm(from, n, to); } #define __copy_to_user_inatomic __copy_to_user @@ -246,6 +294,8 @@ copy_to_user(void __user *to, const void *from, unsigned long n) return n; } +extern long __copy_from_user_asm(void *to, long n, const void __user *from); + /** * __copy_from_user: - Copy a block of data from user space, with less checking. * @to: Destination address, in kernel space. @@ -266,10 +316,7 @@ copy_to_user(void __user *to, const void *from, unsigned long n) static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) { - if (__builtin_constant_p(n) && (n <= 256)) - return uaccess.copy_from_user_small(n, from, to); - else - return uaccess.copy_from_user(n, from, to); + return __copy_from_user_asm(to, n, from); } /** @@ -299,10 +346,13 @@ copy_from_user(void *to, const void __user *from, unsigned long n) return n; } +extern unsigned long __copy_in_user_asm(const void __user *from, long n, + void __user *to); + static inline unsigned long __copy_in_user(void __user *to, const void __user *from, unsigned long n) { - return uaccess.copy_in_user(n, to, from); + return __copy_in_user_asm(from, n, to); } static inline unsigned long @@ -310,28 +360,34 @@ copy_in_user(void __user *to, const void __user *from, unsigned long n) { might_sleep(); if (__access_ok(from,n) && __access_ok(to,n)) - n = __copy_in_user(to, from, n); + n = __copy_in_user_asm(from, n, to); return n; } /* * Copy a null terminated string from userspace. */ +extern long __strncpy_from_user_asm(long count, char *dst, + const char __user *src); + static inline long strncpy_from_user(char *dst, const char __user *src, long count) { long res = -EFAULT; might_sleep(); if (access_ok(VERIFY_READ, src, 1)) - res = uaccess.strncpy_from_user(count, src, dst); + res = __strncpy_from_user_asm(count, dst, src); return res; } + +extern long __strnlen_user_asm(long count, const char __user *src); + static inline unsigned long strnlen_user(const char __user * src, unsigned long n) { might_sleep(); - return uaccess.strnlen_user(n, src); + return __strnlen_user_asm(n, src); } /** @@ -354,10 +410,12 @@ strnlen_user(const char __user * src, unsigned long n) * Zero Userspace */ +extern long __clear_user_asm(void __user *to, long n); + static inline unsigned long __clear_user(void __user *to, unsigned long n) { - return uaccess.clear_user(n, to); + return __clear_user_asm(to, n); } static inline unsigned long @@ -365,7 +423,7 @@ clear_user(void __user *to, unsigned long n) { might_sleep(); if (access_ok(VERIFY_WRITE, to, n)) - n = uaccess.clear_user(n, to); + n = __clear_user_asm(to, n); return n; } diff --git a/trunk/include/asm-s390/unistd.h b/trunk/include/asm-s390/unistd.h index 02b942d85c37..aa7a243862e1 100644 --- a/trunk/include/asm-s390/unistd.h +++ b/trunk/include/asm-s390/unistd.h @@ -25,12 +25,17 @@ #define __NR_unlink 10 #define __NR_execve 11 #define __NR_chdir 12 +#define __NR_time 13 #define __NR_mknod 14 #define __NR_chmod 15 +#define __NR_lchown 16 #define __NR_lseek 19 #define __NR_getpid 20 #define __NR_mount 21 #define __NR_umount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_stime 25 #define __NR_ptrace 26 #define __NR_alarm 27 #define __NR_pause 29 @@ -46,7 +51,11 @@ #define __NR_pipe 42 #define __NR_times 43 #define __NR_brk 45 +#define __NR_setgid 46 +#define __NR_getgid 47 #define __NR_signal 48 +#define __NR_geteuid 49 +#define __NR_getegid 50 #define __NR_acct 51 #define __NR_umount2 52 #define __NR_ioctl 54 @@ -60,13 +69,18 @@ #define __NR_getpgrp 65 #define __NR_setsid 66 #define __NR_sigaction 67 +#define __NR_setreuid 70 +#define __NR_setregid 71 #define __NR_sigsuspend 72 #define __NR_sigpending 73 #define __NR_sethostname 74 #define __NR_setrlimit 75 +#define __NR_getrlimit 76 #define __NR_getrusage 77 #define __NR_gettimeofday 78 #define __NR_settimeofday 79 +#define __NR_getgroups 80 +#define __NR_setgroups 81 #define __NR_symlink 83 #define __NR_readlink 85 #define __NR_uselib 86 @@ -78,10 +92,12 @@ #define __NR_truncate 92 #define __NR_ftruncate 93 #define __NR_fchmod 94 +#define __NR_fchown 95 #define __NR_getpriority 96 #define __NR_setpriority 97 #define __NR_statfs 99 #define __NR_fstatfs 100 +#define __NR_ioperm 101 #define __NR_socketcall 102 #define __NR_syslog 103 #define __NR_setitimer 104 @@ -115,7 +131,11 @@ #define __NR_sysfs 135 #define __NR_personality 136 #define __NR_afs_syscall 137 /* Syscall for Andrew File System */ +#define __NR_setfsuid 138 +#define __NR_setfsgid 139 +#define __NR__llseek 140 #define __NR_getdents 141 +#define __NR__newselect 142 #define __NR_flock 143 #define __NR_msync 144 #define __NR_readv 145 @@ -137,9 +157,13 @@ #define __NR_sched_rr_get_interval 161 #define __NR_nanosleep 162 #define __NR_mremap 163 +#define __NR_setresuid 164 +#define __NR_getresuid 165 #define __NR_query_module 167 #define __NR_poll 168 #define __NR_nfsservctl 169 +#define __NR_setresgid 170 +#define __NR_getresgid 171 #define __NR_prctl 172 #define __NR_rt_sigreturn 173 #define __NR_rt_sigaction 174 @@ -150,6 +174,7 @@ #define __NR_rt_sigsuspend 179 #define __NR_pread64 180 #define __NR_pwrite64 181 +#define __NR_chown 182 #define __NR_getcwd 183 #define __NR_capget 184 #define __NR_capset 185 @@ -158,11 +183,39 @@ #define __NR_getpmsg 188 #define __NR_putpmsg 189 #define __NR_vfork 190 +#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */ +#define __NR_mmap2 192 +#define __NR_truncate64 193 +#define __NR_ftruncate64 194 +#define __NR_stat64 195 +#define __NR_lstat64 196 +#define __NR_fstat64 197 +#define __NR_lchown32 198 +#define __NR_getuid32 199 +#define __NR_getgid32 200 +#define __NR_geteuid32 201 +#define __NR_getegid32 202 +#define __NR_setreuid32 203 +#define __NR_setregid32 204 +#define __NR_getgroups32 205 +#define __NR_setgroups32 206 +#define __NR_fchown32 207 +#define __NR_setresuid32 208 +#define __NR_getresuid32 209 +#define __NR_setresgid32 210 +#define __NR_getresgid32 211 +#define __NR_chown32 212 +#define __NR_setuid32 213 +#define __NR_setgid32 214 +#define __NR_setfsuid32 215 +#define __NR_setfsgid32 216 #define __NR_pivot_root 217 #define __NR_mincore 218 #define __NR_madvise 219 #define __NR_getdents64 220 +#define __NR_fcntl64 221 #define __NR_readahead 222 +#define __NR_sendfile64 223 #define __NR_setxattr 224 #define __NR_lsetxattr 225 #define __NR_fsetxattr 226 @@ -203,6 +256,7 @@ #define __NR_clock_getres (__NR_timer_create+7) #define __NR_clock_nanosleep (__NR_timer_create+8) /* Number 263 is reserved for vserver */ +#define __NR_fadvise64_64 264 #define __NR_statfs64 265 #define __NR_fstatfs64 266 #define __NR_remap_file_pages 267 @@ -231,6 +285,7 @@ #define __NR_mknodat 290 #define __NR_fchownat 291 #define __NR_futimesat 292 +#define __NR_fstatat64 293 #define __NR_unlinkat 294 #define __NR_renameat 295 #define __NR_linkat 296 @@ -255,65 +310,62 @@ * have a different name although they do the same (e.g. __NR_chown32 * is __NR_chown on 64 bit). */ -#ifndef __s390x__ - -#define __NR_time 13 -#define __NR_lchown 16 -#define __NR_setuid 23 -#define __NR_getuid 24 -#define __NR_stime 25 -#define __NR_setgid 46 -#define __NR_getgid 47 -#define __NR_geteuid 49 -#define __NR_getegid 50 -#define __NR_setreuid 70 -#define __NR_setregid 71 -#define __NR_getrlimit 76 -#define __NR_getgroups 80 -#define __NR_setgroups 81 -#define __NR_fchown 95 -#define __NR_ioperm 101 -#define __NR_setfsuid 138 -#define __NR_setfsgid 139 -#define __NR__llseek 140 -#define __NR__newselect 142 -#define __NR_setresuid 164 -#define __NR_getresuid 165 -#define __NR_setresgid 170 -#define __NR_getresgid 171 -#define __NR_chown 182 -#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */ -#define __NR_mmap2 192 -#define __NR_truncate64 193 -#define __NR_ftruncate64 194 -#define __NR_stat64 195 -#define __NR_lstat64 196 -#define __NR_fstat64 197 -#define __NR_lchown32 198 -#define __NR_getuid32 199 -#define __NR_getgid32 200 -#define __NR_geteuid32 201 -#define __NR_getegid32 202 -#define __NR_setreuid32 203 -#define __NR_setregid32 204 -#define __NR_getgroups32 205 -#define __NR_setgroups32 206 -#define __NR_fchown32 207 -#define __NR_setresuid32 208 -#define __NR_getresuid32 209 -#define __NR_setresgid32 210 -#define __NR_getresgid32 211 -#define __NR_chown32 212 -#define __NR_setuid32 213 -#define __NR_setgid32 214 -#define __NR_setfsuid32 215 -#define __NR_setfsgid32 216 -#define __NR_fcntl64 221 -#define __NR_sendfile64 223 -#define __NR_fadvise64_64 264 -#define __NR_fstatat64 293 - -#else +#ifdef __s390x__ +#undef __NR_time +#undef __NR_lchown +#undef __NR_setuid +#undef __NR_getuid +#undef __NR_stime +#undef __NR_setgid +#undef __NR_getgid +#undef __NR_geteuid +#undef __NR_getegid +#undef __NR_setreuid +#undef __NR_setregid +#undef __NR_getrlimit +#undef __NR_getgroups +#undef __NR_setgroups +#undef __NR_fchown +#undef __NR_ioperm +#undef __NR_setfsuid +#undef __NR_setfsgid +#undef __NR__llseek +#undef __NR__newselect +#undef __NR_setresuid +#undef __NR_getresuid +#undef __NR_setresgid +#undef __NR_getresgid +#undef __NR_chown +#undef __NR_ugetrlimit +#undef __NR_mmap2 +#undef __NR_truncate64 +#undef __NR_ftruncate64 +#undef __NR_stat64 +#undef __NR_lstat64 +#undef __NR_fstat64 +#undef __NR_lchown32 +#undef __NR_getuid32 +#undef __NR_getgid32 +#undef __NR_geteuid32 +#undef __NR_getegid32 +#undef __NR_setreuid32 +#undef __NR_setregid32 +#undef __NR_getgroups32 +#undef __NR_setgroups32 +#undef __NR_fchown32 +#undef __NR_setresuid32 +#undef __NR_getresuid32 +#undef __NR_setresgid32 +#undef __NR_getresgid32 +#undef __NR_chown32 +#undef __NR_setuid32 +#undef __NR_setgid32 +#undef __NR_setfsuid32 +#undef __NR_setfsgid32 +#undef __NR_fcntl64 +#undef __NR_sendfile64 +#undef __NR_fadvise64_64 +#undef __NR_fstatat64 #define __NR_select 142 #define __NR_getrlimit 191 /* SuS compliant getrlimit */ diff --git a/trunk/include/asm-s390/z90crypt.h b/trunk/include/asm-s390/z90crypt.h new file mode 100644 index 000000000000..31a2439b07bd --- /dev/null +++ b/trunk/include/asm-s390/z90crypt.h @@ -0,0 +1,212 @@ +/* + * include/asm-s390/z90crypt.h + * + * z90crypt 1.3.3 (user-visible header) + * + * Copyright (C) 2001, 2005 IBM Corporation + * Author(s): Robert Burroughs + * Eric Rossman (edrossma@us.ibm.com) + * + * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ASM_S390_Z90CRYPT_H +#define __ASM_S390_Z90CRYPT_H +#include + +#define z90crypt_VERSION 1 +#define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards +#define z90crypt_VARIANT 3 // 3 = CEX2A support + +/** + * struct ica_rsa_modexpo + * + * Requirements: + * - outputdatalength is at least as large as inputdatalength. + * - All key parts are right justified in their fields, padded on + * the left with zeroes. + * - length(b_key) = inputdatalength + * - length(n_modulus) = inputdatalength + */ +struct ica_rsa_modexpo { + char __user * inputdata; + unsigned int inputdatalength; + char __user * outputdata; + unsigned int outputdatalength; + char __user * b_key; + char __user * n_modulus; +}; + +/** + * struct ica_rsa_modexpo_crt + * + * Requirements: + * - inputdatalength is even. + * - outputdatalength is at least as large as inputdatalength. + * - All key parts are right justified in their fields, padded on + * the left with zeroes. + * - length(bp_key) = inputdatalength/2 + 8 + * - length(bq_key) = inputdatalength/2 + * - length(np_key) = inputdatalength/2 + 8 + * - length(nq_key) = inputdatalength/2 + * - length(u_mult_inv) = inputdatalength/2 + 8 + */ +struct ica_rsa_modexpo_crt { + char __user * inputdata; + unsigned int inputdatalength; + char __user * outputdata; + unsigned int outputdatalength; + char __user * bp_key; + char __user * bq_key; + char __user * np_prime; + char __user * nq_prime; + char __user * u_mult_inv; +}; + +#define Z90_IOCTL_MAGIC 'z' // NOTE: Need to allocate from linux folks + +/** + * Interface notes: + * + * The ioctl()s which are implemented (along with relevant details) + * are: + * + * ICARSAMODEXPO + * Perform an RSA operation using a Modulus-Exponent pair + * This takes an ica_rsa_modexpo struct as its arg. + * + * NOTE: please refer to the comments preceding this structure + * for the implementation details for the contents of the + * block + * + * ICARSACRT + * Perform an RSA operation using a Chinese-Remainder Theorem key + * This takes an ica_rsa_modexpo_crt struct as its arg. + * + * NOTE: please refer to the comments preceding this structure + * for the implementation details for the contents of the + * block + * + * Z90STAT_TOTALCOUNT + * Return an integer count of all device types together. + * + * Z90STAT_PCICACOUNT + * Return an integer count of all PCICAs. + * + * Z90STAT_PCICCCOUNT + * Return an integer count of all PCICCs. + * + * Z90STAT_PCIXCCMCL2COUNT + * Return an integer count of all MCL2 PCIXCCs. + * + * Z90STAT_PCIXCCMCL3COUNT + * Return an integer count of all MCL3 PCIXCCs. + * + * Z90STAT_CEX2CCOUNT + * Return an integer count of all CEX2Cs. + * + * Z90STAT_CEX2ACOUNT + * Return an integer count of all CEX2As. + * + * Z90STAT_REQUESTQ_COUNT + * Return an integer count of the number of entries waiting to be + * sent to a device. + * + * Z90STAT_PENDINGQ_COUNT + * Return an integer count of the number of entries sent to a + * device awaiting the reply. + * + * Z90STAT_TOTALOPEN_COUNT + * Return an integer count of the number of open file handles. + * + * Z90STAT_DOMAIN_INDEX + * Return the integer value of the Cryptographic Domain. + * + * Z90STAT_STATUS_MASK + * Return an 64 element array of unsigned chars for the status of + * all devices. + * 0x01: PCICA + * 0x02: PCICC + * 0x03: PCIXCC_MCL2 + * 0x04: PCIXCC_MCL3 + * 0x05: CEX2C + * 0x06: CEX2A + * 0x0d: device is disabled via the proc filesystem + * + * Z90STAT_QDEPTH_MASK + * Return an 64 element array of unsigned chars for the queue + * depth of all devices. + * + * Z90STAT_PERDEV_REQCNT + * Return an 64 element array of unsigned integers for the number + * of successfully completed requests per device since the device + * was detected and made available. + * + * ICAZ90STATUS (deprecated) + * Return some device driver status in a ica_z90_status struct + * This takes an ica_z90_status struct as its arg. + * + * NOTE: this ioctl() is deprecated, and has been replaced with + * single ioctl()s for each type of status being requested + * + * Z90STAT_PCIXCCCOUNT (deprecated) + * Return an integer count of all PCIXCCs (MCL2 + MCL3). + * This is DEPRECATED now that MCL3 PCIXCCs are treated differently from + * MCL2 PCIXCCs. + * + * Z90QUIESCE (not recommended) + * Quiesce the driver. This is intended to stop all new + * requests from being processed. Its use is NOT recommended, + * except in circumstances where there is no other way to stop + * callers from accessing the driver. Its original use was to + * allow the driver to be "drained" of work in preparation for + * a system shutdown. + * + * NOTE: once issued, this ban on new work cannot be undone + * except by unloading and reloading the driver. + */ + +/** + * Supported ioctl calls + */ +#define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0) +#define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0) + +/* DEPRECATED status calls (bound for removal at some point) */ +#define ICAZ90STATUS _IOR(Z90_IOCTL_MAGIC, 0x10, struct ica_z90_status) +#define Z90STAT_PCIXCCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x43, int) + +/* unrelated to ICA callers */ +#define Z90QUIESCE _IO(Z90_IOCTL_MAGIC, 0x11) + +/* New status calls */ +#define Z90STAT_TOTALCOUNT _IOR(Z90_IOCTL_MAGIC, 0x40, int) +#define Z90STAT_PCICACOUNT _IOR(Z90_IOCTL_MAGIC, 0x41, int) +#define Z90STAT_PCICCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x42, int) +#define Z90STAT_PCIXCCMCL2COUNT _IOR(Z90_IOCTL_MAGIC, 0x4b, int) +#define Z90STAT_PCIXCCMCL3COUNT _IOR(Z90_IOCTL_MAGIC, 0x4c, int) +#define Z90STAT_CEX2CCOUNT _IOR(Z90_IOCTL_MAGIC, 0x4d, int) +#define Z90STAT_CEX2ACOUNT _IOR(Z90_IOCTL_MAGIC, 0x4e, int) +#define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int) +#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int) +#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int) +#define Z90STAT_DOMAIN_INDEX _IOR(Z90_IOCTL_MAGIC, 0x47, int) +#define Z90STAT_STATUS_MASK _IOR(Z90_IOCTL_MAGIC, 0x48, char[64]) +#define Z90STAT_QDEPTH_MASK _IOR(Z90_IOCTL_MAGIC, 0x49, char[64]) +#define Z90STAT_PERDEV_REQCNT _IOR(Z90_IOCTL_MAGIC, 0x4a, int[64]) + +#endif /* __ASM_S390_Z90CRYPT_H */ diff --git a/trunk/include/asm-s390/zcrypt.h b/trunk/include/asm-s390/zcrypt.h deleted file mode 100644 index 7244c68464f2..000000000000 --- a/trunk/include/asm-s390/zcrypt.h +++ /dev/null @@ -1,285 +0,0 @@ -/* - * include/asm-s390/zcrypt.h - * - * zcrypt 2.1.0 (user-visible header) - * - * Copyright (C) 2001, 2006 IBM Corporation - * Author(s): Robert Burroughs - * Eric Rossman (edrossma@us.ibm.com) - * - * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ASM_S390_ZCRYPT_H -#define __ASM_S390_ZCRYPT_H - -#define ZCRYPT_VERSION 2 -#define ZCRYPT_RELEASE 1 -#define ZCRYPT_VARIANT 0 - -#include -#include - -/** - * struct ica_rsa_modexpo - * - * Requirements: - * - outputdatalength is at least as large as inputdatalength. - * - All key parts are right justified in their fields, padded on - * the left with zeroes. - * - length(b_key) = inputdatalength - * - length(n_modulus) = inputdatalength - */ -struct ica_rsa_modexpo { - char __user * inputdata; - unsigned int inputdatalength; - char __user * outputdata; - unsigned int outputdatalength; - char __user * b_key; - char __user * n_modulus; -}; - -/** - * struct ica_rsa_modexpo_crt - * - * Requirements: - * - inputdatalength is even. - * - outputdatalength is at least as large as inputdatalength. - * - All key parts are right justified in their fields, padded on - * the left with zeroes. - * - length(bp_key) = inputdatalength/2 + 8 - * - length(bq_key) = inputdatalength/2 - * - length(np_key) = inputdatalength/2 + 8 - * - length(nq_key) = inputdatalength/2 - * - length(u_mult_inv) = inputdatalength/2 + 8 - */ -struct ica_rsa_modexpo_crt { - char __user * inputdata; - unsigned int inputdatalength; - char __user * outputdata; - unsigned int outputdatalength; - char __user * bp_key; - char __user * bq_key; - char __user * np_prime; - char __user * nq_prime; - char __user * u_mult_inv; -}; - -/** - * CPRBX - * Note that all shorts and ints are big-endian. - * All pointer fields are 16 bytes long, and mean nothing. - * - * A request CPRB is followed by a request_parameter_block. - * - * The request (or reply) parameter block is organized thus: - * function code - * VUD block - * key block - */ -struct ica_CPRBX { - unsigned short cprb_len; /* CPRB length 220 */ - unsigned char cprb_ver_id; /* CPRB version id. 0x02 */ - unsigned char pad_000[3]; /* Alignment pad bytes */ - unsigned char func_id[2]; /* function id 0x5432 */ - unsigned char cprb_flags[4]; /* Flags */ - unsigned int req_parml; /* request parameter buffer len */ - unsigned int req_datal; /* request data buffer */ - unsigned int rpl_msgbl; /* reply message block length */ - unsigned int rpld_parml; /* replied parameter block len */ - unsigned int rpl_datal; /* reply data block len */ - unsigned int rpld_datal; /* replied data block len */ - unsigned int req_extbl; /* request extension block len */ - unsigned char pad_001[4]; /* reserved */ - unsigned int rpld_extbl; /* replied extension block len */ - unsigned char padx000[16 - sizeof (char *)]; - unsigned char * req_parmb; /* request parm block 'address' */ - unsigned char padx001[16 - sizeof (char *)]; - unsigned char * req_datab; /* request data block 'address' */ - unsigned char padx002[16 - sizeof (char *)]; - unsigned char * rpl_parmb; /* reply parm block 'address' */ - unsigned char padx003[16 - sizeof (char *)]; - unsigned char * rpl_datab; /* reply data block 'address' */ - unsigned char padx004[16 - sizeof (char *)]; - unsigned char * req_extb; /* request extension block 'addr'*/ - unsigned char padx005[16 - sizeof (char *)]; - unsigned char * rpl_extb; /* reply extension block 'addres'*/ - unsigned short ccp_rtcode; /* server return code */ - unsigned short ccp_rscode; /* server reason code */ - unsigned int mac_data_len; /* Mac Data Length */ - unsigned char logon_id[8]; /* Logon Identifier */ - unsigned char mac_value[8]; /* Mac Value */ - unsigned char mac_content_flgs;/* Mac content flag byte */ - unsigned char pad_002; /* Alignment */ - unsigned short domain; /* Domain */ - unsigned char usage_domain[4];/* Usage domain */ - unsigned char cntrl_domain[4];/* Control domain */ - unsigned char S390enf_mask[4];/* S/390 enforcement mask */ - unsigned char pad_004[36]; /* reserved */ -}; - -/** - * xcRB - */ -struct ica_xcRB { - unsigned short agent_ID; - unsigned int user_defined; - unsigned short request_ID; - unsigned int request_control_blk_length; - unsigned char padding1[16 - sizeof (char *)]; - char __user * request_control_blk_addr; - unsigned int request_data_length; - char padding2[16 - sizeof (char *)]; - char __user * request_data_address; - unsigned int reply_control_blk_length; - char padding3[16 - sizeof (char *)]; - char __user * reply_control_blk_addr; - unsigned int reply_data_length; - char padding4[16 - sizeof (char *)]; - char __user * reply_data_addr; - unsigned short priority_window; - unsigned int status; -} __attribute__((packed)); -#define AUTOSELECT ((unsigned int)0xFFFFFFFF) - -#define ZCRYPT_IOCTL_MAGIC 'z' - -/** - * Interface notes: - * - * The ioctl()s which are implemented (along with relevant details) - * are: - * - * ICARSAMODEXPO - * Perform an RSA operation using a Modulus-Exponent pair - * This takes an ica_rsa_modexpo struct as its arg. - * - * NOTE: please refer to the comments preceding this structure - * for the implementation details for the contents of the - * block - * - * ICARSACRT - * Perform an RSA operation using a Chinese-Remainder Theorem key - * This takes an ica_rsa_modexpo_crt struct as its arg. - * - * NOTE: please refer to the comments preceding this structure - * for the implementation details for the contents of the - * block - * - * Z90STAT_TOTALCOUNT - * Return an integer count of all device types together. - * - * Z90STAT_PCICACOUNT - * Return an integer count of all PCICAs. - * - * Z90STAT_PCICCCOUNT - * Return an integer count of all PCICCs. - * - * Z90STAT_PCIXCCMCL2COUNT - * Return an integer count of all MCL2 PCIXCCs. - * - * Z90STAT_PCIXCCMCL3COUNT - * Return an integer count of all MCL3 PCIXCCs. - * - * Z90STAT_CEX2CCOUNT - * Return an integer count of all CEX2Cs. - * - * Z90STAT_CEX2ACOUNT - * Return an integer count of all CEX2As. - * - * Z90STAT_REQUESTQ_COUNT - * Return an integer count of the number of entries waiting to be - * sent to a device. - * - * Z90STAT_PENDINGQ_COUNT - * Return an integer count of the number of entries sent to a - * device awaiting the reply. - * - * Z90STAT_TOTALOPEN_COUNT - * Return an integer count of the number of open file handles. - * - * Z90STAT_DOMAIN_INDEX - * Return the integer value of the Cryptographic Domain. - * - * Z90STAT_STATUS_MASK - * Return an 64 element array of unsigned chars for the status of - * all devices. - * 0x01: PCICA - * 0x02: PCICC - * 0x03: PCIXCC_MCL2 - * 0x04: PCIXCC_MCL3 - * 0x05: CEX2C - * 0x06: CEX2A - * 0x0d: device is disabled via the proc filesystem - * - * Z90STAT_QDEPTH_MASK - * Return an 64 element array of unsigned chars for the queue - * depth of all devices. - * - * Z90STAT_PERDEV_REQCNT - * Return an 64 element array of unsigned integers for the number - * of successfully completed requests per device since the device - * was detected and made available. - * - * ICAZ90STATUS (deprecated) - * Return some device driver status in a ica_z90_status struct - * This takes an ica_z90_status struct as its arg. - * - * NOTE: this ioctl() is deprecated, and has been replaced with - * single ioctl()s for each type of status being requested - * - * Z90STAT_PCIXCCCOUNT (deprecated) - * Return an integer count of all PCIXCCs (MCL2 + MCL3). - * This is DEPRECATED now that MCL3 PCIXCCs are treated differently from - * MCL2 PCIXCCs. - * - * Z90QUIESCE (not recommended) - * Quiesce the driver. This is intended to stop all new - * requests from being processed. Its use is NOT recommended, - * except in circumstances where there is no other way to stop - * callers from accessing the driver. Its original use was to - * allow the driver to be "drained" of work in preparation for - * a system shutdown. - * - * NOTE: once issued, this ban on new work cannot be undone - * except by unloading and reloading the driver. - */ - -/** - * Supported ioctl calls - */ -#define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x05, 0) -#define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x06, 0) -#define ZSECSENDCPRB _IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x81, 0) - -/* New status calls */ -#define Z90STAT_TOTALCOUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x40, int) -#define Z90STAT_PCICACOUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x41, int) -#define Z90STAT_PCICCCOUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x42, int) -#define Z90STAT_PCIXCCMCL2COUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x4b, int) -#define Z90STAT_PCIXCCMCL3COUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x4c, int) -#define Z90STAT_CEX2CCOUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x4d, int) -#define Z90STAT_CEX2ACOUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x4e, int) -#define Z90STAT_REQUESTQ_COUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x44, int) -#define Z90STAT_PENDINGQ_COUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x45, int) -#define Z90STAT_TOTALOPEN_COUNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x46, int) -#define Z90STAT_DOMAIN_INDEX _IOR(ZCRYPT_IOCTL_MAGIC, 0x47, int) -#define Z90STAT_STATUS_MASK _IOR(ZCRYPT_IOCTL_MAGIC, 0x48, char[64]) -#define Z90STAT_QDEPTH_MASK _IOR(ZCRYPT_IOCTL_MAGIC, 0x49, char[64]) -#define Z90STAT_PERDEV_REQCNT _IOR(ZCRYPT_IOCTL_MAGIC, 0x4a, int[64]) - -#endif /* __ASM_S390_ZCRYPT_H */ diff --git a/trunk/include/asm-sh/page.h b/trunk/include/asm-sh/page.h index 5a057b00f19a..a5559e38744e 100644 --- a/trunk/include/asm-sh/page.h +++ b/trunk/include/asm-sh/page.h @@ -104,7 +104,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; /* PFN start number, because of __MEMORY_START */ #define PFN_START (__MEMORY_START >> PAGE_SHIFT) -#define ARCH_PFN_OFFSET (PFN_START) +#define ARCH_PFN_OFFSET (FPN_START) #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) #define pfn_valid(pfn) (((pfn) - PFN_START) < max_mapnr) #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) diff --git a/trunk/include/asm-sh64/bug.h b/trunk/include/asm-sh64/bug.h index f3a9c9248ef4..81f722efeb63 100644 --- a/trunk/include/asm-sh64/bug.h +++ b/trunk/include/asm-sh64/bug.h @@ -1,7 +1,7 @@ #ifndef __ASM_SH64_BUG_H #define __ASM_SH64_BUG_H -#ifdef CONFIG_BUG + /* * Tell the user there is some problem, then force a segfault (in process * context) or a panic (interrupt context). @@ -11,9 +11,17 @@ *(volatile int *)0 = 0; \ } while (0) -#define HAVE_ARCH_BUG -#endif +#define BUG_ON(condition) do { \ + if (unlikely((condition)!=0)) \ + BUG(); \ +} while(0) -#include +#define WARN_ON(condition) do { \ + if (unlikely((condition)!=0)) { \ + printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \ + dump_stack(); \ + } \ +} while (0) #endif /* __ASM_SH64_BUG_H */ + diff --git a/trunk/include/asm-sh64/byteorder.h b/trunk/include/asm-sh64/byteorder.h index 7419d78820ee..f602ebe334eb 100644 --- a/trunk/include/asm-sh64/byteorder.h +++ b/trunk/include/asm-sh64/byteorder.h @@ -14,7 +14,7 @@ #include -static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) +static __inline__ __const__ __u32 ___arch__swab32(__u32 x) { __asm__("byterev %0, %0\n\t" "shari %0, 32, %0" @@ -23,7 +23,7 @@ static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) return x; } -static inline __attribute_const__ __u16 ___arch__swab16(__u16 x) +static __inline__ __const__ __u16 ___arch__swab16(__u16 x) { __asm__("byterev %0, %0\n\t" "shari %0, 48, %0" diff --git a/trunk/include/asm-sh64/dma-mapping.h b/trunk/include/asm-sh64/dma-mapping.h index 68e27a8fca31..a74a49e47922 100644 --- a/trunk/include/asm-sh64/dma-mapping.h +++ b/trunk/include/asm-sh64/dma-mapping.h @@ -126,30 +126,22 @@ static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg, static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction dir) -{ - dma_sync_single(dev, dma_handle, size, dir); -} + __attribute__ ((alias("dma_sync_single"))); static inline void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction dir) -{ - dma_sync_single(dev, dma_handle, size, dir); -} + __attribute__ ((alias("dma_sync_single"))); static inline void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction dir) -{ - dma_sync_sg(dev, sg, nelems, dir); -} + __attribute__ ((alias("dma_sync_sg"))); static inline void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, enum dma_data_direction dir) -{ - dma_sync_sg(dev, sg, nelems, dir); -} + __attribute__ ((alias("dma_sync_sg"))); static inline int dma_get_cache_alignment(void) { diff --git a/trunk/include/asm-sh64/io.h b/trunk/include/asm-sh64/io.h index 252fedbb6621..dee4f77929a4 100644 --- a/trunk/include/asm-sh64/io.h +++ b/trunk/include/asm-sh64/io.h @@ -123,13 +123,6 @@ void insw(unsigned long port, void *addr, unsigned long count); void outsl(unsigned long port, const void *addr, unsigned long count); void insl(unsigned long port, void *addr, unsigned long count); -#define __raw_readb readb -#define __raw_readw readw -#define __raw_readl readl -#define __raw_writeb writeb -#define __raw_writew writew -#define __raw_writel writel - void memcpy_toio(void __iomem *to, const void *from, long count); void memcpy_fromio(void *to, void __iomem *from, long count); diff --git a/trunk/include/asm-sh64/ptrace.h b/trunk/include/asm-sh64/ptrace.h index a6d4da519db6..56190f521587 100644 --- a/trunk/include/asm-sh64/ptrace.h +++ b/trunk/include/asm-sh64/ptrace.h @@ -28,7 +28,7 @@ struct pt_regs { #ifdef __KERNEL__ #define user_mode(regs) (((regs)->sr & 0x40000000)==0) #define instruction_pointer(regs) ((regs)->pc) -#define profile_pc(regs) ((unsigned long)instruction_pointer(regs)) +#define profile_pc(regs) instruction_pointer(regs) extern void show_regs(struct pt_regs *); #endif diff --git a/trunk/include/asm-sh64/system.h b/trunk/include/asm-sh64/system.h index b1598c26fcb0..87ef6f1ad5a4 100644 --- a/trunk/include/asm-sh64/system.h +++ b/trunk/include/asm-sh64/system.h @@ -64,7 +64,7 @@ extern void __xchg_called_with_bad_pointer(void); #define smp_read_barrier_depends() do { } while (0) #endif /* CONFIG_SMP */ -#define set_rmb(var, value) do { (void)xchg(&var, value); } while (0) +#define set_rmb(var, value) do { xchg(&var, value); } while (0) #define set_mb(var, value) set_rmb(var, value) /* Interrupt Control */ diff --git a/trunk/include/asm-sh64/uaccess.h b/trunk/include/asm-sh64/uaccess.h index 644c67b65f94..f4936d8fa617 100644 --- a/trunk/include/asm-sh64/uaccess.h +++ b/trunk/include/asm-sh64/uaccess.h @@ -128,20 +128,25 @@ do { \ #define __get_user_nocheck(x,ptr,size) \ ({ \ - long __gu_err, __gu_val; \ - __get_user_size((void *)&__gu_val, (long)(ptr), \ - (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ + long __gu_addr = (long)(ptr); \ + long __gu_err; \ + __typeof(*(ptr)) __gu_val; \ + __asm__ ("":"=r" (__gu_val)); \ + __asm__ ("":"=r" (__gu_err)); \ + __get_user_size((void *)&__gu_val, __gu_addr, (size), __gu_err); \ + (x) = (__typeof__(*(ptr))) __gu_val; \ __gu_err; \ }) #define __get_user_check(x,ptr,size) \ ({ \ long __gu_addr = (long)(ptr); \ - long __gu_err = -EFAULT, __gu_val; \ + long __gu_err = -EFAULT; \ + __typeof(*(ptr)) __gu_val; \ + __asm__ ("":"=r" (__gu_val)); \ + __asm__ ("":"=r" (__gu_err)); \ if (__access_ok(__gu_addr, (size))) \ - __get_user_size((void *)&__gu_val, __gu_addr, \ - (size), __gu_err); \ + __get_user_size((void *)&__gu_val, __gu_addr, (size), __gu_err); \ (x) = (__typeof__(*(ptr))) __gu_val; \ __gu_err; \ }) diff --git a/trunk/include/asm-sparc/Kbuild b/trunk/include/asm-sparc/Kbuild index b22b67a64ecc..e2a57fd7abfa 100644 --- a/trunk/include/asm-sparc/Kbuild +++ b/trunk/include/asm-sparc/Kbuild @@ -1,22 +1,6 @@ include include/asm-generic/Kbuild.asm -header-y += apc.h -header-y += asi.h -header-y += auxio.h -header-y += bpp.h -header-y += head.h -header-y += ipc.h -header-y += jsflash.h -header-y += openpromio.h -header-y += pbm.h -header-y += pconf.h -header-y += pgtsun4.h -header-y += reg.h -header-y += traps.h -header-y += turbosparc.h -header-y += vfc_ioctls.h -header-y += winmacro.h - -unifdef-y += fbio.h -unifdef-y += perfctr.h -unifdef-y += psr.h +unifdef-y += fbio.h perfctr.h psr.h +header-y += apc.h asi.h auxio.h bpp.h head.h ipc.h jsflash.h \ + openpromio.h pbm.h pconf.h pgtsun4.h reg.h traps.h \ + turbosparc.h vfc_ioctls.h winmacro.h diff --git a/trunk/include/asm-sparc/mman.h b/trunk/include/asm-sparc/mman.h index b7dc40bc68f4..88d1886abf3b 100644 --- a/trunk/include/asm-sparc/mman.h +++ b/trunk/include/asm-sparc/mman.h @@ -35,12 +35,4 @@ #define MADV_FREE 0x5 /* (Solaris) contents can be freed */ -#ifdef __KERNEL__ -#ifndef __ASSEMBLY__ -#define arch_mmap_check sparc_mmap_check -int sparc_mmap_check(unsigned long addr, unsigned long len, - unsigned long flags); -#endif -#endif - #endif /* __SPARC_MMAN_H__ */ diff --git a/trunk/include/asm-sparc64/Kbuild b/trunk/include/asm-sparc64/Kbuild index 4b59ce46cc2d..9284c3cb27ec 100644 --- a/trunk/include/asm-sparc64/Kbuild +++ b/trunk/include/asm-sparc64/Kbuild @@ -4,26 +4,7 @@ ALTARCH := sparc ARCHDEF := defined __sparc__ && defined __arch64__ ALTARCHDEF := defined __sparc__ && !defined __arch64__ -header-y += apb.h -header-y += asi.h -header-y += bbc.h -header-y += bpp.h -header-y += display7seg.h -header-y += envctrl.h -header-y += floppy.h -header-y += ipc.h -header-y += kdebug.h -header-y += mostek.h -header-y += openprom.h -header-y += openpromio.h -header-y += parport.h -header-y += pconf.h -header-y += psrcompat.h -header-y += pstate.h -header-y += reg.h -header-y += uctx.h -header-y += utrap.h -header-y += watchdog.h - -unifdef-y += fbio.h -unifdef-y += perfctr.h +unifdef-y += fbio.h perfctr.h +header-y += apb.h asi.h bbc.h bpp.h display7seg.h envctrl.h floppy.h \ + ipc.h kdebug.h mostek.h openprom.h openpromio.h parport.h \ + pconf.h psrcompat.h pstate.h reg.h uctx.h utrap.h watchdog.h diff --git a/trunk/include/asm-sparc64/kprobes.h b/trunk/include/asm-sparc64/kprobes.h index c9f5c34d318c..15065af566c2 100644 --- a/trunk/include/asm-sparc64/kprobes.h +++ b/trunk/include/asm-sparc64/kprobes.h @@ -13,7 +13,6 @@ typedef u32 kprobe_opcode_t; #define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry #define arch_remove_kprobe(p) do {} while (0) #define ARCH_INACTIVE_KPROBE_COUNT 0 -#define flush_insn_slot(p) do { } while (0) /* Architecture specific copy of original instruction*/ struct arch_specific_insn { diff --git a/trunk/include/asm-sparc64/mman.h b/trunk/include/asm-sparc64/mman.h index 8cc1860be630..6fd878e61435 100644 --- a/trunk/include/asm-sparc64/mman.h +++ b/trunk/include/asm-sparc64/mman.h @@ -35,12 +35,4 @@ #define MADV_FREE 0x5 /* (Solaris) contents can be freed */ -#ifdef __KERNEL__ -#ifndef __ASSEMBLY__ -#define arch_mmap_check sparc64_mmap_check -int sparc64_mmap_check(unsigned long addr, unsigned long len, - unsigned long flags); -#endif -#endif - #endif /* __SPARC64_MMAN_H__ */ diff --git a/trunk/include/asm-sparc64/pgtable.h b/trunk/include/asm-sparc64/pgtable.h index ebfe395cfb87..03f5bc9b6bec 100644 --- a/trunk/include/asm-sparc64/pgtable.h +++ b/trunk/include/asm-sparc64/pgtable.h @@ -234,7 +234,7 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot) sz_bits = 0UL; if (_PAGE_SZBITS_4U != 0UL || _PAGE_SZBITS_4V != 0UL) { __asm__ __volatile__( - "\n661: sethi %%uhi(%1), %0\n" + "\n661: sethi %uhi(%1), %0\n" " sllx %0, 32, %0\n" " .section .sun4v_2insn_patch, \"ax\"\n" " .word 661b\n" @@ -339,7 +339,7 @@ static inline pgprot_t pgprot_noncached(pgprot_t prot) " .section .sun4v_2insn_patch, \"ax\"\n" " .word 661b\n" " andn %0, %4, %0\n" - " or %0, %5, %0\n" + " or %0, %3, %0\n" " .previous\n" : "=r" (val) : "0" (val), "i" (_PAGE_CP_4U | _PAGE_CV_4U), "i" (_PAGE_E_4U), diff --git a/trunk/include/asm-sparc64/sfp-machine.h b/trunk/include/asm-sparc64/sfp-machine.h index 89d42431efb5..5015bb8d6c32 100644 --- a/trunk/include/asm-sparc64/sfp-machine.h +++ b/trunk/include/asm-sparc64/sfp-machine.h @@ -34,7 +34,7 @@ #define _FP_MUL_MEAT_D(R,X,Y) \ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) #define _FP_MUL_MEAT_Q(R,X,Y) \ - _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) + _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm) #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y) diff --git a/trunk/include/asm-x86_64/Kbuild b/trunk/include/asm-x86_64/Kbuild index 40f2f13fe174..dc4d101e8a16 100644 --- a/trunk/include/asm-x86_64/Kbuild +++ b/trunk/include/asm-x86_64/Kbuild @@ -4,18 +4,8 @@ ALTARCH := i386 ARCHDEF := defined __x86_64__ ALTARCHDEF := defined __i386__ -header-y += boot.h -header-y += bootsetup.h -header-y += cpufeature.h -header-y += debugreg.h -header-y += ldt.h -header-y += msr.h -header-y += prctl.h -header-y += setup.h -header-y += sigcontext32.h -header-y += ucontext.h -header-y += vsyscall32.h +header-y += boot.h bootsetup.h cpufeature.h debugreg.h ldt.h \ + msr.h prctl.h setup.h sigcontext32.h ucontext.h \ + vsyscall32.h -unifdef-y += mce.h -unifdef-y += mtrr.h -unifdef-y += vsyscall.h +unifdef-y += mce.h mtrr.h vsyscall.h diff --git a/trunk/include/asm-x86_64/alternative.h b/trunk/include/asm-x86_64/alternative.h index a584826cc570..aa67bfd1b3ce 100644 --- a/trunk/include/asm-x86_64/alternative.h +++ b/trunk/include/asm-x86_64/alternative.h @@ -4,7 +4,6 @@ #ifdef __KERNEL__ #include -#include struct alt_instr { u8 *instr; /* original instruction */ @@ -103,6 +102,9 @@ static inline void alternatives_smp_switch(int smp) {} /* * Alternative inline assembly for SMP. * + * alternative_smp() takes two versions (SMP first, UP second) and is + * for more complex stuff such as spinlocks. + * * The LOCK_PREFIX macro defined here replaces the LOCK and * LOCK_PREFIX macros used everywhere in the source tree. * @@ -122,6 +124,21 @@ static inline void alternatives_smp_switch(int smp) {} */ #ifdef CONFIG_SMP +#define alternative_smp(smpinstr, upinstr, args...) \ + asm volatile ("661:\n\t" smpinstr "\n662:\n" \ + ".section .smp_altinstructions,\"a\"\n" \ + " .align 8\n" \ + " .quad 661b\n" /* label */ \ + " .quad 663f\n" /* new instruction */ \ + " .byte 0x66\n" /* X86_FEATURE_UP */ \ + " .byte 662b-661b\n" /* sourcelen */ \ + " .byte 664f-663f\n" /* replacementlen */ \ + ".previous\n" \ + ".section .smp_altinstr_replacement,\"awx\"\n" \ + "663:\n\t" upinstr "\n" /* replacement */ \ + "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \ + ".previous" : args) + #define LOCK_PREFIX \ ".section .smp_locks,\"a\"\n" \ " .align 8\n" \ @@ -130,6 +147,8 @@ static inline void alternatives_smp_switch(int smp) {} "661:\n\tlock; " #else /* ! CONFIG_SMP */ +#define alternative_smp(smpinstr, upinstr, args...) \ + asm volatile (upinstr : args) #define LOCK_PREFIX "" #endif diff --git a/trunk/include/asm-x86_64/calgary.h b/trunk/include/asm-x86_64/calgary.h index 4e3919524240..fbfb50136edb 100644 --- a/trunk/include/asm-x86_64/calgary.h +++ b/trunk/include/asm-x86_64/calgary.h @@ -60,4 +60,9 @@ static inline int calgary_iommu_init(void) { return 1; } static inline void detect_calgary(void) { return; } #endif +static inline unsigned int bus_to_phb(unsigned char busno) +{ + return ((busno % 15 == 0) ? 0 : busno / 2 + 1); +} + #endif /* _ASM_X86_64_CALGARY_H */ diff --git a/trunk/include/asm-x86_64/elf.h b/trunk/include/asm-x86_64/elf.h index a406fcb1e924..b4f8f4a41a6e 100644 --- a/trunk/include/asm-x86_64/elf.h +++ b/trunk/include/asm-x86_64/elf.h @@ -7,6 +7,8 @@ #include #include +#include +#include /* x86-64 relocation types */ #define R_X86_64_NONE 0 /* No reloc */ @@ -36,23 +38,18 @@ typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef struct user_i387_struct elf_fpregset_t; -/* - * These are used to set parameters in the core dumps. - */ -#define ELF_CLASS ELFCLASS64 -#define ELF_DATA ELFDATA2LSB -#define ELF_ARCH EM_X86_64 - -#ifdef __KERNEL__ -#include -#include - /* * This is used to ensure we don't load something for the wrong architecture. */ #define elf_check_arch(x) \ ((x)->e_machine == EM_X86_64) +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_X86_64 /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program starts %edx contains a pointer to a function which might be registered using `atexit'. @@ -144,6 +141,7 @@ typedef struct user_i387_struct elf_fpregset_t; /* I'm not sure if we can use '-' here */ #define ELF_PLATFORM ("x86_64") +#ifdef __KERNEL__ extern void set_personality_64bit(void); #define SET_PERSONALITY(ex, ibcs2) set_personality_64bit() /* diff --git a/trunk/include/asm-x86_64/kprobes.h b/trunk/include/asm-x86_64/kprobes.h index cf5317898fb0..d36febd9bb18 100644 --- a/trunk/include/asm-x86_64/kprobes.h +++ b/trunk/include/asm-x86_64/kprobes.h @@ -47,7 +47,6 @@ typedef u8 kprobe_opcode_t; void kretprobe_trampoline(void); extern void arch_remove_kprobe(struct kprobe *p); -#define flush_insn_slot(p) do { } while (0) /* Architecture specific copy of original instruction*/ struct arch_specific_insn { diff --git a/trunk/include/asm-x86_64/page.h b/trunk/include/asm-x86_64/page.h index 10f346165cab..f7bf875aae40 100644 --- a/trunk/include/asm-x86_64/page.h +++ b/trunk/include/asm-x86_64/page.h @@ -19,7 +19,7 @@ #define EXCEPTION_STACK_ORDER 0 #define EXCEPTION_STKSZ (PAGE_SIZE << EXCEPTION_STACK_ORDER) -#define DEBUG_STACK_ORDER (EXCEPTION_STACK_ORDER + 1) +#define DEBUG_STACK_ORDER EXCEPTION_STACK_ORDER #define DEBUG_STKSZ (PAGE_SIZE << DEBUG_STACK_ORDER) #define IRQSTACK_ORDER 2 diff --git a/trunk/include/asm-x86_64/processor.h b/trunk/include/asm-x86_64/processor.h index de9c3147ee4c..3b3c1217fe61 100644 --- a/trunk/include/asm-x86_64/processor.h +++ b/trunk/include/asm-x86_64/processor.h @@ -232,14 +232,8 @@ struct tss_struct { unsigned long io_bitmap[IO_BITMAP_LONGS + 1]; } __attribute__((packed)) ____cacheline_aligned; - extern struct cpuinfo_x86 boot_cpu_data; DECLARE_PER_CPU(struct tss_struct,init_tss); -/* Save the original ist values for checking stack pointers during debugging */ -struct orig_ist { - unsigned long ist[7]; -}; -DECLARE_PER_CPU(struct orig_ist, orig_ist); #ifdef CONFIG_X86_VSMP #define ARCH_MIN_TASKALIGN (1 << INTERNODE_CACHE_SHIFT) diff --git a/trunk/include/asm-x86_64/signal.h b/trunk/include/asm-x86_64/signal.h index 3ede2a61973a..cef7a7d51b7e 100644 --- a/trunk/include/asm-x86_64/signal.h +++ b/trunk/include/asm-x86_64/signal.h @@ -3,13 +3,13 @@ #ifndef __ASSEMBLY__ #include +#include #include /* Avoid too many header ordering problems. */ struct siginfo; #ifdef __KERNEL__ -#include /* Most things should be clean enough to redefine this at will, if care is taken to make libc match. */ diff --git a/trunk/include/asm-x86_64/spinlock.h b/trunk/include/asm-x86_64/spinlock.h index 248a79f0eaff..8d3421996f94 100644 --- a/trunk/include/asm-x86_64/spinlock.h +++ b/trunk/include/asm-x86_64/spinlock.h @@ -21,7 +21,7 @@ #define __raw_spin_lock_string \ "\n1:\t" \ - LOCK_PREFIX " ; decl %0\n\t" \ + "lock ; decl %0\n\t" \ "js 2f\n" \ LOCK_SECTION_START("") \ "2:\t" \ @@ -40,7 +40,10 @@ static inline void __raw_spin_lock(raw_spinlock_t *lock) { - asm volatile(__raw_spin_lock_string : "=m" (lock->slock) : : "memory"); + alternative_smp( + __raw_spin_lock_string, + __raw_spin_lock_string_up, + "=m" (lock->slock) : : "memory"); } #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) @@ -122,12 +125,12 @@ static inline int __raw_write_trylock(raw_rwlock_t *lock) static inline void __raw_read_unlock(raw_rwlock_t *rw) { - asm volatile(LOCK_PREFIX " ; incl %0" :"=m" (rw->lock) : : "memory"); + asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory"); } static inline void __raw_write_unlock(raw_rwlock_t *rw) { - asm volatile(LOCK_PREFIX " ; addl $" RW_LOCK_BIAS_STR ",%0" + asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0" : "=m" (rw->lock) : : "memory"); } diff --git a/trunk/include/asm-x86_64/swiotlb.h b/trunk/include/asm-x86_64/swiotlb.h index ba94ab3d2673..5f9a01805821 100644 --- a/trunk/include/asm-x86_64/swiotlb.h +++ b/trunk/include/asm-x86_64/swiotlb.h @@ -42,8 +42,6 @@ extern void swiotlb_free_coherent (struct device *hwdev, size_t size, extern int swiotlb_dma_supported(struct device *hwdev, u64 mask); extern void swiotlb_init(void); -extern int swiotlb_force; - #ifdef CONFIG_SWIOTLB extern int swiotlb; #else diff --git a/trunk/include/asm-x86_64/unistd.h b/trunk/include/asm-x86_64/unistd.h index 80fd48e84bbb..94387c915e53 100644 --- a/trunk/include/asm-x86_64/unistd.h +++ b/trunk/include/asm-x86_64/unistd.h @@ -821,6 +821,8 @@ asmlinkage long sys_fork(struct pt_regs regs); asmlinkage long sys_vfork(struct pt_regs regs); asmlinkage long sys_pipe(int *fildes); +#endif /* __KERNEL_SYSCALLS__ */ + #ifndef __ASSEMBLY__ #include @@ -836,9 +838,9 @@ asmlinkage long sys_rt_sigaction(int sig, struct sigaction __user *oact, size_t sigsetsize); -#endif /* __ASSEMBLY__ */ +#endif /* __ASSEMBLY__ */ -#endif /* __KERNEL_SYSCALLS__ */ +#endif /* __NO_STUBS */ /* * "Conditional" syscalls @@ -848,8 +850,5 @@ asmlinkage long sys_rt_sigaction(int sig, */ #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") -#endif /* __NO_STUBS */ - #endif /* __KERNEL__ */ - -#endif /* _ASM_X86_64_UNISTD_H_ */ +#endif diff --git a/trunk/include/asm-x86_64/unwind.h b/trunk/include/asm-x86_64/unwind.h index 1f6e9bfb569e..f3e7124effe3 100644 --- a/trunk/include/asm-x86_64/unwind.h +++ b/trunk/include/asm-x86_64/unwind.h @@ -95,7 +95,6 @@ static inline int arch_unw_user_mode(const struct unwind_frame_info *info) #else #define UNW_PC(frame) ((void)(frame), 0) -#define UNW_SP(frame) ((void)(frame), 0) static inline int arch_unw_user_mode(const void *info) { diff --git a/trunk/include/asm-x86_64/vsyscall.h b/trunk/include/asm-x86_64/vsyscall.h index 146b24402a5f..a85e16f56d73 100644 --- a/trunk/include/asm-x86_64/vsyscall.h +++ b/trunk/include/asm-x86_64/vsyscall.h @@ -1,6 +1,8 @@ #ifndef _ASM_X86_64_VSYSCALL_H_ #define _ASM_X86_64_VSYSCALL_H_ +#include + enum vsyscall_num { __NR_vgettimeofday, __NR_vtime, @@ -12,7 +14,6 @@ enum vsyscall_num { #define VSYSCALL_ADDR(vsyscall_nr) (VSYSCALL_START+VSYSCALL_SIZE*(vsyscall_nr)) #ifdef __KERNEL__ -#include #define __section_vxtime __attribute__ ((unused, __section__ (".vxtime"), aligned(16))) #define __section_wall_jiffies __attribute__ ((unused, __section__ (".wall_jiffies"), aligned(16))) diff --git a/trunk/include/crypto/algapi.h b/trunk/include/crypto/algapi.h deleted file mode 100644 index 5748aecdb414..000000000000 --- a/trunk/include/crypto/algapi.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Cryptographic API for algorithms (i.e., low-level API). - * - * Copyright (c) 2006 Herbert Xu - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - */ -#ifndef _CRYPTO_ALGAPI_H -#define _CRYPTO_ALGAPI_H - -#include - -struct module; -struct seq_file; - -struct crypto_type { - unsigned int (*ctxsize)(struct crypto_alg *alg); - int (*init)(struct crypto_tfm *tfm); - void (*exit)(struct crypto_tfm *tfm); - void (*show)(struct seq_file *m, struct crypto_alg *alg); -}; - -struct crypto_instance { - struct crypto_alg alg; - - struct crypto_template *tmpl; - struct hlist_node list; - - void *__ctx[] CRYPTO_MINALIGN_ATTR; -}; - -struct crypto_template { - struct list_head list; - struct hlist_head instances; - struct module *module; - - struct crypto_instance *(*alloc)(void *param, unsigned int len); - void (*free)(struct crypto_instance *inst); - - char name[CRYPTO_MAX_ALG_NAME]; -}; - -struct crypto_spawn { - struct list_head list; - struct crypto_alg *alg; - struct crypto_instance *inst; -}; - -struct scatter_walk { - struct scatterlist *sg; - unsigned int offset; -}; - -struct blkcipher_walk { - union { - struct { - struct page *page; - unsigned long offset; - } phys; - - struct { - u8 *page; - u8 *addr; - } virt; - } src, dst; - - struct scatter_walk in; - unsigned int nbytes; - - struct scatter_walk out; - unsigned int total; - - void *page; - u8 *buffer; - u8 *iv; - - int flags; -}; - -extern const struct crypto_type crypto_blkcipher_type; -extern const struct crypto_type crypto_hash_type; - -void crypto_mod_put(struct crypto_alg *alg); - -int crypto_register_template(struct crypto_template *tmpl); -void crypto_unregister_template(struct crypto_template *tmpl); -struct crypto_template *crypto_lookup_template(const char *name); - -int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, - struct crypto_instance *inst); -void crypto_drop_spawn(struct crypto_spawn *spawn); -struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn); - -struct crypto_alg *crypto_get_attr_alg(void *param, unsigned int len, - u32 type, u32 mask); -struct crypto_instance *crypto_alloc_instance(const char *name, - struct crypto_alg *alg); - -int blkcipher_walk_done(struct blkcipher_desc *desc, - struct blkcipher_walk *walk, int err); -int blkcipher_walk_virt(struct blkcipher_desc *desc, - struct blkcipher_walk *walk); -int blkcipher_walk_phys(struct blkcipher_desc *desc, - struct blkcipher_walk *walk); - -static inline void *crypto_tfm_ctx_aligned(struct crypto_tfm *tfm) -{ - unsigned long addr = (unsigned long)crypto_tfm_ctx(tfm); - unsigned long align = crypto_tfm_alg_alignmask(tfm); - - if (align <= crypto_tfm_ctx_alignment()) - align = 1; - return (void *)ALIGN(addr, align); -} - -static inline void *crypto_instance_ctx(struct crypto_instance *inst) -{ - return inst->__ctx; -} - -static inline void *crypto_blkcipher_ctx(struct crypto_blkcipher *tfm) -{ - return crypto_tfm_ctx(&tfm->base); -} - -static inline void *crypto_blkcipher_ctx_aligned(struct crypto_blkcipher *tfm) -{ - return crypto_tfm_ctx_aligned(&tfm->base); -} - -static inline struct cipher_alg *crypto_cipher_alg(struct crypto_cipher *tfm) -{ - return &crypto_cipher_tfm(tfm)->__crt_alg->cra_cipher; -} - -static inline void *crypto_hash_ctx_aligned(struct crypto_hash *tfm) -{ - return crypto_tfm_ctx_aligned(&tfm->base); -} - -static inline void blkcipher_walk_init(struct blkcipher_walk *walk, - struct scatterlist *dst, - struct scatterlist *src, - unsigned int nbytes) -{ - walk->in.sg = src; - walk->out.sg = dst; - walk->total = nbytes; -} - -#endif /* _CRYPTO_ALGAPI_H */ - diff --git a/trunk/include/crypto/twofish.h b/trunk/include/crypto/twofish.h deleted file mode 100644 index c408522595c6..000000000000 --- a/trunk/include/crypto/twofish.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _CRYPTO_TWOFISH_H -#define _CRYPTO_TWOFISH_H - -#include - -#define TF_MIN_KEY_SIZE 16 -#define TF_MAX_KEY_SIZE 32 -#define TF_BLOCK_SIZE 16 - -struct crypto_tfm; - -/* Structure for an expanded Twofish key. s contains the key-dependent - * S-boxes composed with the MDS matrix; w contains the eight "whitening" - * subkeys, K[0] through K[7]. k holds the remaining, "round" subkeys. Note - * that k[i] corresponds to what the Twofish paper calls K[i+8]. */ -struct twofish_ctx { - u32 s[4][256], w[8], k[32]; -}; - -int twofish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len); - -#endif diff --git a/trunk/include/linux/Kbuild b/trunk/include/linux/Kbuild index 7d076d97b2f7..2b8a7d68fae3 100644 --- a/trunk/include/linux/Kbuild +++ b/trunk/include/linux/Kbuild @@ -1,343 +1,63 @@ -header-y += byteorder/ -header-y += dvb/ -header-y += hdlc/ -header-y += isdn/ -header-y += nfsd/ -header-y += raid/ -header-y += sunrpc/ -header-y += tc_act/ -header-y += netfilter/ -header-y += netfilter_arp/ -header-y += netfilter_bridge/ -header-y += netfilter_ipv4/ -header-y += netfilter_ipv6/ +header-y := byteorder/ dvb/ hdlc/ isdn/ nfsd/ raid/ sunrpc/ tc_act/ \ + netfilter/ netfilter_arp/ netfilter_bridge/ netfilter_ipv4/ \ + netfilter_ipv6/ -header-y += affs_fs.h -header-y += affs_hardblocks.h -header-y += aio_abi.h -header-y += a.out.h -header-y += arcfb.h -header-y += atmapi.h -header-y += atmbr2684.h -header-y += atmclip.h -header-y += atm_eni.h -header-y += atm_he.h -header-y += atm_idt77105.h -header-y += atmioc.h -header-y += atmlec.h -header-y += atmmpc.h -header-y += atm_nicstar.h -header-y += atmppp.h -header-y += atmsap.h -header-y += atmsvc.h -header-y += atm_zatm.h -header-y += auto_fs4.h -header-y += auxvec.h -header-y += awe_voice.h -header-y += ax25.h -header-y += b1lli.h -header-y += baycom.h -header-y += bfs_fs.h -header-y += blkpg.h -header-y += bpqether.h -header-y += cdk.h -header-y += chio.h -header-y += coda_psdev.h -header-y += coff.h -header-y += comstats.h -header-y += consolemap.h -header-y += cycx_cfm.h -header-y += dm-ioctl.h -header-y += dn.h -header-y += dqblk_v1.h -header-y += dqblk_v2.h -header-y += dqblk_xfs.h -header-y += efs_fs_sb.h -header-y += elf-fdpic.h -header-y += elf.h -header-y += elf-em.h -header-y += fadvise.h -header-y += fd.h -header-y += fdreg.h -header-y += ftape-header-segment.h -header-y += ftape-vendors.h -header-y += fuse.h -header-y += futex.h -header-y += genetlink.h -header-y += gen_stats.h -header-y += gigaset_dev.h -header-y += hdsmart.h -header-y += hpfs_fs.h -header-y += hysdn_if.h -header-y += i2c-dev.h -header-y += i8k.h -header-y += icmp.h -header-y += if_arcnet.h -header-y += if_arp.h -header-y += if_bonding.h -header-y += if_cablemodem.h -header-y += if_fc.h -header-y += if_fddi.h -header-y += if.h -header-y += if_hippi.h -header-y += if_infiniband.h -header-y += if_packet.h -header-y += if_plip.h -header-y += if_ppp.h -header-y += if_slip.h -header-y += if_strip.h -header-y += if_tunnel.h -header-y += in6.h -header-y += in_route.h -header-y += ioctl.h -header-y += ip.h -header-y += ipmi_msgdefs.h -header-y += ip_mp_alg.h -header-y += ipsec.h -header-y += ipx.h -header-y += irda.h -header-y += isdn_divertif.h -header-y += iso_fs.h -header-y += ite_gpio.h -header-y += ixjuser.h -header-y += jffs2.h -header-y += keyctl.h -header-y += limits.h -header-y += major.h -header-y += matroxfb.h -header-y += meye.h -header-y += minix_fs.h -header-y += mmtimer.h -header-y += mqueue.h -header-y += mtio.h -header-y += ncp_no.h -header-y += netfilter_arp.h -header-y += netrom.h -header-y += nfs2.h -header-y += nfs4_mount.h -header-y += nfs_mount.h -header-y += openprom_fs.h -header-y += param.h -header-y += pci_ids.h -header-y += pci_regs.h -header-y += personality.h -header-y += pfkeyv2.h -header-y += pg.h -header-y += pkt_cls.h -header-y += pkt_sched.h -header-y += posix_types.h -header-y += ppdev.h -header-y += prctl.h -header-y += ps2esdi.h -header-y += qic117.h -header-y += qnxtypes.h -header-y += quotaio_v1.h -header-y += quotaio_v2.h -header-y += radeonfb.h -header-y += raw.h -header-y += resource.h -header-y += rose.h -header-y += sctp.h -header-y += smbno.h -header-y += snmp.h -header-y += sockios.h -header-y += som.h -header-y += sound.h -header-y += stddef.h -header-y += synclink.h -header-y += telephony.h -header-y += termios.h -header-y += ticable.h -header-y += times.h -header-y += tiocl.h -header-y += tipc.h -header-y += toshiba.h -header-y += ultrasound.h -header-y += un.h -header-y += utime.h -header-y += utsname.h -header-y += video_decoder.h -header-y += video_encoder.h -header-y += videotext.h -header-y += vt.h -header-y += wavefront.h -header-y += wireless.h -header-y += xattr.h -header-y += x25.h -header-y += zorro_ids.h +header-y += affs_fs.h affs_hardblocks.h aio_abi.h a.out.h arcfb.h \ + atmapi.h atmbr2684.h atmclip.h atm_eni.h atm_he.h \ + atm_idt77105.h atmioc.h atmlec.h atmmpc.h atm_nicstar.h \ + atmppp.h atmsap.h atmsvc.h atm_zatm.h auto_fs4.h auxvec.h \ + awe_voice.h ax25.h b1lli.h baycom.h bfs_fs.h blkpg.h \ + bpqether.h cdk.h chio.h coda_psdev.h coff.h comstats.h \ + consolemap.h cycx_cfm.h dm-ioctl.h dn.h dqblk_v1.h \ + dqblk_v2.h dqblk_xfs.h efs_fs_sb.h elf-fdpic.h elf.h elf-em.h \ + fadvise.h fd.h fdreg.h ftape-header-segment.h ftape-vendors.h \ + fuse.h futex.h genetlink.h gen_stats.h gigaset_dev.h hdsmart.h \ + hpfs_fs.h hysdn_if.h i2c-dev.h i8k.h icmp.h \ + if_arcnet.h if_arp.h if_bonding.h if_cablemodem.h if_fc.h \ + if_fddi.h if.h if_hippi.h if_infiniband.h if_packet.h \ + if_plip.h if_ppp.h if_slip.h if_strip.h if_tunnel.h in6.h \ + in_route.h ioctl.h ip.h ipmi_msgdefs.h ip_mp_alg.h ipsec.h \ + ipx.h irda.h isdn_divertif.h iso_fs.h ite_gpio.h ixjuser.h \ + jffs2.h keyctl.h limits.h major.h matroxfb.h meye.h minix_fs.h \ + mmtimer.h mqueue.h mtio.h ncp_no.h netfilter_arp.h netrom.h \ + nfs2.h nfs4_mount.h nfs_mount.h openprom_fs.h param.h \ + pci_ids.h pci_regs.h personality.h pfkeyv2.h pg.h pkt_cls.h \ + pkt_sched.h posix_types.h ppdev.h prctl.h ps2esdi.h qic117.h \ + qnxtypes.h quotaio_v1.h quotaio_v2.h radeonfb.h raw.h \ + resource.h rose.h sctp.h smbno.h snmp.h sockios.h som.h \ + sound.h stddef.h synclink.h telephony.h termios.h ticable.h \ + times.h tiocl.h tipc.h toshiba.h ultrasound.h un.h utime.h \ + utsname.h video_decoder.h video_encoder.h videotext.h vt.h \ + wavefront.h wireless.h xattr.h x25.h zorro_ids.h -unifdef-y += acct.h -unifdef-y += adb.h -unifdef-y += adfs_fs.h -unifdef-y += agpgart.h -unifdef-y += apm_bios.h -unifdef-y += atalk.h -unifdef-y += atmarp.h -unifdef-y += atmdev.h -unifdef-y += atm.h -unifdef-y += atm_tcp.h -unifdef-y += audit.h -unifdef-y += auto_fs.h -unifdef-y += binfmts.h -unifdef-y += capability.h -unifdef-y += capi.h -unifdef-y += cciss_ioctl.h -unifdef-y += cdrom.h -unifdef-y += cm4000_cs.h -unifdef-y += cn_proc.h -unifdef-y += coda.h -unifdef-y += connector.h -unifdef-y += cramfs_fs.h -unifdef-y += cuda.h -unifdef-y += cyclades.h -unifdef-y += dccp.h -unifdef-y += dirent.h -unifdef-y += divert.h -unifdef-y += elfcore.h -unifdef-y += errno.h -unifdef-y += errqueue.h -unifdef-y += ethtool.h -unifdef-y += eventpoll.h -unifdef-y += ext2_fs.h -unifdef-y += ext3_fs.h -unifdef-y += fb.h -unifdef-y += fcntl.h -unifdef-y += filter.h -unifdef-y += flat.h -unifdef-y += fs.h -unifdef-y += ftape.h -unifdef-y += gameport.h -unifdef-y += generic_serial.h -unifdef-y += genhd.h -unifdef-y += hayesesp.h -unifdef-y += hdlcdrv.h -unifdef-y += hdlc.h -unifdef-y += hdreg.h -unifdef-y += hiddev.h -unifdef-y += hpet.h -unifdef-y += i2c.h -unifdef-y += i2o-dev.h -unifdef-y += icmpv6.h -unifdef-y += if_bridge.h -unifdef-y += if_ec.h -unifdef-y += if_eql.h -unifdef-y += if_ether.h -unifdef-y += if_frad.h -unifdef-y += if_ltalk.h -unifdef-y += if_pppox.h -unifdef-y += if_shaper.h -unifdef-y += if_tr.h -unifdef-y += if_tun.h -unifdef-y += if_vlan.h -unifdef-y += if_wanpipe.h -unifdef-y += igmp.h -unifdef-y += inet_diag.h -unifdef-y += in.h -unifdef-y += inotify.h -unifdef-y += input.h -unifdef-y += ipc.h -unifdef-y += ipmi.h -unifdef-y += ipv6.h -unifdef-y += ipv6_route.h -unifdef-y += isdn.h -unifdef-y += isdnif.h -unifdef-y += isdn_ppp.h -unifdef-y += isicom.h -unifdef-y += jbd.h -unifdef-y += joystick.h -unifdef-y += kdev_t.h -unifdef-y += kd.h -unifdef-y += kernelcapi.h -unifdef-y += kernel.h -unifdef-y += keyboard.h -unifdef-y += llc.h -unifdef-y += loop.h -unifdef-y += lp.h -unifdef-y += mempolicy.h -unifdef-y += mii.h -unifdef-y += mman.h -unifdef-y += mroute.h -unifdef-y += msdos_fs.h -unifdef-y += msg.h -unifdef-y += nbd.h -unifdef-y += ncp_fs.h -unifdef-y += ncp.h -unifdef-y += ncp_mount.h -unifdef-y += netdevice.h -unifdef-y += netfilter_bridge.h -unifdef-y += netfilter_decnet.h -unifdef-y += netfilter.h -unifdef-y += netfilter_ipv4.h -unifdef-y += netfilter_ipv6.h -unifdef-y += netfilter_logging.h -unifdef-y += net.h -unifdef-y += netlink.h -unifdef-y += nfs3.h -unifdef-y += nfs4.h -unifdef-y += nfsacl.h -unifdef-y += nfs_fs.h -unifdef-y += nfs.h -unifdef-y += nfs_idmap.h -unifdef-y += n_r3964.h -unifdef-y += nubus.h -unifdef-y += nvram.h -unifdef-y += parport.h -unifdef-y += patchkey.h -unifdef-y += pci.h -unifdef-y += pktcdvd.h -unifdef-y += pmu.h -unifdef-y += poll.h -unifdef-y += ppp_defs.h -unifdef-y += ppp-comp.h -unifdef-y += ptrace.h -unifdef-y += qnx4_fs.h -unifdef-y += quota.h -unifdef-y += random.h -unifdef-y += reboot.h -unifdef-y += reiserfs_fs.h -unifdef-y += reiserfs_xattr.h -unifdef-y += romfs_fs.h -unifdef-y += route.h -unifdef-y += rtc.h -unifdef-y += rtnetlink.h -unifdef-y += scc.h -unifdef-y += sched.h -unifdef-y += sdla.h -unifdef-y += selinux_netlink.h -unifdef-y += sem.h -unifdef-y += serial_core.h -unifdef-y += serial.h -unifdef-y += serio.h -unifdef-y += shm.h -unifdef-y += signal.h -unifdef-y += smb_fs.h -unifdef-y += smb.h -unifdef-y += smb_mount.h -unifdef-y += socket.h -unifdef-y += sonet.h -unifdef-y += sonypi.h -unifdef-y += soundcard.h -unifdef-y += stat.h -unifdef-y += sysctl.h -unifdef-y += tcp.h -unifdef-y += time.h -unifdef-y += timex.h -unifdef-y += tty.h -unifdef-y += types.h -unifdef-y += udf_fs_i.h -unifdef-y += udp.h -unifdef-y += uinput.h -unifdef-y += uio.h -unifdef-y += unistd.h -unifdef-y += usb_ch9.h -unifdef-y += usbdevice_fs.h -unifdef-y += user.h -unifdef-y += videodev2.h -unifdef-y += videodev.h -unifdef-y += wait.h -unifdef-y += wanrouter.h -unifdef-y += watchdog.h -unifdef-y += xfrm.h -unifdef-y += zftape.h +unifdef-y += acct.h adb.h adfs_fs.h agpgart.h apm_bios.h atalk.h \ + atmarp.h atmdev.h atm.h atm_tcp.h audit.h auto_fs.h binfmts.h \ + capability.h capi.h cciss_ioctl.h cdrom.h cm4000_cs.h \ + cn_proc.h coda.h connector.h cramfs_fs.h cuda.h cyclades.h \ + dccp.h dirent.h divert.h elfcore.h errno.h errqueue.h \ + ethtool.h eventpoll.h ext2_fs.h ext3_fs.h fb.h fcntl.h \ + filter.h flat.h fs.h ftape.h gameport.h generic_serial.h \ + genhd.h hayesesp.h hdlcdrv.h hdlc.h hdreg.h hiddev.h hpet.h \ + i2c.h i2o-dev.h icmpv6.h if_bridge.h if_ec.h \ + if_eql.h if_ether.h if_frad.h if_ltalk.h if_pppox.h \ + if_shaper.h if_tr.h if_tun.h if_vlan.h if_wanpipe.h igmp.h \ + inet_diag.h in.h inotify.h input.h ipc.h ipmi.h ipv6.h \ + ipv6_route.h isdn.h isdnif.h isdn_ppp.h isicom.h jbd.h \ + joystick.h kdev_t.h kd.h kernelcapi.h kernel.h keyboard.h \ + llc.h loop.h lp.h mempolicy.h mii.h mman.h mroute.h msdos_fs.h \ + msg.h nbd.h ncp_fs.h ncp.h ncp_mount.h netdevice.h \ + netfilter_bridge.h netfilter_decnet.h netfilter.h \ + netfilter_ipv4.h netfilter_ipv6.h netfilter_logging.h net.h \ + netlink.h nfs3.h nfs4.h nfsacl.h nfs_fs.h nfs.h nfs_idmap.h \ + n_r3964.h nubus.h nvram.h parport.h patchkey.h pci.h pktcdvd.h \ + pmu.h poll.h ppp_defs.h ppp-comp.h ptrace.h qnx4_fs.h quota.h \ + random.h reboot.h reiserfs_fs.h reiserfs_xattr.h romfs_fs.h \ + route.h rtc.h rtnetlink.h scc.h sched.h sdla.h \ + selinux_netlink.h sem.h serial_core.h serial.h serio.h shm.h \ + signal.h smb_fs.h smb.h smb_mount.h socket.h sonet.h sonypi.h \ + soundcard.h stat.h sysctl.h tcp.h time.h timex.h tty.h types.h \ + udf_fs_i.h udp.h uinput.h uio.h unistd.h usb_ch9.h \ + usbdevice_fs.h user.h videodev2.h videodev.h wait.h \ + wanrouter.h watchdog.h xfrm.h zftape.h -objhdr-y += version.h +objhdr-y := version.h diff --git a/trunk/include/linux/atmdev.h b/trunk/include/linux/atmdev.h index 2096e5c72827..41788a31c438 100644 --- a/trunk/include/linux/atmdev.h +++ b/trunk/include/linux/atmdev.h @@ -7,6 +7,7 @@ #define LINUX_ATMDEV_H +#include #include #include #include @@ -209,7 +210,6 @@ struct atm_cirange { #ifdef __KERNEL__ -#include #include /* wait_queue_head_t */ #include /* struct timeval */ #include diff --git a/trunk/include/linux/audit.h b/trunk/include/linux/audit.h index 40a6c26294ae..b27d7debc5a1 100644 --- a/trunk/include/linux/audit.h +++ b/trunk/include/linux/audit.h @@ -132,10 +132,6 @@ #define AUDIT_CLASS_DIR_WRITE_32 1 #define AUDIT_CLASS_CHATTR 2 #define AUDIT_CLASS_CHATTR_32 3 -#define AUDIT_CLASS_READ 4 -#define AUDIT_CLASS_READ_32 5 -#define AUDIT_CLASS_WRITE 6 -#define AUDIT_CLASS_WRITE_32 7 /* This bitmask is used to validate user input. It represents all bits that * are currently used in an audit field constant understood by the kernel. @@ -181,7 +177,6 @@ #define AUDIT_EXIT 103 #define AUDIT_SUCCESS 104 /* exit >= 0; value ignored */ #define AUDIT_WATCH 105 -#define AUDIT_PERM 106 #define AUDIT_ARG0 200 #define AUDIT_ARG1 (AUDIT_ARG0+1) @@ -257,11 +252,6 @@ #define AUDIT_ARCH_V850 (EM_V850|__AUDIT_ARCH_LE) #define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE) -#define AUDIT_PERM_EXEC 1 -#define AUDIT_PERM_WRITE 2 -#define AUDIT_PERM_READ 4 -#define AUDIT_PERM_ATTR 8 - struct audit_status { __u32 mask; /* Bit mask for valid entries */ __u32 enabled; /* 1 = enabled, 0 = disabled */ @@ -324,7 +314,6 @@ struct mqstat; #define AUDITSC_FAILURE 2 #define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS ) extern int __init audit_register_class(int class, unsigned *list); -extern int audit_classify_syscall(int abi, unsigned syscall); #ifdef CONFIG_AUDITSYSCALL /* These are defined in auditsc.c */ /* Public API */ @@ -338,31 +327,21 @@ extern void __audit_getname(const char *name); extern void audit_putname(const char *name); extern void __audit_inode(const char *name, const struct inode *inode); extern void __audit_inode_child(const char *dname, const struct inode *inode, - const struct inode *parent); -extern void __audit_inode_update(const struct inode *inode); -static inline int audit_dummy_context(void) -{ - void *p = current->audit_context; - return !p || *(int *)p; -} + unsigned long pino); static inline void audit_getname(const char *name) { - if (unlikely(!audit_dummy_context())) + if (unlikely(current->audit_context)) __audit_getname(name); } static inline void audit_inode(const char *name, const struct inode *inode) { - if (unlikely(!audit_dummy_context())) + if (unlikely(current->audit_context)) __audit_inode(name, inode); } static inline void audit_inode_child(const char *dname, - const struct inode *inode, - const struct inode *parent) { - if (unlikely(!audit_dummy_context())) - __audit_inode_child(dname, inode, parent); -} -static inline void audit_inode_update(const struct inode *inode) { - if (unlikely(!audit_dummy_context())) - __audit_inode_update(inode); + const struct inode *inode, + unsigned long pino) { + if (unlikely(current->audit_context)) + __audit_inode_child(dname, inode, pino); } /* Private API (for audit.c only) */ @@ -386,61 +365,57 @@ extern int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat); static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp) { - if (unlikely(!audit_dummy_context())) + if (unlikely(current->audit_context)) return __audit_ipc_obj(ipcp); return 0; } static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) { - if (unlikely(!audit_dummy_context())) + if (unlikely(current->audit_context)) return __audit_ipc_set_perm(qbytes, uid, gid, mode); return 0; } static inline int audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr) { - if (unlikely(!audit_dummy_context())) + if (unlikely(current->audit_context)) return __audit_mq_open(oflag, mode, u_attr); return 0; } static inline int audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout) { - if (unlikely(!audit_dummy_context())) + if (unlikely(current->audit_context)) return __audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout); return 0; } static inline int audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout) { - if (unlikely(!audit_dummy_context())) + if (unlikely(current->audit_context)) return __audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout); return 0; } static inline int audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification) { - if (unlikely(!audit_dummy_context())) + if (unlikely(current->audit_context)) return __audit_mq_notify(mqdes, u_notification); return 0; } static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) { - if (unlikely(!audit_dummy_context())) + if (unlikely(current->audit_context)) return __audit_mq_getsetattr(mqdes, mqstat); return 0; } -extern int audit_n_rules; #else #define audit_alloc(t) ({ 0; }) #define audit_free(t) do { ; } while (0) #define audit_syscall_entry(ta,a,b,c,d,e) do { ; } while (0) #define audit_syscall_exit(f,r) do { ; } while (0) -#define audit_dummy_context() 1 #define audit_getname(n) do { ; } while (0) #define audit_putname(n) do { ; } while (0) #define __audit_inode(n,i) do { ; } while (0) #define __audit_inode_child(d,i,p) do { ; } while (0) -#define __audit_inode_update(i) do { ; } while (0) #define audit_inode(n,i) do { ; } while (0) #define audit_inode_child(d,i,p) do { ; } while (0) -#define audit_inode_update(i) do { ; } while (0) #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) #define audit_get_loginuid(c) ({ -1; }) #define audit_ipc_obj(i) ({ 0; }) @@ -455,7 +430,6 @@ extern int audit_n_rules; #define audit_mq_timedreceive(d,l,p,t) ({ 0; }) #define audit_mq_notify(d,n) ({ 0; }) #define audit_mq_getsetattr(d,s) ({ 0; }) -#define audit_n_rules 0 #endif #ifdef CONFIG_AUDIT diff --git a/trunk/include/linux/blkdev.h b/trunk/include/linux/blkdev.h index 96c9040c00a8..aafe82788b4e 100644 --- a/trunk/include/linux/blkdev.h +++ b/trunk/include/linux/blkdev.h @@ -746,7 +746,6 @@ extern void blk_queue_free_tags(request_queue_t *); extern int blk_queue_resize_tags(request_queue_t *, int); extern void blk_queue_invalidate_tags(request_queue_t *); extern long blk_congestion_wait(int rw, long timeout); -extern void blk_congestion_end(int rw); extern void blk_rq_bio_prep(request_queue_t *, struct request *, struct bio *); extern int blkdev_issue_flush(struct block_device *, sector_t *); diff --git a/trunk/include/linux/bootmem.h b/trunk/include/linux/bootmem.h index e319c649e4fd..1021f508d82c 100644 --- a/trunk/include/linux/bootmem.h +++ b/trunk/include/linux/bootmem.h @@ -114,7 +114,7 @@ extern void *__init alloc_large_system_hash(const char *tablename, #else #define HASHDIST_DEFAULT 0 #endif -extern int hashdist; /* Distribute hashes across NUMA nodes? */ +extern int __initdata hashdist; /* Distribute hashes across NUMA nodes? */ #endif /* _LINUX_BOOTMEM_H */ diff --git a/trunk/include/linux/byteorder/Kbuild b/trunk/include/linux/byteorder/Kbuild index 56499ab9e32e..84a57d4fb212 100644 --- a/trunk/include/linux/byteorder/Kbuild +++ b/trunk/include/linux/byteorder/Kbuild @@ -1,7 +1,2 @@ -header-y += big_endian.h -header-y += little_endian.h -header-y += pdp_endian.h - -unifdef-y += generic.h -unifdef-y += swabb.h -unifdef-y += swab.h +unifdef-y += generic.h swabb.h swab.h +header-y += big_endian.h little_endian.h pdp_endian.h diff --git a/trunk/include/linux/cn_proc.h b/trunk/include/linux/cn_proc.h index 1c86d65bc4b9..dbb7769009be 100644 --- a/trunk/include/linux/cn_proc.h +++ b/trunk/include/linux/cn_proc.h @@ -57,8 +57,7 @@ struct proc_event { PROC_EVENT_EXIT = 0x80000000 } what; __u32 cpu; - __u64 __attribute__((aligned(8))) timestamp_ns; - /* Number of nano seconds since system boot */ + struct timespec timestamp; union { /* must be last field of proc_event struct */ struct { __u32 err; diff --git a/trunk/include/linux/compat_ioctl.h b/trunk/include/linux/compat_ioctl.h index bea0255196c4..269d000bb2a3 100644 --- a/trunk/include/linux/compat_ioctl.h +++ b/trunk/include/linux/compat_ioctl.h @@ -216,7 +216,6 @@ COMPATIBLE_IOCTL(VT_RESIZE) COMPATIBLE_IOCTL(VT_RESIZEX) COMPATIBLE_IOCTL(VT_LOCKSWITCH) COMPATIBLE_IOCTL(VT_UNLOCKSWITCH) -COMPATIBLE_IOCTL(VT_GETHIFONTMASK) /* Little p (/dev/rtc, /dev/envctrl, etc.) */ COMPATIBLE_IOCTL(RTC_AIE_ON) COMPATIBLE_IOCTL(RTC_AIE_OFF) diff --git a/trunk/include/linux/crypto.h b/trunk/include/linux/crypto.h index 8f2ffa4caabf..7f946241b879 100644 --- a/trunk/include/linux/crypto.h +++ b/trunk/include/linux/crypto.h @@ -17,36 +17,20 @@ #ifndef _LINUX_CRYPTO_H #define _LINUX_CRYPTO_H -#include #include #include +#include #include -#include #include -#include +#include /* * Algorithm masks and types. */ -#define CRYPTO_ALG_TYPE_MASK 0x0000000f +#define CRYPTO_ALG_TYPE_MASK 0x000000ff #define CRYPTO_ALG_TYPE_CIPHER 0x00000001 #define CRYPTO_ALG_TYPE_DIGEST 0x00000002 -#define CRYPTO_ALG_TYPE_HASH 0x00000003 -#define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004 -#define CRYPTO_ALG_TYPE_COMPRESS 0x00000005 - -#define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e - -#define CRYPTO_ALG_LARVAL 0x00000010 -#define CRYPTO_ALG_DEAD 0x00000020 -#define CRYPTO_ALG_DYING 0x00000040 -#define CRYPTO_ALG_ASYNC 0x00000080 - -/* - * Set this bit if and only if the algorithm requires another algorithm of - * the same type to handle corner cases. - */ -#define CRYPTO_ALG_NEED_FALLBACK 0x00000100 +#define CRYPTO_ALG_TYPE_COMPRESS 0x00000004 /* * Transform masks and values (for crt_flags). @@ -77,37 +61,8 @@ #define CRYPTO_DIR_ENCRYPT 1 #define CRYPTO_DIR_DECRYPT 0 -/* - * The macro CRYPTO_MINALIGN_ATTR (along with the void * type in the actual - * declaration) is used to ensure that the crypto_tfm context structure is - * aligned correctly for the given architecture so that there are no alignment - * faults for C data types. In particular, this is required on platforms such - * as arm where pointers are 32-bit aligned but there are data types such as - * u64 which require 64-bit alignment. - */ -#if defined(ARCH_KMALLOC_MINALIGN) -#define CRYPTO_MINALIGN ARCH_KMALLOC_MINALIGN -#elif defined(ARCH_SLAB_MINALIGN) -#define CRYPTO_MINALIGN ARCH_SLAB_MINALIGN -#endif - -#ifdef CRYPTO_MINALIGN -#define CRYPTO_MINALIGN_ATTR __attribute__ ((__aligned__(CRYPTO_MINALIGN))) -#else -#define CRYPTO_MINALIGN_ATTR -#endif - struct scatterlist; -struct crypto_blkcipher; -struct crypto_hash; struct crypto_tfm; -struct crypto_type; - -struct blkcipher_desc { - struct crypto_blkcipher *tfm; - void *info; - u32 flags; -}; struct cipher_desc { struct crypto_tfm *tfm; @@ -117,50 +72,30 @@ struct cipher_desc { void *info; }; -struct hash_desc { - struct crypto_hash *tfm; - u32 flags; -}; - /* * Algorithms: modular crypto algorithm implementations, managed * via crypto_register_alg() and crypto_unregister_alg(). */ -struct blkcipher_alg { - int (*setkey)(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen); - int (*encrypt)(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes); - int (*decrypt)(struct blkcipher_desc *desc, - struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes); - - unsigned int min_keysize; - unsigned int max_keysize; - unsigned int ivsize; -}; - struct cipher_alg { unsigned int cia_min_keysize; unsigned int cia_max_keysize; int (*cia_setkey)(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen); + unsigned int keylen, u32 *flags); void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); unsigned int (*cia_encrypt_ecb)(const struct cipher_desc *desc, u8 *dst, const u8 *src, - unsigned int nbytes) __deprecated; + unsigned int nbytes); unsigned int (*cia_decrypt_ecb)(const struct cipher_desc *desc, u8 *dst, const u8 *src, - unsigned int nbytes) __deprecated; + unsigned int nbytes); unsigned int (*cia_encrypt_cbc)(const struct cipher_desc *desc, u8 *dst, const u8 *src, - unsigned int nbytes) __deprecated; + unsigned int nbytes); unsigned int (*cia_decrypt_cbc)(const struct cipher_desc *desc, u8 *dst, const u8 *src, - unsigned int nbytes) __deprecated; + unsigned int nbytes); }; struct digest_alg { @@ -170,20 +105,7 @@ struct digest_alg { unsigned int len); void (*dia_final)(struct crypto_tfm *tfm, u8 *out); int (*dia_setkey)(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen); -}; - -struct hash_alg { - int (*init)(struct hash_desc *desc); - int (*update)(struct hash_desc *desc, struct scatterlist *sg, - unsigned int nbytes); - int (*final)(struct hash_desc *desc, u8 *out); - int (*digest)(struct hash_desc *desc, struct scatterlist *sg, - unsigned int nbytes, u8 *out); - int (*setkey)(struct crypto_hash *tfm, const u8 *key, - unsigned int keylen); - - unsigned int digestsize; + unsigned int keylen, u32 *flags); }; struct compress_alg { @@ -193,40 +115,30 @@ struct compress_alg { unsigned int slen, u8 *dst, unsigned int *dlen); }; -#define cra_blkcipher cra_u.blkcipher #define cra_cipher cra_u.cipher #define cra_digest cra_u.digest -#define cra_hash cra_u.hash #define cra_compress cra_u.compress struct crypto_alg { struct list_head cra_list; - struct list_head cra_users; - u32 cra_flags; unsigned int cra_blocksize; unsigned int cra_ctxsize; unsigned int cra_alignmask; int cra_priority; - atomic_t cra_refcnt; char cra_name[CRYPTO_MAX_ALG_NAME]; char cra_driver_name[CRYPTO_MAX_ALG_NAME]; - const struct crypto_type *cra_type; - union { - struct blkcipher_alg blkcipher; struct cipher_alg cipher; struct digest_alg digest; - struct hash_alg hash; struct compress_alg compress; } cra_u; int (*cra_init)(struct crypto_tfm *tfm); void (*cra_exit)(struct crypto_tfm *tfm); - void (*cra_destroy)(struct crypto_alg *alg); struct module *cra_module; }; @@ -241,39 +153,20 @@ int crypto_unregister_alg(struct crypto_alg *alg); * Algorithm query interface. */ #ifdef CONFIG_CRYPTO -int crypto_alg_available(const char *name, u32 flags) - __deprecated_for_modules; -int crypto_has_alg(const char *name, u32 type, u32 mask); +int crypto_alg_available(const char *name, u32 flags); #else -static int crypto_alg_available(const char *name, u32 flags); - __deprecated_for_modules; static inline int crypto_alg_available(const char *name, u32 flags) { return 0; } - -static inline int crypto_has_alg(const char *name, u32 type, u32 mask) -{ - return 0; -} #endif /* * Transforms: user-instantiated objects which encapsulate algorithms - * and core processing logic. Managed via crypto_alloc_*() and - * crypto_free_*(), as well as the various helpers below. + * and core processing logic. Managed via crypto_alloc_tfm() and + * crypto_free_tfm(), as well as the various helpers below. */ -struct blkcipher_tfm { - void *iv; - int (*setkey)(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen); - int (*encrypt)(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes); - int (*decrypt)(struct blkcipher_desc *desc, struct scatterlist *dst, - struct scatterlist *src, unsigned int nbytes); -}; - struct cipher_tfm { void *cit_iv; unsigned int cit_ivsize; @@ -297,20 +190,20 @@ struct cipher_tfm { struct scatterlist *src, unsigned int nbytes, u8 *iv); void (*cit_xor_block)(u8 *dst, const u8 *src); - void (*cit_encrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); - void (*cit_decrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); }; -struct hash_tfm { - int (*init)(struct hash_desc *desc); - int (*update)(struct hash_desc *desc, - struct scatterlist *sg, unsigned int nsg); - int (*final)(struct hash_desc *desc, u8 *out); - int (*digest)(struct hash_desc *desc, struct scatterlist *sg, - unsigned int nsg, u8 *out); - int (*setkey)(struct crypto_hash *tfm, const u8 *key, - unsigned int keylen); - unsigned int digestsize; +struct digest_tfm { + void (*dit_init)(struct crypto_tfm *tfm); + void (*dit_update)(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg); + void (*dit_final)(struct crypto_tfm *tfm, u8 *out); + void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg, + unsigned int nsg, u8 *out); + int (*dit_setkey)(struct crypto_tfm *tfm, + const u8 *key, unsigned int keylen); +#ifdef CONFIG_CRYPTO_HMAC + void *dit_hmac_block; +#endif }; struct compress_tfm { @@ -322,9 +215,8 @@ struct compress_tfm { u8 *dst, unsigned int *dlen); }; -#define crt_blkcipher crt_u.blkcipher #define crt_cipher crt_u.cipher -#define crt_hash crt_u.hash +#define crt_digest crt_u.digest #define crt_compress crt_u.compress struct crypto_tfm { @@ -332,43 +224,30 @@ struct crypto_tfm { u32 crt_flags; union { - struct blkcipher_tfm blkcipher; struct cipher_tfm cipher; - struct hash_tfm hash; + struct digest_tfm digest; struct compress_tfm compress; } crt_u; struct crypto_alg *__crt_alg; - void *__crt_ctx[] CRYPTO_MINALIGN_ATTR; -}; - -#define crypto_cipher crypto_tfm -#define crypto_comp crypto_tfm - -struct crypto_blkcipher { - struct crypto_tfm base; -}; - -struct crypto_hash { - struct crypto_tfm base; -}; - -enum { - CRYPTOA_UNSPEC, - CRYPTOA_ALG, -}; - -struct crypto_attr_alg { - char name[CRYPTO_MAX_ALG_NAME]; + char __crt_ctx[] __attribute__ ((__aligned__)); }; /* * Transform user interface. */ +/* + * crypto_alloc_tfm() will first attempt to locate an already loaded algorithm. + * If that fails and the kernel supports dynamically loadable modules, it + * will then attempt to load a module of the same name or alias. A refcount + * is grabbed on the algorithm which is then associated with the new transform. + * + * crypto_free_tfm() frees up the transform and any associated resources, + * then drops the refcount on the associated algorithm. + */ struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags); -struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask); void crypto_free_tfm(struct crypto_tfm *tfm); /* @@ -379,16 +258,6 @@ static inline const char *crypto_tfm_alg_name(struct crypto_tfm *tfm) return tfm->__crt_alg->cra_name; } -static inline const char *crypto_tfm_alg_driver_name(struct crypto_tfm *tfm) -{ - return tfm->__crt_alg->cra_driver_name; -} - -static inline int crypto_tfm_alg_priority(struct crypto_tfm *tfm) -{ - return tfm->__crt_alg->cra_priority; -} - static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm) { return module_name(tfm->__crt_alg->cra_module); @@ -399,23 +268,18 @@ static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm) return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK; } -static unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm) - __deprecated; static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm) { BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); return tfm->__crt_alg->cra_cipher.cia_min_keysize; } -static unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm) - __deprecated; static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm) { BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); return tfm->__crt_alg->cra_cipher.cia_max_keysize; } -static unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm) __deprecated; static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm) { BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); @@ -438,21 +302,6 @@ static inline unsigned int crypto_tfm_alg_alignmask(struct crypto_tfm *tfm) return tfm->__crt_alg->cra_alignmask; } -static inline u32 crypto_tfm_get_flags(struct crypto_tfm *tfm) -{ - return tfm->crt_flags; -} - -static inline void crypto_tfm_set_flags(struct crypto_tfm *tfm, u32 flags) -{ - tfm->crt_flags |= flags; -} - -static inline void crypto_tfm_clear_flags(struct crypto_tfm *tfm, u32 flags) -{ - tfm->crt_flags &= ~flags; -} - static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) { return tfm->__crt_ctx; @@ -467,374 +316,50 @@ static inline unsigned int crypto_tfm_ctx_alignment(void) /* * API wrappers. */ -static inline struct crypto_blkcipher *__crypto_blkcipher_cast( - struct crypto_tfm *tfm) -{ - return (struct crypto_blkcipher *)tfm; -} - -static inline struct crypto_blkcipher *crypto_blkcipher_cast( - struct crypto_tfm *tfm) -{ - BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_BLKCIPHER); - return __crypto_blkcipher_cast(tfm); -} - -static inline struct crypto_blkcipher *crypto_alloc_blkcipher( - const char *alg_name, u32 type, u32 mask) -{ - type &= ~CRYPTO_ALG_TYPE_MASK; - type |= CRYPTO_ALG_TYPE_BLKCIPHER; - mask |= CRYPTO_ALG_TYPE_MASK; - - return __crypto_blkcipher_cast(crypto_alloc_base(alg_name, type, mask)); -} - -static inline struct crypto_tfm *crypto_blkcipher_tfm( - struct crypto_blkcipher *tfm) -{ - return &tfm->base; -} - -static inline void crypto_free_blkcipher(struct crypto_blkcipher *tfm) -{ - crypto_free_tfm(crypto_blkcipher_tfm(tfm)); -} - -static inline int crypto_has_blkcipher(const char *alg_name, u32 type, u32 mask) -{ - type &= ~CRYPTO_ALG_TYPE_MASK; - type |= CRYPTO_ALG_TYPE_BLKCIPHER; - mask |= CRYPTO_ALG_TYPE_MASK; - - return crypto_has_alg(alg_name, type, mask); -} - -static inline const char *crypto_blkcipher_name(struct crypto_blkcipher *tfm) -{ - return crypto_tfm_alg_name(crypto_blkcipher_tfm(tfm)); -} - -static inline struct blkcipher_tfm *crypto_blkcipher_crt( - struct crypto_blkcipher *tfm) -{ - return &crypto_blkcipher_tfm(tfm)->crt_blkcipher; -} - -static inline struct blkcipher_alg *crypto_blkcipher_alg( - struct crypto_blkcipher *tfm) -{ - return &crypto_blkcipher_tfm(tfm)->__crt_alg->cra_blkcipher; -} - -static inline unsigned int crypto_blkcipher_ivsize(struct crypto_blkcipher *tfm) -{ - return crypto_blkcipher_alg(tfm)->ivsize; -} - -static inline unsigned int crypto_blkcipher_blocksize( - struct crypto_blkcipher *tfm) -{ - return crypto_tfm_alg_blocksize(crypto_blkcipher_tfm(tfm)); -} - -static inline unsigned int crypto_blkcipher_alignmask( - struct crypto_blkcipher *tfm) -{ - return crypto_tfm_alg_alignmask(crypto_blkcipher_tfm(tfm)); -} - -static inline u32 crypto_blkcipher_get_flags(struct crypto_blkcipher *tfm) -{ - return crypto_tfm_get_flags(crypto_blkcipher_tfm(tfm)); -} - -static inline void crypto_blkcipher_set_flags(struct crypto_blkcipher *tfm, - u32 flags) -{ - crypto_tfm_set_flags(crypto_blkcipher_tfm(tfm), flags); -} - -static inline void crypto_blkcipher_clear_flags(struct crypto_blkcipher *tfm, - u32 flags) -{ - crypto_tfm_clear_flags(crypto_blkcipher_tfm(tfm), flags); -} - -static inline int crypto_blkcipher_setkey(struct crypto_blkcipher *tfm, - const u8 *key, unsigned int keylen) -{ - return crypto_blkcipher_crt(tfm)->setkey(crypto_blkcipher_tfm(tfm), - key, keylen); -} - -static inline int crypto_blkcipher_encrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, - unsigned int nbytes) -{ - desc->info = crypto_blkcipher_crt(desc->tfm)->iv; - return crypto_blkcipher_crt(desc->tfm)->encrypt(desc, dst, src, nbytes); -} - -static inline int crypto_blkcipher_encrypt_iv(struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, - unsigned int nbytes) -{ - return crypto_blkcipher_crt(desc->tfm)->encrypt(desc, dst, src, nbytes); -} - -static inline int crypto_blkcipher_decrypt(struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, - unsigned int nbytes) -{ - desc->info = crypto_blkcipher_crt(desc->tfm)->iv; - return crypto_blkcipher_crt(desc->tfm)->decrypt(desc, dst, src, nbytes); -} - -static inline int crypto_blkcipher_decrypt_iv(struct blkcipher_desc *desc, - struct scatterlist *dst, - struct scatterlist *src, - unsigned int nbytes) -{ - return crypto_blkcipher_crt(desc->tfm)->decrypt(desc, dst, src, nbytes); -} - -static inline void crypto_blkcipher_set_iv(struct crypto_blkcipher *tfm, - const u8 *src, unsigned int len) -{ - memcpy(crypto_blkcipher_crt(tfm)->iv, src, len); -} - -static inline void crypto_blkcipher_get_iv(struct crypto_blkcipher *tfm, - u8 *dst, unsigned int len) -{ - memcpy(dst, crypto_blkcipher_crt(tfm)->iv, len); -} - -static inline struct crypto_cipher *__crypto_cipher_cast(struct crypto_tfm *tfm) +static inline void crypto_digest_init(struct crypto_tfm *tfm) { - return (struct crypto_cipher *)tfm; -} - -static inline struct crypto_cipher *crypto_cipher_cast(struct crypto_tfm *tfm) -{ - BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); - return __crypto_cipher_cast(tfm); -} - -static inline struct crypto_cipher *crypto_alloc_cipher(const char *alg_name, - u32 type, u32 mask) -{ - type &= ~CRYPTO_ALG_TYPE_MASK; - type |= CRYPTO_ALG_TYPE_CIPHER; - mask |= CRYPTO_ALG_TYPE_MASK; - - return __crypto_cipher_cast(crypto_alloc_base(alg_name, type, mask)); -} - -static inline struct crypto_tfm *crypto_cipher_tfm(struct crypto_cipher *tfm) -{ - return tfm; -} - -static inline void crypto_free_cipher(struct crypto_cipher *tfm) -{ - crypto_free_tfm(crypto_cipher_tfm(tfm)); -} - -static inline int crypto_has_cipher(const char *alg_name, u32 type, u32 mask) -{ - type &= ~CRYPTO_ALG_TYPE_MASK; - type |= CRYPTO_ALG_TYPE_CIPHER; - mask |= CRYPTO_ALG_TYPE_MASK; - - return crypto_has_alg(alg_name, type, mask); -} - -static inline struct cipher_tfm *crypto_cipher_crt(struct crypto_cipher *tfm) -{ - return &crypto_cipher_tfm(tfm)->crt_cipher; -} - -static inline unsigned int crypto_cipher_blocksize(struct crypto_cipher *tfm) -{ - return crypto_tfm_alg_blocksize(crypto_cipher_tfm(tfm)); -} - -static inline unsigned int crypto_cipher_alignmask(struct crypto_cipher *tfm) -{ - return crypto_tfm_alg_alignmask(crypto_cipher_tfm(tfm)); -} - -static inline u32 crypto_cipher_get_flags(struct crypto_cipher *tfm) -{ - return crypto_tfm_get_flags(crypto_cipher_tfm(tfm)); -} - -static inline void crypto_cipher_set_flags(struct crypto_cipher *tfm, - u32 flags) -{ - crypto_tfm_set_flags(crypto_cipher_tfm(tfm), flags); -} - -static inline void crypto_cipher_clear_flags(struct crypto_cipher *tfm, - u32 flags) -{ - crypto_tfm_clear_flags(crypto_cipher_tfm(tfm), flags); -} - -static inline int crypto_cipher_setkey(struct crypto_cipher *tfm, - const u8 *key, unsigned int keylen) -{ - return crypto_cipher_crt(tfm)->cit_setkey(crypto_cipher_tfm(tfm), - key, keylen); -} - -static inline void crypto_cipher_encrypt_one(struct crypto_cipher *tfm, - u8 *dst, const u8 *src) -{ - crypto_cipher_crt(tfm)->cit_encrypt_one(crypto_cipher_tfm(tfm), - dst, src); + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_init(tfm); } -static inline void crypto_cipher_decrypt_one(struct crypto_cipher *tfm, - u8 *dst, const u8 *src) +static inline void crypto_digest_update(struct crypto_tfm *tfm, + struct scatterlist *sg, + unsigned int nsg) { - crypto_cipher_crt(tfm)->cit_decrypt_one(crypto_cipher_tfm(tfm), - dst, src); + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_update(tfm, sg, nsg); } -void crypto_digest_init(struct crypto_tfm *tfm) __deprecated_for_modules; -void crypto_digest_update(struct crypto_tfm *tfm, - struct scatterlist *sg, unsigned int nsg) - __deprecated_for_modules; -void crypto_digest_final(struct crypto_tfm *tfm, u8 *out) - __deprecated_for_modules; -void crypto_digest_digest(struct crypto_tfm *tfm, - struct scatterlist *sg, unsigned int nsg, u8 *out) - __deprecated_for_modules; - -static inline struct crypto_hash *__crypto_hash_cast(struct crypto_tfm *tfm) +static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out) { - return (struct crypto_hash *)tfm; + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_final(tfm, out); } -static inline struct crypto_hash *crypto_hash_cast(struct crypto_tfm *tfm) +static inline void crypto_digest_digest(struct crypto_tfm *tfm, + struct scatterlist *sg, + unsigned int nsg, u8 *out) { - BUG_ON((crypto_tfm_alg_type(tfm) ^ CRYPTO_ALG_TYPE_HASH) & - CRYPTO_ALG_TYPE_HASH_MASK); - return __crypto_hash_cast(tfm); + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_digest(tfm, sg, nsg, out); } -static int crypto_digest_setkey(struct crypto_tfm *tfm, const u8 *key, - unsigned int keylen) __deprecated; static inline int crypto_digest_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) { - return tfm->crt_hash.setkey(crypto_hash_cast(tfm), key, keylen); -} - -static inline struct crypto_hash *crypto_alloc_hash(const char *alg_name, - u32 type, u32 mask) -{ - type &= ~CRYPTO_ALG_TYPE_MASK; - type |= CRYPTO_ALG_TYPE_HASH; - mask |= CRYPTO_ALG_TYPE_HASH_MASK; - - return __crypto_hash_cast(crypto_alloc_base(alg_name, type, mask)); -} - -static inline struct crypto_tfm *crypto_hash_tfm(struct crypto_hash *tfm) -{ - return &tfm->base; -} - -static inline void crypto_free_hash(struct crypto_hash *tfm) -{ - crypto_free_tfm(crypto_hash_tfm(tfm)); -} - -static inline int crypto_has_hash(const char *alg_name, u32 type, u32 mask) -{ - type &= ~CRYPTO_ALG_TYPE_MASK; - type |= CRYPTO_ALG_TYPE_HASH; - mask |= CRYPTO_ALG_TYPE_HASH_MASK; - - return crypto_has_alg(alg_name, type, mask); -} - -static inline struct hash_tfm *crypto_hash_crt(struct crypto_hash *tfm) -{ - return &crypto_hash_tfm(tfm)->crt_hash; -} - -static inline unsigned int crypto_hash_blocksize(struct crypto_hash *tfm) -{ - return crypto_tfm_alg_blocksize(crypto_hash_tfm(tfm)); -} - -static inline unsigned int crypto_hash_alignmask(struct crypto_hash *tfm) -{ - return crypto_tfm_alg_alignmask(crypto_hash_tfm(tfm)); -} - -static inline unsigned int crypto_hash_digestsize(struct crypto_hash *tfm) -{ - return crypto_hash_crt(tfm)->digestsize; -} - -static inline u32 crypto_hash_get_flags(struct crypto_hash *tfm) -{ - return crypto_tfm_get_flags(crypto_hash_tfm(tfm)); -} - -static inline void crypto_hash_set_flags(struct crypto_hash *tfm, u32 flags) -{ - crypto_tfm_set_flags(crypto_hash_tfm(tfm), flags); -} - -static inline void crypto_hash_clear_flags(struct crypto_hash *tfm, u32 flags) -{ - crypto_tfm_clear_flags(crypto_hash_tfm(tfm), flags); -} - -static inline int crypto_hash_init(struct hash_desc *desc) -{ - return crypto_hash_crt(desc->tfm)->init(desc); -} - -static inline int crypto_hash_update(struct hash_desc *desc, - struct scatterlist *sg, - unsigned int nbytes) -{ - return crypto_hash_crt(desc->tfm)->update(desc, sg, nbytes); -} - -static inline int crypto_hash_final(struct hash_desc *desc, u8 *out) -{ - return crypto_hash_crt(desc->tfm)->final(desc, out); -} - -static inline int crypto_hash_digest(struct hash_desc *desc, - struct scatterlist *sg, - unsigned int nbytes, u8 *out) -{ - return crypto_hash_crt(desc->tfm)->digest(desc, sg, nbytes, out); + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + if (tfm->crt_digest.dit_setkey == NULL) + return -ENOSYS; + return tfm->crt_digest.dit_setkey(tfm, key, keylen); } -static inline int crypto_hash_setkey(struct crypto_hash *hash, - const u8 *key, unsigned int keylen) +static inline int crypto_cipher_setkey(struct crypto_tfm *tfm, + const u8 *key, unsigned int keylen) { - return crypto_hash_crt(hash)->setkey(hash, key, keylen); + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_setkey(tfm, key, keylen); } -static int crypto_cipher_encrypt(struct crypto_tfm *tfm, - struct scatterlist *dst, - struct scatterlist *src, - unsigned int nbytes) __deprecated; static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm, struct scatterlist *dst, struct scatterlist *src, @@ -844,23 +369,16 @@ static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm, return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes); } -static int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm, - struct scatterlist *dst, - struct scatterlist *src, - unsigned int nbytes, u8 *iv) __deprecated; static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes, u8 *iv) { BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv); } -static int crypto_cipher_decrypt(struct crypto_tfm *tfm, - struct scatterlist *dst, - struct scatterlist *src, - unsigned int nbytes) __deprecated; static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, struct scatterlist *dst, struct scatterlist *src, @@ -870,21 +388,16 @@ static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes); } -static int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm, - struct scatterlist *dst, - struct scatterlist *src, - unsigned int nbytes, u8 *iv) __deprecated; static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm, struct scatterlist *dst, struct scatterlist *src, unsigned int nbytes, u8 *iv) { BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv); } -static void crypto_cipher_set_iv(struct crypto_tfm *tfm, - const u8 *src, unsigned int len) __deprecated; static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm, const u8 *src, unsigned int len) { @@ -892,8 +405,6 @@ static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm, memcpy(tfm->crt_cipher.cit_iv, src, len); } -static void crypto_cipher_get_iv(struct crypto_tfm *tfm, - u8 *dst, unsigned int len) __deprecated; static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm, u8 *dst, unsigned int len) { @@ -901,70 +412,34 @@ static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm, memcpy(dst, tfm->crt_cipher.cit_iv, len); } -static inline struct crypto_comp *__crypto_comp_cast(struct crypto_tfm *tfm) -{ - return (struct crypto_comp *)tfm; -} - -static inline struct crypto_comp *crypto_comp_cast(struct crypto_tfm *tfm) -{ - BUG_ON((crypto_tfm_alg_type(tfm) ^ CRYPTO_ALG_TYPE_COMPRESS) & - CRYPTO_ALG_TYPE_MASK); - return __crypto_comp_cast(tfm); -} - -static inline struct crypto_comp *crypto_alloc_comp(const char *alg_name, - u32 type, u32 mask) -{ - type &= ~CRYPTO_ALG_TYPE_MASK; - type |= CRYPTO_ALG_TYPE_COMPRESS; - mask |= CRYPTO_ALG_TYPE_MASK; - - return __crypto_comp_cast(crypto_alloc_base(alg_name, type, mask)); -} - -static inline struct crypto_tfm *crypto_comp_tfm(struct crypto_comp *tfm) -{ - return tfm; -} - -static inline void crypto_free_comp(struct crypto_comp *tfm) -{ - crypto_free_tfm(crypto_comp_tfm(tfm)); -} - -static inline int crypto_has_comp(const char *alg_name, u32 type, u32 mask) -{ - type &= ~CRYPTO_ALG_TYPE_MASK; - type |= CRYPTO_ALG_TYPE_COMPRESS; - mask |= CRYPTO_ALG_TYPE_MASK; - - return crypto_has_alg(alg_name, type, mask); -} - -static inline const char *crypto_comp_name(struct crypto_comp *tfm) -{ - return crypto_tfm_alg_name(crypto_comp_tfm(tfm)); -} - -static inline struct compress_tfm *crypto_comp_crt(struct crypto_comp *tfm) -{ - return &crypto_comp_tfm(tfm)->crt_compress; -} - -static inline int crypto_comp_compress(struct crypto_comp *tfm, +static inline int crypto_comp_compress(struct crypto_tfm *tfm, const u8 *src, unsigned int slen, u8 *dst, unsigned int *dlen) { - return crypto_comp_crt(tfm)->cot_compress(tfm, src, slen, dst, dlen); + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); + return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen); } -static inline int crypto_comp_decompress(struct crypto_comp *tfm, +static inline int crypto_comp_decompress(struct crypto_tfm *tfm, const u8 *src, unsigned int slen, u8 *dst, unsigned int *dlen) { - return crypto_comp_crt(tfm)->cot_decompress(tfm, src, slen, dst, dlen); + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); + return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen); } +/* + * HMAC support. + */ +#ifdef CONFIG_CRYPTO_HMAC +void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen); +void crypto_hmac_update(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg); +void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, + unsigned int *keylen, u8 *out); +void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, + struct scatterlist *sg, unsigned int nsg, u8 *out); +#endif /* CONFIG_CRYPTO_HMAC */ + #endif /* _LINUX_CRYPTO_H */ diff --git a/trunk/include/linux/dcache.h b/trunk/include/linux/dcache.h index 44605be59409..471781ffeab1 100644 --- a/trunk/include/linux/dcache.h +++ b/trunk/include/linux/dcache.h @@ -221,7 +221,6 @@ static inline int dname_external(struct dentry *dentry) */ extern void d_instantiate(struct dentry *, struct inode *); extern struct dentry * d_instantiate_unique(struct dentry *, struct inode *); -extern struct dentry * d_materialise_unique(struct dentry *, struct inode *); extern void d_delete(struct dentry *); /* allocate/de-allocate */ diff --git a/trunk/include/linux/dccp.h b/trunk/include/linux/dccp.h index 2d7671c92c0b..676333b9fad0 100644 --- a/trunk/include/linux/dccp.h +++ b/trunk/include/linux/dccp.h @@ -438,7 +438,6 @@ struct dccp_ackvec; * @dccps_role - Role of this sock, one of %dccp_role * @dccps_ndp_count - number of Non Data Packets since last data packet * @dccps_hc_rx_ackvec - rx half connection ack vector - * @dccps_xmit_timer - timer for when CCID is not ready to send */ struct dccp_sock { /* inet_connection_sock has to be the first member of dccp_sock */ @@ -471,7 +470,6 @@ struct dccp_sock { enum dccp_role dccps_role:2; __u8 dccps_hc_rx_insert_options:1; __u8 dccps_hc_tx_insert_options:1; - struct timer_list dccps_xmit_timer; }; static inline struct dccp_sock *dccp_sk(const struct sock *sk) diff --git a/trunk/include/linux/debug_locks.h b/trunk/include/linux/debug_locks.h index 88dafa246d87..6a7047851e48 100644 --- a/trunk/include/linux/debug_locks.h +++ b/trunk/include/linux/debug_locks.h @@ -1,8 +1,6 @@ #ifndef __LINUX_DEBUG_LOCKING_H #define __LINUX_DEBUG_LOCKING_H -struct task_struct; - extern int debug_locks; extern int debug_locks_silent; diff --git a/trunk/include/linux/delayacct.h b/trunk/include/linux/delayacct.h index 561e2a77805c..7e8b6011b8f3 100644 --- a/trunk/include/linux/delayacct.h +++ b/trunk/include/linux/delayacct.h @@ -55,18 +55,14 @@ static inline void delayacct_tsk_init(struct task_struct *tsk) { /* reinitialize in case parent's non-null pointer was dup'ed*/ tsk->delays = NULL; - if (delayacct_on) + if (unlikely(delayacct_on)) __delayacct_tsk_init(tsk); } -/* Free tsk->delays. Called from bad fork and __put_task_struct - * where there's no risk of tsk->delays being accessed elsewhere - */ -static inline void delayacct_tsk_free(struct task_struct *tsk) +static inline void delayacct_tsk_exit(struct task_struct *tsk) { if (tsk->delays) - kmem_cache_free(delayacct_cache, tsk->delays); - tsk->delays = NULL; + __delayacct_tsk_exit(tsk); } static inline void delayacct_blkio_start(void) @@ -84,7 +80,9 @@ static inline void delayacct_blkio_end(void) static inline int delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) { - if (!delayacct_on || !tsk->delays) + if (likely(!delayacct_on)) + return -EINVAL; + if (!tsk->delays) return 0; return __delayacct_add_tsk(d, tsk); } @@ -105,7 +103,7 @@ static inline void delayacct_init(void) {} static inline void delayacct_tsk_init(struct task_struct *tsk) {} -static inline void delayacct_tsk_free(struct task_struct *tsk) +static inline void delayacct_tsk_exit(struct task_struct *tsk) {} static inline void delayacct_blkio_start(void) {} diff --git a/trunk/include/linux/dvb/Kbuild b/trunk/include/linux/dvb/Kbuild index d97b3a51e227..63973af72fd5 100644 --- a/trunk/include/linux/dvb/Kbuild +++ b/trunk/include/linux/dvb/Kbuild @@ -1,9 +1,2 @@ -header-y += ca.h -header-y += frontend.h -header-y += net.h -header-y += osd.h -header-y += version.h - -unifdef-y += audio.h -unifdef-y += dmx.h -unifdef-y += video.h +header-y += ca.h frontend.h net.h osd.h version.h +unifdef-y := audio.h dmx.h video.h diff --git a/trunk/include/linux/ext3_fs.h b/trunk/include/linux/ext3_fs.h index 9f9cce7bd86d..5607e6457a65 100644 --- a/trunk/include/linux/ext3_fs.h +++ b/trunk/include/linux/ext3_fs.h @@ -492,15 +492,6 @@ static inline struct ext3_inode_info *EXT3_I(struct inode *inode) { return container_of(inode, struct ext3_inode_info, vfs_inode); } - -static inline int ext3_valid_inum(struct super_block *sb, unsigned long ino) -{ - return ino == EXT3_ROOT_INO || - ino == EXT3_JOURNAL_INO || - ino == EXT3_RESIZE_INO || - (ino >= EXT3_FIRST_INO(sb) && - ino <= le32_to_cpu(EXT3_SB(sb)->s_es->s_inodes_count)); -} #else /* Assume that user mode programs are passing in an ext3fs superblock, not * a kernel struct super_block. This will allow us to call the feature-test diff --git a/trunk/include/linux/fb.h b/trunk/include/linux/fb.h index 2f335e966011..405f44e44e5d 100644 --- a/trunk/include/linux/fb.h +++ b/trunk/include/linux/fb.h @@ -1,6 +1,7 @@ #ifndef _LINUX_FB_H #define _LINUX_FB_H +#include #include /* Definitions of frame buffers */ @@ -380,7 +381,6 @@ struct fb_cursor { #include #include #include -#include #include struct vm_area_struct; @@ -524,7 +524,7 @@ struct fb_event { extern int fb_register_client(struct notifier_block *nb); extern int fb_unregister_client(struct notifier_block *nb); -extern int fb_notifier_call_chain(unsigned long val, void *v); + /* * Pixmap structure definition * diff --git a/trunk/include/linux/fib_rules.h b/trunk/include/linux/fib_rules.h deleted file mode 100644 index 4418c8d9d479..000000000000 --- a/trunk/include/linux/fib_rules.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef __LINUX_FIB_RULES_H -#define __LINUX_FIB_RULES_H - -#include -#include - -/* rule is permanent, and cannot be deleted */ -#define FIB_RULE_PERMANENT 1 - -struct fib_rule_hdr -{ - __u8 family; - __u8 dst_len; - __u8 src_len; - __u8 tos; - - __u8 table; - __u8 res1; /* reserved */ - __u8 res2; /* reserved */ - __u8 action; - - __u32 flags; -}; - -enum -{ - FRA_UNSPEC, - FRA_DST, /* destination address */ - FRA_SRC, /* source address */ - FRA_IFNAME, /* interface name */ - FRA_UNUSED1, - FRA_UNUSED2, - FRA_PRIORITY, /* priority/preference */ - FRA_UNUSED3, - FRA_UNUSED4, - FRA_UNUSED5, - FRA_FWMARK, /* netfilter mark */ - FRA_FLOW, /* flow/class id */ - FRA_UNUSED6, - FRA_UNUSED7, - FRA_UNUSED8, - FRA_TABLE, /* Extended table id */ - FRA_FWMASK, /* mask for netfilter mark */ - __FRA_MAX -}; - -#define FRA_MAX (__FRA_MAX - 1) - -enum -{ - FR_ACT_UNSPEC, - FR_ACT_TO_TBL, /* Pass to fixed table */ - FR_ACT_RES1, - FR_ACT_RES2, - FR_ACT_RES3, - FR_ACT_RES4, - FR_ACT_BLACKHOLE, /* Drop without notification */ - FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */ - FR_ACT_PROHIBIT, /* Drop with EACCES */ - __FR_ACT_MAX, -}; - -#define FR_ACT_MAX (__FR_ACT_MAX - 1) - -#endif diff --git a/trunk/include/linux/filter.h b/trunk/include/linux/filter.h index 91b2e3b9251e..c6cb8f095088 100644 --- a/trunk/include/linux/filter.h +++ b/trunk/include/linux/filter.h @@ -25,10 +25,10 @@ struct sock_filter /* Filter block */ { - __u16 code; /* Actual filter code */ - __u8 jt; /* Jump true */ - __u8 jf; /* Jump false */ - __u32 k; /* Generic multiuse field */ + __u16 code; /* Actual filter code */ + __u8 jt; /* Jump true */ + __u8 jf; /* Jump false */ + __u32 k; /* Generic multiuse field */ }; struct sock_fprog /* Required for SO_ATTACH_FILTER. */ @@ -41,9 +41,8 @@ struct sock_fprog /* Required for SO_ATTACH_FILTER. */ struct sk_filter { atomic_t refcnt; - unsigned int len; /* Number of filter blocks */ - struct rcu_head rcu; - struct sock_filter insns[0]; + unsigned int len; /* Number of filter blocks */ + struct sock_filter insns[0]; }; static inline unsigned int sk_filter_len(struct sk_filter *fp) diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 555bc195c420..25610205c90d 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -570,14 +570,13 @@ struct inode { * 3: quota file * * The locking order between these classes is - * parent -> child -> normal -> xattr -> quota + * parent -> child -> normal -> quota */ enum inode_i_mutex_lock_class { I_MUTEX_NORMAL, I_MUTEX_PARENT, I_MUTEX_CHILD, - I_MUTEX_XATTR, I_MUTEX_QUOTA }; diff --git a/trunk/include/linux/fs_enet_pd.h b/trunk/include/linux/fs_enet_pd.h index 74ed35a00a94..783c476b8674 100644 --- a/trunk/include/linux/fs_enet_pd.h +++ b/trunk/include/linux/fs_enet_pd.h @@ -69,21 +69,34 @@ enum fs_ioport { fsiop_porte, }; -struct fs_mii_bit { - u32 offset; - u8 bit; - u8 polarity; -}; -struct fs_mii_bb_platform_info { - struct fs_mii_bit mdio_dir; - struct fs_mii_bit mdio_dat; - struct fs_mii_bit mdc_dat; - int mdio_port; /* port & bit for MDIO */ - int mdio_bit; - int mdc_port; /* port & bit for MDC */ - int mdc_bit; - int delay; /* delay in us */ - int irq[32]; /* irqs per phy's */ +struct fs_mii_bus_info { + int method; /* mii method */ + int id; /* the id of the mii_bus */ + int disable_aneg; /* if the controller needs to negothiate speed & duplex */ + int lpa; /* the default board-specific vallues will be applied otherwise */ + + union { + struct { + int duplex; + int speed; + } fixed; + + struct { + /* nothing */ + } fec; + + struct { + /* nothing */ + } scc; + + struct { + int mdio_port; /* port & bit for MDIO */ + int mdio_bit; + int mdc_port; /* port & bit for MDC */ + int mdc_bit; + int delay; /* delay in us */ + } bitbang; + } i; }; struct fs_platform_info { @@ -106,7 +119,6 @@ struct fs_platform_info { u32 device_flags; int phy_addr; /* the phy address (-1 no phy) */ - const char* bus_id; int phy_irq; /* the phy irq (if it exists) */ const struct fs_mii_bus_info *bus_info; @@ -118,10 +130,6 @@ struct fs_platform_info { int napi_weight; /* NAPI weight */ int use_rmii; /* use RMII mode */ - int has_phy; /* if the network is phy container as well...*/ -}; -struct fs_mii_fec_platform_info { - u32 irq[32]; - u32 mii_speed; }; + #endif diff --git a/trunk/include/linux/fsnotify.h b/trunk/include/linux/fsnotify.h index d4f219ffaa5d..cc5dec70c32c 100644 --- a/trunk/include/linux/fsnotify.h +++ b/trunk/include/linux/fsnotify.h @@ -67,7 +67,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, if (source) { inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL); } - audit_inode_child(new_name, source, new_dir); + audit_inode_child(new_name, source, new_dir->i_ino); } /* @@ -98,7 +98,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) inode_dir_notify(inode, DN_CREATE); inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name, dentry->d_inode); - audit_inode_child(dentry->d_name.name, dentry->d_inode, inode); + audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino); } /* @@ -109,7 +109,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) inode_dir_notify(inode, DN_CREATE); inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, dentry->d_name.name, dentry->d_inode); - audit_inode_child(dentry->d_name.name, dentry->d_inode, inode); + audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino); } /* diff --git a/trunk/include/linux/futex.h b/trunk/include/linux/futex.h index d097b5b72bc6..34c3a215f2cd 100644 --- a/trunk/include/linux/futex.h +++ b/trunk/include/linux/futex.h @@ -96,8 +96,7 @@ struct robust_list_head { long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout, u32 __user *uaddr2, u32 val2, u32 val3); -extern int -handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi); +extern int handle_futex_death(u32 __user *uaddr, struct task_struct *curr); #ifdef CONFIG_FUTEX extern void exit_robust_list(struct task_struct *curr); diff --git a/trunk/include/linux/genetlink.h b/trunk/include/linux/genetlink.h index 9049dc65ae51..84f12a41dc01 100644 --- a/trunk/include/linux/genetlink.h +++ b/trunk/include/linux/genetlink.h @@ -16,8 +16,6 @@ struct genlmsghdr { #define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr)) -#define GENL_ADMIN_PERM 0x01 - /* * List of reserved static generic netlink identifiers: */ @@ -45,25 +43,9 @@ enum { CTRL_ATTR_UNSPEC, CTRL_ATTR_FAMILY_ID, CTRL_ATTR_FAMILY_NAME, - CTRL_ATTR_VERSION, - CTRL_ATTR_HDRSIZE, - CTRL_ATTR_MAXATTR, - CTRL_ATTR_OPS, __CTRL_ATTR_MAX, }; #define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1) -enum { - CTRL_ATTR_OP_UNSPEC, - CTRL_ATTR_OP_ID, - CTRL_ATTR_OP_FLAGS, - CTRL_ATTR_OP_POLICY, - CTRL_ATTR_OP_DOIT, - CTRL_ATTR_OP_DUMPIT, - __CTRL_ATTR_OP_MAX, -}; - -#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1) - #endif /* __LINUX_GENERIC_NETLINK_H */ diff --git a/trunk/include/linux/hrtimer.h b/trunk/include/linux/hrtimer.h index 4fc379de6c2f..e4bccbcc2750 100644 --- a/trunk/include/linux/hrtimer.h +++ b/trunk/include/linux/hrtimer.h @@ -80,7 +80,6 @@ struct hrtimer_sleeper { * @get_softirq_time: function to retrieve the current time from the softirq * @curr_timer: the timer which is executing a callback right now * @softirq_time: the time when running the hrtimer queue in the softirq - * @lock_key: the lock_class_key for use with lockdep */ struct hrtimer_base { clockid_t index; diff --git a/trunk/include/linux/ide.h b/trunk/include/linux/ide.h index 99620451d958..dc7abef10965 100644 --- a/trunk/include/linux/ide.h +++ b/trunk/include/linux/ide.h @@ -571,7 +571,6 @@ typedef struct ide_drive_s { u8 waiting_for_dma; /* dma currently in progress */ u8 unmask; /* okay to unmask other irqs */ u8 bswap; /* byte swap data */ - u8 noflush; /* don't attempt flushes */ u8 dsc_overlap; /* DSC overlap */ u8 nice1; /* give potential excess bandwidth */ diff --git a/trunk/include/linux/if.h b/trunk/include/linux/if.h index cd080d765324..374e20ad8b0d 100644 --- a/trunk/include/linux/if.h +++ b/trunk/include/linux/if.h @@ -212,134 +212,5 @@ struct ifconf #define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ #define ifc_req ifc_ifcu.ifcu_req /* array of structures */ -/* The struct should be in sync with struct net_device_stats */ -struct rtnl_link_stats -{ - __u32 rx_packets; /* total packets received */ - __u32 tx_packets; /* total packets transmitted */ - __u32 rx_bytes; /* total bytes received */ - __u32 tx_bytes; /* total bytes transmitted */ - __u32 rx_errors; /* bad packets received */ - __u32 tx_errors; /* packet transmit problems */ - __u32 rx_dropped; /* no space in linux buffers */ - __u32 tx_dropped; /* no space available in linux */ - __u32 multicast; /* multicast packets received */ - __u32 collisions; - - /* detailed rx_errors: */ - __u32 rx_length_errors; - __u32 rx_over_errors; /* receiver ring buff overflow */ - __u32 rx_crc_errors; /* recved pkt with crc error */ - __u32 rx_frame_errors; /* recv'd frame alignment error */ - __u32 rx_fifo_errors; /* recv'r fifo overrun */ - __u32 rx_missed_errors; /* receiver missed packet */ - - /* detailed tx_errors */ - __u32 tx_aborted_errors; - __u32 tx_carrier_errors; - __u32 tx_fifo_errors; - __u32 tx_heartbeat_errors; - __u32 tx_window_errors; - - /* for cslip etc */ - __u32 rx_compressed; - __u32 tx_compressed; -}; - -/* The struct should be in sync with struct ifmap */ -struct rtnl_link_ifmap -{ - __u64 mem_start; - __u64 mem_end; - __u64 base_addr; - __u16 irq; - __u8 dma; - __u8 port; -}; - -enum -{ - IFLA_UNSPEC, - IFLA_ADDRESS, - IFLA_BROADCAST, - IFLA_IFNAME, - IFLA_MTU, - IFLA_LINK, - IFLA_QDISC, - IFLA_STATS, - IFLA_COST, -#define IFLA_COST IFLA_COST - IFLA_PRIORITY, -#define IFLA_PRIORITY IFLA_PRIORITY - IFLA_MASTER, -#define IFLA_MASTER IFLA_MASTER - IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ -#define IFLA_WIRELESS IFLA_WIRELESS - IFLA_PROTINFO, /* Protocol specific information for a link */ -#define IFLA_PROTINFO IFLA_PROTINFO - IFLA_TXQLEN, -#define IFLA_TXQLEN IFLA_TXQLEN - IFLA_MAP, -#define IFLA_MAP IFLA_MAP - IFLA_WEIGHT, -#define IFLA_WEIGHT IFLA_WEIGHT - IFLA_OPERSTATE, - IFLA_LINKMODE, - __IFLA_MAX -}; - - -#define IFLA_MAX (__IFLA_MAX - 1) - -/* ifi_flags. - - IFF_* flags. - - The only change is: - IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are - more not changeable by user. They describe link media - characteristics and set by device driver. - - Comments: - - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid - - If neither of these three flags are set; - the interface is NBMA. - - - IFF_MULTICAST does not mean anything special: - multicasts can be used on all not-NBMA links. - IFF_MULTICAST means that this media uses special encapsulation - for multicast frames. Apparently, all IFF_POINTOPOINT and - IFF_BROADCAST devices are able to use multicasts too. - */ - -/* IFLA_LINK. - For usual devices it is equal ifi_index. - If it is a "virtual interface" (f.e. tunnel), ifi_link - can point to real physical interface (f.e. for bandwidth calculations), - or maybe 0, what means, that real media is unknown (usual - for IPIP tunnels, when route to endpoint is allowed to change) - */ - -/* Subtype attributes for IFLA_PROTINFO */ -enum -{ - IFLA_INET6_UNSPEC, - IFLA_INET6_FLAGS, /* link flags */ - IFLA_INET6_CONF, /* sysctl parameters */ - IFLA_INET6_STATS, /* statistics */ - IFLA_INET6_MCAST, /* MC things. What of them? */ - IFLA_INET6_CACHEINFO, /* time values and max reasm size */ - __IFLA_INET6_MAX -}; - -#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) - -struct ifla_cacheinfo -{ - __u32 max_reasm_len; - __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ - __u32 reachable_time; - __u32 retrans_time; -}; #endif /* _LINUX_IF_H */ diff --git a/trunk/include/linux/if_addr.h b/trunk/include/linux/if_addr.h deleted file mode 100644 index dbe8f6120a40..000000000000 --- a/trunk/include/linux/if_addr.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef __LINUX_IF_ADDR_H -#define __LINUX_IF_ADDR_H - -#include - -struct ifaddrmsg -{ - __u8 ifa_family; - __u8 ifa_prefixlen; /* The prefix length */ - __u8 ifa_flags; /* Flags */ - __u8 ifa_scope; /* Address scope */ - __u32 ifa_index; /* Link index */ -}; - -/* - * Important comment: - * IFA_ADDRESS is prefix address, rather than local interface address. - * It makes no difference for normally configured broadcast interfaces, - * but for point-to-point IFA_ADDRESS is DESTINATION address, - * local address is supplied in IFA_LOCAL attribute. - */ -enum -{ - IFA_UNSPEC, - IFA_ADDRESS, - IFA_LOCAL, - IFA_LABEL, - IFA_BROADCAST, - IFA_ANYCAST, - IFA_CACHEINFO, - IFA_MULTICAST, - __IFA_MAX, -}; - -#define IFA_MAX (__IFA_MAX - 1) - -/* ifa_flags */ -#define IFA_F_SECONDARY 0x01 -#define IFA_F_TEMPORARY IFA_F_SECONDARY - -#define IFA_F_NODAD 0x02 -#define IFA_F_HOMEADDRESS 0x10 -#define IFA_F_DEPRECATED 0x20 -#define IFA_F_TENTATIVE 0x40 -#define IFA_F_PERMANENT 0x80 - -struct ifa_cacheinfo -{ - __u32 ifa_prefered; - __u32 ifa_valid; - __u32 cstamp; /* created timestamp, hundredths of seconds */ - __u32 tstamp; /* updated timestamp, hundredths of seconds */ -}; - -#endif diff --git a/trunk/include/linux/if_vlan.h b/trunk/include/linux/if_vlan.h index ab2740832742..383627ad328f 100644 --- a/trunk/include/linux/if_vlan.h +++ b/trunk/include/linux/if_vlan.h @@ -155,11 +155,6 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb, { struct net_device_stats *stats; - if (skb_bond_should_drop(skb)) { - dev_kfree_skb_any(skb); - return NET_RX_DROP; - } - skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK]; if (skb->dev == NULL) { dev_kfree_skb_any(skb); diff --git a/trunk/include/linux/in.h b/trunk/include/linux/in.h index bcaca8399aed..94f557fa4636 100644 --- a/trunk/include/linux/in.h +++ b/trunk/include/linux/in.h @@ -52,7 +52,7 @@ enum { /* Internet address. */ struct in_addr { - __be32 s_addr; + __u32 s_addr; }; #define IP_TOS 1 @@ -177,7 +177,7 @@ struct in_pktinfo #define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ struct sockaddr_in { sa_family_t sin_family; /* Address family */ - __be16 sin_port; /* Port number */ + unsigned short int sin_port; /* Port number */ struct in_addr sin_addr; /* Internet address */ /* Pad to size of `struct sockaddr'. */ diff --git a/trunk/include/linux/in6.h b/trunk/include/linux/in6.h index d776829b443f..304aaedea305 100644 --- a/trunk/include/linux/in6.h +++ b/trunk/include/linux/in6.h @@ -134,7 +134,6 @@ struct in6_flowlabel_req #define IPPROTO_ICMPV6 58 /* ICMPv6 */ #define IPPROTO_NONE 59 /* IPv6 no next header */ #define IPPROTO_DSTOPTS 60 /* IPv6 destination options */ -#define IPPROTO_MH 135 /* IPv6 mobility header */ /* * IPv6 TLV options. @@ -143,7 +142,6 @@ struct in6_flowlabel_req #define IPV6_TLV_PADN 1 #define IPV6_TLV_ROUTERALERT 5 #define IPV6_TLV_JUMBO 194 -#define IPV6_TLV_HAO 201 /* home address option */ /* * IPV6 socket options diff --git a/trunk/include/linux/inet.h b/trunk/include/linux/inet.h index b7c6da7d6d32..6c5587af118d 100644 --- a/trunk/include/linux/inet.h +++ b/trunk/include/linux/inet.h @@ -46,7 +46,5 @@ #include extern __be32 in_aton(const char *str); -extern int in4_pton(const char *src, int srclen, u8 *dst, char delim, const char **end); -extern int in6_pton(const char *src, int srclen, u8 *dst, char delim, const char **end); #endif #endif /* _LINUX_INET_H */ diff --git a/trunk/include/linux/input.h b/trunk/include/linux/input.h index b3253ab72ff7..56f1e0e1e598 100644 --- a/trunk/include/linux/input.h +++ b/trunk/include/linux/input.h @@ -893,6 +893,7 @@ struct input_dev { int (*open)(struct input_dev *dev); void (*close)(struct input_dev *dev); + int (*accept)(struct input_dev *dev, struct file *file); int (*flush)(struct input_dev *dev, struct file *file); int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value); int (*upload_effect)(struct input_dev *dev, struct ff_effect *effect); @@ -960,26 +961,6 @@ struct input_dev { struct input_handle; -/** - * struct input_handler - implements one of interfaces for input devices - * @private: driver-specific data - * @event: event handler - * @connect: called when attaching a handler to an input device - * @disconnect: disconnects a handler from input device - * @start: starts handler for given handle. This function is called by - * input core right after connect() method and also when a process - * that "grabbed" a device releases it - * @fops: file operations this driver implements - * @minor: beginning of range of 32 minors for devices this driver - * can provide - * @name: name of the handler, to be shown in /proc/bus/input/handlers - * @id_table: pointer to a table of input_device_ids this driver can - * handle - * @blacklist: prointer to a table of input_device_ids this driver should - * ignore even if they match @id_table - * @h_list: list of input handles associated with the handler - * @node: for placing the driver onto input_handler_list - */ struct input_handler { void *private; @@ -987,7 +968,6 @@ struct input_handler { void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); struct input_handle* (*connect)(struct input_handler *handler, struct input_dev *dev, struct input_device_id *id); void (*disconnect)(struct input_handle *handle); - void (*start)(struct input_handle *handle); const struct file_operations *fops; int minor; @@ -1050,10 +1030,10 @@ void input_release_device(struct input_handle *); int input_open_device(struct input_handle *); void input_close_device(struct input_handle *); +int input_accept_process(struct input_handle *handle, struct file *file); int input_flush_device(struct input_handle* handle, struct file* file); void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); -void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value); static inline void input_report_key(struct input_dev *dev, unsigned int code, int value) { diff --git a/trunk/include/linux/ioprio.h b/trunk/include/linux/ioprio.h index 8e2042b9d471..88d5961f7a3f 100644 --- a/trunk/include/linux/ioprio.h +++ b/trunk/include/linux/ioprio.h @@ -59,6 +59,27 @@ static inline int task_nice_ioprio(struct task_struct *task) /* * For inheritance, return the highest of the two given priorities */ -extern int ioprio_best(unsigned short aprio, unsigned short bprio); +static inline int ioprio_best(unsigned short aprio, unsigned short bprio) +{ + unsigned short aclass = IOPRIO_PRIO_CLASS(aprio); + unsigned short bclass = IOPRIO_PRIO_CLASS(bprio); + + if (!ioprio_valid(aprio)) + return bprio; + if (!ioprio_valid(bprio)) + return aprio; + + if (aclass == IOPRIO_CLASS_NONE) + aclass = IOPRIO_CLASS_BE; + if (bclass == IOPRIO_CLASS_NONE) + bclass = IOPRIO_CLASS_BE; + + if (aclass == bclass) + return min(aprio, bprio); + if (aclass > bclass) + return bprio; + else + return aprio; +} #endif diff --git a/trunk/include/linux/ip.h b/trunk/include/linux/ip.h index 2f4600146f83..4b55cf1df732 100644 --- a/trunk/include/linux/ip.h +++ b/trunk/include/linux/ip.h @@ -57,7 +57,6 @@ #define IPOPT_SEC (2 |IPOPT_CONTROL|IPOPT_COPY) #define IPOPT_LSRR (3 |IPOPT_CONTROL|IPOPT_COPY) #define IPOPT_TIMESTAMP (4 |IPOPT_MEASUREMENT) -#define IPOPT_CIPSO (6 |IPOPT_CONTROL|IPOPT_COPY) #define IPOPT_RR (7 |IPOPT_CONTROL) #define IPOPT_SID (8 |IPOPT_CONTROL|IPOPT_COPY) #define IPOPT_SSRR (9 |IPOPT_CONTROL|IPOPT_COPY) diff --git a/trunk/include/linux/ipv6.h b/trunk/include/linux/ipv6.h index caca57df0d7d..297853c841b4 100644 --- a/trunk/include/linux/ipv6.h +++ b/trunk/include/linux/ipv6.h @@ -29,7 +29,6 @@ struct in6_ifreq { #define IPV6_SRCRT_STRICT 0x01 /* this hop must be a neighbor */ #define IPV6_SRCRT_TYPE_0 0 /* IPv6 type 0 Routing Header */ -#define IPV6_SRCRT_TYPE_2 2 /* IPv6 type 2 Routing Header */ /* * routing header @@ -74,28 +73,6 @@ struct rt0_hdr { #define rt0_type rt_hdr.type }; -/* - * routing header type 2 - */ - -struct rt2_hdr { - struct ipv6_rt_hdr rt_hdr; - __u32 reserved; - struct in6_addr addr; - -#define rt2_type rt_hdr.type -}; - -/* - * home address option in destination options header - */ - -struct ipv6_destopt_hao { - __u8 type; - __u8 length; - struct in6_addr addr; -} __attribute__ ((__packed__)); - struct ipv6_auth_hdr { __u8 nexthdr; __u8 hdrlen; /* This one is measured in 32 bit units! */ @@ -176,7 +153,6 @@ struct ipv6_devconf { __s32 accept_ra_rt_info_max_plen; #endif #endif - __s32 proxy_ndp; void *sysctl; }; @@ -204,7 +180,6 @@ enum { DEVCONF_ACCEPT_RA_RTR_PREF, DEVCONF_RTR_PROBE_INTERVAL, DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN, - DEVCONF_PROXY_NDP, DEVCONF_MAX }; @@ -231,9 +206,6 @@ struct inet6_skb_parm { __u16 lastopt; __u32 nhoff; __u16 flags; -#ifdef CONFIG_IPV6_MIP6 - __u16 dsthao; -#endif #define IP6SKB_XFRM_TRANSFORMED 1 }; @@ -270,9 +242,6 @@ struct ipv6_pinfo { struct in6_addr rcv_saddr; struct in6_addr daddr; struct in6_addr *daddr_cache; -#ifdef CONFIG_IPV6_SUBTREES - struct in6_addr *saddr_cache; -#endif __u32 flow_label; __u32 frag_size; diff --git a/trunk/include/linux/irq.h b/trunk/include/linux/irq.h index fbf6d901e9c2..b48eae32dc61 100644 --- a/trunk/include/linux/irq.h +++ b/trunk/include/linux/irq.h @@ -47,8 +47,8 @@ #define IRQ_WAITING 0x00200000 /* IRQ not yet seen - for autodetection */ #define IRQ_LEVEL 0x00400000 /* IRQ level triggered */ #define IRQ_MASKED 0x00800000 /* IRQ masked - shouldn't be seen again */ -#define IRQ_PER_CPU 0x01000000 /* IRQ is per CPU */ #ifdef CONFIG_IRQ_PER_CPU +# define IRQ_PER_CPU 0x01000000 /* IRQ is per CPU */ # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU) #else # define CHECK_IRQ_PER_CPU(var) 0 @@ -58,7 +58,6 @@ #define IRQ_NOREQUEST 0x04000000 /* IRQ cannot be requested */ #define IRQ_NOAUTOEN 0x08000000 /* IRQ will not be enabled on request irq */ #define IRQ_DELAYED_DISABLE 0x10000000 /* IRQ disable (masking) happens delayed. */ -#define IRQ_WAKEUP 0x20000000 /* IRQ triggers system wakeup */ struct proc_dir_entry; @@ -125,7 +124,6 @@ struct irq_chip { * @action: the irq action chain * @status: status information * @depth: disable-depth, for nested irq_disable() calls - * @wake_depth: enable depth, for multiple set_irq_wake() callers * @irq_count: stats field to detect stalled irqs * @irqs_unhandled: stats field for spurious unhandled interrupts * @lock: locking for SMP @@ -149,7 +147,6 @@ struct irq_desc { unsigned int status; /* IRQ status */ unsigned int depth; /* nested irq disables */ - unsigned int wake_depth; /* nested wake enables */ unsigned int irq_count; /* For detecting broken IRQs */ unsigned int irqs_unhandled; spinlock_t lock; diff --git a/trunk/include/linux/jbd.h b/trunk/include/linux/jbd.h index a04c154c5207..20eb34403d0c 100644 --- a/trunk/include/linux/jbd.h +++ b/trunk/include/linux/jbd.h @@ -72,9 +72,6 @@ extern int journal_enable_debug; #endif extern void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry); -extern void * jbd_slab_alloc(size_t size, gfp_t flags); -extern void jbd_slab_free(void *ptr, size_t size); - #define jbd_kmalloc(size, flags) \ __jbd_kmalloc(__FUNCTION__, (size), (flags), journal_oom_retry) #define jbd_rep_kmalloc(size, flags) \ diff --git a/trunk/include/linux/jiffies.h b/trunk/include/linux/jiffies.h index 329ebcffa106..043376920f51 100644 --- a/trunk/include/linux/jiffies.h +++ b/trunk/include/linux/jiffies.h @@ -47,8 +47,8 @@ * - (NOM / DEN) fits in (32 - LSH) bits. * - (NOM % DEN) fits in (32 - LSH) bits. */ -#define SH_DIV(NOM,DEN,LSH) ( (((NOM) / (DEN)) << (LSH)) \ - + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN)) +#define SH_DIV(NOM,DEN,LSH) ( ((NOM / DEN) << LSH) \ + + (((NOM % DEN) << LSH) + DEN / 2) / DEN) /* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */ #define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) diff --git a/trunk/include/linux/kernel.h b/trunk/include/linux/kernel.h index 2b2ae4fdce8b..181c69cad4e3 100644 --- a/trunk/include/linux/kernel.h +++ b/trunk/include/linux/kernel.h @@ -31,7 +31,7 @@ extern const char linux_banner[]; #define STACK_MAGIC 0xdeadbeef #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) -#define ALIGN(x,a) (((x)+(a)-1UL)&~((a)-1UL)) +#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) @@ -210,7 +210,6 @@ extern enum system_states { extern void dump_stack(void); #ifdef DEBUG -/* If you are writing a driver, please use dev_dbg instead */ #define pr_debug(fmt,arg...) \ printk(KERN_DEBUG fmt,##arg) #else diff --git a/trunk/include/linux/kobject.h b/trunk/include/linux/kobject.h index 2d229327959e..0503b2ed8bae 100644 --- a/trunk/include/linux/kobject.h +++ b/trunk/include/linux/kobject.h @@ -46,6 +46,8 @@ enum kobject_action { KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices (broken) */ KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* device offline */ KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* device online */ + KOBJ_UNDOCK = (__force kobject_action_t) 0x08, /* undocking */ + KOBJ_DOCK = (__force kobject_action_t) 0x09, /* dock */ }; struct kobject { diff --git a/trunk/include/linux/ktime.h b/trunk/include/linux/ktime.h index 84eeecd60a02..ed3396dcc4f7 100644 --- a/trunk/include/linux/ktime.h +++ b/trunk/include/linux/ktime.h @@ -56,8 +56,7 @@ typedef union { #endif } ktime_t; -#define KTIME_MAX ((s64)~((u64)1 << 63)) -#define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) +#define KTIME_MAX (~((u64)1 << 63)) /* * ktime_t definitions when using the 64-bit scalar representation: @@ -74,10 +73,6 @@ typedef union { */ static inline ktime_t ktime_set(const long secs, const unsigned long nsecs) { -#if (BITS_PER_LONG == 64) - if (unlikely(secs >= KTIME_SEC_MAX)) - return (ktime_t){ .tv64 = KTIME_MAX }; -#endif return (ktime_t) { .tv64 = (s64)secs * NSEC_PER_SEC + (s64)nsecs }; } diff --git a/trunk/include/linux/libata.h b/trunk/include/linux/libata.h index 66c3100c2b94..6cc497a2b6da 100644 --- a/trunk/include/linux/libata.h +++ b/trunk/include/linux/libata.h @@ -265,14 +265,12 @@ enum { /* ata_eh_info->flags */ ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ - ATA_EHI_RESUME_LINK = (1 << 1), /* resume link (reset modifier) */ + ATA_EHI_RESUME_LINK = (1 << 1), /* need to resume link */ ATA_EHI_NO_AUTOPSY = (1 << 2), /* no autopsy */ ATA_EHI_QUIET = (1 << 3), /* be quiet */ ATA_EHI_DID_RESET = (1 << 16), /* already reset this port */ - ATA_EHI_RESET_MODIFIER_MASK = ATA_EHI_RESUME_LINK, - /* max repeat if error condition is still set after ->error_handler */ ATA_EH_MAX_REPEAT = 5, diff --git a/trunk/include/linux/lockd/lockd.h b/trunk/include/linux/lockd/lockd.h index 0d92c468d55a..aa4fe905bb4d 100644 --- a/trunk/include/linux/lockd/lockd.h +++ b/trunk/include/linux/lockd/lockd.h @@ -123,6 +123,7 @@ struct nlm_block { unsigned int b_id; /* block id */ unsigned char b_queued; /* re-queued */ unsigned char b_granted; /* VFS granted lock */ + unsigned char b_done; /* callback complete */ struct nlm_file * b_file; /* file in question */ }; diff --git a/trunk/include/linux/mm.h b/trunk/include/linux/mm.h index 224178a000d2..990957e0929f 100644 --- a/trunk/include/linux/mm.h +++ b/trunk/include/linux/mm.h @@ -336,7 +336,6 @@ static inline void init_page_count(struct page *page) } void put_page(struct page *page); -void put_pages_list(struct list_head *pages); void split_page(struct page *page, unsigned int order); @@ -1013,7 +1012,6 @@ static inline unsigned long vma_pages(struct vm_area_struct *vma) return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; } -pgprot_t vm_get_page_prot(unsigned long vm_flags); struct vm_area_struct *find_extend_vma(struct mm_struct *, unsigned long addr); struct page *vmalloc_to_page(void *addr); unsigned long vmalloc_to_pfn(void *addr); diff --git a/trunk/include/linux/mmc/host.h b/trunk/include/linux/mmc/host.h index ba095aebedff..c1f021eddffa 100644 --- a/trunk/include/linux/mmc/host.h +++ b/trunk/include/linux/mmc/host.h @@ -77,7 +77,7 @@ struct mmc_host { struct device *dev; struct class_device class_dev; int index; - const struct mmc_host_ops *ops; + struct mmc_host_ops *ops; unsigned int f_min; unsigned int f_max; u32 ocr_avail; diff --git a/trunk/include/linux/mmc/mmc.h b/trunk/include/linux/mmc/mmc.h index 627e2c08ce41..03a14a30c46a 100644 --- a/trunk/include/linux/mmc/mmc.h +++ b/trunk/include/linux/mmc/mmc.h @@ -105,8 +105,6 @@ extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int); extern int mmc_wait_for_app_cmd(struct mmc_host *, unsigned int, struct mmc_command *, int); -extern void mmc_set_data_timeout(struct mmc_data *, const struct mmc_card *, int); - extern int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card); static inline void mmc_claim_host(struct mmc_host *host) diff --git a/trunk/include/linux/mmzone.h b/trunk/include/linux/mmzone.h index f45163c528e8..656b588a9f96 100644 --- a/trunk/include/linux/mmzone.h +++ b/trunk/include/linux/mmzone.h @@ -77,7 +77,6 @@ struct per_cpu_pages { struct per_cpu_pageset { struct per_cpu_pages pcp[2]; /* 0: hot. 1: cold */ #ifdef CONFIG_SMP - s8 stat_threshold; s8 vm_stat_diff[NR_VM_ZONE_STAT_ITEMS]; #endif } ____cacheline_aligned_in_smp; diff --git a/trunk/include/linux/mod_devicetable.h b/trunk/include/linux/mod_devicetable.h index f7ca0b09075d..f6977708585c 100644 --- a/trunk/include/linux/mod_devicetable.h +++ b/trunk/include/linux/mod_devicetable.h @@ -148,17 +148,6 @@ struct ccw_device_id { #define CCW_DEVICE_ID_MATCH_DEVICE_TYPE 0x04 #define CCW_DEVICE_ID_MATCH_DEVICE_MODEL 0x08 -/* s390 AP bus devices */ -struct ap_device_id { - __u16 match_flags; /* which fields to match against */ - __u8 dev_type; /* device type */ - __u8 pad1; - __u32 pad2; - kernel_ulong_t driver_info; -}; - -#define AP_DEVICE_ID_MATCH_DEVICE_TYPE 0x01 - #define PNP_ID_LEN 8 #define PNP_MAX_DEVICES 8 diff --git a/trunk/include/linux/mtd/cfi.h b/trunk/include/linux/mtd/cfi.h index 123948b14547..09bfae6938b3 100644 --- a/trunk/include/linux/mtd/cfi.h +++ b/trunk/include/linux/mtd/cfi.h @@ -199,18 +199,6 @@ struct cfi_pri_amdstd { uint8_t TopBottom; } __attribute__((packed)); -/* Vendor-Specific PRI for Atmel chips (command set 0x0002) */ - -struct cfi_pri_atmel { - uint8_t pri[3]; - uint8_t MajorVersion; - uint8_t MinorVersion; - uint8_t Features; - uint8_t BottomBoot; - uint8_t BurstMode; - uint8_t PageMode; -} __attribute__((packed)); - struct cfi_pri_query { uint8_t NumFields; uint32_t ProtField[1]; /* Not host ordered */ @@ -476,7 +464,6 @@ struct cfi_fixup { #define CFI_ID_ANY 0xffff #define CFI_MFR_AMD 0x0001 -#define CFI_MFR_ATMEL 0x001F #define CFI_MFR_ST 0x0020 /* STMicroelectronics */ void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup* fixups); diff --git a/trunk/include/linux/neighbour.h b/trunk/include/linux/neighbour.h deleted file mode 100644 index bd3bbf668cdb..000000000000 --- a/trunk/include/linux/neighbour.h +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef __LINUX_NEIGHBOUR_H -#define __LINUX_NEIGHBOUR_H - -#include - -struct ndmsg -{ - __u8 ndm_family; - __u8 ndm_pad1; - __u16 ndm_pad2; - __s32 ndm_ifindex; - __u16 ndm_state; - __u8 ndm_flags; - __u8 ndm_type; -}; - -enum -{ - NDA_UNSPEC, - NDA_DST, - NDA_LLADDR, - NDA_CACHEINFO, - NDA_PROBES, - __NDA_MAX -}; - -#define NDA_MAX (__NDA_MAX - 1) - -/* - * Neighbor Cache Entry Flags - */ - -#define NTF_PROXY 0x08 /* == ATF_PUBL */ -#define NTF_ROUTER 0x80 - -/* - * Neighbor Cache Entry States. - */ - -#define NUD_INCOMPLETE 0x01 -#define NUD_REACHABLE 0x02 -#define NUD_STALE 0x04 -#define NUD_DELAY 0x08 -#define NUD_PROBE 0x10 -#define NUD_FAILED 0x20 - -/* Dummy states */ -#define NUD_NOARP 0x40 -#define NUD_PERMANENT 0x80 -#define NUD_NONE 0x00 - -/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change - and make no address resolution or NUD. - NUD_PERMANENT is also cannot be deleted by garbage collectors. - */ - -struct nda_cacheinfo -{ - __u32 ndm_confirmed; - __u32 ndm_used; - __u32 ndm_updated; - __u32 ndm_refcnt; -}; - -/***************************************************************** - * Neighbour tables specific messages. - * - * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the - * NLM_F_DUMP flag set. Every neighbour table configuration is - * spread over multiple messages to avoid running into message - * size limits on systems with many interfaces. The first message - * in the sequence transports all not device specific data such as - * statistics, configuration, and the default parameter set. - * This message is followed by 0..n messages carrying device - * specific parameter sets. - * Although the ordering should be sufficient, NDTA_NAME can be - * used to identify sequences. The initial message can be identified - * by checking for NDTA_CONFIG. The device specific messages do - * not contain this TLV but have NDTPA_IFINDEX set to the - * corresponding interface index. - * - * To change neighbour table attributes, send RTM_SETNEIGHTBL - * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3], - * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked - * otherwise. Device specific parameter sets can be changed by - * setting NDTPA_IFINDEX to the interface index of the corresponding - * device. - ****/ - -struct ndt_stats -{ - __u64 ndts_allocs; - __u64 ndts_destroys; - __u64 ndts_hash_grows; - __u64 ndts_res_failed; - __u64 ndts_lookups; - __u64 ndts_hits; - __u64 ndts_rcv_probes_mcast; - __u64 ndts_rcv_probes_ucast; - __u64 ndts_periodic_gc_runs; - __u64 ndts_forced_gc_runs; -}; - -enum { - NDTPA_UNSPEC, - NDTPA_IFINDEX, /* u32, unchangeable */ - NDTPA_REFCNT, /* u32, read-only */ - NDTPA_REACHABLE_TIME, /* u64, read-only, msecs */ - NDTPA_BASE_REACHABLE_TIME, /* u64, msecs */ - NDTPA_RETRANS_TIME, /* u64, msecs */ - NDTPA_GC_STALETIME, /* u64, msecs */ - NDTPA_DELAY_PROBE_TIME, /* u64, msecs */ - NDTPA_QUEUE_LEN, /* u32 */ - NDTPA_APP_PROBES, /* u32 */ - NDTPA_UCAST_PROBES, /* u32 */ - NDTPA_MCAST_PROBES, /* u32 */ - NDTPA_ANYCAST_DELAY, /* u64, msecs */ - NDTPA_PROXY_DELAY, /* u64, msecs */ - NDTPA_PROXY_QLEN, /* u32 */ - NDTPA_LOCKTIME, /* u64, msecs */ - __NDTPA_MAX -}; -#define NDTPA_MAX (__NDTPA_MAX - 1) - -struct ndtmsg -{ - __u8 ndtm_family; - __u8 ndtm_pad1; - __u16 ndtm_pad2; -}; - -struct ndt_config -{ - __u16 ndtc_key_len; - __u16 ndtc_entry_size; - __u32 ndtc_entries; - __u32 ndtc_last_flush; /* delta to now in msecs */ - __u32 ndtc_last_rand; /* delta to now in msecs */ - __u32 ndtc_hash_rnd; - __u32 ndtc_hash_mask; - __u32 ndtc_hash_chain_gc; - __u32 ndtc_proxy_qlen; -}; - -enum { - NDTA_UNSPEC, - NDTA_NAME, /* char *, unchangeable */ - NDTA_THRESH1, /* u32 */ - NDTA_THRESH2, /* u32 */ - NDTA_THRESH3, /* u32 */ - NDTA_CONFIG, /* struct ndt_config, read-only */ - NDTA_PARMS, /* nested TLV NDTPA_* */ - NDTA_STATS, /* struct ndt_stats, read-only */ - NDTA_GC_INTERVAL, /* u64, msecs */ - __NDTA_MAX -}; -#define NDTA_MAX (__NDTA_MAX - 1) - -#endif diff --git a/trunk/include/linux/net.h b/trunk/include/linux/net.h index c257f716e00f..b20c53c74413 100644 --- a/trunk/include/linux/net.h +++ b/trunk/include/linux/net.h @@ -169,6 +169,11 @@ struct proto_ops { struct net_proto_family { int family; int (*create)(struct socket *sock, int protocol); + /* These are counters for the number of different methods of + each we support */ + short authentication; + short encryption; + short encrypt_net; struct module *owner; }; @@ -176,8 +181,8 @@ struct iovec; struct kvec; extern int sock_wake_async(struct socket *sk, int how, int band); -extern int sock_register(const struct net_proto_family *fam); -extern void sock_unregister(int family); +extern int sock_register(struct net_proto_family *fam); +extern int sock_unregister(int family); extern int sock_create(int family, int type, int proto, struct socket **res); extern int sock_create_kern(int family, int type, int proto, @@ -203,25 +208,6 @@ extern int kernel_recvmsg(struct socket *sock, struct msghdr *msg, struct kvec *vec, size_t num, size_t len, int flags); -extern int kernel_bind(struct socket *sock, struct sockaddr *addr, - int addrlen); -extern int kernel_listen(struct socket *sock, int backlog); -extern int kernel_accept(struct socket *sock, struct socket **newsock, - int flags); -extern int kernel_connect(struct socket *sock, struct sockaddr *addr, - int addrlen, int flags); -extern int kernel_getsockname(struct socket *sock, struct sockaddr *addr, - int *addrlen); -extern int kernel_getpeername(struct socket *sock, struct sockaddr *addr, - int *addrlen); -extern int kernel_getsockopt(struct socket *sock, int level, int optname, - char *optval, int *optlen); -extern int kernel_setsockopt(struct socket *sock, int level, int optname, - char *optval, int optlen); -extern int kernel_sendpage(struct socket *sock, struct page *page, int offset, - size_t size, int flags); -extern int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg); - #ifndef CONFIG_SMP #define SOCKOPS_WRAPPED(name) name #define SOCKOPS_WRAP(name, fam) diff --git a/trunk/include/linux/netdevice.h b/trunk/include/linux/netdevice.h index 4f2c2b6beb5e..75f02d8c6ed3 100644 --- a/trunk/include/linux/netdevice.h +++ b/trunk/include/linux/netdevice.h @@ -320,9 +320,6 @@ struct net_device #define NETIF_F_TSO_ECN (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT) #define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT) - /* List of features with software fallbacks. */ -#define NETIF_F_GSO_SOFTWARE (NETIF_F_TSO | NETIF_F_TSO_ECN | NETIF_F_TSO6) - #define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM) #define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM) @@ -976,7 +973,7 @@ extern void dev_mcast_init(void); extern int netdev_max_backlog; extern int weight_p; extern int netdev_set_master(struct net_device *dev, struct net_device *master); -extern int skb_checksum_help(struct sk_buff *skb); +extern int skb_checksum_help(struct sk_buff *skb, int inward); extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features); #ifdef CONFIG_BUG extern void netdev_rx_csum_fault(struct net_device *dev); @@ -1012,31 +1009,7 @@ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) { return skb_is_gso(skb) && (!skb_gso_ok(skb, dev->features) || - unlikely(skb->ip_summed != CHECKSUM_PARTIAL)); -} - -/* On bonding slaves other than the currently active slave, suppress - * duplicates except for 802.3ad ETH_P_SLOW and alb non-mcast/bcast. - */ -static inline int skb_bond_should_drop(struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - struct net_device *master = dev->master; - - if (master && - (dev->priv_flags & IFF_SLAVE_INACTIVE)) { - if (master->priv_flags & IFF_MASTER_ALB) { - if (skb->pkt_type != PACKET_BROADCAST && - skb->pkt_type != PACKET_MULTICAST) - return 0; - } - if (master->priv_flags & IFF_MASTER_8023AD && - skb->protocol == __constant_htons(ETH_P_SLOW)) - return 0; - - return 1; - } - return 0; + unlikely(skb->ip_summed != CHECKSUM_HW)); } #endif /* __KERNEL__ */ diff --git a/trunk/include/linux/netfilter.h b/trunk/include/linux/netfilter.h index b7e67d1d4382..10168e26a846 100644 --- a/trunk/include/linux/netfilter.h +++ b/trunk/include/linux/netfilter.h @@ -282,12 +282,6 @@ extern void nf_invalidate_cache(int pf); Returns true or false. */ extern int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len); -extern u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval, - u_int32_t csum); -extern u_int16_t nf_proto_csum_update(struct sk_buff *skb, - u_int32_t oldval, u_int32_t newval, - u_int16_t csum, int pseudohdr); - struct nf_afinfo { unsigned short family; unsigned int (*checksum)(struct sk_buff *skb, unsigned int hook, diff --git a/trunk/include/linux/netfilter/Kbuild b/trunk/include/linux/netfilter/Kbuild index 9a285cecf249..d06311acd448 100644 --- a/trunk/include/linux/netfilter/Kbuild +++ b/trunk/include/linux/netfilter/Kbuild @@ -1,38 +1,11 @@ -header-y += nf_conntrack_sctp.h -header-y += nf_conntrack_tuple_common.h -header-y += nfnetlink_conntrack.h -header-y += nfnetlink_log.h -header-y += nfnetlink_queue.h -header-y += xt_CLASSIFY.h -header-y += xt_comment.h -header-y += xt_connbytes.h -header-y += xt_connmark.h -header-y += xt_CONNMARK.h -header-y += xt_conntrack.h -header-y += xt_dccp.h -header-y += xt_esp.h -header-y += xt_helper.h -header-y += xt_length.h -header-y += xt_limit.h -header-y += xt_mac.h -header-y += xt_mark.h -header-y += xt_MARK.h -header-y += xt_multiport.h -header-y += xt_NFQUEUE.h -header-y += xt_pkttype.h -header-y += xt_policy.h -header-y += xt_realm.h -header-y += xt_sctp.h -header-y += xt_state.h -header-y += xt_string.h -header-y += xt_tcpmss.h -header-y += xt_tcpudp.h -header-y += xt_SECMARK.h -header-y += xt_CONNSECMARK.h +header-y := nf_conntrack_sctp.h nf_conntrack_tuple_common.h \ + nfnetlink_conntrack.h nfnetlink_log.h nfnetlink_queue.h \ + xt_CLASSIFY.h xt_comment.h xt_connbytes.h xt_connmark.h \ + xt_CONNMARK.h xt_conntrack.h xt_dccp.h xt_esp.h \ + xt_helper.h xt_length.h xt_limit.h xt_mac.h xt_mark.h \ + xt_MARK.h xt_multiport.h xt_NFQUEUE.h xt_pkttype.h \ + xt_policy.h xt_realm.h xt_sctp.h xt_state.h xt_string.h \ + xt_tcpmss.h xt_tcpudp.h -unifdef-y += nf_conntrack_common.h -unifdef-y += nf_conntrack_ftp.h -unifdef-y += nf_conntrack_tcp.h -unifdef-y += nfnetlink.h -unifdef-y += x_tables.h -unifdef-y += xt_physdev.h +unifdef-y := nf_conntrack_common.h nf_conntrack_ftp.h \ + nf_conntrack_tcp.h nfnetlink.h x_tables.h xt_physdev.h diff --git a/trunk/include/linux/netfilter/nf_conntrack_common.h b/trunk/include/linux/netfilter/nf_conntrack_common.h index 9e0dae07861e..d2e4bd7a7a14 100644 --- a/trunk/include/linux/netfilter/nf_conntrack_common.h +++ b/trunk/include/linux/netfilter/nf_conntrack_common.h @@ -125,10 +125,6 @@ enum ip_conntrack_events /* Counter highest bit has been set */ IPCT_COUNTER_FILLING_BIT = 11, IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT), - - /* Mark is set */ - IPCT_MARK_BIT = 12, - IPCT_MARK = (1 << IPCT_MARK_BIT), }; enum ip_conntrack_expect_events { diff --git a/trunk/include/linux/netfilter/nf_conntrack_tcp.h b/trunk/include/linux/netfilter/nf_conntrack_tcp.h index 6b01ba297727..b2feeffde384 100644 --- a/trunk/include/linux/netfilter/nf_conntrack_tcp.h +++ b/trunk/include/linux/netfilter/nf_conntrack_tcp.h @@ -49,7 +49,6 @@ struct ip_ct_tcp u_int32_t last_seq; /* Last sequence number seen in dir */ u_int32_t last_ack; /* Last sequence number seen in opposite dir */ u_int32_t last_end; /* Last seq + len */ - u_int16_t last_win; /* Last window advertisement seen in dir */ }; #endif /* __KERNEL__ */ diff --git a/trunk/include/linux/netfilter/nfnetlink.h b/trunk/include/linux/netfilter/nfnetlink.h index 6d8e3e5a80e9..9f5b12cf489b 100644 --- a/trunk/include/linux/netfilter/nfnetlink.h +++ b/trunk/include/linux/netfilter/nfnetlink.h @@ -43,7 +43,7 @@ struct nfattr u_int16_t nfa_len; u_int16_t nfa_type; /* we use 15 bits for the type, and the highest * bit to indicate whether the payload is nested */ -}; +} __attribute__ ((packed)); /* FIXME: Apart from NFNL_NFA_NESTED shamelessly copy and pasted from * rtnetlink.h, it's time to put this in a generic file */ @@ -79,7 +79,7 @@ struct nfgenmsg { u_int8_t nfgen_family; /* AF_xxx */ u_int8_t version; /* nfnetlink version */ u_int16_t res_id; /* resource id */ -}; +} __attribute__ ((packed)); #define NFNETLINK_V0 0 diff --git a/trunk/include/linux/netfilter/nfnetlink_log.h b/trunk/include/linux/netfilter/nfnetlink_log.h index 87b92f8b988f..a7497c7436df 100644 --- a/trunk/include/linux/netfilter/nfnetlink_log.h +++ b/trunk/include/linux/netfilter/nfnetlink_log.h @@ -19,18 +19,18 @@ struct nfulnl_msg_packet_hdr { u_int16_t hw_protocol; /* hw protocol (network order) */ u_int8_t hook; /* netfilter hook */ u_int8_t _pad; -}; +} __attribute__ ((packed)); struct nfulnl_msg_packet_hw { u_int16_t hw_addrlen; u_int16_t _pad; u_int8_t hw_addr[8]; -}; +} __attribute__ ((packed)); struct nfulnl_msg_packet_timestamp { aligned_u64 sec; aligned_u64 usec; -}; +} __attribute__ ((packed)); #define NFULNL_PREFIXLEN 30 /* just like old log target */ diff --git a/trunk/include/linux/netfilter/nfnetlink_queue.h b/trunk/include/linux/netfilter/nfnetlink_queue.h index 36af0360b56d..9e774373244c 100644 --- a/trunk/include/linux/netfilter/nfnetlink_queue.h +++ b/trunk/include/linux/netfilter/nfnetlink_queue.h @@ -22,12 +22,12 @@ struct nfqnl_msg_packet_hw { u_int16_t hw_addrlen; u_int16_t _pad; u_int8_t hw_addr[8]; -}; +} __attribute__ ((packed)); struct nfqnl_msg_packet_timestamp { aligned_u64 sec; aligned_u64 usec; -}; +} __attribute__ ((packed)); enum nfqnl_attr_type { NFQA_UNSPEC, @@ -49,7 +49,7 @@ enum nfqnl_attr_type { struct nfqnl_msg_verdict_hdr { u_int32_t verdict; u_int32_t id; -}; +} __attribute__ ((packed)); enum nfqnl_msg_config_cmds { @@ -64,7 +64,7 @@ struct nfqnl_msg_config_cmd { u_int8_t command; /* nfqnl_msg_config_cmds */ u_int8_t _pad; u_int16_t pf; /* AF_xxx for PF_[UN]BIND */ -}; +} __attribute__ ((packed)); enum nfqnl_config_mode { NFQNL_COPY_NONE, diff --git a/trunk/include/linux/netfilter/x_tables.h b/trunk/include/linux/netfilter/x_tables.h index 739a98eebe2c..48cc32d83f77 100644 --- a/trunk/include/linux/netfilter/x_tables.h +++ b/trunk/include/linux/netfilter/x_tables.h @@ -138,6 +138,16 @@ struct xt_counters_info #include +#define ASSERT_READ_LOCK(x) +#define ASSERT_WRITE_LOCK(x) +#include + +#ifdef CONFIG_COMPAT +#define COMPAT_TO_USER 1 +#define COMPAT_FROM_USER -1 +#define COMPAT_CALC_SIZE 0 +#endif + struct xt_match { struct list_head list; @@ -164,24 +174,21 @@ struct xt_match const void *ip, const struct xt_match *match, void *matchinfo, + unsigned int matchinfosize, unsigned int hook_mask); /* Called when entry of this type deleted. */ - void (*destroy)(const struct xt_match *match, void *matchinfo); + void (*destroy)(const struct xt_match *match, void *matchinfo, + unsigned int matchinfosize); /* Called when userspace align differs from kernel space one */ - void (*compat_from_user)(void *dst, void *src); - int (*compat_to_user)(void __user *dst, void *src); + int (*compat)(void *match, void **dstptr, int *size, int convert); /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; - /* Free to use by each match */ - unsigned long data; - char *table; unsigned int matchsize; - unsigned int compatsize; unsigned int hooks; unsigned short proto; @@ -204,7 +211,8 @@ struct xt_target const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo); + const void *targinfo, + void *userdata); /* Called when user tries to insert an entry of this type: hook_mask is a bitmask of hooks from which it can be @@ -214,21 +222,21 @@ struct xt_target const void *entry, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask); /* Called when entry of this type deleted. */ - void (*destroy)(const struct xt_target *target, void *targinfo); + void (*destroy)(const struct xt_target *target, void *targinfo, + unsigned int targinfosize); /* Called when userspace align differs from kernel space one */ - void (*compat_from_user)(void *dst, void *src); - int (*compat_to_user)(void __user *dst, void *src); + int (*compat)(void *target, void **dstptr, int *size, int convert); /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; char *table; unsigned int targetsize; - unsigned int compatsize; unsigned int hooks; unsigned short proto; @@ -282,13 +290,8 @@ struct xt_table_info extern int xt_register_target(struct xt_target *target); extern void xt_unregister_target(struct xt_target *target); -extern int xt_register_targets(struct xt_target *target, unsigned int n); -extern void xt_unregister_targets(struct xt_target *target, unsigned int n); - extern int xt_register_match(struct xt_match *target); extern void xt_unregister_match(struct xt_match *target); -extern int xt_register_matches(struct xt_match *match, unsigned int n); -extern void xt_unregister_matches(struct xt_match *match, unsigned int n); extern int xt_check_match(const struct xt_match *match, unsigned short family, unsigned int size, const char *table, unsigned int hook, @@ -385,18 +388,9 @@ struct compat_xt_counters_info extern void xt_compat_lock(int af); extern void xt_compat_unlock(int af); - -extern int xt_compat_match_offset(struct xt_match *match); -extern void xt_compat_match_from_user(struct xt_entry_match *m, - void **dstptr, int *size); -extern int xt_compat_match_to_user(struct xt_entry_match *m, - void * __user *dstptr, int *size); - -extern int xt_compat_target_offset(struct xt_target *target); -extern void xt_compat_target_from_user(struct xt_entry_target *t, - void **dstptr, int *size); -extern int xt_compat_target_to_user(struct xt_entry_target *t, - void * __user *dstptr, int *size); +extern int xt_compat_match(void *match, void **dstptr, int *size, int convert); +extern int xt_compat_target(void *target, void **dstptr, int *size, + int convert); #endif /* CONFIG_COMPAT */ #endif /* __KERNEL__ */ diff --git a/trunk/include/linux/netfilter/xt_DSCP.h b/trunk/include/linux/netfilter/xt_DSCP.h deleted file mode 100644 index 3c7c963997bd..000000000000 --- a/trunk/include/linux/netfilter/xt_DSCP.h +++ /dev/null @@ -1,20 +0,0 @@ -/* x_tables module for setting the IPv4/IPv6 DSCP field - * - * (C) 2002 Harald Welte - * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh - * This software is distributed under GNU GPL v2, 1991 - * - * See RFC2474 for a description of the DSCP field within the IP Header. - * - * xt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp -*/ -#ifndef _XT_DSCP_TARGET_H -#define _XT_DSCP_TARGET_H -#include - -/* target info */ -struct xt_DSCP_info { - u_int8_t dscp; -}; - -#endif /* _XT_DSCP_TARGET_H */ diff --git a/trunk/include/linux/netfilter/xt_dscp.h b/trunk/include/linux/netfilter/xt_dscp.h deleted file mode 100644 index 1da61e6acaf7..000000000000 --- a/trunk/include/linux/netfilter/xt_dscp.h +++ /dev/null @@ -1,23 +0,0 @@ -/* x_tables module for matching the IPv4/IPv6 DSCP field - * - * (C) 2002 Harald Welte - * This software is distributed under GNU GPL v2, 1991 - * - * See RFC2474 for a description of the DSCP field within the IP Header. - * - * xt_dscp.h,v 1.3 2002/08/05 19:00:21 laforge Exp -*/ -#ifndef _XT_DSCP_H -#define _XT_DSCP_H - -#define XT_DSCP_MASK 0xfc /* 11111100 */ -#define XT_DSCP_SHIFT 2 -#define XT_DSCP_MAX 0x3f /* 00111111 */ - -/* match info */ -struct xt_dscp_info { - u_int8_t dscp; - u_int8_t invert; -}; - -#endif /* _XT_DSCP_H */ diff --git a/trunk/include/linux/netfilter_arp/Kbuild b/trunk/include/linux/netfilter_arp/Kbuild index 4f13dfcb92ea..198ec5e7b17d 100644 --- a/trunk/include/linux/netfilter_arp/Kbuild +++ b/trunk/include/linux/netfilter_arp/Kbuild @@ -1,3 +1,2 @@ -header-y += arpt_mangle.h - -unifdef-y += arp_tables.h +header-y := arpt_mangle.h +unifdef-y := arp_tables.h diff --git a/trunk/include/linux/netfilter_arp/arp_tables.h b/trunk/include/linux/netfilter_arp/arp_tables.h index 149e87c9ab13..62cc27daca4e 100644 --- a/trunk/include/linux/netfilter_arp/arp_tables.h +++ b/trunk/include/linux/netfilter_arp/arp_tables.h @@ -248,7 +248,8 @@ extern unsigned int arpt_do_table(struct sk_buff **pskb, unsigned int hook, const struct net_device *in, const struct net_device *out, - struct arpt_table *table); + struct arpt_table *table, + void *userdata); #define ARPT_ALIGN(s) (((s) + (__alignof__(struct arpt_entry)-1)) & ~(__alignof__(struct arpt_entry)-1)) #endif /*__KERNEL__*/ diff --git a/trunk/include/linux/netfilter_bridge.h b/trunk/include/linux/netfilter_bridge.h index 9a4dd11af86e..31f02ba036ce 100644 --- a/trunk/include/linux/netfilter_bridge.h +++ b/trunk/include/linux/netfilter_bridge.h @@ -5,8 +5,10 @@ */ #include +#if defined(__KERNEL__) && defined(CONFIG_BRIDGE_NETFILTER) +#include #include -#include +#endif /* Bridge Hooks */ /* After promisc drops, checksum checks. */ @@ -46,20 +48,30 @@ enum nf_br_hook_priorities { /* Only used in br_forward.c */ -extern int nf_bridge_copy_header(struct sk_buff *skb); -static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb) +static inline +void nf_bridge_maybe_copy_header(struct sk_buff *skb) { - if (skb->nf_bridge) - return nf_bridge_copy_header(skb); - return 0; + if (skb->nf_bridge) { + if (skb->protocol == __constant_htons(ETH_P_8021Q)) { + memcpy(skb->data - 18, skb->nf_bridge->data, 18); + skb_push(skb, 4); + } else + memcpy(skb->data - 16, skb->nf_bridge->data, 16); + } } /* This is called by the IP fragmenting code and it ensures there is * enough room for the encapsulating header (if there is one). */ -static inline int nf_bridge_pad(const struct sk_buff *skb) +static inline +int nf_bridge_pad(struct sk_buff *skb) { - return (skb->nf_bridge && skb->protocol == htons(ETH_P_8021Q)) - ? VLAN_HLEN : 0; + if (skb->protocol == __constant_htons(ETH_P_IP)) + return 0; + if (skb->nf_bridge) { + if (skb->protocol == __constant_htons(ETH_P_8021Q)) + return 4; + } + return 0; } struct bridge_skb_cb { @@ -69,9 +81,6 @@ struct bridge_skb_cb { }; extern int brnf_deferred_hooks; -#else -#define nf_bridge_maybe_copy_header(skb) (0) -#define nf_bridge_pad(skb) (0) #endif /* CONFIG_BRIDGE_NETFILTER */ #endif /* __KERNEL__ */ diff --git a/trunk/include/linux/netfilter_bridge/Kbuild b/trunk/include/linux/netfilter_bridge/Kbuild index 76ff4c47d8c4..5b1aba6abbad 100644 --- a/trunk/include/linux/netfilter_bridge/Kbuild +++ b/trunk/include/linux/netfilter_bridge/Kbuild @@ -1,17 +1,4 @@ -header-y += ebt_among.h -header-y += ebt_arp.h -header-y += ebt_arpreply.h -header-y += ebt_ip.h -header-y += ebt_limit.h -header-y += ebt_log.h -header-y += ebt_mark_m.h -header-y += ebt_mark_t.h -header-y += ebt_nat.h -header-y += ebt_pkttype.h -header-y += ebt_redirect.h -header-y += ebt_stp.h -header-y += ebt_ulog.h -header-y += ebt_vlan.h - -unifdef-y += ebtables.h -unifdef-y += ebt_802_3.h +header-y += ebt_among.h ebt_arp.h ebt_arpreply.h ebt_ip.h ebt_limit.h \ + ebt_log.h ebt_mark_m.h ebt_mark_t.h ebt_nat.h ebt_pkttype.h \ + ebt_redirect.h ebt_stp.h ebt_ulog.h ebt_vlan.h +unifdef-y := ebtables.h ebt_802_3.h diff --git a/trunk/include/linux/netfilter_ipv4/Kbuild b/trunk/include/linux/netfilter_ipv4/Kbuild index 591c1a809c00..04e4d2721689 100644 --- a/trunk/include/linux/netfilter_ipv4/Kbuild +++ b/trunk/include/linux/netfilter_ipv4/Kbuild @@ -1,63 +1,21 @@ -header-y += ip_conntrack_helper.h -header-y += ip_conntrack_helper_h323_asn1.h -header-y += ip_conntrack_helper_h323_types.h -header-y += ip_conntrack_protocol.h -header-y += ip_conntrack_sctp.h -header-y += ip_conntrack_tcp.h -header-y += ip_conntrack_tftp.h -header-y += ip_nat_pptp.h -header-y += ipt_addrtype.h -header-y += ipt_ah.h -header-y += ipt_CLASSIFY.h -header-y += ipt_CLUSTERIP.h -header-y += ipt_comment.h -header-y += ipt_connbytes.h -header-y += ipt_connmark.h -header-y += ipt_CONNMARK.h -header-y += ipt_conntrack.h -header-y += ipt_dccp.h -header-y += ipt_dscp.h -header-y += ipt_DSCP.h -header-y += ipt_ecn.h -header-y += ipt_ECN.h -header-y += ipt_esp.h -header-y += ipt_hashlimit.h -header-y += ipt_helper.h -header-y += ipt_iprange.h -header-y += ipt_length.h -header-y += ipt_limit.h -header-y += ipt_LOG.h -header-y += ipt_mac.h -header-y += ipt_mark.h -header-y += ipt_MARK.h -header-y += ipt_multiport.h -header-y += ipt_NFQUEUE.h -header-y += ipt_owner.h -header-y += ipt_physdev.h -header-y += ipt_pkttype.h -header-y += ipt_policy.h -header-y += ipt_realm.h -header-y += ipt_recent.h -header-y += ipt_REJECT.h -header-y += ipt_SAME.h -header-y += ipt_sctp.h -header-y += ipt_state.h -header-y += ipt_string.h -header-y += ipt_tcpmss.h -header-y += ipt_TCPMSS.h -header-y += ipt_tos.h -header-y += ipt_TOS.h -header-y += ipt_ttl.h -header-y += ipt_TTL.h -header-y += ipt_ULOG.h -unifdef-y += ip_conntrack.h -unifdef-y += ip_conntrack_h323.h -unifdef-y += ip_conntrack_irc.h -unifdef-y += ip_conntrack_pptp.h -unifdef-y += ip_conntrack_proto_gre.h -unifdef-y += ip_conntrack_tuple.h -unifdef-y += ip_nat.h -unifdef-y += ip_nat_rule.h -unifdef-y += ip_queue.h -unifdef-y += ip_tables.h +header-y := ip_conntrack_helper.h ip_conntrack_helper_h323_asn1.h \ + ip_conntrack_helper_h323_types.h ip_conntrack_protocol.h \ + ip_conntrack_sctp.h ip_conntrack_tcp.h ip_conntrack_tftp.h \ + ip_nat_pptp.h ipt_addrtype.h ipt_ah.h \ + ipt_CLASSIFY.h ipt_CLUSTERIP.h ipt_comment.h \ + ipt_connbytes.h ipt_connmark.h ipt_CONNMARK.h \ + ipt_conntrack.h ipt_dccp.h ipt_dscp.h ipt_DSCP.h ipt_ecn.h \ + ipt_ECN.h ipt_esp.h ipt_hashlimit.h ipt_helper.h \ + ipt_iprange.h ipt_length.h ipt_limit.h ipt_LOG.h ipt_mac.h \ + ipt_mark.h ipt_MARK.h ipt_multiport.h ipt_NFQUEUE.h \ + ipt_owner.h ipt_physdev.h ipt_pkttype.h ipt_policy.h \ + ipt_realm.h ipt_recent.h ipt_REJECT.h ipt_SAME.h \ + ipt_sctp.h ipt_state.h ipt_string.h ipt_tcpmss.h \ + ipt_TCPMSS.h ipt_tos.h ipt_TOS.h ipt_ttl.h ipt_TTL.h \ + ipt_ULOG.h + +unifdef-y := ip_conntrack.h ip_conntrack_h323.h ip_conntrack_irc.h \ + ip_conntrack_pptp.h ip_conntrack_proto_gre.h \ + ip_conntrack_tuple.h ip_nat.h ip_nat_rule.h ip_queue.h \ + ip_tables.h diff --git a/trunk/include/linux/netfilter_ipv4/ip_conntrack_helper.h b/trunk/include/linux/netfilter_ipv4/ip_conntrack_helper.h index 77fe868d36ff..8d69279ccfe4 100644 --- a/trunk/include/linux/netfilter_ipv4/ip_conntrack_helper.h +++ b/trunk/include/linux/netfilter_ipv4/ip_conntrack_helper.h @@ -25,8 +25,6 @@ struct ip_conntrack_helper struct ip_conntrack *ct, enum ip_conntrack_info conntrackinfo); - void (*destroy)(struct ip_conntrack *ct); - int (*to_nfattr)(struct sk_buff *skb, const struct ip_conntrack *ct); }; diff --git a/trunk/include/linux/netfilter_ipv4/ip_conntrack_pptp.h b/trunk/include/linux/netfilter_ipv4/ip_conntrack_pptp.h index 2644b1faddd6..816144c75de0 100644 --- a/trunk/include/linux/netfilter_ipv4/ip_conntrack_pptp.h +++ b/trunk/include/linux/netfilter_ipv4/ip_conntrack_pptp.h @@ -31,8 +31,8 @@ struct ip_ct_pptp_master { /* everything below is going to be per-expectation in newnat, * since there could be more than one call within one session */ enum pptp_ctrlcall_state cstate; /* call state */ - __be16 pac_call_id; /* call id of PAC, host byte order */ - __be16 pns_call_id; /* call id of PNS, host byte order */ + u_int16_t pac_call_id; /* call id of PAC, host byte order */ + u_int16_t pns_call_id; /* call id of PNS, host byte order */ /* in pre-2.6.11 this used to be per-expect. Now it is per-conntrack * and therefore imposes a fixed limit on the number of maps */ @@ -42,8 +42,8 @@ struct ip_ct_pptp_master { /* conntrack_expect private member */ struct ip_ct_pptp_expect { enum pptp_ctrlcall_state cstate; /* call state */ - __be16 pac_call_id; /* call id of PAC */ - __be16 pns_call_id; /* call id of PNS */ + u_int16_t pac_call_id; /* call id of PAC */ + u_int16_t pns_call_id; /* call id of PNS */ }; @@ -107,7 +107,8 @@ struct PptpControlHeader { struct PptpStartSessionRequest { __be16 protocolVersion; - __u16 reserved1; + __u8 reserved1; + __u8 reserved2; __be32 framingCapability; __be32 bearerCapability; __be16 maxChannels; @@ -142,8 +143,6 @@ struct PptpStartSessionReply { struct PptpStopSessionRequest { __u8 reason; - __u8 reserved1; - __u16 reserved2; }; /* PptpStopSessionResultCode */ @@ -153,7 +152,6 @@ struct PptpStopSessionRequest { struct PptpStopSessionReply { __u8 resultCode; __u8 generalErrorCode; - __u16 reserved1; }; struct PptpEchoRequest { @@ -190,8 +188,9 @@ struct PptpOutCallRequest { __be32 framingType; __be16 packetWindow; __be16 packetProcDelay; - __be16 phoneNumberLength; __u16 reserved1; + __be16 phoneNumberLength; + __u16 reserved2; __u8 phoneNumber[64]; __u8 subAddress[64]; }; @@ -286,19 +285,19 @@ struct PptpSetLinkInfo { }; union pptp_ctrl_union { - struct PptpStartSessionRequest sreq; - struct PptpStartSessionReply srep; - struct PptpStopSessionRequest streq; - struct PptpStopSessionReply strep; - struct PptpOutCallRequest ocreq; - struct PptpOutCallReply ocack; - struct PptpInCallRequest icreq; - struct PptpInCallReply icack; - struct PptpInCallConnected iccon; - struct PptpClearCallRequest clrreq; - struct PptpCallDisconnectNotify disc; - struct PptpWanErrorNotify wanerr; - struct PptpSetLinkInfo setlink; + struct PptpStartSessionRequest sreq; + struct PptpStartSessionReply srep; + struct PptpStopSessionRequest streq; + struct PptpStopSessionReply strep; + struct PptpOutCallRequest ocreq; + struct PptpOutCallReply ocack; + struct PptpInCallRequest icreq; + struct PptpInCallReply icack; + struct PptpInCallConnected iccon; + struct PptpClearCallRequest clrreq; + struct PptpCallDisconnectNotify disc; + struct PptpWanErrorNotify wanerr; + struct PptpSetLinkInfo setlink; }; extern int @@ -315,7 +314,7 @@ extern int struct PptpControlHeader *ctlh, union pptp_ctrl_union *pptpReq); -extern void +extern int (*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *exp_orig, struct ip_conntrack_expect *exp_reply); diff --git a/trunk/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h b/trunk/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h index 1d853aa873eb..8d090ef82f5f 100644 --- a/trunk/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h +++ b/trunk/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h @@ -49,18 +49,18 @@ struct gre_hdr { #else #error "Adjust your defines" #endif - __be16 protocol; + __u16 protocol; }; /* modified GRE header for PPTP */ struct gre_hdr_pptp { - __u8 flags; /* bitfield */ - __u8 version; /* should be GRE_VERSION_PPTP */ - __be16 protocol; /* should be GRE_PROTOCOL_PPTP */ - __be16 payload_len; /* size of ppp payload, not inc. gre header */ - __be16 call_id; /* peer's call_id for this session */ - __be32 seq; /* sequence number. Present if S==1 */ - __be32 ack; /* seq number of highest packet recieved by */ + __u8 flags; /* bitfield */ + __u8 version; /* should be GRE_VERSION_PPTP */ + __u16 protocol; /* should be GRE_PROTOCOL_PPTP */ + __u16 payload_len; /* size of ppp payload, not inc. gre header */ + __u16 call_id; /* peer's call_id for this session */ + __u32 seq; /* sequence number. Present if S==1 */ + __u32 ack; /* seq number of highest packet recieved by */ /* sender in this session */ }; @@ -92,13 +92,13 @@ void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct); /* get pointer to gre key, if present */ -static inline __be32 *gre_key(struct gre_hdr *greh) +static inline u_int32_t *gre_key(struct gre_hdr *greh) { if (!greh->key) return NULL; if (greh->csum || greh->routing) - return (__be32 *) (greh+sizeof(*greh)+4); - return (__be32 *) (greh+sizeof(*greh)); + return (u_int32_t *) (greh+sizeof(*greh)+4); + return (u_int32_t *) (greh+sizeof(*greh)); } /* get pointer ot gre csum, if present */ diff --git a/trunk/include/linux/netfilter_ipv4/ip_nat.h b/trunk/include/linux/netfilter_ipv4/ip_nat.h index 98f8407e4cb5..e9f5ed1d9f68 100644 --- a/trunk/include/linux/netfilter_ipv4/ip_nat.h +++ b/trunk/include/linux/netfilter_ipv4/ip_nat.h @@ -72,6 +72,10 @@ extern unsigned int ip_nat_setup_info(struct ip_conntrack *conntrack, extern int ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple, const struct ip_conntrack *ignored_conntrack); +/* Calculate relative checksum. */ +extern u_int16_t ip_nat_cheat_check(u_int32_t oldvalinv, + u_int32_t newval, + u_int16_t oldcheck); #else /* !__KERNEL__: iptables wants this to compile. */ #define ip_nat_multi_range ip_nat_multi_range_compat #endif /*__KERNEL__*/ diff --git a/trunk/include/linux/netfilter_ipv4/ip_nat_core.h b/trunk/include/linux/netfilter_ipv4/ip_nat_core.h index 60566f9fd7b3..30db23f06b03 100644 --- a/trunk/include/linux/netfilter_ipv4/ip_nat_core.h +++ b/trunk/include/linux/netfilter_ipv4/ip_nat_core.h @@ -11,8 +11,8 @@ extern unsigned int ip_nat_packet(struct ip_conntrack *ct, unsigned int hooknum, struct sk_buff **pskb); -extern int ip_nat_icmp_reply_translation(struct ip_conntrack *ct, - enum ip_conntrack_info ctinfo, - unsigned int hooknum, - struct sk_buff **pskb); +extern int ip_nat_icmp_reply_translation(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_nat_manip_type manip, + enum ip_conntrack_dir dir); #endif /* _IP_NAT_CORE_H */ diff --git a/trunk/include/linux/netfilter_ipv4/ip_nat_pptp.h b/trunk/include/linux/netfilter_ipv4/ip_nat_pptp.h index 36668bf0f373..eaf66c2e8f93 100644 --- a/trunk/include/linux/netfilter_ipv4/ip_nat_pptp.h +++ b/trunk/include/linux/netfilter_ipv4/ip_nat_pptp.h @@ -4,8 +4,8 @@ /* conntrack private data */ struct ip_nat_pptp { - __be16 pns_call_id; /* NAT'ed PNS call id */ - __be16 pac_call_id; /* NAT'ed PAC call id */ + u_int16_t pns_call_id; /* NAT'ed PNS call id */ + u_int16_t pac_call_id; /* NAT'ed PAC call id */ }; #endif /* _NAT_PPTP_H */ diff --git a/trunk/include/linux/netfilter_ipv4/ip_tables.h b/trunk/include/linux/netfilter_ipv4/ip_tables.h index a536bbdef145..c0dac16e1902 100644 --- a/trunk/include/linux/netfilter_ipv4/ip_tables.h +++ b/trunk/include/linux/netfilter_ipv4/ip_tables.h @@ -312,7 +312,8 @@ extern unsigned int ipt_do_table(struct sk_buff **pskb, unsigned int hook, const struct net_device *in, const struct net_device *out, - struct ipt_table *table); + struct ipt_table *table, + void *userdata); #define IPT_ALIGN(s) XT_ALIGN(s) diff --git a/trunk/include/linux/netfilter_ipv4/ipt_DSCP.h b/trunk/include/linux/netfilter_ipv4/ipt_DSCP.h index 3491e524d5ea..b30f510b5bef 100644 --- a/trunk/include/linux/netfilter_ipv4/ipt_DSCP.h +++ b/trunk/include/linux/netfilter_ipv4/ipt_DSCP.h @@ -11,8 +11,10 @@ #ifndef _IPT_DSCP_TARGET_H #define _IPT_DSCP_TARGET_H #include -#include -#define ipt_DSCP_info xt_DSCP_info +/* target info */ +struct ipt_DSCP_info { + u_int8_t dscp; +}; #endif /* _IPT_DSCP_TARGET_H */ diff --git a/trunk/include/linux/netfilter_ipv4/ipt_dscp.h b/trunk/include/linux/netfilter_ipv4/ipt_dscp.h index 4b82ca912b0e..2fa6dfe92894 100644 --- a/trunk/include/linux/netfilter_ipv4/ipt_dscp.h +++ b/trunk/include/linux/netfilter_ipv4/ipt_dscp.h @@ -10,12 +10,14 @@ #ifndef _IPT_DSCP_H #define _IPT_DSCP_H -#include +#define IPT_DSCP_MASK 0xfc /* 11111100 */ +#define IPT_DSCP_SHIFT 2 +#define IPT_DSCP_MAX 0x3f /* 00111111 */ -#define IPT_DSCP_MASK XT_DSCP_MASK -#define IPT_DSCP_SHIFT XT_DSCP_SHIFT -#define IPT_DSCP_MAX XT_DSCP_MAX - -#define ipt_dscp_info xt_dscp_info +/* match info */ +struct ipt_dscp_info { + u_int8_t dscp; + u_int8_t invert; +}; #endif /* _IPT_DSCP_H */ diff --git a/trunk/include/linux/netfilter_ipv4/listhelp.h b/trunk/include/linux/netfilter_ipv4/listhelp.h new file mode 100644 index 000000000000..5d92cf044d91 --- /dev/null +++ b/trunk/include/linux/netfilter_ipv4/listhelp.h @@ -0,0 +1,123 @@ +#ifndef _LISTHELP_H +#define _LISTHELP_H +#include + +/* Header to do more comprehensive job than linux/list.h; assume list + is first entry in structure. */ + +/* Return pointer to first true entry, if any, or NULL. A macro + required to allow inlining of cmpfn. */ +#define LIST_FIND(head, cmpfn, type, args...) \ +({ \ + const struct list_head *__i, *__j = NULL; \ + \ + ASSERT_READ_LOCK(head); \ + list_for_each(__i, (head)) \ + if (cmpfn((const type)__i , ## args)) { \ + __j = __i; \ + break; \ + } \ + (type)__j; \ +}) + +#define LIST_FIND_W(head, cmpfn, type, args...) \ +({ \ + const struct list_head *__i, *__j = NULL; \ + \ + ASSERT_WRITE_LOCK(head); \ + list_for_each(__i, (head)) \ + if (cmpfn((type)__i , ## args)) { \ + __j = __i; \ + break; \ + } \ + (type)__j; \ +}) + +/* Just like LIST_FIND but we search backwards */ +#define LIST_FIND_B(head, cmpfn, type, args...) \ +({ \ + const struct list_head *__i, *__j = NULL; \ + \ + ASSERT_READ_LOCK(head); \ + list_for_each_prev(__i, (head)) \ + if (cmpfn((const type)__i , ## args)) { \ + __j = __i; \ + break; \ + } \ + (type)__j; \ +}) + +static inline int +__list_cmp_same(const void *p1, const void *p2) { return p1 == p2; } + +/* Is this entry in the list? */ +static inline int +list_inlist(struct list_head *head, const void *entry) +{ + return LIST_FIND(head, __list_cmp_same, void *, entry) != NULL; +} + +/* Delete from list. */ +#ifdef CONFIG_NETFILTER_DEBUG +#define LIST_DELETE(head, oldentry) \ +do { \ + ASSERT_WRITE_LOCK(head); \ + if (!list_inlist(head, oldentry)) \ + printk("LIST_DELETE: %s:%u `%s'(%p) not in %s.\n", \ + __FILE__, __LINE__, #oldentry, oldentry, #head); \ + else list_del((struct list_head *)oldentry); \ +} while(0) +#else +#define LIST_DELETE(head, oldentry) list_del((struct list_head *)oldentry) +#endif + +/* Append. */ +static inline void +list_append(struct list_head *head, void *new) +{ + ASSERT_WRITE_LOCK(head); + list_add((new), (head)->prev); +} + +/* Prepend. */ +static inline void +list_prepend(struct list_head *head, void *new) +{ + ASSERT_WRITE_LOCK(head); + list_add(new, head); +} + +/* Insert according to ordering function; insert before first true. */ +#define LIST_INSERT(head, new, cmpfn) \ +do { \ + struct list_head *__i; \ + ASSERT_WRITE_LOCK(head); \ + list_for_each(__i, (head)) \ + if ((new), (typeof (new))__i) \ + break; \ + list_add((struct list_head *)(new), __i->prev); \ +} while(0) + +/* If the field after the list_head is a nul-terminated string, you + can use these functions. */ +static inline int __list_cmp_name(const void *i, const char *name) +{ + return strcmp(name, i+sizeof(struct list_head)) == 0; +} + +/* Returns false if same name already in list, otherwise does insert. */ +static inline int +list_named_insert(struct list_head *head, void *new) +{ + if (LIST_FIND(head, __list_cmp_name, void *, + new + sizeof(struct list_head))) + return 0; + list_prepend(head, new); + return 1; +} + +/* Find this named element in the list. */ +#define list_named_find(head, name) \ +LIST_FIND(head, __list_cmp_name, void *, name) + +#endif /*_LISTHELP_H*/ diff --git a/trunk/include/linux/netfilter_ipv6.h b/trunk/include/linux/netfilter_ipv6.h index d97e268cdfe5..52a7b9e76428 100644 --- a/trunk/include/linux/netfilter_ipv6.h +++ b/trunk/include/linux/netfilter_ipv6.h @@ -73,7 +73,6 @@ enum nf_ip6_hook_priorities { }; #ifdef CONFIG_NETFILTER -extern int ip6_route_me_harder(struct sk_buff *skb); extern unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol); diff --git a/trunk/include/linux/netfilter_ipv6/Kbuild b/trunk/include/linux/netfilter_ipv6/Kbuild index 9dd978d149ff..913ddbf55b4b 100644 --- a/trunk/include/linux/netfilter_ipv6/Kbuild +++ b/trunk/include/linux/netfilter_ipv6/Kbuild @@ -1,21 +1,6 @@ -header-y += ip6t_HL.h -header-y += ip6t_LOG.h -header-y += ip6t_MARK.h -header-y += ip6t_REJECT.h -header-y += ip6t_ah.h -header-y += ip6t_esp.h -header-y += ip6t_frag.h -header-y += ip6t_hl.h -header-y += ip6t_ipv6header.h -header-y += ip6t_length.h -header-y += ip6t_limit.h -header-y += ip6t_mac.h -header-y += ip6t_mark.h -header-y += ip6t_multiport.h -header-y += ip6t_opts.h -header-y += ip6t_owner.h -header-y += ip6t_policy.h -header-y += ip6t_physdev.h -header-y += ip6t_rt.h - -unifdef-y += ip6_tables.h +header-y += ip6t_HL.h ip6t_LOG.h ip6t_MARK.h ip6t_REJECT.h ip6t_ah.h \ + ip6t_esp.h ip6t_frag.h ip6t_hl.h ip6t_ipv6header.h \ + ip6t_length.h ip6t_limit.h ip6t_mac.h ip6t_mark.h \ + ip6t_multiport.h ip6t_opts.h ip6t_owner.h ip6t_policy.h \ + ip6t_physdev.h ip6t_rt.h +unifdef-y := ip6_tables.h diff --git a/trunk/include/linux/netfilter_ipv6/ip6_tables.h b/trunk/include/linux/netfilter_ipv6/ip6_tables.h index d7a8e9c0dad0..d0d5d1ee4be3 100644 --- a/trunk/include/linux/netfilter_ipv6/ip6_tables.h +++ b/trunk/include/linux/netfilter_ipv6/ip6_tables.h @@ -300,7 +300,8 @@ extern unsigned int ip6t_do_table(struct sk_buff **pskb, unsigned int hook, const struct net_device *in, const struct net_device *out, - struct ip6t_table *table); + struct ip6t_table *table, + void *userdata); /* Check for an extension */ extern int ip6t_ext_hdr(u8 nexthdr); diff --git a/trunk/include/linux/netfilter_logging.h b/trunk/include/linux/netfilter_logging.h new file mode 100644 index 000000000000..562bb6aad4e1 --- /dev/null +++ b/trunk/include/linux/netfilter_logging.h @@ -0,0 +1,33 @@ +/* Internal logging interface, which relies on the real + LOG target modules */ +#ifndef __LINUX_NETFILTER_LOGGING_H +#define __LINUX_NETFILTER_LOGGING_H + +#ifdef __KERNEL__ +#include + +struct nf_logging_t { + void (*nf_log_packet)(struct sk_buff **pskb, + unsigned int hooknum, + const struct net_device *in, + const struct net_device *out, + const char *prefix); + void (*nf_log)(char *pfh, size_t len, + const char *prefix); +}; + +extern void nf_log_register(int pf, const struct nf_logging_t *logging); +extern void nf_log_unregister(int pf, const struct nf_logging_t *logging); + +extern void nf_log_packet(int pf, + struct sk_buff **pskb, + unsigned int hooknum, + const struct net_device *in, + const struct net_device *out, + const char *fmt, ...); +extern void nf_log(int pf, + char *pfh, size_t len, + const char *fmt, ...); +#endif /*__KERNEL__*/ + +#endif /*__LINUX_NETFILTER_LOGGING_H*/ diff --git a/trunk/include/linux/nfs_fs.h b/trunk/include/linux/nfs_fs.h index 3b5b04193fee..55ea853d57bc 100644 --- a/trunk/include/linux/nfs_fs.h +++ b/trunk/include/linux/nfs_fs.h @@ -9,6 +9,27 @@ #ifndef _LINUX_NFS_FS_H #define _LINUX_NFS_FS_H +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + /* * Enable debugging support for nfs client. * Requires RPC_DEBUG. @@ -26,6 +47,11 @@ */ #define NFS_SUPER_MAGIC 0x6969 +/* + * These are the default flags for swap requests + */ +#define NFS_RPC_SWAPFLAGS (RPC_TASK_SWAPPER|RPC_TASK_ROOTCREDS) + /* * When flushing a cluster of dirty pages, there can be different * strategies: @@ -39,39 +65,10 @@ #ifdef __KERNEL__ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include - -/* - * These are the default flags for swap requests - */ -#define NFS_RPC_SWAPFLAGS (RPC_TASK_SWAPPER|RPC_TASK_ROOTCREDS) - /* * NFSv3/v4 Access mode cache entry */ struct nfs_access_entry { - struct rb_node rb_node; - struct list_head lru; unsigned long jiffies; struct rpc_cred * cred; int mask; @@ -148,9 +145,7 @@ struct nfs_inode { */ atomic_t data_updates; - struct rb_root access_cache; - struct list_head access_cache_entry_lru; - struct list_head access_cache_inode_lru; + struct nfs_access_entry cache_access; #ifdef CONFIG_NFS_V3_ACL struct posix_acl *acl_access; struct posix_acl *acl_default; @@ -204,7 +199,6 @@ struct nfs_inode { #define NFS_INO_REVALIDATING (0) /* revalidating attrs */ #define NFS_INO_ADVISE_RDPLUS (1) /* advise readdirplus */ #define NFS_INO_STALE (2) /* possible stale inode */ -#define NFS_INO_ACL_LRU_SET (3) /* Inode is on the LRU list */ static inline struct nfs_inode *NFS_I(struct inode *inode) { @@ -215,7 +209,8 @@ static inline struct nfs_inode *NFS_I(struct inode *inode) #define NFS_FH(inode) (&NFS_I(inode)->fh) #define NFS_SERVER(inode) (NFS_SB(inode->i_sb)) #define NFS_CLIENT(inode) (NFS_SERVER(inode)->client) -#define NFS_PROTO(inode) (NFS_SERVER(inode)->nfs_client->rpc_ops) +#define NFS_PROTO(inode) (NFS_SERVER(inode)->rpc_ops) +#define NFS_ADDR(inode) (RPC_PEERADDR(NFS_CLIENT(inode))) #define NFS_COOKIEVERF(inode) (NFS_I(inode)->cookieverf) #define NFS_READTIME(inode) (NFS_I(inode)->read_cache_jiffies) #define NFS_CHANGE_ATTR(inode) (NFS_I(inode)->change_attr) @@ -302,7 +297,6 @@ extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); extern int nfs_permission(struct inode *, int, struct nameidata *); extern int nfs_access_get_cached(struct inode *, struct rpc_cred *, struct nfs_access_entry *); extern void nfs_access_add_cache(struct inode *, struct nfs_access_entry *); -extern void nfs_access_zap_cache(struct inode *inode); extern int nfs_open(struct inode *, struct file *); extern int nfs_release(struct inode *, struct file *); extern int nfs_attribute_timeout(struct inode *inode); @@ -433,7 +427,7 @@ extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *); extern void nfs_writedata_release(void *); #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) -struct nfs_write_data *nfs_commit_alloc(void); +struct nfs_write_data *nfs_commit_alloc(unsigned int pagecount); void nfs_commit_free(struct nfs_write_data *p); #endif @@ -482,9 +476,10 @@ static inline int nfs_wb_page(struct inode *inode, struct page* page) } /* - * Allocate nfs_write_data structures + * Allocate and free nfs_write_data structures */ -extern struct nfs_write_data *nfs_writedata_alloc(size_t len); +extern struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount); +extern void nfs_writedata_free(struct nfs_write_data *p); /* * linux/fs/nfs/read.c @@ -496,9 +491,10 @@ extern int nfs_readpage_result(struct rpc_task *, struct nfs_read_data *); extern void nfs_readdata_release(void *data); /* - * Allocate nfs_read_data structures + * Allocate and free nfs_read_data structures */ -extern struct nfs_read_data *nfs_readdata_alloc(size_t len); +extern struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount); +extern void nfs_readdata_free(struct nfs_read_data *p); /* * linux/fs/nfs3proc.c @@ -585,7 +581,6 @@ extern void * nfs_root_data(void); #define NFSDBG_FILE 0x0040 #define NFSDBG_ROOT 0x0080 #define NFSDBG_CALLBACK 0x0100 -#define NFSDBG_CLIENT 0x0200 #define NFSDBG_ALL 0xFFFF #ifdef __KERNEL__ diff --git a/trunk/include/linux/nfs_fs_sb.h b/trunk/include/linux/nfs_fs_sb.h index 7ccfc7ef0a83..6b4a13c79474 100644 --- a/trunk/include/linux/nfs_fs_sb.h +++ b/trunk/include/linux/nfs_fs_sb.h @@ -6,80 +6,14 @@ struct nfs_iostats; -/* - * The nfs_client identifies our client state to the server. - */ -struct nfs_client { - atomic_t cl_count; - int cl_cons_state; /* current construction state (-ve: init error) */ -#define NFS_CS_READY 0 /* ready to be used */ -#define NFS_CS_INITING 1 /* busy initialising */ - int cl_nfsversion; /* NFS protocol version */ - unsigned long cl_res_state; /* NFS resources state */ -#define NFS_CS_RPCIOD 0 /* - rpciod started */ -#define NFS_CS_CALLBACK 1 /* - callback started */ -#define NFS_CS_IDMAP 2 /* - idmap started */ -#define NFS_CS_RENEWD 3 /* - renewd started */ - struct sockaddr_in cl_addr; /* server identifier */ - char * cl_hostname; /* hostname of server */ - struct list_head cl_share_link; /* link in global client list */ - struct list_head cl_superblocks; /* List of nfs_server structs */ - - struct rpc_clnt * cl_rpcclient; - const struct nfs_rpc_ops *rpc_ops; /* NFS protocol vector */ - unsigned long retrans_timeo; /* retransmit timeout */ - unsigned int retrans_count; /* number of retransmit tries */ - -#ifdef CONFIG_NFS_V4 - u64 cl_clientid; /* constant */ - nfs4_verifier cl_confirm; - unsigned long cl_state; - - u32 cl_lockowner_id; - - /* - * The following rwsem ensures exclusive access to the server - * while we recover the state following a lease expiration. - */ - struct rw_semaphore cl_sem; - - struct list_head cl_delegations; - struct list_head cl_state_owners; - struct list_head cl_unused; - int cl_nunused; - spinlock_t cl_lock; - - unsigned long cl_lease_time; - unsigned long cl_last_renewal; - struct work_struct cl_renewd; - - struct rpc_wait_queue cl_rpcwaitq; - - /* used for the setclientid verifier */ - struct timespec cl_boot_time; - - /* idmapper */ - struct idmap * cl_idmap; - - /* Our own IP address, as a null-terminated string. - * This is used to generate the clientid, and the callback address. - */ - char cl_ipaddr[16]; - unsigned char cl_id_uniquifier; -#endif -}; - /* * NFS client parameters stored in the superblock. */ struct nfs_server { - struct nfs_client * nfs_client; /* shared client and NFS4 state */ - struct list_head client_link; /* List of other nfs_server structs - * that share the same client - */ - struct list_head master_link; /* link in master servers list */ struct rpc_clnt * client; /* RPC client handle */ + struct rpc_clnt * client_sys; /* 2nd handle for FSINFO */ struct rpc_clnt * client_acl; /* ACL RPC client handle */ + struct nfs_rpc_ops * rpc_ops; /* NFS protocol vector */ struct nfs_iostats * io_stats; /* I/O statistics */ struct backing_dev_info backing_dev_info; int flags; /* various flags */ @@ -95,14 +29,24 @@ struct nfs_server { unsigned int acregmax; unsigned int acdirmin; unsigned int acdirmax; + unsigned long retrans_timeo; /* retransmit timeout */ + unsigned int retrans_count; /* number of retransmit tries */ unsigned int namelen; - + char * hostname; /* remote hostname */ + struct nfs_fh fh; + struct sockaddr_in addr; struct nfs_fsid fsid; - __u64 maxfilesize; /* maximum file size */ unsigned long mount_time; /* when this fs was mounted */ - dev_t s_dev; /* superblock dev numbers */ - #ifdef CONFIG_NFS_V4 + /* Our own IP address, as a null-terminated string. + * This is used to generate the clientid, and the callback address. + */ + char ip_addr[16]; + char * mnt_path; + struct nfs4_client * nfs4_state; /* all NFSv4 state starts here */ + struct list_head nfs4_siblings; /* List of other nfs_server structs + * that share the same clientid + */ u32 attr_bitmask[2];/* V4 bitmask representing the set of attributes supported on this filesystem */ @@ -110,7 +54,6 @@ struct nfs_server { that are supported on this filesystem */ #endif - void (*destroy)(struct nfs_server *); }; /* Server capabilities */ diff --git a/trunk/include/linux/nfs_idmap.h b/trunk/include/linux/nfs_idmap.h index 15a9f3b7289a..102e56094296 100644 --- a/trunk/include/linux/nfs_idmap.h +++ b/trunk/include/linux/nfs_idmap.h @@ -62,15 +62,15 @@ struct idmap_msg { #ifdef __KERNEL__ /* Forward declaration to make this header independent of others */ -struct nfs_client; +struct nfs4_client; -int nfs_idmap_new(struct nfs_client *); -void nfs_idmap_delete(struct nfs_client *); +void nfs_idmap_new(struct nfs4_client *); +void nfs_idmap_delete(struct nfs4_client *); -int nfs_map_name_to_uid(struct nfs_client *, const char *, size_t, __u32 *); -int nfs_map_group_to_gid(struct nfs_client *, const char *, size_t, __u32 *); -int nfs_map_uid_to_name(struct nfs_client *, __u32, char *); -int nfs_map_gid_to_group(struct nfs_client *, __u32, char *); +int nfs_map_name_to_uid(struct nfs4_client *, const char *, size_t, __u32 *); +int nfs_map_group_to_gid(struct nfs4_client *, const char *, size_t, __u32 *); +int nfs_map_uid_to_name(struct nfs4_client *, __u32, char *); +int nfs_map_gid_to_group(struct nfs4_client *, __u32, char *); extern unsigned int nfs_idmap_cache_timeout; #endif /* __KERNEL__ */ diff --git a/trunk/include/linux/nfs_xdr.h b/trunk/include/linux/nfs_xdr.h index dc5397d9d23c..2d3fb6416d91 100644 --- a/trunk/include/linux/nfs_xdr.h +++ b/trunk/include/linux/nfs_xdr.h @@ -1,6 +1,7 @@ #ifndef _LINUX_NFS_XDR_H #define _LINUX_NFS_XDR_H +#include #include /* @@ -358,8 +359,8 @@ struct nfs_symlinkargs { struct nfs_fh * fromfh; const char * fromname; unsigned int fromlen; - struct page ** pages; - unsigned int pathlen; + const char * topath; + unsigned int tolen; struct iattr * sattr; }; @@ -434,8 +435,8 @@ struct nfs3_symlinkargs { struct nfs_fh * fromfh; const char * fromname; unsigned int fromlen; - struct page ** pages; - unsigned int pathlen; + const char * topath; + unsigned int tolen; struct iattr * sattr; }; @@ -533,10 +534,7 @@ struct nfs4_accessres { struct nfs4_create_arg { u32 ftype; union { - struct { - struct page ** pages; - unsigned int len; - } symlink; /* NF4LNK */ + struct qstr * symlink; /* NF4LNK */ struct { u32 specdata1; u32 specdata2; @@ -661,7 +659,7 @@ struct nfs4_rename_res { struct nfs4_setclientid { const nfs4_verifier * sc_verifier; /* request */ unsigned int sc_name_len; - char sc_name[48]; /* request */ + char sc_name[32]; /* request */ u32 sc_prog; /* request */ unsigned int sc_netid_len; char sc_netid[4]; /* request */ @@ -731,7 +729,7 @@ struct nfs_read_data { struct list_head pages; /* Coalesced read requests */ struct nfs_page *req; /* multi ops per nfs_page */ struct page **pagevec; - unsigned int npages; /* Max length of pagevec */ + unsigned int npages; /* active pages in pagevec */ struct nfs_readargs args; struct nfs_readres res; #ifdef CONFIG_NFS_V4 @@ -750,7 +748,7 @@ struct nfs_write_data { struct list_head pages; /* Coalesced requests we wish to flush */ struct nfs_page *req; /* multi ops per nfs_page */ struct page **pagevec; - unsigned int npages; /* Max length of pagevec */ + unsigned int npages; /* active pages in pagevec */ struct nfs_writeargs args; /* argument struct */ struct nfs_writeres res; /* result struct */ #ifdef CONFIG_NFS_V4 @@ -772,9 +770,6 @@ struct nfs_rpc_ops { int (*getroot) (struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); - int (*lookupfh)(struct nfs_server *, struct nfs_fh *, - struct qstr *, struct nfs_fh *, - struct nfs_fattr *); int (*getattr) (struct nfs_server *, struct nfs_fh *, struct nfs_fattr *); int (*setattr) (struct dentry *, struct nfs_fattr *, @@ -796,8 +791,9 @@ struct nfs_rpc_ops { int (*rename) (struct inode *, struct qstr *, struct inode *, struct qstr *); int (*link) (struct inode *, struct inode *, struct qstr *); - int (*symlink) (struct inode *, struct dentry *, struct page *, - unsigned int, struct iattr *); + int (*symlink) (struct inode *, struct qstr *, struct qstr *, + struct iattr *, struct nfs_fh *, + struct nfs_fattr *); int (*mkdir) (struct inode *, struct dentry *, struct iattr *); int (*rmdir) (struct inode *, struct qstr *); int (*readdir) (struct dentry *, struct rpc_cred *, @@ -810,7 +806,6 @@ struct nfs_rpc_ops { struct nfs_fsinfo *); int (*pathconf) (struct nfs_server *, struct nfs_fh *, struct nfs_pathconf *); - int (*set_capabilities)(struct nfs_server *, struct nfs_fh *); u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus); void (*read_setup) (struct nfs_read_data *); int (*read_done) (struct rpc_task *, struct nfs_read_data *); @@ -834,9 +829,9 @@ struct nfs_rpc_ops { /* * Function vectors etc. for the NFS client */ -extern const struct nfs_rpc_ops nfs_v2_clientops; -extern const struct nfs_rpc_ops nfs_v3_clientops; -extern const struct nfs_rpc_ops nfs_v4_clientops; +extern struct nfs_rpc_ops nfs_v2_clientops; +extern struct nfs_rpc_ops nfs_v3_clientops; +extern struct nfs_rpc_ops nfs_v4_clientops; extern struct rpc_version nfs_version2; extern struct rpc_version nfs_version3; extern struct rpc_version nfs_version4; diff --git a/trunk/include/linux/nfsd/Kbuild b/trunk/include/linux/nfsd/Kbuild index d9c5455808e5..c8c545665885 100644 --- a/trunk/include/linux/nfsd/Kbuild +++ b/trunk/include/linux/nfsd/Kbuild @@ -1,7 +1,2 @@ -unifdef-y += const.h -unifdef-y += export.h -unifdef-y += stats.h -unifdef-y += syscall.h -unifdef-y += nfsfh.h -unifdef-y += debug.h -unifdef-y += auth.h +unifdef-y := const.h export.h stats.h syscall.h nfsfh.h debug.h auth.h + diff --git a/trunk/include/linux/node.h b/trunk/include/linux/node.h index bc001bc225c3..81dcec84cd8f 100644 --- a/trunk/include/linux/node.h +++ b/trunk/include/linux/node.h @@ -30,20 +30,12 @@ extern struct node node_devices[]; extern int register_node(struct node *, int, struct node *); extern void unregister_node(struct node *node); -#ifdef CONFIG_NUMA extern int register_one_node(int nid); extern void unregister_one_node(int nid); +#ifdef CONFIG_NUMA extern int register_cpu_under_node(unsigned int cpu, unsigned int nid); extern int unregister_cpu_under_node(unsigned int cpu, unsigned int nid); #else -static inline int register_one_node(int nid) -{ - return 0; -} -static inline int unregister_one_node(int nid) -{ - return 0; -} static inline int register_cpu_under_node(unsigned int cpu, unsigned int nid) { return 0; diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index 7a249155ee4e..c09396d2c77b 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -648,8 +648,6 @@ #define PCI_DEVICE_ID_SI_962 0x0962 #define PCI_DEVICE_ID_SI_963 0x0963 #define PCI_DEVICE_ID_SI_965 0x0965 -#define PCI_DEVICE_ID_SI_966 0x0966 -#define PCI_DEVICE_ID_SI_968 0x0968 #define PCI_DEVICE_ID_SI_5511 0x5511 #define PCI_DEVICE_ID_SI_5513 0x5513 #define PCI_DEVICE_ID_SI_5517 0x5517 @@ -1294,7 +1292,6 @@ #define PCI_DEVICE_ID_VIA_8367_0 0x3099 #define PCI_DEVICE_ID_VIA_8653_0 0x3101 #define PCI_DEVICE_ID_VIA_8622 0x3102 -#define PCI_DEVICE_ID_VIA_8235_USB_2 0x3104 #define PCI_DEVICE_ID_VIA_8233C_0 0x3109 #define PCI_DEVICE_ID_VIA_8361 0x3112 #define PCI_DEVICE_ID_VIA_XM266 0x3116 @@ -1729,9 +1726,6 @@ #define PCI_VENDOR_ID_DOMEX 0x134a #define PCI_DEVICE_ID_DOMEX_DMX3191D 0x0001 -#define PCI_VENDOR_ID_INTASHIELD 0x135a -#define PCI_DEVICE_ID_INTASHIELD_IS200 0x0d80 - #define PCI_VENDOR_ID_QUATECH 0x135C #define PCI_DEVICE_ID_QUATECH_QSC100 0x0010 #define PCI_DEVICE_ID_QUATECH_DSC100 0x0020 @@ -2148,7 +2142,6 @@ #define PCI_DEVICE_ID_INTEL_82820_UP_HB 0x2501 #define PCI_DEVICE_ID_INTEL_82850_HB 0x2530 #define PCI_DEVICE_ID_INTEL_82860_HB 0x2531 -#define PCI_DEVICE_ID_INTEL_E7501_MCH 0x254c #define PCI_DEVICE_ID_INTEL_82845G_HB 0x2560 #define PCI_DEVICE_ID_INTEL_82845G_IG 0x2562 #define PCI_DEVICE_ID_INTEL_82865_HB 0x2570 diff --git a/trunk/include/linux/phy.h b/trunk/include/linux/phy.h index 9447a57ee8a9..331521a10a2d 100644 --- a/trunk/include/linux/phy.h +++ b/trunk/include/linux/phy.h @@ -378,7 +378,6 @@ int phy_mii_ioctl(struct phy_device *phydev, struct mii_ioctl_data *mii_data, int cmd); int phy_start_interrupts(struct phy_device *phydev); void phy_print_status(struct phy_device *phydev); -struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id); extern struct bus_type mdio_bus_type; #endif /* __PHY_H */ diff --git a/trunk/include/linux/pkt_cls.h b/trunk/include/linux/pkt_cls.h index c3f01b3085a4..bd2c5a2bbbf5 100644 --- a/trunk/include/linux/pkt_cls.h +++ b/trunk/include/linux/pkt_cls.h @@ -305,7 +305,6 @@ enum TCA_FW_POLICE, TCA_FW_INDEV, /* used by CONFIG_NET_CLS_IND */ TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */ - TCA_FW_MASK, __TCA_FW_MAX }; diff --git a/trunk/include/linux/pmu.h b/trunk/include/linux/pmu.h index 783177387ac6..2ed807ddc08c 100644 --- a/trunk/include/linux/pmu.h +++ b/trunk/include/linux/pmu.h @@ -231,6 +231,7 @@ extern struct pmu_battery_info pmu_batteries[PMU_MAX_BATTERIES]; extern unsigned int pmu_power_flags; /* Backlight */ -extern void pmu_backlight_init(void); +extern int disable_kernel_backlight; +extern void pmu_backlight_init(struct device_node*); #endif /* __KERNEL__ */ diff --git a/trunk/include/linux/raid/Kbuild b/trunk/include/linux/raid/Kbuild index 2415a64c5e51..73fa27a8d552 100644 --- a/trunk/include/linux/raid/Kbuild +++ b/trunk/include/linux/raid/Kbuild @@ -1,2 +1 @@ -header-y += md_p.h -header-y += md_u.h +header-y += md_p.h md_u.h diff --git a/trunk/include/linux/rtnetlink.h b/trunk/include/linux/rtnetlink.h index 9c92dc8b9a08..facd9ee37b76 100644 --- a/trunk/include/linux/rtnetlink.h +++ b/trunk/include/linux/rtnetlink.h @@ -2,7 +2,6 @@ #define __LINUX_RTNETLINK_H #include -#include /**** * Routing/neighbour discovery messages. @@ -239,8 +238,10 @@ enum rt_class_t RT_TABLE_DEFAULT=253, RT_TABLE_MAIN=254, RT_TABLE_LOCAL=255, - RT_TABLE_MAX=0xFFFFFFFF + __RT_TABLE_MAX }; +#define RT_TABLE_MAX (__RT_TABLE_MAX - 1) + /* Routing message attributes */ @@ -262,7 +263,6 @@ enum rtattr_type_t RTA_CACHEINFO, RTA_SESSION, RTA_MP_ALGO, - RTA_TABLE, __RTA_MAX }; @@ -383,6 +383,226 @@ struct rta_session } u; }; + +/********************************************************* + * Interface address. + ****/ + +struct ifaddrmsg +{ + unsigned char ifa_family; + unsigned char ifa_prefixlen; /* The prefix length */ + unsigned char ifa_flags; /* Flags */ + unsigned char ifa_scope; /* See above */ + int ifa_index; /* Link index */ +}; + +enum +{ + IFA_UNSPEC, + IFA_ADDRESS, + IFA_LOCAL, + IFA_LABEL, + IFA_BROADCAST, + IFA_ANYCAST, + IFA_CACHEINFO, + IFA_MULTICAST, + __IFA_MAX +}; + +#define IFA_MAX (__IFA_MAX - 1) + +/* ifa_flags */ + +#define IFA_F_SECONDARY 0x01 +#define IFA_F_TEMPORARY IFA_F_SECONDARY + +#define IFA_F_DEPRECATED 0x20 +#define IFA_F_TENTATIVE 0x40 +#define IFA_F_PERMANENT 0x80 + +struct ifa_cacheinfo +{ + __u32 ifa_prefered; + __u32 ifa_valid; + __u32 cstamp; /* created timestamp, hundredths of seconds */ + __u32 tstamp; /* updated timestamp, hundredths of seconds */ +}; + + +#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) +#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg)) + +/* + Important comment: + IFA_ADDRESS is prefix address, rather than local interface address. + It makes no difference for normally configured broadcast interfaces, + but for point-to-point IFA_ADDRESS is DESTINATION address, + local address is supplied in IFA_LOCAL attribute. + */ + +/************************************************************** + * Neighbour discovery. + ****/ + +struct ndmsg +{ + unsigned char ndm_family; + unsigned char ndm_pad1; + unsigned short ndm_pad2; + int ndm_ifindex; /* Link index */ + __u16 ndm_state; + __u8 ndm_flags; + __u8 ndm_type; +}; + +enum +{ + NDA_UNSPEC, + NDA_DST, + NDA_LLADDR, + NDA_CACHEINFO, + NDA_PROBES, + __NDA_MAX +}; + +#define NDA_MAX (__NDA_MAX - 1) + +#define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) +#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg)) + +/* + * Neighbor Cache Entry Flags + */ + +#define NTF_PROXY 0x08 /* == ATF_PUBL */ +#define NTF_ROUTER 0x80 + +/* + * Neighbor Cache Entry States. + */ + +#define NUD_INCOMPLETE 0x01 +#define NUD_REACHABLE 0x02 +#define NUD_STALE 0x04 +#define NUD_DELAY 0x08 +#define NUD_PROBE 0x10 +#define NUD_FAILED 0x20 + +/* Dummy states */ +#define NUD_NOARP 0x40 +#define NUD_PERMANENT 0x80 +#define NUD_NONE 0x00 + + +struct nda_cacheinfo +{ + __u32 ndm_confirmed; + __u32 ndm_used; + __u32 ndm_updated; + __u32 ndm_refcnt; +}; + + +/***************************************************************** + * Neighbour tables specific messages. + * + * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the + * NLM_F_DUMP flag set. Every neighbour table configuration is + * spread over multiple messages to avoid running into message + * size limits on systems with many interfaces. The first message + * in the sequence transports all not device specific data such as + * statistics, configuration, and the default parameter set. + * This message is followed by 0..n messages carrying device + * specific parameter sets. + * Although the ordering should be sufficient, NDTA_NAME can be + * used to identify sequences. The initial message can be identified + * by checking for NDTA_CONFIG. The device specific messages do + * not contain this TLV but have NDTPA_IFINDEX set to the + * corresponding interface index. + * + * To change neighbour table attributes, send RTM_SETNEIGHTBL + * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3], + * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked + * otherwise. Device specific parameter sets can be changed by + * setting NDTPA_IFINDEX to the interface index of the corresponding + * device. + ****/ + +struct ndt_stats +{ + __u64 ndts_allocs; + __u64 ndts_destroys; + __u64 ndts_hash_grows; + __u64 ndts_res_failed; + __u64 ndts_lookups; + __u64 ndts_hits; + __u64 ndts_rcv_probes_mcast; + __u64 ndts_rcv_probes_ucast; + __u64 ndts_periodic_gc_runs; + __u64 ndts_forced_gc_runs; +}; + +enum { + NDTPA_UNSPEC, + NDTPA_IFINDEX, /* u32, unchangeable */ + NDTPA_REFCNT, /* u32, read-only */ + NDTPA_REACHABLE_TIME, /* u64, read-only, msecs */ + NDTPA_BASE_REACHABLE_TIME, /* u64, msecs */ + NDTPA_RETRANS_TIME, /* u64, msecs */ + NDTPA_GC_STALETIME, /* u64, msecs */ + NDTPA_DELAY_PROBE_TIME, /* u64, msecs */ + NDTPA_QUEUE_LEN, /* u32 */ + NDTPA_APP_PROBES, /* u32 */ + NDTPA_UCAST_PROBES, /* u32 */ + NDTPA_MCAST_PROBES, /* u32 */ + NDTPA_ANYCAST_DELAY, /* u64, msecs */ + NDTPA_PROXY_DELAY, /* u64, msecs */ + NDTPA_PROXY_QLEN, /* u32 */ + NDTPA_LOCKTIME, /* u64, msecs */ + __NDTPA_MAX +}; +#define NDTPA_MAX (__NDTPA_MAX - 1) + +struct ndtmsg +{ + __u8 ndtm_family; + __u8 ndtm_pad1; + __u16 ndtm_pad2; +}; + +struct ndt_config +{ + __u16 ndtc_key_len; + __u16 ndtc_entry_size; + __u32 ndtc_entries; + __u32 ndtc_last_flush; /* delta to now in msecs */ + __u32 ndtc_last_rand; /* delta to now in msecs */ + __u32 ndtc_hash_rnd; + __u32 ndtc_hash_mask; + __u32 ndtc_hash_chain_gc; + __u32 ndtc_proxy_qlen; +}; + +enum { + NDTA_UNSPEC, + NDTA_NAME, /* char *, unchangeable */ + NDTA_THRESH1, /* u32 */ + NDTA_THRESH2, /* u32 */ + NDTA_THRESH3, /* u32 */ + NDTA_CONFIG, /* struct ndt_config, read-only */ + NDTA_PARMS, /* nested TLV NDTPA_* */ + NDTA_STATS, /* struct ndt_stats, read-only */ + NDTA_GC_INTERVAL, /* u64, msecs */ + __NDTA_MAX +}; +#define NDTA_MAX (__NDTA_MAX - 1) + +#define NDTA_RTA(r) ((struct rtattr*)(((char*)(r)) + \ + NLMSG_ALIGN(sizeof(struct ndtmsg)))) +#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg)) + + /**** * General form of address family dependent message. ****/ @@ -443,6 +663,138 @@ struct prefix_cacheinfo __u32 valid_time; }; +/* The struct should be in sync with struct net_device_stats */ +struct rtnl_link_stats +{ + __u32 rx_packets; /* total packets received */ + __u32 tx_packets; /* total packets transmitted */ + __u32 rx_bytes; /* total bytes received */ + __u32 tx_bytes; /* total bytes transmitted */ + __u32 rx_errors; /* bad packets received */ + __u32 tx_errors; /* packet transmit problems */ + __u32 rx_dropped; /* no space in linux buffers */ + __u32 tx_dropped; /* no space available in linux */ + __u32 multicast; /* multicast packets received */ + __u32 collisions; + + /* detailed rx_errors: */ + __u32 rx_length_errors; + __u32 rx_over_errors; /* receiver ring buff overflow */ + __u32 rx_crc_errors; /* recved pkt with crc error */ + __u32 rx_frame_errors; /* recv'd frame alignment error */ + __u32 rx_fifo_errors; /* recv'r fifo overrun */ + __u32 rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ + __u32 tx_aborted_errors; + __u32 tx_carrier_errors; + __u32 tx_fifo_errors; + __u32 tx_heartbeat_errors; + __u32 tx_window_errors; + + /* for cslip etc */ + __u32 rx_compressed; + __u32 tx_compressed; +}; + +/* The struct should be in sync with struct ifmap */ +struct rtnl_link_ifmap +{ + __u64 mem_start; + __u64 mem_end; + __u64 base_addr; + __u16 irq; + __u8 dma; + __u8 port; +}; + +enum +{ + IFLA_UNSPEC, + IFLA_ADDRESS, + IFLA_BROADCAST, + IFLA_IFNAME, + IFLA_MTU, + IFLA_LINK, + IFLA_QDISC, + IFLA_STATS, + IFLA_COST, +#define IFLA_COST IFLA_COST + IFLA_PRIORITY, +#define IFLA_PRIORITY IFLA_PRIORITY + IFLA_MASTER, +#define IFLA_MASTER IFLA_MASTER + IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */ +#define IFLA_WIRELESS IFLA_WIRELESS + IFLA_PROTINFO, /* Protocol specific information for a link */ +#define IFLA_PROTINFO IFLA_PROTINFO + IFLA_TXQLEN, +#define IFLA_TXQLEN IFLA_TXQLEN + IFLA_MAP, +#define IFLA_MAP IFLA_MAP + IFLA_WEIGHT, +#define IFLA_WEIGHT IFLA_WEIGHT + IFLA_OPERSTATE, + IFLA_LINKMODE, + __IFLA_MAX +}; + + +#define IFLA_MAX (__IFLA_MAX - 1) + +#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) +#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) + +/* ifi_flags. + + IFF_* flags. + + The only change is: + IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are + more not changeable by user. They describe link media + characteristics and set by device driver. + + Comments: + - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid + - If neither of these three flags are set; + the interface is NBMA. + + - IFF_MULTICAST does not mean anything special: + multicasts can be used on all not-NBMA links. + IFF_MULTICAST means that this media uses special encapsulation + for multicast frames. Apparently, all IFF_POINTOPOINT and + IFF_BROADCAST devices are able to use multicasts too. + */ + +/* IFLA_LINK. + For usual devices it is equal ifi_index. + If it is a "virtual interface" (f.e. tunnel), ifi_link + can point to real physical interface (f.e. for bandwidth calculations), + or maybe 0, what means, that real media is unknown (usual + for IPIP tunnels, when route to endpoint is allowed to change) + */ + +/* Subtype attributes for IFLA_PROTINFO */ +enum +{ + IFLA_INET6_UNSPEC, + IFLA_INET6_FLAGS, /* link flags */ + IFLA_INET6_CONF, /* sysctl parameters */ + IFLA_INET6_STATS, /* statistics */ + IFLA_INET6_MCAST, /* MC things. What of them? */ + IFLA_INET6_CACHEINFO, /* time values and max reasm size */ + __IFLA_INET6_MAX +}; + +#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1) + +struct ifla_cacheinfo +{ + __u32 max_reasm_len; + __u32 tstamp; /* ipv6InterfaceTable updated timestamp */ + __u32 reachable_time; + __u32 retrans_time; +}; /***************************************************************** * Traffic control messages. @@ -533,13 +885,10 @@ enum rtnetlink_groups { RTNLGRP_NOP2, RTNLGRP_DECnet_ROUTE, #define RTNLGRP_DECnet_ROUTE RTNLGRP_DECnet_ROUTE - RTNLGRP_DECnet_RULE, -#define RTNLGRP_DECnet_RULE RTNLGRP_DECnet_RULE + RTNLGRP_NOP3, RTNLGRP_NOP4, RTNLGRP_IPV6_PREFIX, #define RTNLGRP_IPV6_PREFIX RTNLGRP_IPV6_PREFIX - RTNLGRP_IPV6_RULE, -#define RTNLGRP_IPV6_RULE RTNLGRP_IPV6_RULE __RTNLGRP_MAX }; #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) @@ -574,6 +923,8 @@ extern int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, in #define rtattr_parse_nested(tb, max, rta) \ rtattr_parse((tb), (max), RTA_DATA((rta)), RTA_PAYLOAD((rta))) +extern struct sock *rtnl; + struct rtnetlink_link { int (*doit)(struct sk_buff *, struct nlmsghdr*, void *attr); @@ -582,10 +933,6 @@ struct rtnetlink_link extern struct rtnetlink_link * rtnetlink_links[NPROTO]; extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo); -extern int rtnl_unicast(struct sk_buff *skb, u32 pid); -extern int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group, - struct nlmsghdr *nlh, gfp_t flags); -extern void rtnl_set_sk_err(u32 group, int error); extern int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics); extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data); @@ -718,13 +1065,6 @@ extern void __rtnl_unlock(void); } \ } while(0) -static inline u32 rtm_get_table(struct rtattr **rta, u8 table) -{ - return RTA_GET_U32(rta[RTA_TABLE-1]); -rtattr_failure: - return table; -} - #endif /* __KERNEL__ */ diff --git a/trunk/include/linux/scatterlist.h b/trunk/include/linux/scatterlist.h index 4efbd9c445f5..66ff545552f7 100644 --- a/trunk/include/linux/scatterlist.h +++ b/trunk/include/linux/scatterlist.h @@ -5,7 +5,7 @@ #include #include -static inline void sg_set_buf(struct scatterlist *sg, const void *buf, +static inline void sg_set_buf(struct scatterlist *sg, void *buf, unsigned int buflen) { sg->page = virt_to_page(buf); @@ -13,7 +13,7 @@ static inline void sg_set_buf(struct scatterlist *sg, const void *buf, sg->length = buflen; } -static inline void sg_init_one(struct scatterlist *sg, const void *buf, +static inline void sg_init_one(struct scatterlist *sg, void *buf, unsigned int buflen) { memset(sg, 0, sizeof(*sg)); diff --git a/trunk/include/linux/sched.h b/trunk/include/linux/sched.h index 34ed0d99b1bd..6afa72e080cb 100644 --- a/trunk/include/linux/sched.h +++ b/trunk/include/linux/sched.h @@ -994,6 +994,7 @@ struct task_struct { */ struct pipe_inode_info *splice_pipe; #ifdef CONFIG_TASK_DELAY_ACCT + spinlock_t delays_lock; struct task_delay_info *delays; #endif }; @@ -1556,14 +1557,6 @@ static inline void freeze(struct task_struct *p) p->flags |= PF_FREEZE; } -/* - * Sometimes we may need to cancel the previous 'freeze' request - */ -static inline void do_not_freeze(struct task_struct *p) -{ - p->flags &= ~PF_FREEZE; -} - /* * Wake up a frozen process */ diff --git a/trunk/include/linux/security.h b/trunk/include/linux/security.h index 9f56fb8a4a6c..f75303831d09 100644 --- a/trunk/include/linux/security.h +++ b/trunk/include/linux/security.h @@ -31,8 +31,6 @@ #include #include #include -#include -#include struct ctl_table; @@ -90,7 +88,6 @@ extern int cap_netlink_recv(struct sk_buff *skb, int cap); struct nfsctl_arg; struct sched_param; struct swap_info_struct; -struct request_sock; /* bprm_apply_creds unsafe reasons */ #define LSM_UNSAFE_SHARE 1 @@ -815,19 +812,9 @@ struct request_sock; * which is used to copy security attributes between local stream sockets. * @sk_free_security: * Deallocate security structure. - * @sk_clone_security: - * Clone/copy security structure. - * @sk_getsecid: - * Retrieve the LSM-specific secid for the sock to enable caching of network + * @sk_getsid: + * Retrieve the LSM-specific sid for the sock to enable caching of network * authorizations. - * @sock_graft: - * Sets the socket's isec sid to the sock's sid. - * @inet_conn_request: - * Sets the openreq's sid to socket's sid with MLS portion taken from peer sid. - * @inet_csk_clone: - * Sets the new child socket's sid to the openreq sid. - * @req_classify_flow: - * Sets the flow's sid to the openreq sid. * * Security hooks for XFRM operations. * @@ -836,10 +823,9 @@ struct request_sock; * used by the XFRM system. * @sec_ctx contains the security context information being provided by * the user-level policy update program (e.g., setkey). - * @sk refers to the sock from which to derive the security context. - * Allocate a security structure to the xp->security field; the security - * field is initialized to NULL when the xfrm_policy is allocated. Only - * one of sec_ctx or sock can be specified. + * Allocate a security structure to the xp->security field. + * The security field is initialized to NULL when the xfrm_policy is + * allocated. * Return 0 if operation was successful (memory to allocate, legal context) * @xfrm_policy_clone_security: * @old contains an existing xfrm_policy in the SPD. @@ -858,14 +844,9 @@ struct request_sock; * Database by the XFRM system. * @sec_ctx contains the security context information being provided by * the user-level SA generation program (e.g., setkey or racoon). - * @polsec contains the security context information associated with a xfrm - * policy rule from which to take the base context. polsec must be NULL - * when sec_ctx is specified. - * @secid contains the secid from which to take the mls portion of the context. - * Allocate a security structure to the x->security field; the security - * field is initialized to NULL when the xfrm_state is allocated. Set the - * context to correspond to either sec_ctx or polsec, with the mls portion - * taken from secid in the latter case. + * Allocate a security structure to the x->security field. The + * security field is initialized to NULL when the xfrm_state is + * allocated. * Return 0 if operation was successful (memory to allocate, legal context). * @xfrm_state_free_security: * @x contains the xfrm_state. @@ -876,27 +857,13 @@ struct request_sock; * @xfrm_policy_lookup: * @xp contains the xfrm_policy for which the access control is being * checked. - * @fl_secid contains the flow security label that is used to authorize + * @sk_sid contains the sock security label that is used to authorize * access to the policy xp. * @dir contains the direction of the flow (input or output). - * Check permission when a flow selects a xfrm_policy for processing + * Check permission when a sock selects a xfrm_policy for processing * XFRMs on a packet. The hook is called when selecting either a * per-socket policy or a generic xfrm policy. * Return 0 if permission is granted. - * @xfrm_state_pol_flow_match: - * @x contains the state to match. - * @xp contains the policy to check for a match. - * @fl contains the flow to check for a match. - * Return 1 if there is a match. - * @xfrm_flow_state_match: - * @fl contains the flow key to match. - * @xfrm points to the xfrm_state to match. - * Return 1 if there is a match. - * @xfrm_decode_session: - * @skb points to skb to decode. - * @secid points to the flow key secid to set. - * @ckall says if all xfrms used should be checked for same secid. - * Return 0 if ckall is zero or all xfrms used have the same secid. * * Security hooks affecting all Key Management operations * @@ -1142,16 +1109,6 @@ struct request_sock; * @name contains the name of the security module being unstacked. * @ops contains a pointer to the struct security_operations of the module to unstack. * - * @secid_to_secctx: - * Convert secid to security context. - * @secid contains the security ID. - * @secdata contains the pointer that stores the converted security context. - * - * @release_secctx: - * Release the security context. - * @secdata contains the security context. - * @seclen contains the length of the security context. - * * This is the main security structure. */ struct security_operations { @@ -1332,8 +1289,6 @@ struct security_operations { int (*getprocattr)(struct task_struct *p, char *name, void *value, size_t size); int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size); - int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen); - void (*release_secctx)(char *secdata, u32 seclen); #ifdef CONFIG_SECURITY_NETWORK int (*unix_stream_connect) (struct socket * sock, @@ -1341,8 +1296,8 @@ struct security_operations { int (*unix_may_send) (struct socket * sock, struct socket * other); int (*socket_create) (int family, int type, int protocol, int kern); - int (*socket_post_create) (struct socket * sock, int family, - int type, int protocol, int kern); + void (*socket_post_create) (struct socket * sock, int family, + int type, int protocol, int kern); int (*socket_bind) (struct socket * sock, struct sockaddr * address, int addrlen); int (*socket_connect) (struct socket * sock, @@ -1362,34 +1317,21 @@ struct security_operations { int (*socket_shutdown) (struct socket * sock, int how); int (*socket_sock_rcv_skb) (struct sock * sk, struct sk_buff * skb); int (*socket_getpeersec_stream) (struct socket *sock, char __user *optval, int __user *optlen, unsigned len); - int (*socket_getpeersec_dgram) (struct socket *sock, struct sk_buff *skb, u32 *secid); + int (*socket_getpeersec_dgram) (struct sk_buff *skb, char **secdata, u32 *seclen); int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority); void (*sk_free_security) (struct sock *sk); - void (*sk_clone_security) (const struct sock *sk, struct sock *newsk); - void (*sk_getsecid) (struct sock *sk, u32 *secid); - void (*sock_graft)(struct sock* sk, struct socket *parent); - int (*inet_conn_request)(struct sock *sk, struct sk_buff *skb, - struct request_sock *req); - void (*inet_csk_clone)(struct sock *newsk, const struct request_sock *req); - void (*req_classify_flow)(const struct request_sock *req, struct flowi *fl); + unsigned int (*sk_getsid) (struct sock *sk, struct flowi *fl, u8 dir); #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM - int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp, - struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk); + int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx); int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new); void (*xfrm_policy_free_security) (struct xfrm_policy *xp); int (*xfrm_policy_delete_security) (struct xfrm_policy *xp); - int (*xfrm_state_alloc_security) (struct xfrm_state *x, - struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *polsec, - u32 secid); + int (*xfrm_state_alloc_security) (struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx); void (*xfrm_state_free_security) (struct xfrm_state *x); int (*xfrm_state_delete_security) (struct xfrm_state *x); - int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir); - int (*xfrm_state_pol_flow_match)(struct xfrm_state *x, - struct xfrm_policy *xp, struct flowi *fl); - int (*xfrm_flow_state_match)(struct flowi *fl, struct xfrm_state *xfrm); - int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall); + int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 sk_sid, u8 dir); #endif /* CONFIG_SECURITY_NETWORK_XFRM */ /* key management security hooks */ @@ -2117,16 +2059,6 @@ static inline int security_netlink_recv(struct sk_buff * skb, int cap) return security_ops->netlink_recv(skb, cap); } -static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) -{ - return security_ops->secid_to_secctx(secid, secdata, seclen); -} - -static inline void security_release_secctx(char *secdata, u32 seclen) -{ - return security_ops->release_secctx(secdata, seclen); -} - /* prototypes */ extern int security_init (void); extern int register_security (struct security_operations *ops); @@ -2793,14 +2725,6 @@ static inline void securityfs_remove(struct dentry *dentry) { } -static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) -{ - return -EOPNOTSUPP; -} - -static inline void security_release_secctx(char *secdata, u32 seclen) -{ -} #endif /* CONFIG_SECURITY */ #ifdef CONFIG_SECURITY_NETWORK @@ -2824,13 +2748,13 @@ static inline int security_socket_create (int family, int type, return security_ops->socket_create(family, type, protocol, kern); } -static inline int security_socket_post_create(struct socket * sock, - int family, - int type, - int protocol, int kern) +static inline void security_socket_post_create(struct socket * sock, + int family, + int type, + int protocol, int kern) { - return security_ops->socket_post_create(sock, family, type, - protocol, kern); + security_ops->socket_post_create(sock, family, type, + protocol, kern); } static inline int security_socket_bind(struct socket * sock, @@ -2916,9 +2840,10 @@ static inline int security_socket_getpeersec_stream(struct socket *sock, char __ return security_ops->socket_getpeersec_stream(sock, optval, optlen, len); } -static inline int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) +static inline int security_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, + u32 *seclen) { - return security_ops->socket_getpeersec_dgram(sock, skb, secid); + return security_ops->socket_getpeersec_dgram(skb, secdata, seclen); } static inline int security_sk_alloc(struct sock *sk, int family, gfp_t priority) @@ -2931,36 +2856,9 @@ static inline void security_sk_free(struct sock *sk) return security_ops->sk_free_security(sk); } -static inline void security_sk_clone(const struct sock *sk, struct sock *newsk) +static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) { - return security_ops->sk_clone_security(sk, newsk); -} - -static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl) -{ - security_ops->sk_getsecid(sk, &fl->secid); -} - -static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl) -{ - security_ops->req_classify_flow(req, fl); -} - -static inline void security_sock_graft(struct sock* sk, struct socket *parent) -{ - security_ops->sock_graft(sk, parent); -} - -static inline int security_inet_conn_request(struct sock *sk, - struct sk_buff *skb, struct request_sock *req) -{ - return security_ops->inet_conn_request(sk, skb, req); -} - -static inline void security_inet_csk_clone(struct sock *newsk, - const struct request_sock *req) -{ - security_ops->inet_csk_clone(newsk, req); + return security_ops->sk_getsid(sk, fl, dir); } #else /* CONFIG_SECURITY_NETWORK */ static inline int security_unix_stream_connect(struct socket * sock, @@ -2982,12 +2880,11 @@ static inline int security_socket_create (int family, int type, return 0; } -static inline int security_socket_post_create(struct socket * sock, - int family, - int type, - int protocol, int kern) +static inline void security_socket_post_create(struct socket * sock, + int family, + int type, + int protocol, int kern) { - return 0; } static inline int security_socket_bind(struct socket * sock, @@ -3071,7 +2968,8 @@ static inline int security_socket_getpeersec_stream(struct socket *sock, char __ return -ENOPROTOOPT; } -static inline int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) +static inline int security_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, + u32 *seclen) { return -ENOPROTOOPT; } @@ -3085,43 +2983,16 @@ static inline void security_sk_free(struct sock *sk) { } -static inline void security_sk_clone(const struct sock *sk, struct sock *newsk) -{ -} - -static inline void security_sk_classify_flow(struct sock *sk, struct flowi *fl) -{ -} - -static inline void security_req_classify_flow(const struct request_sock *req, struct flowi *fl) -{ -} - -static inline void security_sock_graft(struct sock* sk, struct socket *parent) -{ -} - -static inline int security_inet_conn_request(struct sock *sk, - struct sk_buff *skb, struct request_sock *req) +static inline unsigned int security_sk_sid(struct sock *sk, struct flowi *fl, u8 dir) { return 0; } - -static inline void security_inet_csk_clone(struct sock *newsk, - const struct request_sock *req) -{ -} #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx) { - return security_ops->xfrm_policy_alloc_security(xp, sec_ctx, NULL); -} - -static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk) -{ - return security_ops->xfrm_policy_alloc_security(xp, NULL, sk); + return security_ops->xfrm_policy_alloc_security(xp, sec_ctx); } static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) @@ -3139,18 +3010,9 @@ static inline int security_xfrm_policy_delete(struct xfrm_policy *xp) return security_ops->xfrm_policy_delete_security(xp); } -static inline int security_xfrm_state_alloc(struct xfrm_state *x, - struct xfrm_user_sec_ctx *sec_ctx) +static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) { - return security_ops->xfrm_state_alloc_security(x, sec_ctx, NULL, 0); -} - -static inline int security_xfrm_state_alloc_acquire(struct xfrm_state *x, - struct xfrm_sec_ctx *polsec, u32 secid) -{ - if (!polsec) - return 0; - return security_ops->xfrm_state_alloc_security(x, NULL, polsec, secid); + return security_ops->xfrm_state_alloc_security(x, sec_ctx); } static inline int security_xfrm_state_delete(struct xfrm_state *x) @@ -3163,32 +3025,9 @@ static inline void security_xfrm_state_free(struct xfrm_state *x) security_ops->xfrm_state_free_security(x); } -static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) -{ - return security_ops->xfrm_policy_lookup(xp, fl_secid, dir); -} - -static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x, - struct xfrm_policy *xp, struct flowi *fl) -{ - return security_ops->xfrm_state_pol_flow_match(x, xp, fl); -} - -static inline int security_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm) +static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir) { - return security_ops->xfrm_flow_state_match(fl, xfrm); -} - -static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) -{ - return security_ops->xfrm_decode_session(skb, secid, 1); -} - -static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl) -{ - int rc = security_ops->xfrm_decode_session(skb, &fl->secid, 0); - - BUG_ON(rc); + return security_ops->xfrm_policy_lookup(xp, sk_sid, dir); } #else /* CONFIG_SECURITY_NETWORK_XFRM */ static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx) @@ -3196,11 +3035,6 @@ static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm return 0; } -static inline int security_xfrm_sock_policy_alloc(struct xfrm_policy *xp, struct sock *sk) -{ - return 0; -} - static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new) { return 0; @@ -3215,14 +3049,7 @@ static inline int security_xfrm_policy_delete(struct xfrm_policy *xp) return 0; } -static inline int security_xfrm_state_alloc(struct xfrm_state *x, - struct xfrm_user_sec_ctx *sec_ctx) -{ - return 0; -} - -static inline int security_xfrm_state_alloc_acquire(struct xfrm_state *x, - struct xfrm_sec_ctx *polsec, u32 secid) +static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) { return 0; } @@ -3236,32 +3063,10 @@ static inline int security_xfrm_state_delete(struct xfrm_state *x) return 0; } -static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) -{ - return 0; -} - -static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x, - struct xfrm_policy *xp, struct flowi *fl) -{ - return 1; -} - -static inline int security_xfrm_flow_state_match(struct flowi *fl, - struct xfrm_state *xfrm) -{ - return 1; -} - -static inline int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) +static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir) { return 0; } - -static inline void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl) -{ -} - #endif /* CONFIG_SECURITY_NETWORK_XFRM */ #ifdef CONFIG_KEYS diff --git a/trunk/include/linux/skbuff.h b/trunk/include/linux/skbuff.h index 85577a4ffa61..4307e764ef0a 100644 --- a/trunk/include/linux/skbuff.h +++ b/trunk/include/linux/skbuff.h @@ -34,9 +34,8 @@ #define HAVE_ALIGNABLE_SKB /* Ditto 8) */ #define CHECKSUM_NONE 0 -#define CHECKSUM_PARTIAL 1 +#define CHECKSUM_HW 1 #define CHECKSUM_UNNECESSARY 2 -#define CHECKSUM_COMPLETE 3 #define SKB_DATA_ALIGN(X) (((X) + (SMP_CACHE_BYTES - 1)) & \ ~(SMP_CACHE_BYTES - 1)) @@ -57,17 +56,17 @@ * Apparently with secret goal to sell you new device, when you * will add new protocol to your host. F.e. IPv6. 8) * - * COMPLETE: the most generic way. Device supplied checksum of _all_ + * HW: the most generic way. Device supplied checksum of _all_ * the packet as seen by netif_rx in skb->csum. * NOTE: Even if device supports only some protocols, but - * is able to produce some skb->csum, it MUST use COMPLETE, + * is able to produce some skb->csum, it MUST use HW, * not UNNECESSARY. * * B. Checksumming on output. * * NONE: skb is checksummed by protocol or csum is not required. * - * PARTIAL: device is required to csum packet as seen by hard_start_xmit + * HW: device is required to csum packet as seen by hard_start_xmit * from skb->h.raw to the end and to record the checksum * at skb->h.raw+skb->csum. * @@ -605,17 +604,12 @@ static inline __u32 skb_queue_len(const struct sk_buff_head *list_) return list_->qlen; } -/* - * This function creates a split out lock class for each invocation; - * this is needed for now since a whole lot of users of the skb-queue - * infrastructure in drivers have different locking usage (in hardirq) - * than the networking core (in softirq only). In the long run either the - * network layer or drivers should need annotation to consolidate the - * main types of usage into 3 classes. - */ +extern struct lock_class_key skb_queue_lock_key; + static inline void skb_queue_head_init(struct sk_buff_head *list) { spin_lock_init(&list->lock); + lockdep_set_class(&list->lock, &skb_queue_lock_key); list->prev = list->next = (struct sk_buff *)list; list->qlen = 0; } @@ -1040,21 +1034,6 @@ static inline int pskb_trim(struct sk_buff *skb, unsigned int len) return (len < skb->len) ? __pskb_trim(skb, len) : 0; } -/** - * pskb_trim_unique - remove end from a paged unique (not cloned) buffer - * @skb: buffer to alter - * @len: new length - * - * This is identical to pskb_trim except that the caller knows that - * the skb is not cloned so we should never get an error due to out- - * of-memory. - */ -static inline void pskb_trim_unique(struct sk_buff *skb, unsigned int len) -{ - int err = pskb_trim(skb, len); - BUG_ON(err); -} - /** * skb_orphan - orphan a buffer * @skb: buffer to orphan @@ -1097,7 +1076,7 @@ static inline void __skb_queue_purge(struct sk_buff_head *list) * the headroom they think they need without accounting for the * built in space. The built in space is used for optimisations. * - * %NULL is returned if there is no free memory. + * %NULL is returned in there is no free memory. */ static inline struct sk_buff *__dev_alloc_skb(unsigned int length, gfp_t gfp_mask) @@ -1117,7 +1096,7 @@ static inline struct sk_buff *__dev_alloc_skb(unsigned int length, * the headroom they think they need without accounting for the * built in space. The built in space is used for optimisations. * - * %NULL is returned if there is no free memory. Although this function + * %NULL is returned in there is no free memory. Although this function * allocates memory it can be called from an interrupt. */ static inline struct sk_buff *dev_alloc_skb(unsigned int length) @@ -1125,28 +1104,6 @@ static inline struct sk_buff *dev_alloc_skb(unsigned int length) return __dev_alloc_skb(length, GFP_ATOMIC); } -extern struct sk_buff *__netdev_alloc_skb(struct net_device *dev, - unsigned int length, gfp_t gfp_mask); - -/** - * netdev_alloc_skb - allocate an skbuff for rx on a specific device - * @dev: network device to receive on - * @length: length to allocate - * - * Allocate a new &sk_buff and assign it a usage count of one. The - * buffer has unspecified headroom built in. Users should allocate - * the headroom they think they need without accounting for the - * built in space. The built in space is used for optimisations. - * - * %NULL is returned if there is no free memory. Although this function - * allocates memory it can be called from an interrupt. - */ -static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev, - unsigned int length) -{ - return __netdev_alloc_skb(dev, length, GFP_ATOMIC); -} - /** * skb_cow - copy header of skb when it is required * @skb: buffer to cow @@ -1262,14 +1219,14 @@ static inline int skb_linearize_cow(struct sk_buff *skb) * @len: length of data pulled * * After doing a pull on a received packet, you need to call this to - * update the CHECKSUM_COMPLETE checksum, or set ip_summed to - * CHECKSUM_NONE so that it can be recomputed from scratch. + * update the CHECKSUM_HW checksum, or set ip_summed to CHECKSUM_NONE + * so that it can be recomputed from scratch. */ static inline void skb_postpull_rcsum(struct sk_buff *skb, const void *start, unsigned int len) { - if (skb->ip_summed == CHECKSUM_COMPLETE) + if (skb->ip_summed == CHECKSUM_HW) skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); } @@ -1288,7 +1245,7 @@ static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) { if (likely(len >= skb->len)) return 0; - if (skb->ip_summed == CHECKSUM_COMPLETE) + if (skb->ip_summed == CHECKSUM_HW) skb->ip_summed = CHECKSUM_NONE; return __pskb_trim(skb, len); } diff --git a/trunk/include/linux/snmp.h b/trunk/include/linux/snmp.h index 854aa6b543f1..4db25d5c7cd1 100644 --- a/trunk/include/linux/snmp.h +++ b/trunk/include/linux/snmp.h @@ -155,11 +155,42 @@ enum UDP_MIB_NOPORTS, /* NoPorts */ UDP_MIB_INERRORS, /* InErrors */ UDP_MIB_OUTDATAGRAMS, /* OutDatagrams */ - UDP_MIB_RCVBUFERRORS, /* RcvbufErrors */ - UDP_MIB_SNDBUFERRORS, /* SndbufErrors */ __UDP_MIB_MAX }; +/* sctp mib definitions */ +/* + * draft-ietf-sigtran-sctp-mib-07.txt + */ +enum +{ + SCTP_MIB_NUM = 0, + SCTP_MIB_CURRESTAB, /* CurrEstab */ + SCTP_MIB_ACTIVEESTABS, /* ActiveEstabs */ + SCTP_MIB_PASSIVEESTABS, /* PassiveEstabs */ + SCTP_MIB_ABORTEDS, /* Aborteds */ + SCTP_MIB_SHUTDOWNS, /* Shutdowns */ + SCTP_MIB_OUTOFBLUES, /* OutOfBlues */ + SCTP_MIB_CHECKSUMERRORS, /* ChecksumErrors */ + SCTP_MIB_OUTCTRLCHUNKS, /* OutCtrlChunks */ + SCTP_MIB_OUTORDERCHUNKS, /* OutOrderChunks */ + SCTP_MIB_OUTUNORDERCHUNKS, /* OutUnorderChunks */ + SCTP_MIB_INCTRLCHUNKS, /* InCtrlChunks */ + SCTP_MIB_INORDERCHUNKS, /* InOrderChunks */ + SCTP_MIB_INUNORDERCHUNKS, /* InUnorderChunks */ + SCTP_MIB_FRAGUSRMSGS, /* FragUsrMsgs */ + SCTP_MIB_REASMUSRMSGS, /* ReasmUsrMsgs */ + SCTP_MIB_OUTSCTPPACKS, /* OutSCTPPacks */ + SCTP_MIB_INSCTPPACKS, /* InSCTPPacks */ + SCTP_MIB_RTOALGORITHM, /* RtoAlgorithm */ + SCTP_MIB_RTOMIN, /* RtoMin */ + SCTP_MIB_RTOMAX, /* RtoMax */ + SCTP_MIB_RTOINITIAL, /* RtoInitial */ + SCTP_MIB_VALCOOKIELIFE, /* ValCookieLife */ + SCTP_MIB_MAXINITRETR, /* MaxInitRetr */ + __SCTP_MIB_MAX +}; + /* linux mib definitions */ enum { diff --git a/trunk/include/linux/sunrpc/Kbuild b/trunk/include/linux/sunrpc/Kbuild index fb438f158eee..0d1d768a27bf 100644 --- a/trunk/include/linux/sunrpc/Kbuild +++ b/trunk/include/linux/sunrpc/Kbuild @@ -1 +1 @@ -unifdef-y += debug.h +unifdef-y := debug.h diff --git a/trunk/include/linux/sunrpc/clnt.h b/trunk/include/linux/sunrpc/clnt.h index f6d1d646ce05..8fe9f35eba31 100644 --- a/trunk/include/linux/sunrpc/clnt.h +++ b/trunk/include/linux/sunrpc/clnt.h @@ -18,6 +18,18 @@ #include #include +/* + * This defines an RPC port mapping + */ +struct rpc_portmap { + __u32 pm_prog; + __u32 pm_vers; + __u32 pm_prot; + __u16 pm_port; + unsigned char pm_binding : 1; /* doing a getport() */ + struct rpc_wait_queue pm_bindwait; /* waiting on getport() */ +}; + struct rpc_inode; /* @@ -28,9 +40,7 @@ struct rpc_clnt { atomic_t cl_users; /* number of references */ struct rpc_xprt * cl_xprt; /* transport */ struct rpc_procinfo * cl_procinfo; /* procedure info */ - u32 cl_prog, /* RPC program number */ - cl_vers, /* RPC version number */ - cl_maxproc; /* max procedure number */ + u32 cl_maxproc; /* max procedure number */ char * cl_server; /* server machine name */ char * cl_protname; /* protocol name */ @@ -45,6 +55,7 @@ struct rpc_clnt { cl_dead : 1;/* abandoned */ struct rpc_rtt * cl_rtt; /* RTO estimator data */ + struct rpc_portmap * cl_pmap; /* port mapping */ int cl_nodelen; /* nodename length */ char cl_nodename[UNX_MAXNODENAME]; @@ -53,8 +64,14 @@ struct rpc_clnt { struct dentry * cl_dentry; /* inode */ struct rpc_clnt * cl_parent; /* Points to parent of clones */ struct rpc_rtt cl_rtt_default; + struct rpc_portmap cl_pmap_default; char cl_inline_name[32]; }; +#define cl_timeout cl_xprt->timeout +#define cl_prog cl_pmap->pm_prog +#define cl_vers cl_pmap->pm_vers +#define cl_port cl_pmap->pm_port +#define cl_prot cl_pmap->pm_prot /* * General RPC program info @@ -89,36 +106,24 @@ struct rpc_procinfo { char * p_name; /* name of procedure */ }; -#ifdef __KERNEL__ - -struct rpc_create_args { - int protocol; - struct sockaddr *address; - size_t addrsize; - struct rpc_timeout *timeout; - char *servername; - struct rpc_program *program; - u32 version; - rpc_authflavor_t authflavor; - unsigned long flags; -}; +#define RPC_CONGESTED(clnt) (RPCXPRT_CONGESTED((clnt)->cl_xprt)) +#define RPC_PEERADDR(clnt) (&(clnt)->cl_xprt->addr) -/* Values for "flags" field */ -#define RPC_CLNT_CREATE_HARDRTRY (1UL << 0) -#define RPC_CLNT_CREATE_INTR (1UL << 1) -#define RPC_CLNT_CREATE_AUTOBIND (1UL << 2) -#define RPC_CLNT_CREATE_ONESHOT (1UL << 3) -#define RPC_CLNT_CREATE_NONPRIVPORT (1UL << 4) -#define RPC_CLNT_CREATE_NOPING (1UL << 5) +#ifdef __KERNEL__ -struct rpc_clnt *rpc_create(struct rpc_create_args *args); +struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname, + struct rpc_program *info, + u32 version, rpc_authflavor_t authflavor); +struct rpc_clnt *rpc_new_client(struct rpc_xprt *xprt, char *servname, + struct rpc_program *info, + u32 version, rpc_authflavor_t authflavor); struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, struct rpc_program *, int); struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); int rpc_shutdown_client(struct rpc_clnt *); int rpc_destroy_client(struct rpc_clnt *); void rpc_release_client(struct rpc_clnt *); -void rpc_getport(struct rpc_task *); +void rpc_getport(struct rpc_task *, struct rpc_clnt *); int rpc_register(u32, u32, int, unsigned short, int *); void rpc_call_setup(struct rpc_task *, struct rpc_message *, int); @@ -135,8 +140,6 @@ void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int); size_t rpc_max_payload(struct rpc_clnt *); void rpc_force_rebind(struct rpc_clnt *); int rpc_ping(struct rpc_clnt *clnt, int flags); -size_t rpc_peeraddr(struct rpc_clnt *, struct sockaddr *, size_t); -char * rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t); /* * Helper function for NFSroot support diff --git a/trunk/include/linux/sunrpc/gss_krb5.h b/trunk/include/linux/sunrpc/gss_krb5.h index e30ba201910a..1279280d7196 100644 --- a/trunk/include/linux/sunrpc/gss_krb5.h +++ b/trunk/include/linux/sunrpc/gss_krb5.h @@ -46,8 +46,8 @@ struct krb5_ctx { unsigned char seed[16]; int signalg; int sealalg; - struct crypto_blkcipher *enc; - struct crypto_blkcipher *seq; + struct crypto_tfm *enc; + struct crypto_tfm *seq; s32 endtime; u32 seq_send; struct xdr_netobj mech_used; @@ -136,27 +136,26 @@ gss_unwrap_kerberos(struct gss_ctx *ctx_id, int offset, u32 -krb5_encrypt(struct crypto_blkcipher *key, +krb5_encrypt(struct crypto_tfm * key, void *iv, void *in, void *out, int length); u32 -krb5_decrypt(struct crypto_blkcipher *key, +krb5_decrypt(struct crypto_tfm * key, void *iv, void *in, void *out, int length); int -gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *outbuf, - int offset, struct page **pages); +gss_encrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *outbuf, int offset, + struct page **pages); int -gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *inbuf, - int offset); +gss_decrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *inbuf, int offset); s32 -krb5_make_seq_num(struct crypto_blkcipher *key, +krb5_make_seq_num(struct crypto_tfm * key, int direction, s32 seqnum, unsigned char *cksum, unsigned char *buf); s32 -krb5_get_seq_num(struct crypto_blkcipher *key, +krb5_get_seq_num(struct crypto_tfm * key, unsigned char *cksum, unsigned char *buf, int *direction, s32 * seqnum); diff --git a/trunk/include/linux/sunrpc/gss_spkm3.h b/trunk/include/linux/sunrpc/gss_spkm3.h index 2cf3fbb40b4f..336e218c2782 100644 --- a/trunk/include/linux/sunrpc/gss_spkm3.h +++ b/trunk/include/linux/sunrpc/gss_spkm3.h @@ -19,9 +19,9 @@ struct spkm3_ctx { unsigned int req_flags ; struct xdr_netobj share_key; int conf_alg; - struct crypto_blkcipher *derived_conf_key; + struct crypto_tfm* derived_conf_key; int intg_alg; - struct crypto_blkcipher *derived_integ_key; + struct crypto_tfm* derived_integ_key; int keyestb_alg; /* alg used to get share_key */ int owf_alg; /* one way function */ }; diff --git a/trunk/include/linux/sunrpc/rpc_pipe_fs.h b/trunk/include/linux/sunrpc/rpc_pipe_fs.h index a2eb9b4a9de3..2c2189cb30aa 100644 --- a/trunk/include/linux/sunrpc/rpc_pipe_fs.h +++ b/trunk/include/linux/sunrpc/rpc_pipe_fs.h @@ -42,9 +42,9 @@ RPC_I(struct inode *inode) extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *); extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *); -extern int rpc_rmdir(struct dentry *); -extern struct dentry *rpc_mkpipe(struct dentry *, const char *, void *, struct rpc_pipe_ops *, int flags); -extern int rpc_unlink(struct dentry *); +extern int rpc_rmdir(char *); +extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags); +extern int rpc_unlink(char *); extern struct vfsmount *rpc_get_mount(void); extern void rpc_put_mount(void); diff --git a/trunk/include/linux/sunrpc/sched.h b/trunk/include/linux/sunrpc/sched.h index f399c138f79d..82a91bb22362 100644 --- a/trunk/include/linux/sunrpc/sched.h +++ b/trunk/include/linux/sunrpc/sched.h @@ -127,6 +127,7 @@ struct rpc_call_ops { */ #define RPC_TASK_ASYNC 0x0001 /* is an async task */ #define RPC_TASK_SWAPPER 0x0002 /* is swapping in/out */ +#define RPC_TASK_CHILD 0x0008 /* is child of other task */ #define RPC_CALL_MAJORSEEN 0x0020 /* major timeout seen */ #define RPC_TASK_ROOTCREDS 0x0040 /* force root creds */ #define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */ @@ -135,6 +136,7 @@ struct rpc_call_ops { #define RPC_TASK_NOINTR 0x0400 /* uninterruptible task */ #define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC) +#define RPC_IS_CHILD(t) ((t)->tk_flags & RPC_TASK_CHILD) #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) #define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS) #define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED) @@ -251,6 +253,7 @@ struct rpc_task *rpc_new_task(struct rpc_clnt *, int flags, const struct rpc_call_ops *ops, void *data); struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *ops, void *data); +struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent); void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, const struct rpc_call_ops *ops, void *data); @@ -258,6 +261,8 @@ void rpc_release_task(struct rpc_task *); void rpc_exit_task(struct rpc_task *); void rpc_killall_tasks(struct rpc_clnt *); int rpc_execute(struct rpc_task *); +void rpc_run_child(struct rpc_task *parent, struct rpc_task *child, + rpc_action action); void rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *); void rpc_init_wait_queue(struct rpc_wait_queue *, const char *); void rpc_sleep_on(struct rpc_wait_queue *, struct rpc_task *, diff --git a/trunk/include/linux/sunrpc/xprt.h b/trunk/include/linux/sunrpc/xprt.h index bdeba8538c71..e8bbe8118de8 100644 --- a/trunk/include/linux/sunrpc/xprt.h +++ b/trunk/include/linux/sunrpc/xprt.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -38,7 +37,7 @@ extern unsigned int xprt_max_resvport; #define RPC_MIN_RESVPORT (1U) #define RPC_MAX_RESVPORT (65535U) -#define RPC_DEF_MIN_RESVPORT (665U) +#define RPC_DEF_MIN_RESVPORT (650U) #define RPC_DEF_MAX_RESVPORT (1023U) /* @@ -52,14 +51,6 @@ struct rpc_timeout { unsigned char to_exponential; }; -enum rpc_display_format_t { - RPC_DISPLAY_ADDR = 0, - RPC_DISPLAY_PORT, - RPC_DISPLAY_PROTO, - RPC_DISPLAY_ALL, - RPC_DISPLAY_MAX, -}; - struct rpc_task; struct rpc_xprt; struct seq_file; @@ -112,10 +103,8 @@ struct rpc_rqst { struct rpc_xprt_ops { void (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize); - char * (*print_addr)(struct rpc_xprt *xprt, enum rpc_display_format_t format); int (*reserve_xprt)(struct rpc_task *task); void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); - void (*rpcbind)(struct rpc_task *task); void (*set_port)(struct rpc_xprt *xprt, unsigned short port); void (*connect)(struct rpc_task *task); void * (*buf_alloc)(struct rpc_task *task, size_t size); @@ -130,14 +119,12 @@ struct rpc_xprt_ops { }; struct rpc_xprt { - struct kref kref; /* Reference count */ struct rpc_xprt_ops * ops; /* transport methods */ struct socket * sock; /* BSD socket layer */ struct sock * inet; /* INET layer */ struct rpc_timeout timeout; /* timeout parms */ - struct sockaddr_storage addr; /* server address */ - size_t addrlen; /* size of server address */ + struct sockaddr_in addr; /* server address */ int prot; /* IP protocol */ unsigned long cong; /* current congestion */ @@ -151,7 +138,6 @@ struct rpc_xprt { unsigned int tsh_size; /* size of transport specific header */ - struct rpc_wait_queue binding; /* requests waiting on rpcbind */ struct rpc_wait_queue sending; /* requests waiting to send */ struct rpc_wait_queue resend; /* requests waiting to resend */ struct rpc_wait_queue pending; /* requests in flight */ @@ -219,8 +205,6 @@ struct rpc_xprt { void (*old_data_ready)(struct sock *, int); void (*old_state_change)(struct sock *); void (*old_write_space)(struct sock *); - - char * address_strings[RPC_DISPLAY_MAX]; }; #define XPRT_LAST_FRAG (1 << 0) @@ -233,25 +217,24 @@ struct rpc_xprt { /* * Transport operations used by ULPs */ +struct rpc_xprt * xprt_create_proto(int proto, struct sockaddr_in *addr, struct rpc_timeout *to); void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long incr); /* * Generic internal transport functions */ -struct rpc_xprt * xprt_create_transport(int proto, struct sockaddr *addr, size_t size, struct rpc_timeout *toparms); void xprt_connect(struct rpc_task *task); void xprt_reserve(struct rpc_task *task); int xprt_reserve_xprt(struct rpc_task *task); int xprt_reserve_xprt_cong(struct rpc_task *task); int xprt_prepare_transmit(struct rpc_task *task); void xprt_transmit(struct rpc_task *task); -void xprt_end_transmit(struct rpc_task *task); +void xprt_abort_transmit(struct rpc_task *task); int xprt_adjust_timeout(struct rpc_rqst *req); void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); void xprt_release(struct rpc_task *task); -struct rpc_xprt * xprt_get(struct rpc_xprt *xprt); -void xprt_put(struct rpc_xprt *xprt); +int xprt_destroy(struct rpc_xprt *xprt); static inline u32 *xprt_skip_transport_header(struct rpc_xprt *xprt, u32 *p) { @@ -286,8 +269,6 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to); #define XPRT_CONNECTED (1) #define XPRT_CONNECTING (2) #define XPRT_CLOSE_WAIT (3) -#define XPRT_BOUND (4) -#define XPRT_BINDING (5) static inline void xprt_set_connected(struct rpc_xprt *xprt) { @@ -331,33 +312,6 @@ static inline int xprt_test_and_set_connecting(struct rpc_xprt *xprt) return test_and_set_bit(XPRT_CONNECTING, &xprt->state); } -static inline void xprt_set_bound(struct rpc_xprt *xprt) -{ - test_and_set_bit(XPRT_BOUND, &xprt->state); -} - -static inline int xprt_bound(struct rpc_xprt *xprt) -{ - return test_bit(XPRT_BOUND, &xprt->state); -} - -static inline void xprt_clear_bound(struct rpc_xprt *xprt) -{ - clear_bit(XPRT_BOUND, &xprt->state); -} - -static inline void xprt_clear_binding(struct rpc_xprt *xprt) -{ - smp_mb__before_clear_bit(); - clear_bit(XPRT_BINDING, &xprt->state); - smp_mb__after_clear_bit(); -} - -static inline int xprt_test_and_set_binding(struct rpc_xprt *xprt) -{ - return test_and_set_bit(XPRT_BINDING, &xprt->state); -} - #endif /* __KERNEL__*/ #endif /* _LINUX_SUNRPC_XPRT_H */ diff --git a/trunk/include/linux/sysctl.h b/trunk/include/linux/sysctl.h index 736ed917a4f8..e4b1a4d4dcf3 100644 --- a/trunk/include/linux/sysctl.h +++ b/trunk/include/linux/sysctl.h @@ -411,10 +411,6 @@ enum NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS=115, NET_TCP_DMA_COPYBREAK=116, NET_TCP_SLOW_START_AFTER_IDLE=117, - NET_CIPSOV4_CACHE_ENABLE=118, - NET_CIPSOV4_CACHE_BUCKET_SIZE=119, - NET_CIPSOV4_RBM_OPTFMT=120, - NET_CIPSOV4_RBM_STRICTVALID=121, }; enum { @@ -556,7 +552,6 @@ enum { NET_IPV6_ACCEPT_RA_RTR_PREF=20, NET_IPV6_RTR_PROBE_INTERVAL=21, NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=22, - NET_IPV6_PROXY_NDP=23, __NET_IPV6_MAX }; diff --git a/trunk/include/linux/tc_act/Kbuild b/trunk/include/linux/tc_act/Kbuild index 78dfbac36375..5251a505b2f1 100644 --- a/trunk/include/linux/tc_act/Kbuild +++ b/trunk/include/linux/tc_act/Kbuild @@ -1,4 +1 @@ -header-y += tc_gact.h -header-y += tc_ipt.h -header-y += tc_mirred.h -header-y += tc_pedit.h +header-y += tc_gact.h tc_ipt.h tc_mirred.h tc_pedit.h diff --git a/trunk/include/linux/tc_ematch/Kbuild b/trunk/include/linux/tc_ematch/Kbuild index 4a58a1c32a00..381e93018df6 100644 --- a/trunk/include/linux/tc_ematch/Kbuild +++ b/trunk/include/linux/tc_ematch/Kbuild @@ -1,4 +1 @@ -header-y += tc_em_cmp.h -header-y += tc_em_meta.h -header-y += tc_em_nbyte.h -header-y += tc_em_text.h +headers-y := tc_em_cmp.h tc_em_meta.h tc_em_nbyte.h tc_em_text.h diff --git a/trunk/include/linux/timex.h b/trunk/include/linux/timex.h index d543d3871e38..19bb6538b49e 100644 --- a/trunk/include/linux/timex.h +++ b/trunk/include/linux/timex.h @@ -57,6 +57,7 @@ #include #include +#include /* * SHIFT_KG and SHIFT_KF establish the damping of the PLL and are chosen @@ -190,8 +191,6 @@ struct timex { #define TIME_BAD TIME_ERROR /* bw compat */ #ifdef __KERNEL__ -#include - /* * kernel variables * Note: maximum error = NTP synch distance = dispersion + delay / 2; diff --git a/trunk/include/linux/tty.h b/trunk/include/linux/tty.h index 04827ca65781..e421d5e34818 100644 --- a/trunk/include/linux/tty.h +++ b/trunk/include/linux/tty.h @@ -59,7 +59,6 @@ struct tty_bufhead { struct tty_buffer *head; /* Queue head */ struct tty_buffer *tail; /* Active buffer */ struct tty_buffer *free; /* Free queue head */ - int memory_used; /* Buffer space used excluding free queue */ }; /* * The pty uses char_buf and flag_buf as a contiguous buffer diff --git a/trunk/include/linux/usb.h b/trunk/include/linux/usb.h index d2bd0c8e0154..c944e8f06a4a 100644 --- a/trunk/include/linux/usb.h +++ b/trunk/include/linux/usb.h @@ -103,7 +103,8 @@ enum usb_interface_condition { * @condition: binding state of the interface: not bound, binding * (in probe()), bound to a driver, or unbinding (in disconnect()) * @dev: driver model's view of this device - * @class_dev: driver model's class view of this device. + * @usb_dev: if an interface is bound to the USB major, this will point + * to the sysfs representation for that device. * * USB device drivers attach to interfaces on a physical device. Each * interface encapsulates a single high level function, such as feeding @@ -143,7 +144,7 @@ struct usb_interface { * bound to */ enum usb_interface_condition condition; /* state of binding */ struct device dev; /* interface specific device info */ - struct class_device *class_dev; + struct device *usb_dev; /* pointer to the usb class's device, if any */ }; #define to_usb_interface(d) container_of(d, struct usb_interface, dev) #define interface_to_usbdev(intf) \ @@ -360,7 +361,7 @@ struct usb_device { char *serial; /* iSerialNumber string, if present */ struct list_head filelist; - struct class_device *class_dev; + struct device *usbfs_dev; struct dentry *usbfs_dentry; /* usbfs dentry entry for the device */ /* diff --git a/trunk/include/linux/usb_usual.h b/trunk/include/linux/usb_usual.h index e7fc5fed5b98..f38f43f20fae 100644 --- a/trunk/include/linux/usb_usual.h +++ b/trunk/include/linux/usb_usual.h @@ -44,9 +44,7 @@ US_FLAG(NO_WP_DETECT, 0x00000200) \ /* Don't check for write-protect */ \ US_FLAG(MAX_SECTORS_64, 0x00000400) \ - /* Sets max_sectors to 64 */ \ - US_FLAG(IGNORE_DEVICE, 0x00000800) \ - /* Don't claim device */ + /* Sets max_sectors to 64 */ #define US_FLAG(name, value) US_FL_##name = value , enum { US_DO_ALL_FLAGS }; diff --git a/trunk/include/linux/videodev.h b/trunk/include/linux/videodev.h index 8dba97a291f6..41bc7e9603cd 100644 --- a/trunk/include/linux/videodev.h +++ b/trunk/include/linux/videodev.h @@ -12,9 +12,9 @@ #ifndef __LINUX_VIDEODEV_H #define __LINUX_VIDEODEV_H -#include +#define HAVE_V4L1 1 -#if defined(CONFIG_VIDEO_V4L1_COMPAT) || !defined (__KERNEL__) +#include struct video_capability { @@ -336,8 +336,6 @@ struct video_code #define VID_HARDWARE_SN9C102 38 #define VID_HARDWARE_ARV 39 -#endif /* CONFIG_VIDEO_V4L1_COMPAT */ - #endif /* __LINUX_VIDEODEV_H */ /* diff --git a/trunk/include/linux/videodev2.h b/trunk/include/linux/videodev2.h index e3715d774197..a62673dad76e 100644 --- a/trunk/include/linux/videodev2.h +++ b/trunk/include/linux/videodev2.h @@ -22,6 +22,8 @@ #endif #include +#define HAVE_V4L2 1 + /* * Common stuff for both V4L1 and V4L2 * Moved from videodev.h @@ -714,7 +716,7 @@ struct v4l2_ext_control __s64 value64; void *reserved; }; -} __attribute__ ((packed)); +}; struct v4l2_ext_controls { diff --git a/trunk/include/linux/vmstat.h b/trunk/include/linux/vmstat.h index 2d9b1b60798a..1ab806c47514 100644 --- a/trunk/include/linux/vmstat.h +++ b/trunk/include/linux/vmstat.h @@ -41,23 +41,23 @@ DECLARE_PER_CPU(struct vm_event_state, vm_event_states); static inline void __count_vm_event(enum vm_event_item item) { - __get_cpu_var(vm_event_states).event[item]++; + __get_cpu_var(vm_event_states.event[item])++; } static inline void count_vm_event(enum vm_event_item item) { - get_cpu_var(vm_event_states).event[item]++; + get_cpu_var(vm_event_states.event[item])++; put_cpu(); } static inline void __count_vm_events(enum vm_event_item item, long delta) { - __get_cpu_var(vm_event_states).event[item] += delta; + __get_cpu_var(vm_event_states.event[item]) += delta; } static inline void count_vm_events(enum vm_event_item item, long delta) { - get_cpu_var(vm_event_states).event[item] += delta; + get_cpu_var(vm_event_states.event[item]) += delta; put_cpu(); } diff --git a/trunk/include/linux/vt.h b/trunk/include/linux/vt.h index ba806e8711be..8ab334a48222 100644 --- a/trunk/include/linux/vt.h +++ b/trunk/include/linux/vt.h @@ -60,6 +60,5 @@ struct vt_consize { #define VT_RESIZEX 0x560A /* set kernel's idea of screensize + more */ #define VT_LOCKSWITCH 0x560B /* disallow vt switching */ #define VT_UNLOCKSWITCH 0x560C /* allow vt switching */ -#define VT_GETHIFONTMASK 0x560D /* return hi font mask */ #endif /* _LINUX_VT_H */ diff --git a/trunk/include/linux/writeback.h b/trunk/include/linux/writeback.h index 0422036af4eb..9e38b566d0e7 100644 --- a/trunk/include/linux/writeback.h +++ b/trunk/include/linux/writeback.h @@ -85,7 +85,6 @@ int wakeup_pdflush(long nr_pages); void laptop_io_completion(void); void laptop_sync_completion(void); void throttle_vm_writeout(void); -void writeback_congestion_end(void); /* These are exported to sysctl. */ extern int dirty_background_ratio; diff --git a/trunk/include/linux/xfrm.h b/trunk/include/linux/xfrm.h index 14ecd19f4cdc..46a15c7a1a13 100644 --- a/trunk/include/linux/xfrm.h +++ b/trunk/include/linux/xfrm.h @@ -102,13 +102,6 @@ struct xfrm_stats { __u32 integrity_failed; }; -enum -{ - XFRM_POLICY_TYPE_MAIN = 0, - XFRM_POLICY_TYPE_SUB = 1, - XFRM_POLICY_TYPE_MAX = 2 -}; - enum { XFRM_POLICY_IN = 0, @@ -127,9 +120,7 @@ enum #define XFRM_MODE_TRANSPORT 0 #define XFRM_MODE_TUNNEL 1 -#define XFRM_MODE_ROUTEOPTIMIZATION 2 -#define XFRM_MODE_IN_TRIGGER 3 -#define XFRM_MODE_MAX 4 +#define XFRM_MODE_MAX 2 /* Netlink configuration messages. */ enum { @@ -173,10 +164,6 @@ enum { #define XFRM_MSG_NEWAE XFRM_MSG_NEWAE XFRM_MSG_GETAE, #define XFRM_MSG_GETAE XFRM_MSG_GETAE - - XFRM_MSG_REPORT, -#define XFRM_MSG_REPORT XFRM_MSG_REPORT - __XFRM_MSG_MAX }; #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1) @@ -230,12 +217,6 @@ enum xfrm_ae_ftype_t { #define XFRM_AE_MAX (__XFRM_AE_MAX - 1) }; -struct xfrm_userpolicy_type { - __u8 type; - __u16 reserved1; - __u8 reserved2; -}; - /* Netlink message attributes. */ enum xfrm_attr_type_t { XFRMA_UNSPEC, @@ -251,10 +232,6 @@ enum xfrm_attr_type_t { XFRMA_REPLAY_VAL, XFRMA_REPLAY_THRESH, XFRMA_ETIMER_THRESH, - XFRMA_SRCADDR, /* xfrm_address_t */ - XFRMA_COADDR, /* xfrm_address_t */ - XFRMA_LASTUSED, - XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */ __XFRMA_MAX #define XFRMA_MAX (__XFRMA_MAX - 1) @@ -270,13 +247,12 @@ struct xfrm_usersa_info { __u32 seq; __u32 reqid; __u16 family; - __u8 mode; /* XFRM_MODE_xxx */ + __u8 mode; /* 0=transport,1=tunnel */ __u8 replay_window; __u8 flags; #define XFRM_STATE_NOECN 1 #define XFRM_STATE_DECAP_DSCP 2 #define XFRM_STATE_NOPMTUDISC 4 -#define XFRM_STATE_WILDRECV 8 }; struct xfrm_usersa_id { @@ -343,18 +319,12 @@ struct xfrm_usersa_flush { __u8 proto; }; -struct xfrm_user_report { - __u8 proto; - struct xfrm_selector sel; -}; - #ifndef __KERNEL__ /* backwards compatibility for userspace */ #define XFRMGRP_ACQUIRE 1 #define XFRMGRP_EXPIRE 2 #define XFRMGRP_SA 4 #define XFRMGRP_POLICY 8 -#define XFRMGRP_REPORT 0x10 #endif enum xfrm_nlgroups { @@ -370,8 +340,6 @@ enum xfrm_nlgroups { #define XFRMNLGRP_POLICY XFRMNLGRP_POLICY XFRMNLGRP_AEVENTS, #define XFRMNLGRP_AEVENTS XFRMNLGRP_AEVENTS - XFRMNLGRP_REPORT, -#define XFRMNLGRP_REPORT XFRMNLGRP_REPORT __XFRMNLGRP_MAX }; #define XFRMNLGRP_MAX (__XFRMNLGRP_MAX - 1) diff --git a/trunk/include/media/v4l2-dev.h b/trunk/include/media/v4l2-dev.h index 810462f8a374..62dae1a8c441 100644 --- a/trunk/include/media/v4l2-dev.h +++ b/trunk/include/media/v4l2-dev.h @@ -16,7 +16,7 @@ #include #include #include /* need __user */ -#ifdef CONFIG_VIDEO_V4L1_COMPAT +#ifdef CONFIG_VIDEO_V4L1 #include #else #include @@ -194,7 +194,7 @@ struct video_device int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i); -#ifdef CONFIG_VIDEO_V4L1_COMPAT +#ifdef HAVE_V4L1 /* buffer type is struct vidio_mbuf * */ int (*vidiocgmbuf) (struct file *file, void *fh, struct video_mbuf *p); #endif @@ -335,20 +335,17 @@ extern int video_usercopy(struct inode *inode, struct file *file, unsigned int cmd, void *arg)); -#ifdef CONFIG_VIDEO_V4L1_COMPAT +#ifdef HAVE_V4L1 #include extern struct video_device* video_devdata(struct file*); #define to_video_device(cd) container_of(cd, struct video_device, class_dev) -static inline int +static inline void video_device_create_file(struct video_device *vfd, struct class_device_attribute *attr) { - int ret = class_device_create_file(&vfd->class_dev, attr); - if (ret < 0) - printk(KERN_WARNING "%s error: %d\n", __FUNCTION__, ret); - return ret; + class_device_create_file(&vfd->class_dev, attr); } static inline void video_device_remove_file(struct video_device *vfd, @@ -357,8 +354,6 @@ video_device_remove_file(struct video_device *vfd, class_device_remove_file(&vfd->class_dev, attr); } -#endif /* CONFIG_VIDEO_V4L1_COMPAT */ - #ifdef OBSOLETE_OWNER /* to be removed soon */ /* helper functions to access driver private data. */ static inline void *video_get_drvdata(struct video_device *dev) @@ -374,5 +369,6 @@ static inline void video_set_drvdata(struct video_device *dev, void *data) extern int video_exclusive_open(struct inode *inode, struct file *file); extern int video_exclusive_release(struct inode *inode, struct file *file); +#endif /* HAVE_V4L1 */ #endif /* _V4L2_DEV_H */ diff --git a/trunk/include/mtd/Kbuild b/trunk/include/mtd/Kbuild index 13e7a3c6d794..e1da2a5b2a57 100644 --- a/trunk/include/mtd/Kbuild +++ b/trunk/include/mtd/Kbuild @@ -1,6 +1,2 @@ -header-y += inftl-user.h -header-y += jffs2-user.h -header-y += mtd-user.h -header-y += nftl-user.h - -unifdef-y += mtd-abi.h +unifdef-y := mtd-abi.h +header-y := inftl-user.h jffs2-user.h mtd-user.h nftl-user.h diff --git a/trunk/include/mtd/mtd-abi.h b/trunk/include/mtd/mtd-abi.h index b0a67b7ffdcd..1da3f7fa7993 100644 --- a/trunk/include/mtd/mtd-abi.h +++ b/trunk/include/mtd/mtd-abi.h @@ -34,7 +34,6 @@ struct mtd_oob_buf { #define MTD_WRITEABLE 0x400 /* Device is writeable */ #define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */ #define MTD_NO_ERASE 0x1000 /* No erase necessary */ -#define MTD_STUPID_LOCK 0x2000 /* Always locked after reset */ // Some common devices / combinations of capabilities #define MTD_CAP_ROM 0 diff --git a/trunk/include/net/act_api.h b/trunk/include/net/act_api.h index 8b06c2f3657f..11e9eaf79f5a 100644 --- a/trunk/include/net/act_api.h +++ b/trunk/include/net/act_api.h @@ -8,110 +8,70 @@ #include #include -struct tcf_common { - struct tcf_common *tcfc_next; - u32 tcfc_index; - int tcfc_refcnt; - int tcfc_bindcnt; - u32 tcfc_capab; - int tcfc_action; - struct tcf_t tcfc_tm; - struct gnet_stats_basic tcfc_bstats; - struct gnet_stats_queue tcfc_qstats; - struct gnet_stats_rate_est tcfc_rate_est; - spinlock_t *tcfc_stats_lock; - spinlock_t tcfc_lock; -}; -#define tcf_next common.tcfc_next -#define tcf_index common.tcfc_index -#define tcf_refcnt common.tcfc_refcnt -#define tcf_bindcnt common.tcfc_bindcnt -#define tcf_capab common.tcfc_capab -#define tcf_action common.tcfc_action -#define tcf_tm common.tcfc_tm -#define tcf_bstats common.tcfc_bstats -#define tcf_qstats common.tcfc_qstats -#define tcf_rate_est common.tcfc_rate_est -#define tcf_stats_lock common.tcfc_stats_lock -#define tcf_lock common.tcfc_lock - -struct tcf_police { - struct tcf_common common; - int tcfp_result; - u32 tcfp_ewma_rate; - u32 tcfp_burst; - u32 tcfp_mtu; - u32 tcfp_toks; - u32 tcfp_ptoks; - psched_time_t tcfp_t_c; - struct qdisc_rate_table *tcfp_R_tab; - struct qdisc_rate_table *tcfp_P_tab; -}; -#define to_police(pc) \ - container_of(pc, struct tcf_police, common) - -struct tcf_hashinfo { - struct tcf_common **htab; - unsigned int hmask; - rwlock_t *lock; -}; - -static inline unsigned int tcf_hash(u32 index, unsigned int hmask) +#define tca_gen(name) \ +struct tcf_##name *next; \ + u32 index; \ + int refcnt; \ + int bindcnt; \ + u32 capab; \ + int action; \ + struct tcf_t tm; \ + struct gnet_stats_basic bstats; \ + struct gnet_stats_queue qstats; \ + struct gnet_stats_rate_est rate_est; \ + spinlock_t *stats_lock; \ + spinlock_t lock + +struct tcf_police { - return index & hmask; -} + tca_gen(police); + int result; + u32 ewma_rate; + u32 burst; + u32 mtu; + u32 toks; + u32 ptoks; + psched_time_t t_c; + struct qdisc_rate_table *R_tab; + struct qdisc_rate_table *P_tab; +}; #ifdef CONFIG_NET_CLS_ACT #define ACT_P_CREATED 1 #define ACT_P_DELETED 1 -struct tcf_act_hdr { - struct tcf_common common; +struct tcf_act_hdr +{ + tca_gen(act_hdr); }; -struct tc_action { - void *priv; - struct tc_action_ops *ops; - __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ - __u32 order; - struct tc_action *next; +struct tc_action +{ + void *priv; + struct tc_action_ops *ops; + __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ + __u32 order; + struct tc_action *next; }; #define TCA_CAP_NONE 0 -struct tc_action_ops { +struct tc_action_ops +{ struct tc_action_ops *next; - struct tcf_hashinfo *hinfo; char kind[IFNAMSIZ]; __u32 type; /* TBD to match kind */ __u32 capab; /* capabilities includes 4 bit version */ struct module *owner; int (*act)(struct sk_buff *, struct tc_action *, struct tcf_result *); int (*get_stats)(struct sk_buff *, struct tc_action *); - int (*dump)(struct sk_buff *, struct tc_action *, int, int); + int (*dump)(struct sk_buff *, struct tc_action *,int , int); int (*cleanup)(struct tc_action *, int bind); - int (*lookup)(struct tc_action *, u32); - int (*init)(struct rtattr *, struct rtattr *, struct tc_action *, int , int); - int (*walk)(struct sk_buff *, struct netlink_callback *, int, struct tc_action *); + int (*lookup)(struct tc_action *, u32 ); + int (*init)(struct rtattr *,struct rtattr *,struct tc_action *, int , int ); + int (*walk)(struct sk_buff *, struct netlink_callback *, int , struct tc_action *); }; -extern struct tcf_common *tcf_hash_lookup(u32 index, - struct tcf_hashinfo *hinfo); -extern void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo); -extern int tcf_hash_release(struct tcf_common *p, int bind, - struct tcf_hashinfo *hinfo); -extern int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, - int type, struct tc_action *a); -extern u32 tcf_hash_new_index(u32 *idx_gen, struct tcf_hashinfo *hinfo); -extern int tcf_hash_search(struct tc_action *a, u32 index); -extern struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, - int bind, struct tcf_hashinfo *hinfo); -extern struct tcf_common *tcf_hash_create(u32 index, struct rtattr *est, - struct tc_action *a, int size, - int bind, u32 *idx_gen, - struct tcf_hashinfo *hinfo); -extern void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo); - extern int tcf_register_action(struct tc_action_ops *a); extern int tcf_unregister_action(struct tc_action_ops *a); extern void tcf_action_destroy(struct tc_action *a, int bind); @@ -136,17 +96,17 @@ tcf_police_release(struct tcf_police *p, int bind) int ret = 0; #ifdef CONFIG_NET_CLS_ACT if (p) { - if (bind) - p->tcf_bindcnt--; - - p->tcf_refcnt--; - if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) { + if (bind) { + p->bindcnt--; + } + p->refcnt--; + if (p->refcnt <= 0 && !p->bindcnt) { tcf_police_destroy(p); ret = 1; } } #else - if (p && --p->tcf_refcnt == 0) + if (p && --p->refcnt == 0) tcf_police_destroy(p); #endif /* CONFIG_NET_CLS_ACT */ diff --git a/trunk/include/net/act_generic.h b/trunk/include/net/act_generic.h new file mode 100644 index 000000000000..c9daa7e52300 --- /dev/null +++ b/trunk/include/net/act_generic.h @@ -0,0 +1,142 @@ +/* + * include/net/act_generic.h + * +*/ +#ifndef _NET_ACT_GENERIC_H +#define _NET_ACT_GENERIC_H +static inline int tcf_defact_release(struct tcf_defact *p, int bind) +{ + int ret = 0; + if (p) { + if (bind) { + p->bindcnt--; + } + p->refcnt--; + if (p->bindcnt <= 0 && p->refcnt <= 0) { + kfree(p->defdata); + tcf_hash_destroy(p); + ret = 1; + } + } + return ret; +} + +static inline int +alloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata) +{ + p->defdata = kmalloc(datalen, GFP_KERNEL); + if (p->defdata == NULL) + return -ENOMEM; + p->datalen = datalen; + memcpy(p->defdata, defdata, datalen); + return 0; +} + +static inline int +realloc_defdata(struct tcf_defact *p, u32 datalen, void *defdata) +{ + /* safer to be just brute force for now */ + kfree(p->defdata); + return alloc_defdata(p, datalen, defdata); +} + +static inline int +tcf_defact_init(struct rtattr *rta, struct rtattr *est, + struct tc_action *a, int ovr, int bind) +{ + struct rtattr *tb[TCA_DEF_MAX]; + struct tc_defact *parm; + struct tcf_defact *p; + void *defdata; + u32 datalen = 0; + int ret = 0; + + if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0) + return -EINVAL; + + if (tb[TCA_DEF_PARMS - 1] == NULL || + RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm)) + return -EINVAL; + + parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]); + defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]); + if (defdata == NULL) + return -EINVAL; + + datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]); + if (datalen <= 0) + return -EINVAL; + + p = tcf_hash_check(parm->index, a, ovr, bind); + if (p == NULL) { + p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); + if (p == NULL) + return -ENOMEM; + + ret = alloc_defdata(p, datalen, defdata); + if (ret < 0) { + kfree(p); + return ret; + } + ret = ACT_P_CREATED; + } else { + if (!ovr) { + tcf_defact_release(p, bind); + return -EEXIST; + } + realloc_defdata(p, datalen, defdata); + } + + spin_lock_bh(&p->lock); + p->action = parm->action; + spin_unlock_bh(&p->lock); + if (ret == ACT_P_CREATED) + tcf_hash_insert(p); + return ret; +} + +static inline int tcf_defact_cleanup(struct tc_action *a, int bind) +{ + struct tcf_defact *p = PRIV(a, defact); + + if (p != NULL) + return tcf_defact_release(p, bind); + return 0; +} + +static inline int +tcf_defact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) +{ + unsigned char *b = skb->tail; + struct tc_defact opt; + struct tcf_defact *p = PRIV(a, defact); + struct tcf_t t; + + opt.index = p->index; + opt.refcnt = p->refcnt - ref; + opt.bindcnt = p->bindcnt - bind; + opt.action = p->action; + RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt); + RTA_PUT(skb, TCA_DEF_DATA, p->datalen, p->defdata); + t.install = jiffies_to_clock_t(jiffies - p->tm.install); + t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); + t.expires = jiffies_to_clock_t(p->tm.expires); + RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t); + return skb->len; + +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; +} + +#define tca_use_default_ops \ + .dump = tcf_defact_dump, \ + .cleanup = tcf_defact_cleanup, \ + .init = tcf_defact_init, \ + .walk = tcf_generic_walker, \ + +#define tca_use_default_defines(name) \ + static u32 idx_gen; \ + static struct tcf_defact *tcf_##name_ht[MY_TAB_SIZE]; \ + static DEFINE_RWLOCK(##name_lock); +#endif /* _NET_ACT_GENERIC_H */ diff --git a/trunk/include/net/addrconf.h b/trunk/include/net/addrconf.h index 44f1b673f916..3d71251b3eca 100644 --- a/trunk/include/net/addrconf.h +++ b/trunk/include/net/addrconf.h @@ -61,9 +61,6 @@ extern int addrconf_set_dstaddr(void __user *arg); extern int ipv6_chk_addr(struct in6_addr *addr, struct net_device *dev, int strict); -#ifdef CONFIG_IPV6_MIP6 -extern int ipv6_chk_home_addr(struct in6_addr *addr); -#endif extern struct inet6_ifaddr * ipv6_get_ifaddr(struct in6_addr *addr, struct net_device *dev, int strict); @@ -129,18 +126,20 @@ extern int unregister_inet6addr_notifier(struct notifier_block *nb); static inline struct inet6_dev * __in6_dev_get(struct net_device *dev) { - return rcu_dereference(dev->ip6_ptr); + return (struct inet6_dev *)dev->ip6_ptr; } +extern rwlock_t addrconf_lock; + static inline struct inet6_dev * in6_dev_get(struct net_device *dev) { struct inet6_dev *idev = NULL; - rcu_read_lock(); - idev = __in6_dev_get(dev); + read_lock(&addrconf_lock); + idev = dev->ip6_ptr; if (idev) atomic_inc(&idev->refcnt); - rcu_read_unlock(); + read_unlock(&addrconf_lock); return idev; } diff --git a/trunk/include/net/af_unix.h b/trunk/include/net/af_unix.h index c0398f5a8cb9..2fec827c8801 100644 --- a/trunk/include/net/af_unix.h +++ b/trunk/include/net/af_unix.h @@ -54,13 +54,15 @@ struct unix_skb_parms { struct ucred creds; /* Skb credentials */ struct scm_fp_list *fp; /* Passed files */ #ifdef CONFIG_SECURITY_NETWORK - u32 secid; /* Security ID */ + char *secdata; /* Security context */ + u32 seclen; /* Security length */ #endif }; #define UNIXCB(skb) (*(struct unix_skb_parms*)&((skb)->cb)) #define UNIXCREDS(skb) (&UNIXCB((skb)).creds) -#define UNIXSID(skb) (&UNIXCB((skb)).secid) +#define UNIXSECDATA(skb) (&UNIXCB((skb)).secdata) +#define UNIXSECLEN(skb) (&UNIXCB((skb)).seclen) #define unix_state_rlock(s) spin_lock(&unix_sk(s)->lock) #define unix_state_runlock(s) spin_unlock(&unix_sk(s)->lock) diff --git a/trunk/include/net/ah.h b/trunk/include/net/ah.h index 8f257c159902..ceff00afae09 100644 --- a/trunk/include/net/ah.h +++ b/trunk/include/net/ah.h @@ -1,7 +1,6 @@ #ifndef _NET_AH_H #define _NET_AH_H -#include #include /* This is the maximum truncated ICV length that we know of. */ @@ -15,29 +14,22 @@ struct ah_data int icv_full_len; int icv_trunc_len; - struct crypto_hash *tfm; + void (*icv)(struct ah_data*, + struct sk_buff *skb, u8 *icv); + + struct crypto_tfm *tfm; }; -static inline int ah_mac_digest(struct ah_data *ahp, struct sk_buff *skb, - u8 *auth_data) +static inline void +ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data) { - struct hash_desc desc; - int err; - - desc.tfm = ahp->tfm; - desc.flags = 0; + struct crypto_tfm *tfm = ahp->tfm; memset(auth_data, 0, ahp->icv_trunc_len); - err = crypto_hash_init(&desc); - if (unlikely(err)) - goto out; - err = skb_icv_walk(skb, &desc, 0, skb->len, crypto_hash_update); - if (unlikely(err)) - goto out; - err = crypto_hash_final(&desc, ahp->work_icv); - -out: - return err; + crypto_hmac_init(tfm, ahp->key, &ahp->key_len); + skb_icv_walk(skb, tfm, 0, skb->len, crypto_hmac_update); + crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_icv); + memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len); } #endif diff --git a/trunk/include/net/cipso_ipv4.h b/trunk/include/net/cipso_ipv4.h deleted file mode 100644 index 59406e0dc5b2..000000000000 --- a/trunk/include/net/cipso_ipv4.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * CIPSO - Commercial IP Security Option - * - * This is an implementation of the CIPSO 2.2 protocol as specified in - * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in - * FIPS-188, copies of both documents can be found in the Documentation - * directory. While CIPSO never became a full IETF RFC standard many vendors - * have chosen to adopt the protocol and over the years it has become a - * de-facto standard for labeled networking. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _CIPSO_IPV4_H -#define _CIPSO_IPV4_H - -#include -#include -#include -#include -#include -#include - -/* known doi values */ -#define CIPSO_V4_DOI_UNKNOWN 0x00000000 - -/* tag types */ -#define CIPSO_V4_TAG_INVALID 0 -#define CIPSO_V4_TAG_RBITMAP 1 -#define CIPSO_V4_TAG_ENUM 2 -#define CIPSO_V4_TAG_RANGE 5 -#define CIPSO_V4_TAG_PBITMAP 6 -#define CIPSO_V4_TAG_FREEFORM 7 - -/* doi mapping types */ -#define CIPSO_V4_MAP_UNKNOWN 0 -#define CIPSO_V4_MAP_STD 1 -#define CIPSO_V4_MAP_PASS 2 - -/* limits */ -#define CIPSO_V4_MAX_REM_LVLS 256 -#define CIPSO_V4_INV_LVL 0x80000000 -#define CIPSO_V4_MAX_LOC_LVLS (CIPSO_V4_INV_LVL - 1) -#define CIPSO_V4_MAX_REM_CATS 65536 -#define CIPSO_V4_INV_CAT 0x80000000 -#define CIPSO_V4_MAX_LOC_CATS (CIPSO_V4_INV_CAT - 1) - -/* - * CIPSO DOI definitions - */ - -/* DOI definition struct */ -#define CIPSO_V4_TAG_MAXCNT 5 -struct cipso_v4_doi { - u32 doi; - u32 type; - union { - struct cipso_v4_std_map_tbl *std; - } map; - u8 tags[CIPSO_V4_TAG_MAXCNT]; - - u32 valid; - struct list_head list; - struct rcu_head rcu; - struct list_head dom_list; -}; - -/* Standard CIPSO mapping table */ -/* NOTE: the highest order bit (i.e. 0x80000000) is an 'invalid' flag, if the - * bit is set then consider that value as unspecified, meaning the - * mapping for that particular level/category is invalid */ -struct cipso_v4_std_map_tbl { - struct { - u32 *cipso; - u32 *local; - u32 cipso_size; - u32 local_size; - } lvl; - struct { - u32 *cipso; - u32 *local; - u32 cipso_size; - u32 local_size; - } cat; -}; - -/* - * Sysctl Variables - */ - -#ifdef CONFIG_NETLABEL -extern int cipso_v4_cache_enabled; -extern int cipso_v4_cache_bucketsize; -extern int cipso_v4_rbm_optfmt; -extern int cipso_v4_rbm_strictvalid; -#endif - -/* - * Helper Functions - */ - -#define CIPSO_V4_OPTEXIST(x) (IPCB(x)->opt.cipso != 0) -#define CIPSO_V4_OPTPTR(x) ((x)->nh.raw + IPCB(x)->opt.cipso) - -/* - * DOI List Functions - */ - -#ifdef CONFIG_NETLABEL -int cipso_v4_doi_add(struct cipso_v4_doi *doi_def); -int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head)); -struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi); -struct sk_buff *cipso_v4_doi_dump_all(size_t headroom); -struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom); -int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain); -int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, - const char *domain); -#else -static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) -{ - return -ENOSYS; -} - -static inline int cipso_v4_doi_remove(u32 doi, - void (*callback) (struct rcu_head * head)) -{ - return 0; -} - -static inline struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi) -{ - return NULL; -} - -static inline struct sk_buff *cipso_v4_doi_dump_all(size_t headroom) -{ - return NULL; -} - -static inline struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom) -{ - return NULL; -} - -static inline int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, - const char *domain) -{ - return -ENOSYS; -} - -static inline int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, - const char *domain) -{ - return 0; -} -#endif /* CONFIG_NETLABEL */ - -/* - * Label Mapping Cache Functions - */ - -#ifdef CONFIG_NETLABEL -void cipso_v4_cache_invalidate(void); -int cipso_v4_cache_add(const struct sk_buff *skb, - const struct netlbl_lsm_secattr *secattr); -#else -static inline void cipso_v4_cache_invalidate(void) -{ - return; -} - -static inline int cipso_v4_cache_add(const struct sk_buff *skb, - const struct netlbl_lsm_secattr *secattr) -{ - return 0; -} -#endif /* CONFIG_NETLABEL */ - -/* - * Protocol Handling Functions - */ - -#ifdef CONFIG_NETLABEL -void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway); -int cipso_v4_socket_setattr(const struct socket *sock, - const struct cipso_v4_doi *doi_def, - const struct netlbl_lsm_secattr *secattr); -int cipso_v4_socket_getattr(const struct socket *sock, - struct netlbl_lsm_secattr *secattr); -int cipso_v4_skbuff_getattr(const struct sk_buff *skb, - struct netlbl_lsm_secattr *secattr); -int cipso_v4_validate(unsigned char **option); -#else -static inline void cipso_v4_error(struct sk_buff *skb, - int error, - u32 gateway) -{ - return; -} - -static inline int cipso_v4_socket_setattr(const struct socket *sock, - const struct cipso_v4_doi *doi_def, - const struct netlbl_lsm_secattr *secattr) -{ - return -ENOSYS; -} - -static inline int cipso_v4_socket_getattr(const struct socket *sock, - struct netlbl_lsm_secattr *secattr) -{ - return -ENOSYS; -} - -static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb, - struct netlbl_lsm_secattr *secattr) -{ - return -ENOSYS; -} - -static inline int cipso_v4_validate(unsigned char **option) -{ - return -ENOSYS; -} -#endif /* CONFIG_NETLABEL */ - -#endif /* _CIPSO_IPV4_H */ diff --git a/trunk/include/net/dn_fib.h b/trunk/include/net/dn_fib.h index f01626cbbed6..a15dcf0d5c1e 100644 --- a/trunk/include/net/dn_fib.h +++ b/trunk/include/net/dn_fib.h @@ -22,7 +22,7 @@ struct dn_kern_rta }; struct dn_fib_res { - struct fib_rule *r; + struct dn_fib_rule *r; struct dn_fib_info *fi; unsigned char prefixlen; unsigned char nh_sel; @@ -94,8 +94,7 @@ struct dn_fib_node { struct dn_fib_table { - struct hlist_node hlist; - u32 n; + int n; int (*insert)(struct dn_fib_table *t, struct rtmsg *r, struct dn_kern_rta *rta, struct nlmsghdr *n, @@ -131,11 +130,14 @@ extern __le16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type); extern void dn_fib_flush(void); extern void dn_fib_select_multipath(const struct flowi *fl, struct dn_fib_res *res); +extern int dn_fib_sync_down(__le16 local, struct net_device *dev, + int force); +extern int dn_fib_sync_up(struct net_device *dev); /* * dn_tables.c */ -extern struct dn_fib_table *dn_fib_get_table(u32 n, int creat); +extern struct dn_fib_table *dn_fib_get_table(int n, int creat); extern struct dn_fib_table *dn_fib_empty_table(void); extern void dn_fib_table_init(void); extern void dn_fib_table_cleanup(void); @@ -145,8 +147,10 @@ extern void dn_fib_table_cleanup(void); */ extern void dn_fib_rules_init(void); extern void dn_fib_rules_cleanup(void); +extern void dn_fib_rule_put(struct dn_fib_rule *); +extern __le16 dn_fib_rules_policy(__le16 saddr, struct dn_fib_res *res, unsigned *flags); extern unsigned dnet_addr_type(__le16 addr); -extern int dn_fib_lookup(struct flowi *fl, struct dn_fib_res *res); +extern int dn_fib_lookup(const struct flowi *fl, struct dn_fib_res *res); /* * rtnetlink interface @@ -172,9 +176,11 @@ static inline void dn_fib_res_put(struct dn_fib_res *res) if (res->fi) dn_fib_info_put(res->fi); if (res->r) - fib_rule_put(res->r); + dn_fib_rule_put(res->r); } +extern struct dn_fib_table *dn_fib_tables[]; + #else /* Endnode */ #define dn_fib_init() do { } while(0) diff --git a/trunk/include/net/dst.h b/trunk/include/net/dst.h index a8d825f90305..36d54fc248b0 100644 --- a/trunk/include/net/dst.h +++ b/trunk/include/net/dst.h @@ -54,7 +54,6 @@ struct dst_entry unsigned long expires; unsigned short header_len; /* more space at head required */ - unsigned short nfheader_len; /* more non-fragment space at head required */ unsigned short trailer_len; /* space to reserve at tail */ u32 metrics[RTAX_MAX]; diff --git a/trunk/include/net/esp.h b/trunk/include/net/esp.h index 713d039f4af7..90cd94fad7d9 100644 --- a/trunk/include/net/esp.h +++ b/trunk/include/net/esp.h @@ -1,7 +1,6 @@ #ifndef _NET_ESP_H #define _NET_ESP_H -#include #include #include @@ -15,15 +14,14 @@ struct esp_data struct { u8 *key; /* Key */ int key_len; /* Key length */ - int padlen; /* 0..255 */ + u8 *ivec; /* ivec buffer */ /* ivlen is offset from enc_data, where encrypted data start. * It is logically different of crypto_tfm_alg_ivsize(tfm). * We assume that it is either zero (no ivec), or * >= crypto_tfm_alg_ivsize(tfm). */ int ivlen; - int ivinitted; - u8 *ivec; /* ivec buffer */ - struct crypto_blkcipher *tfm; /* crypto handle */ + int padlen; /* 0..255 */ + struct crypto_tfm *tfm; /* crypto handle */ } conf; /* Integrity. It is active when icv_full_len != 0 */ @@ -36,7 +34,7 @@ struct esp_data void (*icv)(struct esp_data*, struct sk_buff *skb, int offset, int len, u8 *icv); - struct crypto_hash *tfm; + struct crypto_tfm *tfm; } auth; }; @@ -44,22 +42,18 @@ extern int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, extern int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer); extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len); -static inline int esp_mac_digest(struct esp_data *esp, struct sk_buff *skb, - int offset, int len) +static inline void +esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset, + int len, u8 *auth_data) { - struct hash_desc desc; - int err; - - desc.tfm = esp->auth.tfm; - desc.flags = 0; - - err = crypto_hash_init(&desc); - if (unlikely(err)) - return err; - err = skb_icv_walk(skb, &desc, offset, len, crypto_hash_update); - if (unlikely(err)) - return err; - return crypto_hash_final(&desc, esp->auth.work_icv); + struct crypto_tfm *tfm = esp->auth.tfm; + char *icv = esp->auth.work_icv; + + memset(auth_data, 0, esp->auth.icv_trunc_len); + crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len); + skb_icv_walk(skb, tfm, offset, len, crypto_hmac_update); + crypto_hmac_final(tfm, esp->auth.key, &esp->auth.key_len, icv); + memcpy(auth_data, icv, esp->auth.icv_trunc_len); } #endif diff --git a/trunk/include/net/fib_rules.h b/trunk/include/net/fib_rules.h deleted file mode 100644 index 8e2f473d3e82..000000000000 --- a/trunk/include/net/fib_rules.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef __NET_FIB_RULES_H -#define __NET_FIB_RULES_H - -#include -#include -#include -#include -#include - -struct fib_rule -{ - struct list_head list; - atomic_t refcnt; - int ifindex; - char ifname[IFNAMSIZ]; - u32 pref; - u32 flags; - u32 table; - u8 action; - struct rcu_head rcu; -}; - -struct fib_lookup_arg -{ - void *lookup_ptr; - void *result; - struct fib_rule *rule; -}; - -struct fib_rules_ops -{ - int family; - struct list_head list; - int rule_size; - - int (*action)(struct fib_rule *, - struct flowi *, int, - struct fib_lookup_arg *); - int (*match)(struct fib_rule *, - struct flowi *, int); - int (*configure)(struct fib_rule *, - struct sk_buff *, - struct nlmsghdr *, - struct fib_rule_hdr *, - struct nlattr **); - int (*compare)(struct fib_rule *, - struct fib_rule_hdr *, - struct nlattr **); - int (*fill)(struct fib_rule *, struct sk_buff *, - struct nlmsghdr *, - struct fib_rule_hdr *); - u32 (*default_pref)(void); - - int nlgroup; - struct nla_policy *policy; - struct list_head *rules_list; - struct module *owner; -}; - -static inline void fib_rule_get(struct fib_rule *rule) -{ - atomic_inc(&rule->refcnt); -} - -static inline void fib_rule_put_rcu(struct rcu_head *head) -{ - struct fib_rule *rule = container_of(head, struct fib_rule, rcu); - kfree(rule); -} - -static inline void fib_rule_put(struct fib_rule *rule) -{ - if (atomic_dec_and_test(&rule->refcnt)) - call_rcu(&rule->rcu, fib_rule_put_rcu); -} - -static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla) -{ - if (nla[FRA_TABLE]) - return nla_get_u32(nla[FRA_TABLE]); - return frh->table; -} - -extern int fib_rules_register(struct fib_rules_ops *); -extern int fib_rules_unregister(struct fib_rules_ops *); - -extern int fib_rules_lookup(struct fib_rules_ops *, - struct flowi *, int flags, - struct fib_lookup_arg *); - -extern int fib_nl_newrule(struct sk_buff *, - struct nlmsghdr *, void *); -extern int fib_nl_delrule(struct sk_buff *, - struct nlmsghdr *, void *); -extern int fib_rules_dump(struct sk_buff *, - struct netlink_callback *, int); -#endif diff --git a/trunk/include/net/flow.h b/trunk/include/net/flow.h index 3ca210ec1379..04d89f763451 100644 --- a/trunk/include/net/flow.h +++ b/trunk/include/net/flow.h @@ -26,7 +26,6 @@ struct flowi { struct { struct in6_addr daddr; struct in6_addr saddr; - __u32 fwmark; __u32 flowlabel; } ip6_u; @@ -43,7 +42,6 @@ struct flowi { #define fld_scope nl_u.dn_u.scope #define fl6_dst nl_u.ip6_u.daddr #define fl6_src nl_u.ip6_u.saddr -#define fl6_fwmark nl_u.ip6_u.fwmark #define fl6_flowlabel nl_u.ip6_u.flowlabel #define fl4_dst nl_u.ip4_u.daddr #define fl4_src nl_u.ip4_u.saddr @@ -74,22 +72,12 @@ struct flowi { } dnports; __u32 spi; - -#ifdef CONFIG_IPV6_MIP6 - struct { - __u8 type; - } mht; -#endif } uli_u; #define fl_ip_sport uli_u.ports.sport #define fl_ip_dport uli_u.ports.dport #define fl_icmp_type uli_u.icmpt.type #define fl_icmp_code uli_u.icmpt.code #define fl_ipsec_spi uli_u.spi -#ifdef CONFIG_IPV6_MIP6 -#define fl_mh_type uli_u.mht.type -#endif - __u32 secid; /* used by xfrm; see secid.txt */ } __attribute__((__aligned__(BITS_PER_LONG/8))); #define FLOW_DIR_IN 0 @@ -97,10 +85,10 @@ struct flowi { #define FLOW_DIR_FWD 2 struct sock; -typedef void (*flow_resolve_t)(struct flowi *key, u16 family, u8 dir, +typedef void (*flow_resolve_t)(struct flowi *key, u32 sk_sid, u16 family, u8 dir, void **objp, atomic_t **obj_refp); -extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, +extern void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir, flow_resolve_t resolver); extern void flow_cache_flush(void); extern atomic_t flow_cache_genid; diff --git a/trunk/include/net/genetlink.h b/trunk/include/net/genetlink.h index 4a38d85e4e25..8c2287264266 100644 --- a/trunk/include/net/genetlink.h +++ b/trunk/include/net/genetlink.h @@ -27,6 +27,8 @@ struct genl_family struct list_head family_list; /* private */ }; +#define GENL_ADMIN_PERM 0x01 + /** * struct genl_info - receiving information * @snd_seq: sending sequence number @@ -131,12 +133,11 @@ static inline int genlmsg_cancel(struct sk_buff *skb, void *hdr) * @skb: netlink message as socket buffer * @pid: own netlink pid to avoid sending to yourself * @group: multicast group id - * @flags: allocation flags */ static inline int genlmsg_multicast(struct sk_buff *skb, u32 pid, - unsigned int group, gfp_t flags) + unsigned int group) { - return nlmsg_multicast(genl_sock, skb, pid, group, flags); + return nlmsg_multicast(genl_sock, skb, pid, group); } /** diff --git a/trunk/include/net/if_inet6.h b/trunk/include/net/if_inet6.h index 34489c13c119..e459e1a0ae4a 100644 --- a/trunk/include/net/if_inet6.h +++ b/trunk/include/net/if_inet6.h @@ -189,7 +189,6 @@ struct inet6_dev struct ipv6_devconf cnf; struct ipv6_devstat stats; unsigned long tstamp; /* ipv6InterfaceTable update timestamp */ - struct rcu_head rcu; }; extern struct ipv6_devconf ipv6_devconf; diff --git a/trunk/include/net/inet_connection_sock.h b/trunk/include/net/inet_connection_sock.h index de4e83b6da4b..9bf73fe50948 100644 --- a/trunk/include/net/inet_connection_sock.h +++ b/trunk/include/net/inet_connection_sock.h @@ -147,8 +147,7 @@ extern struct sock *inet_csk_clone(struct sock *sk, enum inet_csk_ack_state_t { ICSK_ACK_SCHED = 1, ICSK_ACK_TIMER = 2, - ICSK_ACK_PUSHED = 4, - ICSK_ACK_PUSHED2 = 8 + ICSK_ACK_PUSHED = 4 }; extern void inet_csk_init_xmit_timers(struct sock *sk, diff --git a/trunk/include/net/inet_hashtables.h b/trunk/include/net/inet_hashtables.h index b4491c9e2a5a..98e0bb3014fe 100644 --- a/trunk/include/net/inet_hashtables.h +++ b/trunk/include/net/inet_hashtables.h @@ -271,15 +271,38 @@ static inline int inet_iif(const struct sk_buff *skb) return ((struct rtable *)skb->dst)->rt_iif; } -extern struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo, +extern struct sock *__inet_lookup_listener(const struct hlist_head *head, const u32 daddr, const unsigned short hnum, const int dif); -static inline struct sock *inet_lookup_listener(struct inet_hashinfo *hashinfo, - u32 daddr, u16 dport, int dif) +/* Optimize the common listener case. */ +static inline struct sock * + inet_lookup_listener(struct inet_hashinfo *hashinfo, + const u32 daddr, + const unsigned short hnum, const int dif) { - return __inet_lookup_listener(hashinfo, daddr, ntohs(dport), dif); + struct sock *sk = NULL; + const struct hlist_head *head; + + read_lock(&hashinfo->lhash_lock); + head = &hashinfo->listening_hash[inet_lhashfn(hnum)]; + if (!hlist_empty(head)) { + const struct inet_sock *inet = inet_sk((sk = __sk_head(head))); + + if (inet->num == hnum && !sk->sk_node.next && + (!inet->rcv_saddr || inet->rcv_saddr == daddr) && + (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) && + !sk->sk_bound_dev_if) + goto sherry_cache; + sk = __inet_lookup_listener(head, daddr, hnum, dif); + } + if (sk) { +sherry_cache: + sock_hold(sk); + } + read_unlock(&hashinfo->lhash_lock); + return sk; } /* Socket demux engine toys. */ @@ -368,25 +391,14 @@ static inline struct sock * goto out; } -static inline struct sock * - inet_lookup_established(struct inet_hashinfo *hashinfo, - const u32 saddr, const u16 sport, - const u32 daddr, const u16 dport, - const int dif) -{ - return __inet_lookup_established(hashinfo, saddr, sport, daddr, - ntohs(dport), dif); -} - static inline struct sock *__inet_lookup(struct inet_hashinfo *hashinfo, const u32 saddr, const u16 sport, - const u32 daddr, const u16 dport, + const u32 daddr, const u16 hnum, const int dif) { - u16 hnum = ntohs(dport); struct sock *sk = __inet_lookup_established(hashinfo, saddr, sport, daddr, hnum, dif); - return sk ? : __inet_lookup_listener(hashinfo, daddr, hnum, dif); + return sk ? : inet_lookup_listener(hashinfo, daddr, hnum, dif); } static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo, @@ -397,7 +409,7 @@ static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo, struct sock *sk; local_bh_disable(); - sk = __inet_lookup(hashinfo, saddr, sport, daddr, dport, dif); + sk = __inet_lookup(hashinfo, saddr, sport, daddr, ntohs(dport), dif); local_bh_enable(); return sk; diff --git a/trunk/include/net/inet_sock.h b/trunk/include/net/inet_sock.h index f6242710f2ff..1f4a9a60d4cc 100644 --- a/trunk/include/net/inet_sock.h +++ b/trunk/include/net/inet_sock.h @@ -27,6 +27,7 @@ /** struct ip_options - IP Options * * @faddr - Saved first hop address + * @is_setbyuser - Set by setsockopt? * @is_data - Options in __data, rather than skb * @is_strictroute - Strict source route * @srr_is_hit - Packet destination addr was our one @@ -41,7 +42,8 @@ struct ip_options { unsigned char srr; unsigned char rr; unsigned char ts; - unsigned char is_data:1, + unsigned char is_setbyuser:1, + is_data:1, is_strictroute:1, srr_is_hit:1, is_changed:1, @@ -49,7 +51,7 @@ struct ip_options { ts_needtime:1, ts_needaddr:1; unsigned char router_alert; - unsigned char cipso; + unsigned char __pad1; unsigned char __pad2; unsigned char __data[0]; }; diff --git a/trunk/include/net/ip6_fib.h b/trunk/include/net/ip6_fib.h index e4438de3bd6b..a66e9de16a6c 100644 --- a/trunk/include/net/ip6_fib.h +++ b/trunk/include/net/ip6_fib.h @@ -16,35 +16,14 @@ #ifdef __KERNEL__ #include -#include -#include + #include #include -#include +#include +#include struct rt6_info; -struct fib6_config -{ - u32 fc_table; - u32 fc_metric; - int fc_dst_len; - int fc_src_len; - int fc_ifindex; - u32 fc_flags; - u32 fc_protocol; - - struct in6_addr fc_dst; - struct in6_addr fc_src; - struct in6_addr fc_gateway; - - unsigned long fc_expires; - struct nlattr *fc_mx; - int fc_mx_len; - - struct nl_info fc_nlinfo; -}; - struct fib6_node { struct fib6_node *parent; @@ -60,11 +39,6 @@ struct fib6_node __u32 fn_sernum; }; -#ifndef CONFIG_IPV6_SUBTREES -#define FIB6_SUBTREE(fn) NULL -#else -#define FIB6_SUBTREE(fn) ((fn)->subtree) -#endif /* * routing information @@ -77,8 +51,6 @@ struct rt6key int plen; }; -struct fib6_table; - struct rt6_info { union { @@ -99,7 +71,6 @@ struct rt6_info u32 rt6i_flags; u32 rt6i_metric; atomic_t rt6i_ref; - struct fib6_table *rt6i_table; struct rt6key rt6i_dst; struct rt6key rt6i_src; @@ -118,6 +89,28 @@ struct fib6_walker_t void *args; }; +extern struct fib6_walker_t fib6_walker_list; +extern rwlock_t fib6_walker_lock; + +static inline void fib6_walker_link(struct fib6_walker_t *w) +{ + write_lock_bh(&fib6_walker_lock); + w->next = fib6_walker_list.next; + w->prev = &fib6_walker_list; + w->next->prev = w; + w->prev->next = w; + write_unlock_bh(&fib6_walker_lock); +} + +static inline void fib6_walker_unlink(struct fib6_walker_t *w) +{ + write_lock_bh(&fib6_walker_lock); + w->next->prev = w->prev; + w->prev->next = w->next; + w->prev = w->next = w; + write_unlock_bh(&fib6_walker_lock); +} + struct rt6_statistics { __u32 fib_nodes; __u32 fib_route_nodes; @@ -150,41 +143,12 @@ struct rt6_statistics { typedef void (*f_pnode)(struct fib6_node *fn, void *); -struct fib6_table { - struct hlist_node tb6_hlist; - u32 tb6_id; - rwlock_t tb6_lock; - struct fib6_node tb6_root; -}; - -#define RT6_TABLE_UNSPEC RT_TABLE_UNSPEC -#define RT6_TABLE_MAIN RT_TABLE_MAIN -#define RT6_TABLE_DFLT RT6_TABLE_MAIN -#define RT6_TABLE_INFO RT6_TABLE_MAIN -#define RT6_TABLE_PREFIX RT6_TABLE_MAIN - -#ifdef CONFIG_IPV6_MULTIPLE_TABLES -#define FIB6_TABLE_MIN 1 -#define FIB6_TABLE_MAX RT_TABLE_MAX -#define RT6_TABLE_LOCAL RT_TABLE_LOCAL -#else -#define FIB6_TABLE_MIN RT_TABLE_MAIN -#define FIB6_TABLE_MAX FIB6_TABLE_MIN -#define RT6_TABLE_LOCAL RT6_TABLE_MAIN -#endif - -typedef struct rt6_info *(*pol_lookup_t)(struct fib6_table *, - struct flowi *, int); +extern struct fib6_node ip6_routing_table; /* * exported functions */ -extern struct fib6_table * fib6_get_table(u32 id); -extern struct fib6_table * fib6_new_table(u32 id); -extern struct dst_entry * fib6_rule_lookup(struct flowi *fl, int flags, - pol_lookup_t lookup); - extern struct fib6_node *fib6_lookup(struct fib6_node *root, struct in6_addr *daddr, struct in6_addr *saddr); @@ -193,29 +157,32 @@ struct fib6_node *fib6_locate(struct fib6_node *root, struct in6_addr *daddr, int dst_len, struct in6_addr *saddr, int src_len); -extern void fib6_clean_all(int (*func)(struct rt6_info *, void *arg), - int prune, void *arg); +extern void fib6_clean_tree(struct fib6_node *root, + int (*func)(struct rt6_info *, void *arg), + int prune, void *arg); + +extern int fib6_walk(struct fib6_walker_t *w); +extern int fib6_walk_continue(struct fib6_walker_t *w); extern int fib6_add(struct fib6_node *root, struct rt6_info *rt, - struct nl_info *info); + struct nlmsghdr *nlh, + void *rtattr, + struct netlink_skb_parms *req); extern int fib6_del(struct rt6_info *rt, - struct nl_info *info); + struct nlmsghdr *nlh, + void *rtattr, + struct netlink_skb_parms *req); extern void inet6_rt_notify(int event, struct rt6_info *rt, - struct nl_info *info); + struct nlmsghdr *nlh, + struct netlink_skb_parms *req); extern void fib6_run_gc(unsigned long dummy); extern void fib6_gc_cleanup(void); extern void fib6_init(void); - -extern void fib6_rules_init(void); -extern void fib6_rules_cleanup(void); -extern int fib6_rules_dump(struct sk_buff *, - struct netlink_callback *); - #endif #endif diff --git a/trunk/include/net/ip6_route.h b/trunk/include/net/ip6_route.h index 6ca6b71dfe0f..ab29dafb1a6a 100644 --- a/trunk/include/net/ip6_route.h +++ b/trunk/include/net/ip6_route.h @@ -32,10 +32,6 @@ struct route_info { #include #include -#define RT6_LOOKUP_F_IFACE 0x1 -#define RT6_LOOKUP_F_REACHABLE 0x2 -#define RT6_LOOKUP_F_HAS_SADDR 0x4 - struct pol_chain { int type; int priority; @@ -45,11 +41,6 @@ struct pol_chain { extern struct rt6_info ip6_null_entry; -#ifdef CONFIG_IPV6_MULTIPLE_TABLES -extern struct rt6_info ip6_prohibit_entry; -extern struct rt6_info ip6_blk_hole_entry; -#endif - extern int ip6_rt_gc_interval; extern void ip6_route_input(struct sk_buff *skb); @@ -57,14 +48,25 @@ extern void ip6_route_input(struct sk_buff *skb); extern struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl); +extern int ip6_route_me_harder(struct sk_buff *skb); + extern void ip6_route_init(void); extern void ip6_route_cleanup(void); extern int ipv6_route_ioctl(unsigned int cmd, void __user *arg); -extern int ip6_route_add(struct fib6_config *cfg); -extern int ip6_ins_rt(struct rt6_info *); -extern int ip6_del_rt(struct rt6_info *); +extern int ip6_route_add(struct in6_rtmsg *rtmsg, + struct nlmsghdr *, + void *rtattr, + struct netlink_skb_parms *req); +extern int ip6_ins_rt(struct rt6_info *, + struct nlmsghdr *, + void *rtattr, + struct netlink_skb_parms *req); +extern int ip6_del_rt(struct rt6_info *, + struct nlmsghdr *, + void *rtattr, + struct netlink_skb_parms *req); extern int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev, @@ -112,7 +114,6 @@ extern int rt6_route_rcv(struct net_device *dev, struct in6_addr *gwaddr); extern void rt6_redirect(struct in6_addr *dest, - struct in6_addr *src, struct in6_addr *saddr, struct neighbour *neigh, u8 *lladdr, @@ -130,13 +131,6 @@ extern int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a extern int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); extern int inet6_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); -struct rt6_rtnl_dump_arg -{ - struct sk_buff *skb; - struct netlink_callback *cb; -}; - -extern int rt6_dump_route(struct rt6_info *rt, void *p_arg); extern void rt6_ifdown(struct net_device *dev); extern void rt6_mtu_change(struct net_device *dev, unsigned mtu); @@ -145,25 +139,16 @@ extern rwlock_t rt6_lock; /* * Store a destination cache entry in a socket */ -static inline void __ip6_dst_store(struct sock *sk, struct dst_entry *dst, - struct in6_addr *daddr, struct in6_addr *saddr) +static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, + struct in6_addr *daddr) { struct ipv6_pinfo *np = inet6_sk(sk); struct rt6_info *rt = (struct rt6_info *) dst; + write_lock(&sk->sk_dst_lock); sk_setup_caps(sk, dst); np->daddr_cache = daddr; -#ifdef CONFIG_IPV6_SUBTREES - np->saddr_cache = saddr; -#endif np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; -} - -static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, - struct in6_addr *daddr, struct in6_addr *saddr) -{ - write_lock(&sk->sk_dst_lock); - __ip6_dst_store(sk, dst, daddr, saddr); write_unlock(&sk->sk_dst_lock); } diff --git a/trunk/include/net/ip_fib.h b/trunk/include/net/ip_fib.h index fcc159a4ac17..a095d1dec7a4 100644 --- a/trunk/include/net/ip_fib.h +++ b/trunk/include/net/ip_fib.h @@ -18,34 +18,26 @@ #include #include -#include - -struct fib_config { - u8 fc_family; - u8 fc_dst_len; - u8 fc_src_len; - u8 fc_tos; - u8 fc_protocol; - u8 fc_scope; - u8 fc_type; - /* 1 byte unused */ - u32 fc_table; - u32 fc_dst; - u32 fc_src; - u32 fc_gw; - int fc_oif; - u32 fc_flags; - u32 fc_priority; - u32 fc_prefsrc; - struct nlattr *fc_mx; - struct rtnexthop *fc_mp; - int fc_mx_len; - int fc_mp_len; - u32 fc_flow; - u32 fc_mp_alg; - u32 fc_nlflags; - struct nl_info fc_nlinfo; - }; + +/* WARNING: The ordering of these elements must match ordering + * of RTA_* rtnetlink attribute numbers. + */ +struct kern_rta { + void *rta_dst; + void *rta_src; + int *rta_iif; + int *rta_oif; + void *rta_gw; + u32 *rta_priority; + void *rta_prefsrc; + struct rtattr *rta_mx; + struct rtattr *rta_mp; + unsigned char *rta_protoinfo; + u32 *rta_flow; + struct rta_cacheinfo *rta_ci; + struct rta_session *rta_sess; + u32 *rta_mp_alg; +}; struct fib_info; @@ -157,12 +149,15 @@ struct fib_result_nl { #endif /* CONFIG_IP_ROUTE_MULTIPATH_WRANDOM */ struct fib_table { - struct hlist_node tb_hlist; - u32 tb_id; + unsigned char tb_id; unsigned tb_stamp; int (*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res); - int (*tb_insert)(struct fib_table *, struct fib_config *); - int (*tb_delete)(struct fib_table *, struct fib_config *); + int (*tb_insert)(struct fib_table *table, struct rtmsg *r, + struct kern_rta *rta, struct nlmsghdr *n, + struct netlink_skb_parms *req); + int (*tb_delete)(struct fib_table *table, struct rtmsg *r, + struct kern_rta *rta, struct nlmsghdr *n, + struct netlink_skb_parms *req); int (*tb_dump)(struct fib_table *table, struct sk_buff *skb, struct netlink_callback *cb); int (*tb_flush)(struct fib_table *table); @@ -177,14 +172,14 @@ struct fib_table { extern struct fib_table *ip_fib_local_table; extern struct fib_table *ip_fib_main_table; -static inline struct fib_table *fib_get_table(u32 id) +static inline struct fib_table *fib_get_table(int id) { if (id != RT_TABLE_LOCAL) return ip_fib_main_table; return ip_fib_local_table; } -static inline struct fib_table *fib_new_table(u32 id) +static inline struct fib_table *fib_new_table(int id) { return fib_get_table(id); } @@ -204,19 +199,35 @@ static inline void fib_select_default(const struct flowi *flp, struct fib_result } #else /* CONFIG_IP_MULTIPLE_TABLES */ -#define ip_fib_local_table fib_get_table(RT_TABLE_LOCAL) -#define ip_fib_main_table fib_get_table(RT_TABLE_MAIN) +#define ip_fib_local_table (fib_tables[RT_TABLE_LOCAL]) +#define ip_fib_main_table (fib_tables[RT_TABLE_MAIN]) + +extern struct fib_table * fib_tables[RT_TABLE_MAX+1]; +extern int fib_lookup(const struct flowi *flp, struct fib_result *res); +extern struct fib_table *__fib_new_table(int id); +extern void fib_rule_put(struct fib_rule *r); -extern int fib_lookup(struct flowi *flp, struct fib_result *res); +static inline struct fib_table *fib_get_table(int id) +{ + if (id == 0) + id = RT_TABLE_MAIN; + + return fib_tables[id]; +} + +static inline struct fib_table *fib_new_table(int id) +{ + if (id == 0) + id = RT_TABLE_MAIN; + + return fib_tables[id] ? : __fib_new_table(id); +} -extern struct fib_table *fib_new_table(u32 id); -extern struct fib_table *fib_get_table(u32 id); extern void fib_select_default(const struct flowi *flp, struct fib_result *res); #endif /* CONFIG_IP_MULTIPLE_TABLES */ /* Exported by fib_frontend.c */ -extern struct nla_policy rtm_ipv4_policy[]; extern void ip_fib_init(void); extern int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); extern int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); @@ -232,20 +243,23 @@ struct rtentry; extern int ip_fib_check_default(u32 gw, struct net_device *dev); extern int fib_sync_down(u32 local, struct net_device *dev, int force); extern int fib_sync_up(struct net_device *dev); +extern int fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm, + struct kern_rta *rta, struct rtentry *r); extern u32 __fib_res_prefsrc(struct fib_result *res); /* Exported by fib_hash.c */ -extern struct fib_table *fib_hash_init(u32 id); +extern struct fib_table *fib_hash_init(int id); #ifdef CONFIG_IP_MULTIPLE_TABLES -extern int fib4_rules_dump(struct sk_buff *skb, struct netlink_callback *cb); - -extern void __init fib4_rules_init(void); +/* Exported by fib_rules.c */ +extern int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); +extern int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg); +extern int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb); #ifdef CONFIG_NET_CLS_ROUTE extern u32 fib_rules_tclass(struct fib_result *res); #endif - +extern void fib_rules_init(void); #endif static inline void fib_combine_itag(u32 *itag, struct fib_result *res) diff --git a/trunk/include/net/ipcomp.h b/trunk/include/net/ipcomp.h index 87c1af3e5e82..e651a57ecdd5 100644 --- a/trunk/include/net/ipcomp.h +++ b/trunk/include/net/ipcomp.h @@ -1,14 +1,11 @@ #ifndef _NET_IPCOMP_H #define _NET_IPCOMP_H -#include -#include - #define IPCOMP_SCRATCH_SIZE 65400 struct ipcomp_data { u16 threshold; - struct crypto_comp **tfms; + struct crypto_tfm **tfms; }; #endif diff --git a/trunk/include/net/ipv6.h b/trunk/include/net/ipv6.h index 72bf47b2a4e0..a8fdf7970b37 100644 --- a/trunk/include/net/ipv6.h +++ b/trunk/include/net/ipv6.h @@ -40,7 +40,6 @@ #define NEXTHDR_ICMP 58 /* ICMP for IPv6. */ #define NEXTHDR_NONE 59 /* No next header */ #define NEXTHDR_DEST 60 /* Destination options header. */ -#define NEXTHDR_MOBILITY 135 /* Mobility header. */ #define NEXTHDR_MAX 255 @@ -230,7 +229,7 @@ extern int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)); -extern int ipv6_parse_hopopts(struct sk_buff **skbp); +extern int ipv6_parse_hopopts(struct sk_buff *skb); extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt); extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, @@ -469,9 +468,6 @@ extern void ip6_flush_pending_frames(struct sock *sk); extern int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl); -extern int ip6_sk_dst_lookup(struct sock *sk, - struct dst_entry **dst, - struct flowi *fl); /* * skb processing functions @@ -507,8 +503,6 @@ extern int ipv6_skip_exthdr(const struct sk_buff *, int start, extern int ipv6_ext_hdr(u8 nexthdr); -extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type); - extern struct ipv6_txoptions * ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr); diff --git a/trunk/include/net/mip6.h b/trunk/include/net/mip6.h deleted file mode 100644 index 68263c6d9996..000000000000 --- a/trunk/include/net/mip6.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C)2003-2006 Helsinki University of Technology - * Copyright (C)2003-2006 USAGI/WIDE Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* - * Authors: - * Noriaki TAKAMIYA @USAGI - * Masahide NAKAMURA @USAGI - * YOSHIFUJI Hideaki @USAGI - */ -#ifndef _NET_MIP6_H -#define _NET_MIP6_H - -#include -#include - -#define MIP6_OPT_PAD_1 0 -#define MIP6_OPT_PAD_N 1 - -/* - * Mobility Header - */ -struct ip6_mh { - __u8 ip6mh_proto; - __u8 ip6mh_hdrlen; - __u8 ip6mh_type; - __u8 ip6mh_reserved; - __u16 ip6mh_cksum; - /* Followed by type specific messages */ - __u8 data[0]; -} __attribute__ ((__packed__)); - -#define IP6_MH_TYPE_BRR 0 /* Binding Refresh Request */ -#define IP6_MH_TYPE_HOTI 1 /* HOTI Message */ -#define IP6_MH_TYPE_COTI 2 /* COTI Message */ -#define IP6_MH_TYPE_HOT 3 /* HOT Message */ -#define IP6_MH_TYPE_COT 4 /* COT Message */ -#define IP6_MH_TYPE_BU 5 /* Binding Update */ -#define IP6_MH_TYPE_BACK 6 /* Binding ACK */ -#define IP6_MH_TYPE_BERROR 7 /* Binding Error */ -#define IP6_MH_TYPE_MAX IP6_MH_TYPE_BERROR - -extern int mip6_init(void); -extern void mip6_fini(void); -extern int mip6_mh_filter(struct sock *sk, struct sk_buff *skb); - -#endif diff --git a/trunk/include/net/neighbour.h b/trunk/include/net/neighbour.h index c8aacbd2e333..4901ee446879 100644 --- a/trunk/include/net/neighbour.h +++ b/trunk/include/net/neighbour.h @@ -1,8 +1,6 @@ #ifndef _NET_NEIGHBOUR_H #define _NET_NEIGHBOUR_H -#include - /* * Generic neighbour manipulation * @@ -16,6 +14,40 @@ * - Add neighbour cache statistics like rtstat */ +/* The following flags & states are exported to user space, + so that they should be moved to include/linux/ directory. + */ + +/* + * Neighbor Cache Entry Flags + */ + +#define NTF_PROXY 0x08 /* == ATF_PUBL */ +#define NTF_ROUTER 0x80 + +/* + * Neighbor Cache Entry States. + */ + +#define NUD_INCOMPLETE 0x01 +#define NUD_REACHABLE 0x02 +#define NUD_STALE 0x04 +#define NUD_DELAY 0x08 +#define NUD_PROBE 0x10 +#define NUD_FAILED 0x20 + +/* Dummy states */ +#define NUD_NOARP 0x40 +#define NUD_PERMANENT 0x80 +#define NUD_NONE 0x00 + +/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change + and make no address resolution or NUD. + NUD_PERMANENT is also cannot be deleted by garbage collectors. + */ + +#ifdef __KERNEL__ + #include #include #include @@ -101,7 +133,7 @@ struct neighbour __u8 dead; atomic_t probes; rwlock_t lock; - unsigned char ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))]; + unsigned char ha[(MAX_ADDR_LEN+sizeof(unsigned long)-1)&~(sizeof(unsigned long)-1)]; struct hh_cache *hh; atomic_t refcnt; int (*output)(struct sk_buff *skb); @@ -126,7 +158,6 @@ struct pneigh_entry { struct pneigh_entry *next; struct net_device *dev; - u8 flags; u8 key[0]; }; @@ -343,3 +374,6 @@ struct neighbour_cb { #define NEIGH_CB(skb) ((struct neighbour_cb *)(skb)->cb) #endif +#endif + + diff --git a/trunk/include/net/netdma.h b/trunk/include/net/netdma.h index 7f53cd1d8b1e..ceae5ee85c04 100644 --- a/trunk/include/net/netdma.h +++ b/trunk/include/net/netdma.h @@ -29,7 +29,7 @@ static inline struct dma_chan *get_softnet_dma(void) { struct dma_chan *chan; rcu_read_lock(); - chan = rcu_dereference(__get_cpu_var(softnet_data).net_dma); + chan = rcu_dereference(__get_cpu_var(softnet_data.net_dma)); if (chan) dma_chan_get(chan); rcu_read_unlock(); diff --git a/trunk/include/net/netevent.h b/trunk/include/net/netevent.h deleted file mode 100644 index e5d216241423..000000000000 --- a/trunk/include/net/netevent.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef _NET_EVENT_H -#define _NET_EVENT_H - -/* - * Generic netevent notifiers - * - * Authors: - * Tom Tucker - * Steve Wise - * - * Changes: - */ -#ifdef __KERNEL__ - -#include - -struct netevent_redirect { - struct dst_entry *old; - struct dst_entry *new; -}; - -enum netevent_notif_type { - NETEVENT_NEIGH_UPDATE = 1, /* arg is struct neighbour ptr */ - NETEVENT_PMTU_UPDATE, /* arg is struct dst_entry ptr */ - NETEVENT_REDIRECT, /* arg is struct netevent_redirect ptr */ -}; - -extern int register_netevent_notifier(struct notifier_block *nb); -extern int unregister_netevent_notifier(struct notifier_block *nb); -extern int call_netevent_notifiers(unsigned long val, void *v); - -#endif -#endif diff --git a/trunk/include/net/netlabel.h b/trunk/include/net/netlabel.h deleted file mode 100644 index fc2b72fc7e07..000000000000 --- a/trunk/include/net/netlabel.h +++ /dev/null @@ -1,292 +0,0 @@ -/* - * NetLabel System - * - * The NetLabel system manages static and dynamic label mappings for network - * protocols such as CIPSO and RIPSO. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _NETLABEL_H -#define _NETLABEL_H - -#include -#include -#include -#include - -/* - * NetLabel - A management interface for maintaining network packet label - * mapping tables for explicit packet labling protocols. - * - * Network protocols such as CIPSO and RIPSO require a label translation layer - * to convert the label on the packet into something meaningful on the host - * machine. In the current Linux implementation these mapping tables live - * inside the kernel; NetLabel provides a mechanism for user space applications - * to manage these mapping tables. - * - * NetLabel makes use of the Generic NETLINK mechanism as a transport layer to - * send messages between kernel and user space. The general format of a - * NetLabel message is shown below: - * - * +-----------------+-------------------+--------- --- -- - - * | struct nlmsghdr | struct genlmsghdr | payload - * +-----------------+-------------------+--------- --- -- - - * - * The 'nlmsghdr' and 'genlmsghdr' structs should be dealt with like normal. - * The payload is dependent on the subsystem specified in the - * 'nlmsghdr->nlmsg_type' and should be defined below, supporting functions - * should be defined in the corresponding net/netlabel/netlabel_.h|c - * file. All of the fields in the NetLabel payload are NETLINK attributes, the - * length of each field is the length of the NETLINK attribute payload, see - * include/net/netlink.h for more information on NETLINK attributes. - * - */ - -/* - * NetLabel NETLINK protocol - */ - -#define NETLBL_PROTO_VERSION 1 - -/* NetLabel NETLINK types/families */ -#define NETLBL_NLTYPE_NONE 0 -#define NETLBL_NLTYPE_MGMT 1 -#define NETLBL_NLTYPE_MGMT_NAME "NLBL_MGMT" -#define NETLBL_NLTYPE_RIPSO 2 -#define NETLBL_NLTYPE_RIPSO_NAME "NLBL_RIPSO" -#define NETLBL_NLTYPE_CIPSOV4 3 -#define NETLBL_NLTYPE_CIPSOV4_NAME "NLBL_CIPSOv4" -#define NETLBL_NLTYPE_CIPSOV6 4 -#define NETLBL_NLTYPE_CIPSOV6_NAME "NLBL_CIPSOv6" -#define NETLBL_NLTYPE_UNLABELED 5 -#define NETLBL_NLTYPE_UNLABELED_NAME "NLBL_UNLBL" - -/* NetLabel return codes */ -#define NETLBL_E_OK 0 - -/* - * Helper functions - */ - -#define NETLBL_LEN_U8 nla_total_size(sizeof(u8)) -#define NETLBL_LEN_U16 nla_total_size(sizeof(u16)) -#define NETLBL_LEN_U32 nla_total_size(sizeof(u32)) - -/** - * netlbl_netlink_alloc_skb - Allocate a NETLINK message buffer - * @head: the amount of headroom in bytes - * @body: the desired size (minus headroom) in bytes - * @gfp_flags: the alloc flags to pass to alloc_skb() - * - * Description: - * Allocate a NETLINK message buffer based on the sizes given in @head and - * @body. If @head is greater than zero skb_reserve() is called to reserve - * @head bytes at the start of the buffer. Returns a valid sk_buff pointer on - * success, NULL on failure. - * - */ -static inline struct sk_buff *netlbl_netlink_alloc_skb(size_t head, - size_t body, - int gfp_flags) -{ - struct sk_buff *skb; - - skb = alloc_skb(NLMSG_ALIGN(head + body), gfp_flags); - if (skb == NULL) - return NULL; - if (head > 0) { - skb_reserve(skb, head); - if (skb_tailroom(skb) < body) { - kfree_skb(skb); - return NULL; - } - } - - return skb; -} - -/* - * NetLabel - Kernel API for accessing the network packet label mappings. - * - * The following functions are provided for use by other kernel modules, - * specifically kernel LSM modules, to provide a consistent, transparent API - * for dealing with explicit packet labeling protocols such as CIPSO and - * RIPSO. The functions defined here are implemented in the - * net/netlabel/netlabel_kapi.c file. - * - */ - -/* Domain mapping definition struct */ -struct netlbl_dom_map; - -/* Domain mapping operations */ -int netlbl_domhsh_remove(const char *domain); - -/* LSM security attributes */ -struct netlbl_lsm_cache { - void (*free) (const void *data); - void *data; -}; -struct netlbl_lsm_secattr { - char *domain; - - u32 mls_lvl; - u32 mls_lvl_vld; - unsigned char *mls_cat; - size_t mls_cat_len; - - struct netlbl_lsm_cache cache; -}; - -/* - * LSM security attribute operations - */ - - -/** - * netlbl_secattr_init - Initialize a netlbl_lsm_secattr struct - * @secattr: the struct to initialize - * - * Description: - * Initialize an already allocated netlbl_lsm_secattr struct. Returns zero on - * success, negative values on error. - * - */ -static inline int netlbl_secattr_init(struct netlbl_lsm_secattr *secattr) -{ - memset(secattr, 0, sizeof(*secattr)); - return 0; -} - -/** - * netlbl_secattr_destroy - Clears a netlbl_lsm_secattr struct - * @secattr: the struct to clear - * @clear_cache: cache clear flag - * - * Description: - * Destroys the @secattr struct, including freeing all of the internal buffers. - * If @clear_cache is true then free the cache fields, otherwise leave them - * intact. The struct must be reset with a call to netlbl_secattr_init() - * before reuse. - * - */ -static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr, - u32 clear_cache) -{ - if (clear_cache && secattr->cache.data != NULL && secattr->cache.free) - secattr->cache.free(secattr->cache.data); - kfree(secattr->domain); - kfree(secattr->mls_cat); -} - -/** - * netlbl_secattr_alloc - Allocate and initialize a netlbl_lsm_secattr struct - * @flags: the memory allocation flags - * - * Description: - * Allocate and initialize a netlbl_lsm_secattr struct. Returns a valid - * pointer on success, or NULL on failure. - * - */ -static inline struct netlbl_lsm_secattr *netlbl_secattr_alloc(int flags) -{ - return kzalloc(sizeof(struct netlbl_lsm_secattr), flags); -} - -/** - * netlbl_secattr_free - Frees a netlbl_lsm_secattr struct - * @secattr: the struct to free - * @clear_cache: cache clear flag - * - * Description: - * Frees @secattr including all of the internal buffers. If @clear_cache is - * true then free the cache fields, otherwise leave them intact. - * - */ -static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr, - u32 clear_cache) -{ - netlbl_secattr_destroy(secattr, clear_cache); - kfree(secattr); -} - -/* - * LSM protocol operations - */ - -#ifdef CONFIG_NETLABEL -int netlbl_socket_setattr(const struct socket *sock, - const struct netlbl_lsm_secattr *secattr); -int netlbl_socket_getattr(const struct socket *sock, - struct netlbl_lsm_secattr *secattr); -int netlbl_skbuff_getattr(const struct sk_buff *skb, - struct netlbl_lsm_secattr *secattr); -void netlbl_skbuff_err(struct sk_buff *skb, int error); -#else -static inline int netlbl_socket_setattr(const struct socket *sock, - const struct netlbl_lsm_secattr *secattr) -{ - return -ENOSYS; -} - -static inline int netlbl_socket_getattr(const struct socket *sock, - struct netlbl_lsm_secattr *secattr) -{ - return -ENOSYS; -} - -static inline int netlbl_skbuff_getattr(const struct sk_buff *skb, - struct netlbl_lsm_secattr *secattr) -{ - return -ENOSYS; -} - -static inline void netlbl_skbuff_err(struct sk_buff *skb, int error) -{ - return; -} -#endif /* CONFIG_NETLABEL */ - -/* - * LSM label mapping cache operations - */ - -#ifdef CONFIG_NETLABEL -void netlbl_cache_invalidate(void); -int netlbl_cache_add(const struct sk_buff *skb, - const struct netlbl_lsm_secattr *secattr); -#else -static inline void netlbl_cache_invalidate(void) -{ - return; -} - -static inline int netlbl_cache_add(const struct sk_buff *skb, - const struct netlbl_lsm_secattr *secattr) -{ - return 0; -} -#endif /* CONFIG_NETLABEL */ - -#endif /* _NETLABEL_H */ diff --git a/trunk/include/net/netlink.h b/trunk/include/net/netlink.h index 11dc2e7f679a..640c26a90cf1 100644 --- a/trunk/include/net/netlink.h +++ b/trunk/include/net/netlink.h @@ -35,15 +35,12 @@ * nlmsg_put() add a netlink message to an skb * nlmsg_put_answer() callback based nlmsg_put() * nlmsg_end() finanlize netlink message - * nlmsg_get_pos() return current position in message - * nlmsg_trim() trim part of message * nlmsg_cancel() cancel message construction * nlmsg_free() free a netlink message * * Message Sending: * nlmsg_multicast() multicast message to several groups * nlmsg_unicast() unicast a message to a single socket - * nlmsg_notify() send notification message * * Message Length Calculations: * nlmsg_msg_size(payload) length of message w/o padding @@ -65,9 +62,6 @@ * nlmsg_validate() validate netlink message incl. attrs * nlmsg_for_each_attr() loop over all attributes * - * Misc: - * nlmsg_report() report back to application? - * * ------------------------------------------------------------------------ * Attributes Interface * ------------------------------------------------------------------------ @@ -86,10 +80,8 @@ * struct nlattr netlink attribtue header * * Attribute Construction: - * nla_reserve(skb, type, len) reserve room for an attribute - * nla_reserve_nohdr(skb, len) reserve room for an attribute w/o hdr + * nla_reserve(skb, type, len) reserve skb tailroom for an attribute * nla_put(skb, type, len, data) add attribute to skb - * nla_put_nohdr(skb, len, data) add attribute w/o hdr * * Attribute Construction for Basic Types: * nla_put_u8(skb, type, value) add u8 attribute to skb @@ -147,7 +139,6 @@ * nla_next(nla, remaining) get next netlink attribute * nla_validate() validate a stream of attributes * nla_find() find attribute in stream of attributes - * nla_find_nested() find attribute in nested attributes * nla_parse() parse and validate stream of attrs * nla_parse_nested() parse nested attribuets * nla_for_each_attr() loop over all attributes @@ -167,7 +158,6 @@ enum { NLA_FLAG, NLA_MSECS, NLA_NESTED, - NLA_NUL_STRING, __NLA_TYPE_MAX, }; @@ -176,37 +166,21 @@ enum { /** * struct nla_policy - attribute validation policy * @type: Type of attribute or NLA_UNSPEC - * @len: Type specific length of payload + * @minlen: Minimal length of payload required to be available * * Policies are defined as arrays of this struct, the array must be * accessible by attribute type up to the highest identifier to be expected. * - * Meaning of `len' field: - * NLA_STRING Maximum length of string - * NLA_NUL_STRING Maximum length of string (excluding NUL) - * NLA_FLAG Unused - * All other Exact length of attribute payload - * * Example: * static struct nla_policy my_policy[ATTR_MAX+1] __read_mostly = { * [ATTR_FOO] = { .type = NLA_U16 }, - * [ATTR_BAR] = { .type = NLA_STRING, len = BARSIZ }, - * [ATTR_BAZ] = { .len = sizeof(struct mystruct) }, + * [ATTR_BAR] = { .type = NLA_STRING }, + * [ATTR_BAZ] = { .minlen = sizeof(struct mystruct) }, * }; */ struct nla_policy { u16 type; - u16 len; -}; - -/** - * struct nl_info - netlink source information - * @nlh: Netlink message header of original request - * @pid: Netlink PID of requesting application - */ -struct nl_info { - struct nlmsghdr *nlh; - u32 pid; + u16 minlen; }; extern void netlink_run_queue(struct sock *sk, unsigned int *qlen, @@ -214,9 +188,6 @@ extern void netlink_run_queue(struct sock *sk, unsigned int *qlen, struct nlmsghdr *, int *)); extern void netlink_queue_skip(struct nlmsghdr *nlh, struct sk_buff *skb); -extern int nlmsg_notify(struct sock *sk, struct sk_buff *skb, - u32 pid, unsigned int group, int report, - gfp_t flags); extern int nla_validate(struct nlattr *head, int len, int maxtype, struct nla_policy *policy); @@ -232,18 +203,12 @@ extern int nla_memcmp(const struct nlattr *nla, const void *data, extern int nla_strcmp(const struct nlattr *nla, const char *str); extern struct nlattr * __nla_reserve(struct sk_buff *skb, int attrtype, int attrlen); -extern void * __nla_reserve_nohdr(struct sk_buff *skb, int attrlen); extern struct nlattr * nla_reserve(struct sk_buff *skb, int attrtype, int attrlen); -extern void * nla_reserve_nohdr(struct sk_buff *skb, int attrlen); extern void __nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data); -extern void __nla_put_nohdr(struct sk_buff *skb, int attrlen, - const void *data); extern int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data); -extern int nla_put_nohdr(struct sk_buff *skb, int attrlen, - const void *data); /************************************************************************** * Netlink Messages @@ -398,17 +363,6 @@ static inline int nlmsg_validate(struct nlmsghdr *nlh, int hdrlen, int maxtype, nlmsg_attrlen(nlh, hdrlen), maxtype, policy); } -/** - * nlmsg_report - need to report back to application? - * @nlh: netlink message header - * - * Returns 1 if a report back to the application is requested. - */ -static inline int nlmsg_report(struct nlmsghdr *nlh) -{ - return !!(nlh->nlmsg_flags & NLM_F_ECHO); -} - /** * nlmsg_for_each_attr - iterate over a stream of attributes * @pos: loop counter, set to current attribute @@ -499,13 +453,12 @@ static inline struct nlmsghdr *nlmsg_put_answer(struct sk_buff *skb, /** * nlmsg_new - Allocate a new netlink message * @size: maximum size of message - * @flags: the type of memory to allocate. * * Use NLMSG_GOODSIZE if size isn't know and you need a good default size. */ -static inline struct sk_buff *nlmsg_new(int size, gfp_t flags) +static inline struct sk_buff *nlmsg_new(int size) { - return alloc_skb(size, flags); + return alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); } /** @@ -526,32 +479,6 @@ static inline int nlmsg_end(struct sk_buff *skb, struct nlmsghdr *nlh) return skb->len; } -/** - * nlmsg_get_pos - return current position in netlink message - * @skb: socket buffer the message is stored in - * - * Returns a pointer to the current tail of the message. - */ -static inline void *nlmsg_get_pos(struct sk_buff *skb) -{ - return skb->tail; -} - -/** - * nlmsg_trim - Trim message to a mark - * @skb: socket buffer the message is stored in - * @mark: mark to trim to - * - * Trims the message to the provided mark. Returns -1. - */ -static inline int nlmsg_trim(struct sk_buff *skb, void *mark) -{ - if (mark) - skb_trim(skb, (unsigned char *) mark - skb->data); - - return -1; -} - /** * nlmsg_cancel - Cancel construction of a netlink message * @skb: socket buffer the message is stored in @@ -562,7 +489,9 @@ static inline int nlmsg_trim(struct sk_buff *skb, void *mark) */ static inline int nlmsg_cancel(struct sk_buff *skb, struct nlmsghdr *nlh) { - return nlmsg_trim(skb, nlh); + skb_trim(skb, (unsigned char *) nlh - skb->data); + + return -1; } /** @@ -580,16 +509,15 @@ static inline void nlmsg_free(struct sk_buff *skb) * @skb: netlink message as socket buffer * @pid: own netlink pid to avoid sending to yourself * @group: multicast group id - * @flags: allocation flags */ static inline int nlmsg_multicast(struct sock *sk, struct sk_buff *skb, - u32 pid, unsigned int group, gfp_t flags) + u32 pid, unsigned int group) { int err; NETLINK_CB(skb).dst_group = group; - err = netlink_broadcast(sk, skb, pid, group, flags); + err = netlink_broadcast(sk, skb, pid, group, GFP_KERNEL); if (err > 0) err = 0; @@ -702,18 +630,6 @@ static inline struct nlattr *nla_next(const struct nlattr *nla, int *remaining) return (struct nlattr *) ((char *) nla + totlen); } -/** - * nla_find_nested - find attribute in a set of nested attributes - * @nla: attribute containing the nested attributes - * @attrtype: type of attribute to look for - * - * Returns the first attribute which matches the specified type. - */ -static inline struct nlattr *nla_find_nested(struct nlattr *nla, int attrtype) -{ - return nla_find(nla_data(nla), nla_len(nla), attrtype); -} - /** * nla_parse_nested - parse nested attributes * @tb: destination array with maxtype+1 elements @@ -835,7 +751,7 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype, #define NLA_PUT_STRING(skb, attrtype, value) \ NLA_PUT(skb, attrtype, strlen(value) + 1, value) -#define NLA_PUT_FLAG(skb, attrtype) \ +#define NLA_PUT_FLAG(skb, attrtype, value) \ NLA_PUT(skb, attrtype, 0, NULL) #define NLA_PUT_MSECS(skb, attrtype, jiffies) \ @@ -946,7 +862,10 @@ static inline int nla_nest_end(struct sk_buff *skb, struct nlattr *start) */ static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start) { - return nlmsg_trim(skb, start); + if (start) + skb_trim(skb, (unsigned char *) start - skb->data); + + return -1; } /** @@ -961,13 +880,4 @@ static inline int nla_nest_cancel(struct sk_buff *skb, struct nlattr *start) nla_ok(pos, rem); \ pos = nla_next(pos, &(rem))) -/** - * nla_for_each_nested - iterate over nested attributes - * @pos: loop counter, set to current attribute - * @nla: attribute containing the nested attributes - * @rem: initialized to len, holds bytes currently remaining in stream - */ -#define nla_for_each_nested(pos, nla, rem) \ - nla_for_each_attr(pos, nla_data(nla), nla_len(nla), rem) - #endif diff --git a/trunk/include/net/nexthop.h b/trunk/include/net/nexthop.h deleted file mode 100644 index 3334dbfa5aa4..000000000000 --- a/trunk/include/net/nexthop.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __NET_NEXTHOP_H -#define __NET_NEXTHOP_H - -#include -#include - -static inline int rtnh_ok(const struct rtnexthop *rtnh, int remaining) -{ - return remaining >= sizeof(*rtnh) && - rtnh->rtnh_len >= sizeof(*rtnh) && - rtnh->rtnh_len <= remaining; -} - -static inline struct rtnexthop *rtnh_next(const struct rtnexthop *rtnh, - int *remaining) -{ - int totlen = NLA_ALIGN(rtnh->rtnh_len); - - *remaining -= totlen; - return (struct rtnexthop *) ((char *) rtnh + totlen); -} - -static inline struct nlattr *rtnh_attrs(const struct rtnexthop *rtnh) -{ - return (struct nlattr *) ((char *) rtnh + NLA_ALIGN(sizeof(*rtnh))); -} - -static inline int rtnh_attrlen(const struct rtnexthop *rtnh) -{ - return rtnh->rtnh_len - NLA_ALIGN(sizeof(*rtnh)); -} - -#endif diff --git a/trunk/include/net/pkt_act.h b/trunk/include/net/pkt_act.h new file mode 100644 index 000000000000..cf5e4d2e4c21 --- /dev/null +++ b/trunk/include/net/pkt_act.h @@ -0,0 +1,273 @@ +#ifndef __NET_PKT_ACT_H +#define __NET_PKT_ACT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define tca_st(val) (struct tcf_##val *) +#define PRIV(a,name) ( tca_st(name) (a)->priv) + +#if 0 /* control */ +#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) +#else +#define DPRINTK(format,args...) +#endif + +#if 0 /* data */ +#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args) +#else +#define D2PRINTK(format,args...) +#endif + +static __inline__ unsigned +tcf_hash(u32 index) +{ + return index & MY_TAB_MASK; +} + +/* probably move this from being inline + * and put into act_generic +*/ +static inline void +tcf_hash_destroy(struct tcf_st *p) +{ + unsigned h = tcf_hash(p->index); + struct tcf_st **p1p; + + for (p1p = &tcf_ht[h]; *p1p; p1p = &(*p1p)->next) { + if (*p1p == p) { + write_lock_bh(&tcf_t_lock); + *p1p = p->next; + write_unlock_bh(&tcf_t_lock); +#ifdef CONFIG_NET_ESTIMATOR + gen_kill_estimator(&p->bstats, &p->rate_est); +#endif + kfree(p); + return; + } + } + BUG_TRAP(0); +} + +static inline int +tcf_hash_release(struct tcf_st *p, int bind ) +{ + int ret = 0; + if (p) { + if (bind) { + p->bindcnt--; + } + p->refcnt--; + if(p->bindcnt <=0 && p->refcnt <= 0) { + tcf_hash_destroy(p); + ret = 1; + } + } + return ret; +} + +static __inline__ int +tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, + struct tc_action *a) +{ + struct tcf_st *p; + int err =0, index = -1,i= 0, s_i = 0, n_i = 0; + struct rtattr *r ; + + read_lock(&tcf_t_lock); + + s_i = cb->args[0]; + + for (i = 0; i < MY_TAB_SIZE; i++) { + p = tcf_ht[tcf_hash(i)]; + + for (; p; p = p->next) { + index++; + if (index < s_i) + continue; + a->priv = p; + a->order = n_i; + r = (struct rtattr*) skb->tail; + RTA_PUT(skb, a->order, 0, NULL); + err = tcf_action_dump_1(skb, a, 0, 0); + if (0 > err) { + index--; + skb_trim(skb, (u8*)r - skb->data); + goto done; + } + r->rta_len = skb->tail - (u8*)r; + n_i++; + if (n_i >= TCA_ACT_MAX_PRIO) { + goto done; + } + } + } +done: + read_unlock(&tcf_t_lock); + if (n_i) + cb->args[0] += n_i; + return n_i; + +rtattr_failure: + skb_trim(skb, (u8*)r - skb->data); + goto done; +} + +static __inline__ int +tcf_del_walker(struct sk_buff *skb, struct tc_action *a) +{ + struct tcf_st *p, *s_p; + struct rtattr *r ; + int i= 0, n_i = 0; + + r = (struct rtattr*) skb->tail; + RTA_PUT(skb, a->order, 0, NULL); + RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind); + for (i = 0; i < MY_TAB_SIZE; i++) { + p = tcf_ht[tcf_hash(i)]; + + while (p != NULL) { + s_p = p->next; + if (ACT_P_DELETED == tcf_hash_release(p, 0)) { + module_put(a->ops->owner); + } + n_i++; + p = s_p; + } + } + RTA_PUT(skb, TCA_FCNT, 4, &n_i); + r->rta_len = skb->tail - (u8*)r; + + return n_i; +rtattr_failure: + skb_trim(skb, (u8*)r - skb->data); + return -EINVAL; +} + +static __inline__ int +tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, int type, + struct tc_action *a) +{ + if (type == RTM_DELACTION) { + return tcf_del_walker(skb,a); + } else if (type == RTM_GETACTION) { + return tcf_dump_walker(skb,cb,a); + } else { + printk("tcf_generic_walker: unknown action %d\n",type); + return -EINVAL; + } +} + +static __inline__ struct tcf_st * +tcf_hash_lookup(u32 index) +{ + struct tcf_st *p; + + read_lock(&tcf_t_lock); + for (p = tcf_ht[tcf_hash(index)]; p; p = p->next) { + if (p->index == index) + break; + } + read_unlock(&tcf_t_lock); + return p; +} + +static __inline__ u32 +tcf_hash_new_index(void) +{ + do { + if (++idx_gen == 0) + idx_gen = 1; + } while (tcf_hash_lookup(idx_gen)); + + return idx_gen; +} + + +static inline int +tcf_hash_search(struct tc_action *a, u32 index) +{ + struct tcf_st *p = tcf_hash_lookup(index); + + if (p != NULL) { + a->priv = p; + return 1; + } + return 0; +} + +#ifdef CONFIG_NET_ACT_INIT +static inline struct tcf_st * +tcf_hash_check(u32 index, struct tc_action *a, int ovr, int bind) +{ + struct tcf_st *p = NULL; + if (index && (p = tcf_hash_lookup(index)) != NULL) { + if (bind) { + p->bindcnt++; + p->refcnt++; + } + a->priv = p; + } + return p; +} + +static inline struct tcf_st * +tcf_hash_create(u32 index, struct rtattr *est, struct tc_action *a, int size, int ovr, int bind) +{ + struct tcf_st *p = NULL; + + p = kmalloc(size, GFP_KERNEL); + if (p == NULL) + return p; + + memset(p, 0, size); + p->refcnt = 1; + + if (bind) { + p->bindcnt = 1; + } + + spin_lock_init(&p->lock); + p->stats_lock = &p->lock; + p->index = index ? : tcf_hash_new_index(); + p->tm.install = jiffies; + p->tm.lastuse = jiffies; +#ifdef CONFIG_NET_ESTIMATOR + if (est) + gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est); +#endif + a->priv = (void *) p; + return p; +} + +static inline void tcf_hash_insert(struct tcf_st *p) +{ + unsigned h = tcf_hash(p->index); + + write_lock_bh(&tcf_t_lock); + p->next = tcf_ht[h]; + tcf_ht[h] = p; + write_unlock_bh(&tcf_t_lock); +} + +#endif + +#endif diff --git a/trunk/include/net/red.h b/trunk/include/net/red.h index a4eb37946f2c..5ccdbb3d4722 100644 --- a/trunk/include/net/red.h +++ b/trunk/include/net/red.h @@ -212,7 +212,7 @@ static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p) * Seems, it is the best solution to * problem of too coarse exponent tabulation. */ - us_idle = (p->qavg * (u64)us_idle) >> p->Scell_log; + us_idle = (p->qavg * us_idle) >> p->Scell_log; if (us_idle < (p->qavg >> 1)) return p->qavg - us_idle; diff --git a/trunk/include/net/request_sock.h b/trunk/include/net/request_sock.h index 8e165ca16bd8..c5d7f920c352 100644 --- a/trunk/include/net/request_sock.h +++ b/trunk/include/net/request_sock.h @@ -53,7 +53,6 @@ struct request_sock { unsigned long expires; struct request_sock_ops *rsk_ops; struct sock *sk; - u32 secid; }; static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops) diff --git a/trunk/include/net/route.h b/trunk/include/net/route.h index 7f93ac0e0899..c4a068692dcc 100644 --- a/trunk/include/net/route.h +++ b/trunk/include/net/route.h @@ -32,7 +32,6 @@ #include #include #include -#include #ifndef __KERNEL__ #warning This file is not supposed to be used outside of kernel. @@ -167,7 +166,6 @@ static inline int ip_route_connect(struct rtable **rp, u32 dst, ip_rt_put(*rp); *rp = NULL; } - security_sk_classify_flow(sk, &fl); return ip_route_output_flow(rp, &fl, sk, 0); } @@ -184,7 +182,6 @@ static inline int ip_route_newports(struct rtable **rp, u8 protocol, fl.proto = protocol; ip_rt_put(*rp); *rp = NULL; - security_sk_classify_flow(sk, &fl); return ip_route_output_flow(rp, &fl, sk, 0); } return 0; diff --git a/trunk/include/net/scm.h b/trunk/include/net/scm.h index 5637d5e22d5f..02daa097cdcd 100644 --- a/trunk/include/net/scm.h +++ b/trunk/include/net/scm.h @@ -3,7 +3,6 @@ #include #include -#include /* Well, we should have at least one descriptor open * to accept passed FDs 8) @@ -21,7 +20,8 @@ struct scm_cookie struct ucred creds; /* Skb credentials */ struct scm_fp_list *fp; /* Passed files */ #ifdef CONFIG_SECURITY_NETWORK - u32 secid; /* Passed security ID */ + char *secdata; /* Security context */ + u32 seclen; /* Security length */ #endif unsigned long seq; /* Connection seqno */ }; @@ -32,16 +32,6 @@ extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie extern void __scm_destroy(struct scm_cookie *scm); extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl); -#ifdef CONFIG_SECURITY_NETWORK -static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm) -{ - security_socket_getpeersec_dgram(sock, NULL, &scm->secid); -} -#else -static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm) -{ } -#endif /* CONFIG_SECURITY_NETWORK */ - static __inline__ void scm_destroy(struct scm_cookie *scm) { if (scm && scm->fp) @@ -57,7 +47,6 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, scm->creds.pid = p->tgid; scm->fp = NULL; scm->seq = 0; - unix_get_peersec_dgram(sock, scm); if (msg->msg_controllen <= 0) return 0; return __scm_send(sock, msg, scm); @@ -66,18 +55,8 @@ static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, #ifdef CONFIG_SECURITY_NETWORK static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) { - char *secdata; - u32 seclen; - int err; - - if (test_bit(SOCK_PASSSEC, &sock->flags)) { - err = security_secid_to_secctx(scm->secid, &secdata, &seclen); - - if (!err) { - put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata); - security_release_secctx(secdata, seclen); - } - } + if (test_bit(SOCK_PASSSEC, &sock->flags) && scm->secdata != NULL) + put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, scm->seclen, scm->secdata); } #else static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm) diff --git a/trunk/include/net/sctp/constants.h b/trunk/include/net/sctp/constants.h index 6c632e26f72d..c51541ee0247 100644 --- a/trunk/include/net/sctp/constants.h +++ b/trunk/include/net/sctp/constants.h @@ -264,10 +264,10 @@ enum { SCTP_MAX_DUP_TSNS = 16 }; enum { SCTP_MAX_GABS = 16 }; /* Heartbeat interval - 30 secs */ -#define SCTP_DEFAULT_TIMEOUT_HEARTBEAT (30*1000) +#define SCTP_DEFAULT_TIMEOUT_HEARTBEAT (30 * HZ) /* Delayed sack timer - 200ms */ -#define SCTP_DEFAULT_TIMEOUT_SACK (200) +#define SCTP_DEFAULT_TIMEOUT_SACK ((200 * HZ) / 1000) /* RTO.Initial - 3 seconds * RTO.Min - 1 second @@ -275,9 +275,9 @@ enum { SCTP_MAX_GABS = 16 }; * RTO.Alpha - 1/8 * RTO.Beta - 1/4 */ -#define SCTP_RTO_INITIAL (3 * 1000) -#define SCTP_RTO_MIN (1 * 1000) -#define SCTP_RTO_MAX (60 * 1000) +#define SCTP_RTO_INITIAL (3 * HZ) +#define SCTP_RTO_MIN (1 * HZ) +#define SCTP_RTO_MAX (60 * HZ) #define SCTP_RTO_ALPHA 3 /* 1/8 when converted to right shifts. */ #define SCTP_RTO_BETA 2 /* 1/4 when converted to right shifts. */ @@ -290,7 +290,8 @@ enum { SCTP_MAX_GABS = 16 }; #define SCTP_DEF_MAX_INIT 6 #define SCTP_DEF_MAX_SEND 10 -#define SCTP_DEFAULT_COOKIE_LIFE (60 * 1000) /* 60 seconds */ +#define SCTP_DEFAULT_COOKIE_LIFE_SEC 60 /* seconds */ +#define SCTP_DEFAULT_COOKIE_LIFE_USEC 0 /* microseconds */ #define SCTP_DEFAULT_MINWINDOW 1500 /* default minimum rwnd size */ #define SCTP_DEFAULT_MAXWINDOW 65535 /* default rwnd size */ @@ -311,9 +312,9 @@ enum { SCTP_MAX_GABS = 16 }; */ #if defined (CONFIG_SCTP_HMAC_MD5) -#define SCTP_COOKIE_HMAC_ALG "hmac(md5)" +#define SCTP_COOKIE_HMAC_ALG "md5" #elif defined (CONFIG_SCTP_HMAC_SHA1) -#define SCTP_COOKIE_HMAC_ALG "hmac(sha1)" +#define SCTP_COOKIE_HMAC_ALG "sha1" #else #define SCTP_COOKIE_HMAC_ALG NULL #endif diff --git a/trunk/include/net/sctp/sctp.h b/trunk/include/net/sctp/sctp.h index ee68a3124076..a9663b49ea54 100644 --- a/trunk/include/net/sctp/sctp.h +++ b/trunk/include/net/sctp/sctp.h @@ -128,8 +128,6 @@ extern int sctp_copy_local_addr_list(struct sctp_bind_addr *, int flags); extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family); extern int sctp_register_pf(struct sctp_pf *, sa_family_t); -int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, - void *ptr); /* * sctp/socket.c @@ -179,17 +177,6 @@ void sctp_icmp_proto_unreachable(struct sock *sk, void sctp_backlog_migrate(struct sctp_association *assoc, struct sock *oldsk, struct sock *newsk); -/* - * sctp/proc.c - */ -int sctp_snmp_proc_init(void); -void sctp_snmp_proc_exit(void); -int sctp_eps_proc_init(void); -void sctp_eps_proc_exit(void); -int sctp_assocs_proc_init(void); -void sctp_assocs_proc_exit(void); - - /* * Section: Macros, externs, and inlines */ @@ -229,50 +216,6 @@ DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics); #endif /* !TEST_FRAME */ -/* sctp mib definitions */ -enum -{ - SCTP_MIB_NUM = 0, - SCTP_MIB_CURRESTAB, /* CurrEstab */ - SCTP_MIB_ACTIVEESTABS, /* ActiveEstabs */ - SCTP_MIB_PASSIVEESTABS, /* PassiveEstabs */ - SCTP_MIB_ABORTEDS, /* Aborteds */ - SCTP_MIB_SHUTDOWNS, /* Shutdowns */ - SCTP_MIB_OUTOFBLUES, /* OutOfBlues */ - SCTP_MIB_CHECKSUMERRORS, /* ChecksumErrors */ - SCTP_MIB_OUTCTRLCHUNKS, /* OutCtrlChunks */ - SCTP_MIB_OUTORDERCHUNKS, /* OutOrderChunks */ - SCTP_MIB_OUTUNORDERCHUNKS, /* OutUnorderChunks */ - SCTP_MIB_INCTRLCHUNKS, /* InCtrlChunks */ - SCTP_MIB_INORDERCHUNKS, /* InOrderChunks */ - SCTP_MIB_INUNORDERCHUNKS, /* InUnorderChunks */ - SCTP_MIB_FRAGUSRMSGS, /* FragUsrMsgs */ - SCTP_MIB_REASMUSRMSGS, /* ReasmUsrMsgs */ - SCTP_MIB_OUTSCTPPACKS, /* OutSCTPPacks */ - SCTP_MIB_INSCTPPACKS, /* InSCTPPacks */ - SCTP_MIB_T1_INIT_EXPIREDS, - SCTP_MIB_T1_COOKIE_EXPIREDS, - SCTP_MIB_T2_SHUTDOWN_EXPIREDS, - SCTP_MIB_T3_RTX_EXPIREDS, - SCTP_MIB_T4_RTO_EXPIREDS, - SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS, - SCTP_MIB_DELAY_SACK_EXPIREDS, - SCTP_MIB_AUTOCLOSE_EXPIREDS, - SCTP_MIB_T3_RETRANSMITS, - SCTP_MIB_PMTUD_RETRANSMITS, - SCTP_MIB_FAST_RETRANSMITS, - SCTP_MIB_IN_PKT_SOFTIRQ, - SCTP_MIB_IN_PKT_BACKLOG, - SCTP_MIB_IN_PKT_DISCARDS, - SCTP_MIB_IN_DATA_CHUNK_DISCARDS, - __SCTP_MIB_MAX -}; - -#define SCTP_MIB_MAX __SCTP_MIB_MAX -struct sctp_mib { - unsigned long mibs[SCTP_MIB_MAX]; -} __SNMP_MIB_ALIGN__; - /* Print debugging messages. */ #if SCTP_DEBUG @@ -387,6 +330,17 @@ static inline void sctp_v6_exit(void) { return; } #endif /* #if defined(CONFIG_IPV6) */ +/* Some wrappers, in case crypto not available. */ +#if defined (CONFIG_CRYPTO_HMAC) +#define sctp_crypto_alloc_tfm crypto_alloc_tfm +#define sctp_crypto_free_tfm crypto_free_tfm +#define sctp_crypto_hmac crypto_hmac +#else +#define sctp_crypto_alloc_tfm(x...) NULL +#define sctp_crypto_free_tfm(x...) +#define sctp_crypto_hmac(x...) +#endif + /* Map an association to an assoc_id. */ static inline sctp_assoc_t sctp_assoc2id(const struct sctp_association *asoc) @@ -450,6 +404,19 @@ static inline int sctp_list_single_entry(struct list_head *head) return ((head->next != head) && (head->next == head->prev)); } +/* Calculate the size (in bytes) occupied by the data of an iovec. */ +static inline size_t get_user_iov_size(struct iovec *iov, int iovlen) +{ + size_t retval = 0; + + for (; iovlen > 0; --iovlen) { + retval += iov->iov_len; + iov++; + } + + return retval; +} + /* Generate a random jitter in the range of -50% ~ +50% of input RTO. */ static inline __s32 sctp_jitter(__u32 rto) { diff --git a/trunk/include/net/sctp/sm.h b/trunk/include/net/sctp/sm.h index de313de4fefe..1eac3d0eb7a9 100644 --- a/trunk/include/net/sctp/sm.h +++ b/trunk/include/net/sctp/sm.h @@ -221,7 +221,8 @@ struct sctp_chunk *sctp_make_abort_no_data(const struct sctp_association *, const struct sctp_chunk *, __u32 tsn); struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *, - const struct msghdr *, size_t msg_len); + const struct sctp_chunk *, + const struct msghdr *); struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *, const struct sctp_chunk *, const __u8 *, diff --git a/trunk/include/net/sctp/structs.h b/trunk/include/net/sctp/structs.h index c6d93bb0dcd2..e5aa7ff1f5b5 100644 --- a/trunk/include/net/sctp/structs.h +++ b/trunk/include/net/sctp/structs.h @@ -87,7 +87,6 @@ struct sctp_bind_addr; struct sctp_ulpq; struct sctp_ep_common; struct sctp_ssnmap; -struct crypto_hash; #include @@ -128,9 +127,9 @@ extern struct sctp_globals { * RTO.Alpha - 1/8 (3 when converted to right shifts.) * RTO.Beta - 1/4 (2 when converted to right shifts.) */ - unsigned int rto_initial; - unsigned int rto_min; - unsigned int rto_max; + unsigned long rto_initial; + unsigned long rto_min; + unsigned long rto_max; /* Note: rto_alpha and rto_beta are really defined as inverse * powers of two to facilitate integer operations. @@ -145,13 +144,13 @@ extern struct sctp_globals { int cookie_preserve_enable; /* Valid.Cookie.Life - 60 seconds */ - unsigned int valid_cookie_life; + unsigned long valid_cookie_life; /* Delayed SACK timeout 200ms default*/ - unsigned int sack_timeout; + unsigned long sack_timeout; /* HB.interval - 30 seconds */ - unsigned int hb_interval; + unsigned long hb_interval; /* Association.Max.Retrans - 10 attempts * Path.Max.Retrans - 5 attempts (per destination address) @@ -265,7 +264,7 @@ struct sctp_sock { struct sctp_pf *pf; /* Access to HMAC transform. */ - struct crypto_hash *hmac; + struct crypto_tfm *hmac; /* What is our base endpointer? */ struct sctp_endpoint *ep; diff --git a/trunk/include/net/snmp.h b/trunk/include/net/snmp.h index 464970e39ec0..a36bed8ea210 100644 --- a/trunk/include/net/snmp.h +++ b/trunk/include/net/snmp.h @@ -100,6 +100,12 @@ struct udp_mib { unsigned long mibs[UDP_MIB_MAX]; } __SNMP_MIB_ALIGN__; +/* SCTP */ +#define SCTP_MIB_MAX __SCTP_MIB_MAX +struct sctp_mib { + unsigned long mibs[SCTP_MIB_MAX]; +} __SNMP_MIB_ALIGN__; + /* Linux */ #define LINUX_MIB_MAX __LINUX_MIB_MAX struct linux_mib { diff --git a/trunk/include/net/sock.h b/trunk/include/net/sock.h index edd4d73ce7f5..324b3ea233d6 100644 --- a/trunk/include/net/sock.h +++ b/trunk/include/net/sock.h @@ -862,24 +862,30 @@ extern void sock_init_data(struct socket *sock, struct sock *sk); * */ -static inline int sk_filter(struct sock *sk, struct sk_buff *skb) +static inline int sk_filter(struct sock *sk, struct sk_buff *skb, int needlock) { int err; - struct sk_filter *filter; err = security_sock_rcv_skb(sk, skb); if (err) return err; - rcu_read_lock_bh(); - filter = sk->sk_filter; - if (filter) { - unsigned int pkt_len = sk_run_filter(skb, filter->insns, - filter->len); - err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM; - } - rcu_read_unlock_bh(); + if (sk->sk_filter) { + struct sk_filter *filter; + + if (needlock) + bh_lock_sock(sk); + + filter = sk->sk_filter; + if (filter) { + unsigned int pkt_len = sk_run_filter(skb, filter->insns, + filter->len); + err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM; + } + if (needlock) + bh_unlock_sock(sk); + } return err; } @@ -891,12 +897,6 @@ static inline int sk_filter(struct sock *sk, struct sk_buff *skb) * Remove a filter from a socket and release its resources. */ -static inline void sk_filter_rcu_free(struct rcu_head *rcu) -{ - struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); - kfree(fp); -} - static inline void sk_filter_release(struct sock *sk, struct sk_filter *fp) { unsigned int size = sk_filter_len(fp); @@ -904,7 +904,7 @@ static inline void sk_filter_release(struct sock *sk, struct sk_filter *fp) atomic_sub(size, &sk->sk_omem_alloc); if (atomic_dec_and_test(&fp->refcnt)) - call_rcu_bh(&fp->rcu, sk_filter_rcu_free); + kfree(fp); } static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp) @@ -969,23 +969,9 @@ static inline void sock_graft(struct sock *sk, struct socket *parent) sk->sk_sleep = &parent->wait; parent->sk = sk; sk->sk_socket = parent; - security_sock_graft(sk, parent); write_unlock_bh(&sk->sk_callback_lock); } -static inline void sock_copy(struct sock *nsk, const struct sock *osk) -{ -#ifdef CONFIG_SECURITY_NETWORK - void *sptr = nsk->sk_security; -#endif - - memcpy(nsk, osk, osk->sk_prot->obj_size); -#ifdef CONFIG_SECURITY_NETWORK - nsk->sk_security = sptr; - security_sk_clone(osk, nsk); -#endif -} - extern int sock_i_uid(struct sock *sk); extern unsigned long sock_i_ino(struct sock *sk); diff --git a/trunk/include/net/tc_act/tc_defact.h b/trunk/include/net/tc_act/tc_defact.h index 65f024b80958..463aa671f95d 100644 --- a/trunk/include/net/tc_act/tc_defact.h +++ b/trunk/include/net/tc_act/tc_defact.h @@ -3,12 +3,11 @@ #include -struct tcf_defact { - struct tcf_common common; - u32 tcfd_datalen; - void *tcfd_defdata; +struct tcf_defact +{ + tca_gen(defact); + u32 datalen; + void *defdata; }; -#define to_defact(pc) \ - container_of(pc, struct tcf_defact, common) -#endif /* __NET_TC_DEF_H */ +#endif diff --git a/trunk/include/net/tc_act/tc_gact.h b/trunk/include/net/tc_act/tc_gact.h index 9e3f6767b80e..59f0d9628ad1 100644 --- a/trunk/include/net/tc_act/tc_gact.h +++ b/trunk/include/net/tc_act/tc_gact.h @@ -3,15 +3,15 @@ #include -struct tcf_gact { - struct tcf_common common; +struct tcf_gact +{ + tca_gen(gact); #ifdef CONFIG_GACT_PROB - u16 tcfg_ptype; - u16 tcfg_pval; - int tcfg_paction; + u16 ptype; + u16 pval; + int paction; #endif + }; -#define to_gact(pc) \ - container_of(pc, struct tcf_gact, common) - -#endif /* __NET_TC_GACT_H */ + +#endif diff --git a/trunk/include/net/tc_act/tc_ipt.h b/trunk/include/net/tc_act/tc_ipt.h index f7d25dfcc4b7..cb37ad08427f 100644 --- a/trunk/include/net/tc_act/tc_ipt.h +++ b/trunk/include/net/tc_act/tc_ipt.h @@ -5,13 +5,12 @@ struct xt_entry_target; -struct tcf_ipt { - struct tcf_common common; - u32 tcfi_hook; - char *tcfi_tname; - struct xt_entry_target *tcfi_t; +struct tcf_ipt +{ + tca_gen(ipt); + u32 hook; + char *tname; + struct xt_entry_target *t; }; -#define to_ipt(pc) \ - container_of(pc, struct tcf_ipt, common) -#endif /* __NET_TC_IPT_H */ +#endif diff --git a/trunk/include/net/tc_act/tc_mirred.h b/trunk/include/net/tc_act/tc_mirred.h index ceac661cdfd5..b5c32f65c12c 100644 --- a/trunk/include/net/tc_act/tc_mirred.h +++ b/trunk/include/net/tc_act/tc_mirred.h @@ -3,14 +3,13 @@ #include -struct tcf_mirred { - struct tcf_common common; - int tcfm_eaction; - int tcfm_ifindex; - int tcfm_ok_push; - struct net_device *tcfm_dev; +struct tcf_mirred +{ + tca_gen(mirred); + int eaction; + int ifindex; + int ok_push; + struct net_device *dev; }; -#define to_mirred(pc) \ - container_of(pc, struct tcf_mirred, common) -#endif /* __NET_TC_MIR_H */ +#endif diff --git a/trunk/include/net/tc_act/tc_pedit.h b/trunk/include/net/tc_act/tc_pedit.h index e6f6e15956f5..eb21689d759d 100644 --- a/trunk/include/net/tc_act/tc_pedit.h +++ b/trunk/include/net/tc_act/tc_pedit.h @@ -3,13 +3,12 @@ #include -struct tcf_pedit { - struct tcf_common common; - unsigned char tcfp_nkeys; - unsigned char tcfp_flags; - struct tc_pedit_key *tcfp_keys; +struct tcf_pedit +{ + tca_gen(pedit); + unsigned char nkeys; + unsigned char flags; + struct tc_pedit_key *keys; }; -#define to_pedit(pc) \ - container_of(pc, struct tcf_pedit, common) -#endif /* __NET_TC_PED_H */ +#endif diff --git a/trunk/include/net/tcp.h b/trunk/include/net/tcp.h index 7a093d0aa0fe..0720bddff1e9 100644 --- a/trunk/include/net/tcp.h +++ b/trunk/include/net/tcp.h @@ -914,9 +914,6 @@ static inline void tcp_set_state(struct sock *sk, int state) static inline void tcp_done(struct sock *sk) { - if(sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV) - TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); - tcp_set_state(sk, TCP_CLOSE); tcp_clear_xmit_timers(sk); diff --git a/trunk/include/net/udp.h b/trunk/include/net/udp.h index db0c05f67546..766fba1369ce 100644 --- a/trunk/include/net/udp.h +++ b/trunk/include/net/udp.h @@ -30,9 +30,25 @@ #define UDP_HTABLE_SIZE 128 +/* udp.c: This needs to be shared by v4 and v6 because the lookup + * and hashing code needs to work with different AF's yet + * the port space is shared. + */ extern struct hlist_head udp_hash[UDP_HTABLE_SIZE]; extern rwlock_t udp_hash_lock; +extern int udp_port_rover; + +static inline int udp_lport_inuse(u16 num) +{ + struct sock *sk; + struct hlist_node *node; + + sk_for_each(sk, node, &udp_hash[num & (UDP_HTABLE_SIZE - 1)]) + if (inet_sk(sk)->num == num) + return 1; + return 0; +} /* Note: this must match 'valbool' in sock_setsockopt */ #define UDP_CSUM_NOXMIT 1 @@ -47,8 +63,6 @@ extern struct proto udp_prot; struct sk_buff; -extern int udp_get_port(struct sock *sk, unsigned short snum, - int (*saddr_cmp)(const struct sock *, const struct sock *)); extern void udp_err(struct sk_buff *, u32); extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, diff --git a/trunk/include/net/xfrm.h b/trunk/include/net/xfrm.h index 11e0b1d6bd47..9c5ee9f20b65 100644 --- a/trunk/include/net/xfrm.h +++ b/trunk/include/net/xfrm.h @@ -8,8 +8,8 @@ #include #include #include +#include #include -#include #include #include @@ -94,9 +94,8 @@ extern struct mutex xfrm_cfg_mutex; struct xfrm_state { /* Note: bydst is re-used during gc */ - struct hlist_node bydst; - struct hlist_node bysrc; - struct hlist_node byspi; + struct list_head bydst; + struct list_head byspi; atomic_t refcnt; spinlock_t lock; @@ -104,8 +103,6 @@ struct xfrm_state struct xfrm_id id; struct xfrm_selector sel; - u32 genid; - /* Key manger bits */ struct { u8 state; @@ -136,9 +133,6 @@ struct xfrm_state /* Data for encapsulator */ struct xfrm_encap_tmpl *encap; - /* Data for care-of address */ - xfrm_address_t *coaddr; - /* IPComp needs an IPIP tunnel for handling uncompressed packets */ struct xfrm_state *tunnel; @@ -169,9 +163,6 @@ struct xfrm_state struct xfrm_lifetime_cur curlft; struct timer_list timer; - /* Last used time */ - u64 lastused; - /* Reference to data common to all the instances of this * transformer. */ struct xfrm_type *type; @@ -205,7 +196,6 @@ struct km_event u32 proto; u32 byid; u32 aevent; - u32 type; } data; u32 seq; @@ -222,7 +212,6 @@ struct xfrm_policy_afinfo { struct dst_ops *dst_ops; void (*garbage_collect)(void); int (*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl); - int (*get_saddr)(xfrm_address_t *saddr, xfrm_address_t *daddr); struct dst_entry *(*find_bundle)(struct flowi *fl, struct xfrm_policy *policy); int (*bundle_create)(struct xfrm_policy *policy, struct xfrm_state **xfrm, @@ -246,12 +235,16 @@ extern int __xfrm_state_delete(struct xfrm_state *x); struct xfrm_state_afinfo { unsigned short family; + struct list_head *state_bydst; + struct list_head *state_byspi; int (*init_flags)(struct xfrm_state *x); void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, struct xfrm_tmpl *tmpl, xfrm_address_t *daddr, xfrm_address_t *saddr); - int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); - int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); + struct xfrm_state *(*state_lookup)(xfrm_address_t *daddr, u32 spi, u8 proto); + struct xfrm_state *(*find_acq)(u8 mode, u32 reqid, u8 proto, + xfrm_address_t *daddr, xfrm_address_t *saddr, + int create); }; extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo); @@ -264,17 +257,11 @@ struct xfrm_type char *description; struct module *owner; __u8 proto; - __u8 flags; -#define XFRM_TYPE_NON_FRAGMENT 1 int (*init_state)(struct xfrm_state *x); void (*destructor)(struct xfrm_state *); int (*input)(struct xfrm_state *, struct sk_buff *skb); int (*output)(struct xfrm_state *, struct sk_buff *pskb); - int (*reject)(struct xfrm_state *, struct sk_buff *, struct flowi *); - int (*hdr_offset)(struct xfrm_state *, struct sk_buff *, u8 **); - xfrm_address_t *(*local_addr)(struct xfrm_state *, xfrm_address_t *); - xfrm_address_t *(*remote_addr)(struct xfrm_state *, xfrm_address_t *); /* Estimate maximal size of result of transformation of a dgram */ u32 (*get_max_size)(struct xfrm_state *, int size); }; @@ -286,7 +273,7 @@ extern void xfrm_put_type(struct xfrm_type *type); struct xfrm_mode { int (*input)(struct xfrm_state *x, struct sk_buff *skb); - int (*output)(struct xfrm_state *x,struct sk_buff *skb); + int (*output)(struct sk_buff *skb); struct module *owner; unsigned int encap; @@ -312,7 +299,7 @@ struct xfrm_tmpl __u32 reqid; -/* Mode: transport, tunnel etc. */ +/* Mode: transport/tunnel */ __u8 mode; /* Sharing mode: unique, this session only, this user only etc. */ @@ -327,20 +314,18 @@ struct xfrm_tmpl __u32 calgos; }; -#define XFRM_MAX_DEPTH 6 +#define XFRM_MAX_DEPTH 4 struct xfrm_policy { struct xfrm_policy *next; - struct hlist_node bydst; - struct hlist_node byidx; + struct list_head list; /* This lock only affects elements except for entry. */ rwlock_t lock; atomic_t refcnt; struct timer_list timer; - u8 type; u32 priority; u32 index; struct xfrm_selector selector; @@ -378,16 +363,16 @@ struct xfrm_mgr char *id; int (*notify)(struct xfrm_state *x, struct km_event *c); int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir); - struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir); + struct xfrm_policy *(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir); int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c); - int (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); }; extern int xfrm_register_km(struct xfrm_mgr *km); extern int xfrm_unregister_km(struct xfrm_mgr *km); -extern unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2]; + +extern struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2]; static inline void xfrm_pol_hold(struct xfrm_policy *policy) { @@ -403,19 +388,67 @@ static inline void xfrm_pol_put(struct xfrm_policy *policy) __xfrm_policy_destroy(policy); } -#ifdef CONFIG_XFRM_SUB_POLICY -static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols) +#define XFRM_DST_HSIZE 1024 + +static __inline__ +unsigned __xfrm4_dst_hash(xfrm_address_t *addr) { - int i; - for (i = npols - 1; i >= 0; --i) - xfrm_pol_put(pols[i]); + unsigned h; + h = ntohl(addr->a4); + h = (h ^ (h>>16)) % XFRM_DST_HSIZE; + return h; } -#else -static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols) + +static __inline__ +unsigned __xfrm6_dst_hash(xfrm_address_t *addr) { - xfrm_pol_put(pols[0]); + unsigned h; + h = ntohl(addr->a6[2]^addr->a6[3]); + h = (h ^ (h>>16)) % XFRM_DST_HSIZE; + return h; +} + +static __inline__ +unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) +{ + switch (family) { + case AF_INET: + return __xfrm4_dst_hash(addr); + case AF_INET6: + return __xfrm6_dst_hash(addr); + } + return 0; +} + +static __inline__ +unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) +{ + unsigned h; + h = ntohl(addr->a4^spi^proto); + h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; + return h; +} + +static __inline__ +unsigned __xfrm6_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) +{ + unsigned h; + h = ntohl(addr->a6[2]^addr->a6[3]^spi^proto); + h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; + return h; +} + +static __inline__ +unsigned xfrm_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, unsigned short family) +{ + switch (family) { + case AF_INET: + return __xfrm4_spi_hash(addr, spi, proto); + case AF_INET6: + return __xfrm6_spi_hash(addr, spi, proto); + } + return 0; /*XXX*/ } -#endif extern void __xfrm_state_destroy(struct xfrm_state *); @@ -475,11 +508,6 @@ u16 xfrm_flowi_sport(struct flowi *fl) case IPPROTO_ICMPV6: port = htons(fl->fl_icmp_type); break; -#ifdef CONFIG_IPV6_MIP6 - case IPPROTO_MH: - port = htons(fl->fl_mh_type); - break; -#endif default: port = 0; /*XXX*/ } @@ -580,7 +608,6 @@ struct xfrm_dst struct rt6_info rt6; } u; struct dst_entry *route; - u32 genid; u32 route_mtu_cached; u32 child_mtu_cached; u32 route_cookie; @@ -631,18 +658,6 @@ secpath_reset(struct sk_buff *skb) #endif } -static inline int -xfrm_addr_any(xfrm_address_t *addr, unsigned short family) -{ - switch (family) { - case AF_INET: - return addr->a4 == 0; - case AF_INET6: - return ipv6_addr_any((struct in6_addr *)&addr->a6); - } - return 0; -} - static inline int __xfrm4_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x) { @@ -677,8 +692,8 @@ static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *sk { if (sk && sk->sk_policy[XFRM_POLICY_IN]) return __xfrm_policy_check(sk, dir, skb, family); - - return (!xfrm_policy_count[dir] && !skb->sp) || + + return (!xfrm_policy_list[dir] && !skb->sp) || (skb->dst->flags & DST_NOPOLICY) || __xfrm_policy_check(sk, dir, skb, family); } @@ -698,7 +713,7 @@ extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family); static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family) { - return !xfrm_policy_count[XFRM_POLICY_OUT] || + return !xfrm_policy_list[XFRM_POLICY_OUT] || (skb->dst->flags & DST_NOXFRM) || __xfrm_route_forward(skb, family); } @@ -816,36 +831,11 @@ xfrm_state_addr_check(struct xfrm_state *x, return 0; } -static __inline__ int -xfrm_state_addr_flow_check(struct xfrm_state *x, struct flowi *fl, - unsigned short family) -{ - switch (family) { - case AF_INET: - return __xfrm4_state_addr_check(x, - (xfrm_address_t *)&fl->fl4_dst, - (xfrm_address_t *)&fl->fl4_src); - case AF_INET6: - return __xfrm6_state_addr_check(x, - (xfrm_address_t *)&fl->fl6_dst, - (xfrm_address_t *)&fl->fl6_src); - } - return 0; -} - static inline int xfrm_state_kern(struct xfrm_state *x) { return atomic_read(&x->tunnel_users); } -static inline int xfrm_id_proto_match(u8 proto, u8 userproto) -{ - return (!userproto || proto == userproto || - (userproto == IPSEC_PROTO_ANY && (proto == IPPROTO_AH || - proto == IPPROTO_ESP || - proto == IPPROTO_COMP))); -} - /* * xfrm algorithm information */ @@ -865,7 +855,6 @@ struct xfrm_algo_comp_info { struct xfrm_algo_desc { char *name; - char *compat; u8 available:1; union { struct xfrm_algo_auth_info auth; @@ -913,25 +902,6 @@ extern void xfrm_state_insert(struct xfrm_state *x); extern int xfrm_state_add(struct xfrm_state *x); extern int xfrm_state_update(struct xfrm_state *x); extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family); -extern struct xfrm_state *xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family); -#ifdef CONFIG_XFRM_SUB_POLICY -extern int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, - int n, unsigned short family); -extern int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, - int n, unsigned short family); -#else -static inline int xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, - int n, unsigned short family) -{ - return -ENOSYS; -} - -static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, - int n, unsigned short family) -{ - return -ENOSYS; -} -#endif extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq); extern int xfrm_state_delete(struct xfrm_state *x); extern void xfrm_state_flush(u8 proto); @@ -947,16 +917,12 @@ extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler); extern int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi); extern int xfrm6_rcv(struct sk_buff **pskb); -extern int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, - xfrm_address_t *saddr, u8 proto); extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler); extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler); extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr); extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr); extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr); extern int xfrm6_output(struct sk_buff *skb); -extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, - u8 **prevhdr); #ifdef CONFIG_XFRM extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type); @@ -981,27 +947,27 @@ static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsig #endif struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp); -extern int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*), void *); +extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *); int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); -struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, - struct xfrm_selector *sel, +struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel, struct xfrm_sec_ctx *ctx, int delete); -struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete); -void xfrm_policy_flush(u8 type); +struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete); +void xfrm_policy_flush(void); u32 xfrm_get_acqseq(void); void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create, unsigned short family); -extern void xfrm_policy_flush(u8 type); +extern void xfrm_policy_flush(void); extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); -extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family, int strict); +extern int xfrm_flush_bundles(void); +extern void xfrm_flush_all_bundles(void); +extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family); extern void xfrm_init_pmtu(struct dst_entry *dst); extern wait_queue_head_t km_waitq; extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid); -extern int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr); extern void xfrm_input_init(void); extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq); @@ -1018,13 +984,11 @@ extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe); extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe); extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe); -struct hash_desc; -struct scatterlist; -typedef int (icv_update_fn_t)(struct hash_desc *, struct scatterlist *, - unsigned int); +struct crypto_tfm; +typedef void (icv_update_fn_t)(struct crypto_tfm *, struct scatterlist *, unsigned int); -extern int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *tfm, - int offset, int len, icv_update_fn_t icv_update); +extern void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, + int offset, int len, icv_update_fn_t icv_update); static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b, int family) diff --git a/trunk/include/rdma/Kbuild b/trunk/include/rdma/Kbuild index e7c043216558..eb710ba9b1a0 100644 --- a/trunk/include/rdma/Kbuild +++ b/trunk/include/rdma/Kbuild @@ -1 +1 @@ -header-y += ib_user_mad.h +header-y := ib_user_mad.h diff --git a/trunk/include/rdma/ib_addr.h b/trunk/include/rdma/ib_addr.h index 81b62307621d..0ff67398928d 100644 --- a/trunk/include/rdma/ib_addr.h +++ b/trunk/include/rdma/ib_addr.h @@ -40,7 +40,7 @@ struct rdma_dev_addr { unsigned char src_dev_addr[MAX_ADDR_LEN]; unsigned char dst_dev_addr[MAX_ADDR_LEN]; unsigned char broadcast[MAX_ADDR_LEN]; - enum rdma_node_type dev_type; + enum ib_node_type dev_type; }; /** @@ -72,9 +72,6 @@ int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr, void rdma_addr_cancel(struct rdma_dev_addr *addr); -int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, - const unsigned char *dst_dev_addr); - static inline int ip_addr_size(struct sockaddr *addr) { return addr->sa_family == AF_INET6 ? @@ -116,16 +113,4 @@ static inline void ib_addr_set_dgid(struct rdma_dev_addr *dev_addr, memcpy(dev_addr->dst_dev_addr + 4, gid, sizeof *gid); } -static inline void iw_addr_get_sgid(struct rdma_dev_addr *dev_addr, - union ib_gid *gid) -{ - memcpy(gid, dev_addr->src_dev_addr, sizeof *gid); -} - -static inline void iw_addr_get_dgid(struct rdma_dev_addr *dev_addr, - union ib_gid *gid) -{ - memcpy(gid, dev_addr->dst_dev_addr, sizeof *gid); -} - #endif /* IB_ADDR_H */ diff --git a/trunk/include/rdma/ib_sa.h b/trunk/include/rdma/ib_sa.h index 97715b0c20b6..c99e4420fd7e 100644 --- a/trunk/include/rdma/ib_sa.h +++ b/trunk/include/rdma/ib_sa.h @@ -1,7 +1,6 @@ /* * Copyright (c) 2004 Topspin Communications. All rights reserved. * Copyright (c) 2005 Voltaire, Inc. All rights reserved. - * Copyright (c) 2006 Intel Corporation. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -37,11 +36,8 @@ #ifndef IB_SA_H #define IB_SA_H -#include #include -#include - #include #include @@ -83,8 +79,8 @@ enum { }; enum ib_sa_selector { - IB_SA_GT = 0, - IB_SA_LT = 1, + IB_SA_GTE = 0, + IB_SA_LTE = 1, IB_SA_EQ = 2, /* * The meaning of "best" depends on the attribute: for @@ -254,28 +250,11 @@ struct ib_sa_service_rec { u64 data64[2]; }; -struct ib_sa_client { - atomic_t users; - struct completion comp; -}; - -/** - * ib_sa_register_client - Register an SA client. - */ -void ib_sa_register_client(struct ib_sa_client *client); - -/** - * ib_sa_unregister_client - Deregister an SA client. - * @client: Client object to deregister. - */ -void ib_sa_unregister_client(struct ib_sa_client *client); - struct ib_sa_query; void ib_sa_cancel_query(int id, struct ib_sa_query *query); -int ib_sa_path_rec_get(struct ib_sa_client *client, - struct ib_device *device, u8 port_num, +int ib_sa_path_rec_get(struct ib_device *device, u8 port_num, struct ib_sa_path_rec *rec, ib_sa_comp_mask comp_mask, int timeout_ms, gfp_t gfp_mask, @@ -285,8 +264,7 @@ int ib_sa_path_rec_get(struct ib_sa_client *client, void *context, struct ib_sa_query **query); -int ib_sa_mcmember_rec_query(struct ib_sa_client *client, - struct ib_device *device, u8 port_num, +int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num, u8 method, struct ib_sa_mcmember_rec *rec, ib_sa_comp_mask comp_mask, @@ -297,8 +275,7 @@ int ib_sa_mcmember_rec_query(struct ib_sa_client *client, void *context, struct ib_sa_query **query); -int ib_sa_service_rec_query(struct ib_sa_client *client, - struct ib_device *device, u8 port_num, +int ib_sa_service_rec_query(struct ib_device *device, u8 port_num, u8 method, struct ib_sa_service_rec *rec, ib_sa_comp_mask comp_mask, @@ -311,7 +288,6 @@ int ib_sa_service_rec_query(struct ib_sa_client *client, /** * ib_sa_mcmember_rec_set - Start an MCMember set query - * @client:SA client * @device:device to send query on * @port_num: port number to send query on * @rec:MCMember Record to send in query @@ -335,8 +311,7 @@ int ib_sa_service_rec_query(struct ib_sa_client *client, * cancel the query. */ static inline int -ib_sa_mcmember_rec_set(struct ib_sa_client *client, - struct ib_device *device, u8 port_num, +ib_sa_mcmember_rec_set(struct ib_device *device, u8 port_num, struct ib_sa_mcmember_rec *rec, ib_sa_comp_mask comp_mask, int timeout_ms, gfp_t gfp_mask, @@ -346,7 +321,7 @@ ib_sa_mcmember_rec_set(struct ib_sa_client *client, void *context, struct ib_sa_query **query) { - return ib_sa_mcmember_rec_query(client, device, port_num, + return ib_sa_mcmember_rec_query(device, port_num, IB_MGMT_METHOD_SET, rec, comp_mask, timeout_ms, gfp_mask, callback, @@ -355,7 +330,6 @@ ib_sa_mcmember_rec_set(struct ib_sa_client *client, /** * ib_sa_mcmember_rec_delete - Start an MCMember delete query - * @client:SA client * @device:device to send query on * @port_num: port number to send query on * @rec:MCMember Record to send in query @@ -379,8 +353,7 @@ ib_sa_mcmember_rec_set(struct ib_sa_client *client, * cancel the query. */ static inline int -ib_sa_mcmember_rec_delete(struct ib_sa_client *client, - struct ib_device *device, u8 port_num, +ib_sa_mcmember_rec_delete(struct ib_device *device, u8 port_num, struct ib_sa_mcmember_rec *rec, ib_sa_comp_mask comp_mask, int timeout_ms, gfp_t gfp_mask, @@ -390,7 +363,7 @@ ib_sa_mcmember_rec_delete(struct ib_sa_client *client, void *context, struct ib_sa_query **query) { - return ib_sa_mcmember_rec_query(client, device, port_num, + return ib_sa_mcmember_rec_query(device, port_num, IB_SA_METHOD_DELETE, rec, comp_mask, timeout_ms, gfp_mask, callback, diff --git a/trunk/include/rdma/ib_user_verbs.h b/trunk/include/rdma/ib_user_verbs.h index db1b814b62cc..7b5372010f4b 100644 --- a/trunk/include/rdma/ib_user_verbs.h +++ b/trunk/include/rdma/ib_user_verbs.h @@ -275,8 +275,6 @@ struct ib_uverbs_resize_cq { struct ib_uverbs_resize_cq_resp { __u32 cqe; - __u32 reserved; - __u64 driver_data[0]; }; struct ib_uverbs_poll_cq { diff --git a/trunk/include/rdma/ib_verbs.h b/trunk/include/rdma/ib_verbs.h index 8eacc3510993..ee1f3a355666 100644 --- a/trunk/include/rdma/ib_verbs.h +++ b/trunk/include/rdma/ib_verbs.h @@ -56,22 +56,12 @@ union ib_gid { } global; }; -enum rdma_node_type { - /* IB values map to NodeInfo:NodeType. */ - RDMA_NODE_IB_CA = 1, - RDMA_NODE_IB_SWITCH, - RDMA_NODE_IB_ROUTER, - RDMA_NODE_RNIC +enum ib_node_type { + IB_NODE_CA = 1, + IB_NODE_SWITCH, + IB_NODE_ROUTER }; -enum rdma_transport_type { - RDMA_TRANSPORT_IB, - RDMA_TRANSPORT_IWARP -}; - -enum rdma_transport_type -rdma_node_get_transport(enum rdma_node_type node_type) __attribute_const__; - enum ib_device_cap_flags { IB_DEVICE_RESIZE_MAX_WR = 1, IB_DEVICE_BAD_PKEY_CNTR = (1<<1), @@ -88,9 +78,6 @@ enum ib_device_cap_flags { IB_DEVICE_RC_RNR_NAK_GEN = (1<<12), IB_DEVICE_SRQ_RESIZE = (1<<13), IB_DEVICE_N_NOTIFY_CQ = (1<<14), - IB_DEVICE_ZERO_STAG = (1<<15), - IB_DEVICE_SEND_W_INV = (1<<16), - IB_DEVICE_MEM_WINDOW = (1<<17) }; enum ib_atomic_cap { @@ -848,8 +835,6 @@ struct ib_cache { u8 *lmc_cache; }; -struct iw_cm_verbs; - struct ib_device { struct device *dma_device; @@ -866,8 +851,6 @@ struct ib_device { u32 flags; - struct iw_cm_verbs *iwcm; - int (*query_device)(struct ib_device *device, struct ib_device_attr *device_attr); int (*query_port)(struct ib_device *device, @@ -905,8 +888,7 @@ struct ib_device { struct ib_udata *udata); int (*modify_srq)(struct ib_srq *srq, struct ib_srq_attr *srq_attr, - enum ib_srq_attr_mask srq_attr_mask, - struct ib_udata *udata); + enum ib_srq_attr_mask srq_attr_mask); int (*query_srq)(struct ib_srq *srq, struct ib_srq_attr *srq_attr); int (*destroy_srq)(struct ib_srq *srq); @@ -918,8 +900,7 @@ struct ib_device { struct ib_udata *udata); int (*modify_qp)(struct ib_qp *qp, struct ib_qp_attr *qp_attr, - int qp_attr_mask, - struct ib_udata *udata); + int qp_attr_mask); int (*query_qp)(struct ib_qp *qp, struct ib_qp_attr *qp_attr, int qp_attr_mask, diff --git a/trunk/include/rdma/iw_cm.h b/trunk/include/rdma/iw_cm.h deleted file mode 100644 index aeefa9b740dc..000000000000 --- a/trunk/include/rdma/iw_cm.h +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) 2005 Network Appliance, Inc. All rights reserved. - * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved. - * - * This software is available to you under a choice of one of two - * licenses. You may choose to be licensed under the terms of the GNU - * General Public License (GPL) Version 2, available from the file - * COPYING in the main directory of this source tree, or the - * OpenIB.org BSD license below: - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef IW_CM_H -#define IW_CM_H - -#include -#include - -struct iw_cm_id; - -enum iw_cm_event_type { - IW_CM_EVENT_CONNECT_REQUEST = 1, /* connect request received */ - IW_CM_EVENT_CONNECT_REPLY, /* reply from active connect request */ - IW_CM_EVENT_ESTABLISHED, /* passive side accept successful */ - IW_CM_EVENT_DISCONNECT, /* orderly shutdown */ - IW_CM_EVENT_CLOSE /* close complete */ -}; - -enum iw_cm_event_status { - IW_CM_EVENT_STATUS_OK = 0, /* request successful */ - IW_CM_EVENT_STATUS_ACCEPTED = 0, /* connect request accepted */ - IW_CM_EVENT_STATUS_REJECTED, /* connect request rejected */ - IW_CM_EVENT_STATUS_TIMEOUT, /* the operation timed out */ - IW_CM_EVENT_STATUS_RESET, /* reset from remote peer */ - IW_CM_EVENT_STATUS_EINVAL, /* asynchronous failure for bad parm */ -}; - -struct iw_cm_event { - enum iw_cm_event_type event; - enum iw_cm_event_status status; - struct sockaddr_in local_addr; - struct sockaddr_in remote_addr; - void *private_data; - u8 private_data_len; - void* provider_data; -}; - -/** - * iw_cm_handler - Function to be called by the IW CM when delivering events - * to the client. - * - * @cm_id: The IW CM identifier associated with the event. - * @event: Pointer to the event structure. - */ -typedef int (*iw_cm_handler)(struct iw_cm_id *cm_id, - struct iw_cm_event *event); - -/** - * iw_event_handler - Function called by the provider when delivering provider - * events to the IW CM. Returns either 0 indicating the event was processed - * or -errno if the event could not be processed. - * - * @cm_id: The IW CM identifier associated with the event. - * @event: Pointer to the event structure. - */ -typedef int (*iw_event_handler)(struct iw_cm_id *cm_id, - struct iw_cm_event *event); - -struct iw_cm_id { - iw_cm_handler cm_handler; /* client callback function */ - void *context; /* client cb context */ - struct ib_device *device; - struct sockaddr_in local_addr; - struct sockaddr_in remote_addr; - void *provider_data; /* provider private data */ - iw_event_handler event_handler; /* cb for provider - events */ - /* Used by provider to add and remove refs on IW cm_id */ - void (*add_ref)(struct iw_cm_id *); - void (*rem_ref)(struct iw_cm_id *); -}; - -struct iw_cm_conn_param { - const void *private_data; - u16 private_data_len; - u32 ord; - u32 ird; - u32 qpn; -}; - -struct iw_cm_verbs { - void (*add_ref)(struct ib_qp *qp); - - void (*rem_ref)(struct ib_qp *qp); - - struct ib_qp * (*get_qp)(struct ib_device *device, - int qpn); - - int (*connect)(struct iw_cm_id *cm_id, - struct iw_cm_conn_param *conn_param); - - int (*accept)(struct iw_cm_id *cm_id, - struct iw_cm_conn_param *conn_param); - - int (*reject)(struct iw_cm_id *cm_id, - const void *pdata, u8 pdata_len); - - int (*create_listen)(struct iw_cm_id *cm_id, - int backlog); - - int (*destroy_listen)(struct iw_cm_id *cm_id); -}; - -/** - * iw_create_cm_id - Create an IW CM identifier. - * - * @device: The IB device on which to create the IW CM identier. - * @event_handler: User callback invoked to report events associated with the - * returned IW CM identifier. - * @context: User specified context associated with the id. - */ -struct iw_cm_id *iw_create_cm_id(struct ib_device *device, - iw_cm_handler cm_handler, void *context); - -/** - * iw_destroy_cm_id - Destroy an IW CM identifier. - * - * @cm_id: The previously created IW CM identifier to destroy. - * - * The client can assume that no events will be delivered for the CM ID after - * this function returns. - */ -void iw_destroy_cm_id(struct iw_cm_id *cm_id); - -/** - * iw_cm_bind_qp - Unbind the specified IW CM identifier and QP - * - * @cm_id: The IW CM idenfier to unbind from the QP. - * @qp: The QP - * - * This is called by the provider when destroying the QP to ensure - * that any references held by the IWCM are released. It may also - * be called by the IWCM when destroying a CM_ID to that any - * references held by the provider are released. - */ -void iw_cm_unbind_qp(struct iw_cm_id *cm_id, struct ib_qp *qp); - -/** - * iw_cm_get_qp - Return the ib_qp associated with a QPN - * - * @ib_device: The IB device - * @qpn: The queue pair number - */ -struct ib_qp *iw_cm_get_qp(struct ib_device *device, int qpn); - -/** - * iw_cm_listen - Listen for incoming connection requests on the - * specified IW CM id. - * - * @cm_id: The IW CM identifier. - * @backlog: The maximum number of outstanding un-accepted inbound listen - * requests to queue. - * - * The source address and port number are specified in the IW CM identifier - * structure. - */ -int iw_cm_listen(struct iw_cm_id *cm_id, int backlog); - -/** - * iw_cm_accept - Called to accept an incoming connect request. - * - * @cm_id: The IW CM identifier associated with the connection request. - * @iw_param: Pointer to a structure containing connection establishment - * parameters. - * - * The specified cm_id will have been provided in the event data for a - * CONNECT_REQUEST event. Subsequent events related to this connection will be - * delivered to the specified IW CM identifier prior and may occur prior to - * the return of this function. If this function returns a non-zero value, the - * client can assume that no events will be delivered to the specified IW CM - * identifier. - */ -int iw_cm_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param); - -/** - * iw_cm_reject - Reject an incoming connection request. - * - * @cm_id: Connection identifier associated with the request. - * @private_daa: Pointer to data to deliver to the remote peer as part of the - * reject message. - * @private_data_len: The number of bytes in the private_data parameter. - * - * The client can assume that no events will be delivered to the specified IW - * CM identifier following the return of this function. The private_data - * buffer is available for reuse when this function returns. - */ -int iw_cm_reject(struct iw_cm_id *cm_id, const void *private_data, - u8 private_data_len); - -/** - * iw_cm_connect - Called to request a connection to a remote peer. - * - * @cm_id: The IW CM identifier for the connection. - * @iw_param: Pointer to a structure containing connection establishment - * parameters. - * - * Events may be delivered to the specified IW CM identifier prior to the - * return of this function. If this function returns a non-zero value, the - * client can assume that no events will be delivered to the specified IW CM - * identifier. - */ -int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param); - -/** - * iw_cm_disconnect - Close the specified connection. - * - * @cm_id: The IW CM identifier to close. - * @abrupt: If 0, the connection will be closed gracefully, otherwise, the - * connection will be reset. - * - * The IW CM identifier is still active until the IW_CM_EVENT_CLOSE event is - * delivered. - */ -int iw_cm_disconnect(struct iw_cm_id *cm_id, int abrupt); - -/** - * iw_cm_init_qp_attr - Called to initialize the attributes of the QP - * associated with a IW CM identifier. - * - * @cm_id: The IW CM identifier associated with the QP - * @qp_attr: Pointer to the QP attributes structure. - * @qp_attr_mask: Pointer to a bit vector specifying which QP attributes are - * valid. - */ -int iw_cm_init_qp_attr(struct iw_cm_id *cm_id, struct ib_qp_attr *qp_attr, - int *qp_attr_mask); - -#endif /* IW_CM_H */ diff --git a/trunk/include/rdma/rdma_cm.h b/trunk/include/rdma/rdma_cm.h index deb5a0a4cee5..402c63d7226b 100644 --- a/trunk/include/rdma/rdma_cm.h +++ b/trunk/include/rdma/rdma_cm.h @@ -117,14 +117,6 @@ struct rdma_cm_id { struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler, void *context, enum rdma_port_space ps); -/** - * rdma_destroy_id - Destroys an RDMA identifier. - * - * @id: RDMA identifier. - * - * Note: calling this function has the effect of canceling in-flight - * asynchronous operations associated with the id. - */ void rdma_destroy_id(struct rdma_cm_id *id); /** @@ -245,10 +237,6 @@ int rdma_listen(struct rdma_cm_id *id, int backlog); * Typically, this routine is only called by the listener to accept a connection * request. It must also be called on the active side of a connection if the * user is performing their own QP transitions. - * - * In the case of error, a reject message is sent to the remote side and the - * state of the qp associated with the id is modified to error, such that any - * previously posted receive buffers would be flushed. */ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param); diff --git a/trunk/include/scsi/Kbuild b/trunk/include/scsi/Kbuild index 744f85011f1e..14a033d73314 100644 --- a/trunk/include/scsi/Kbuild +++ b/trunk/include/scsi/Kbuild @@ -1,4 +1,2 @@ header-y += scsi.h - -unifdef-y += scsi_ioctl.h -unifdef-y += sg.h +unifdef-y := scsi_ioctl.h sg.h diff --git a/trunk/include/scsi/libiscsi.h b/trunk/include/scsi/libiscsi.h index 41904f611d12..ba2760802ded 100644 --- a/trunk/include/scsi/libiscsi.h +++ b/trunk/include/scsi/libiscsi.h @@ -60,7 +60,6 @@ struct iscsi_nopin; #define TMABORT_SUCCESS 0x1 #define TMABORT_FAILED 0x2 #define TMABORT_TIMEDOUT 0x3 -#define TMABORT_NOT_FOUND 0x4 /* Connection suspend "bit" */ #define ISCSI_SUSPEND_BIT 1 @@ -84,12 +83,6 @@ struct iscsi_mgmt_task { struct list_head running; }; -enum { - ISCSI_TASK_COMPLETED, - ISCSI_TASK_PENDING, - ISCSI_TASK_RUNNING, -}; - struct iscsi_cmd_task { /* * Becuae LLDs allocate their hdr differently, this is a pointer to @@ -108,8 +101,6 @@ struct iscsi_cmd_task { struct iscsi_conn *conn; /* used connection */ struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */ - /* state set/tested under session->lock */ - int state; struct list_head running; /* running cmd list */ void *dd_data; /* driver/transport data */ }; @@ -135,14 +126,6 @@ struct iscsi_conn { int id; /* CID */ struct list_head item; /* maintains list of conns */ int c_stage; /* connection state */ - /* - * Preallocated buffer for pdus that have data but do not - * originate from scsi-ml. We never have two pdus using the - * buffer at the same time. It is only allocated to - * the default max recv size because the pdus we support - * should always fit in this buffer - */ - char *data; struct iscsi_mgmt_task *login_mtask; /* mtask used for login/text */ struct iscsi_mgmt_task *mtask; /* xmit mtask in progress */ struct iscsi_cmd_task *ctask; /* xmit ctask in progress */ @@ -151,7 +134,7 @@ struct iscsi_conn { struct kfifo *immqueue; /* immediate xmit queue */ struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ struct list_head mgmt_run_list; /* list of control tasks */ - struct list_head xmitqueue; /* data-path cmd queue */ + struct kfifo *xmitqueue; /* data-path cmd queue */ struct list_head run_list; /* list of cmds in progress */ struct work_struct xmitwork; /* per-conn. xmit workqueue */ /* diff --git a/trunk/include/scsi/scsi_transport_iscsi.h b/trunk/include/scsi/scsi_transport_iscsi.h index 39e833260bd0..5a3df1d7085f 100644 --- a/trunk/include/scsi/scsi_transport_iscsi.h +++ b/trunk/include/scsi/scsi_transport_iscsi.h @@ -57,6 +57,8 @@ struct sockaddr; * @stop_conn: suspend/recover/terminate connection * @send_pdu: send iSCSI PDU, Login, Logout, NOP-Out, Reject, Text. * @session_recovery_timedout: notify LLD a block during recovery timed out + * @suspend_conn_recv: susepend the recv side of the connection + * @termincate_conn: destroy socket connection. Called with mutex lock. * @init_cmd_task: Initialize a iscsi_cmd_task and any internal structs. * Called from queuecommand with session lock held. * @init_mgmt_task: Initialize a iscsi_mgmt_task and any internal structs. @@ -110,6 +112,8 @@ struct iscsi_transport { char *data, uint32_t data_size); void (*get_stats) (struct iscsi_cls_conn *conn, struct iscsi_stats *stats); + void (*suspend_conn_recv) (struct iscsi_conn *conn); + void (*terminate_conn) (struct iscsi_conn *conn); void (*init_cmd_task) (struct iscsi_cmd_task *ctask); void (*init_mgmt_task) (struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, diff --git a/trunk/include/sound/Kbuild b/trunk/include/sound/Kbuild index fd054a344324..3a5a3df61496 100644 --- a/trunk/include/sound/Kbuild +++ b/trunk/include/sound/Kbuild @@ -1,10 +1,2 @@ -header-y += asound_fm.h -header-y += hdsp.h -header-y += hdspm.h -header-y += sfnt_info.h -header-y += sscape_ioctl.h - -unifdef-y += asequencer.h -unifdef-y += asound.h -unifdef-y += emu10k1.h -unifdef-y += sb16_csp.h +header-y := asound_fm.h hdsp.h hdspm.h sfnt_info.h sscape_ioctl.h +unifdef-y := asequencer.h asound.h emu10k1.h sb16_csp.h diff --git a/trunk/include/sound/ac97_codec.h b/trunk/include/sound/ac97_codec.h index 4c43521cc493..758f8bf133c7 100644 --- a/trunk/include/sound/ac97_codec.h +++ b/trunk/include/sound/ac97_codec.h @@ -27,7 +27,6 @@ #include #include -#include #include "pcm.h" #include "control.h" #include "info.h" @@ -141,20 +140,6 @@ #define AC97_GP_DRSS_1011 0x0000 /* LR(C) 10+11(+12) */ #define AC97_GP_DRSS_78 0x0400 /* LR 7+8 */ -/* powerdown bits */ -#define AC97_PD_ADC_STATUS 0x0001 /* ADC status (RO) */ -#define AC97_PD_DAC_STATUS 0x0002 /* DAC status (RO) */ -#define AC97_PD_MIXER_STATUS 0x0004 /* Analog mixer status (RO) */ -#define AC97_PD_VREF_STATUS 0x0008 /* Vref status (RO) */ -#define AC97_PD_PR0 0x0100 /* Power down PCM ADCs and input MUX */ -#define AC97_PD_PR1 0x0200 /* Power down PCM front DAC */ -#define AC97_PD_PR2 0x0400 /* Power down Mixer (Vref still on) */ -#define AC97_PD_PR3 0x0800 /* Power down Mixer (Vref off) */ -#define AC97_PD_PR4 0x1000 /* Power down AC-Link */ -#define AC97_PD_PR5 0x2000 /* Disable internal clock usage */ -#define AC97_PD_PR6 0x4000 /* Headphone amplifier */ -#define AC97_PD_EAPD 0x8000 /* External Amplifer Power Down (EAPD) */ - /* extended audio ID bit defines */ #define AC97_EI_VRA 0x0001 /* Variable bit rate supported */ #define AC97_EI_DRA 0x0002 /* Double rate supported */ @@ -374,7 +359,6 @@ #define AC97_SCAP_INV_EAPD (1<<7) /* inverted EAPD */ #define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */ #define AC97_SCAP_NO_SPDIF (1<<9) /* don't build SPDIF controls */ -#define AC97_SCAP_EAPD_LED (1<<10) /* EAPD as mute LED */ /* ac97->flags */ #define AC97_HAS_PC_BEEP (1<<0) /* force PC Speaker usage */ @@ -507,12 +491,6 @@ struct snd_ac97 { /* jack-sharing info */ unsigned char indep_surround; unsigned char channel_mode; - -#ifdef CONFIG_SND_AC97_POWER_SAVE - unsigned int power_up; /* power states */ - struct workqueue_struct *power_workq; - struct work_struct power_work; -#endif struct device dev; }; @@ -554,15 +532,6 @@ unsigned short snd_ac97_read(struct snd_ac97 *ac97, unsigned short reg); void snd_ac97_write_cache(struct snd_ac97 *ac97, unsigned short reg, unsigned short value); int snd_ac97_update(struct snd_ac97 *ac97, unsigned short reg, unsigned short value); int snd_ac97_update_bits(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value); -#ifdef CONFIG_SND_AC97_POWER_SAVE -int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup); -#else -static inline int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, - int powerup) -{ - return 0; -} -#endif #ifdef CONFIG_PM void snd_ac97_suspend(struct snd_ac97 *ac97); void snd_ac97_resume(struct snd_ac97 *ac97); @@ -614,7 +583,6 @@ struct ac97_pcm { copy_flag: 1, /* lowlevel driver must fill all entries */ spdif: 1; /* spdif pcm */ unsigned short aslots; /* active slots */ - unsigned short cur_dbl; /* current double-rate state */ unsigned int rates; /* available rates */ struct { unsigned short slots; /* driver input: requested AC97 slot numbers */ diff --git a/trunk/include/sound/ad1848.h b/trunk/include/sound/ad1848.h index c8de6f83338f..57af1fe7b309 100644 --- a/trunk/include/sound/ad1848.h +++ b/trunk/include/sound/ad1848.h @@ -179,13 +179,14 @@ enum { AD1848_MIX_SINGLE, AD1848_MIX_DOUBLE, AD1848_MIX_CAPTURE }; #define AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert) \ ((left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22)) +int snd_ad1848_add_ctl(struct snd_ad1848 *chip, const char *name, int index, int type, unsigned long value); + /* for ease of use */ struct ad1848_mix_elem { const char *name; int index; int type; unsigned long private_value; - unsigned int *tlv; }; #define AD1848_SINGLE(xname, xindex, reg, shift, mask, invert) \ @@ -194,26 +195,15 @@ struct ad1848_mix_elem { .type = AD1848_MIX_SINGLE, \ .private_value = AD1848_MIXVAL_SINGLE(reg, shift, mask, invert) } -#define AD1848_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ -{ .name = xname, \ - .index = xindex, \ - .type = AD1848_MIX_SINGLE, \ - .private_value = AD1848_MIXVAL_SINGLE(reg, shift, mask, invert), \ - .tlv = xtlv } - #define AD1848_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ { .name = xname, \ .index = xindex, \ .type = AD1848_MIX_DOUBLE, \ .private_value = AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert) } -#define AD1848_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .name = xname, \ - .index = xindex, \ - .type = AD1848_MIX_DOUBLE, \ - .private_value = AD1848_MIXVAL_DOUBLE(left_reg, right_reg, shift_left, shift_right, mask, invert), \ - .tlv = xtlv } - -int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip, const struct ad1848_mix_elem *c); +static inline int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip, const struct ad1848_mix_elem *c) +{ + return snd_ad1848_add_ctl(chip, c->name, c->index, c->type, c->private_value); +} #endif /* __SOUND_AD1848_H */ diff --git a/trunk/include/sound/ak4xxx-adda.h b/trunk/include/sound/ak4xxx-adda.h index d0deca669b92..3d9888492026 100644 --- a/trunk/include/sound/ak4xxx-adda.h +++ b/trunk/include/sound/ak4xxx-adda.h @@ -39,39 +39,26 @@ struct snd_ak4xxx_ops { #define AK4XXX_IMAGE_SIZE (AK4XXX_MAX_CHIPS * 16) /* 64 bytes */ -/* DAC label and channels */ -struct snd_akm4xxx_dac_channel { - char *name; /* mixer volume name */ - unsigned int num_channels; -}; - -/* ADC labels and channels */ -struct snd_akm4xxx_adc_channel { - char *name; /* capture gain volume label */ - char *switch_name; /* capture switch */ - unsigned int num_channels; -}; - struct snd_akm4xxx { struct snd_card *card; unsigned int num_adcs; /* AK4524 or AK4528 ADCs */ unsigned int num_dacs; /* AK4524 or AK4528 DACs */ unsigned char images[AK4XXX_IMAGE_SIZE]; /* saved register image */ - unsigned char volumes[AK4XXX_IMAGE_SIZE]; /* saved volume values */ + unsigned char ipga_gain[AK4XXX_MAX_CHIPS][2]; /* saved register image + * for IPGA (AK4528) + */ unsigned long private_value[AK4XXX_MAX_CHIPS]; /* helper for driver */ void *private_data[AK4XXX_MAX_CHIPS]; /* helper for driver */ /* template should fill the following fields */ unsigned int idx_offset; /* control index offset */ enum { SND_AK4524, SND_AK4528, SND_AK4529, - SND_AK4355, SND_AK4358, SND_AK4381, - SND_AK5365 + SND_AK4355, SND_AK4358, SND_AK4381 } type; - - /* (array) information of combined codecs */ - struct snd_akm4xxx_dac_channel *dac_info; - struct snd_akm4xxx_adc_channel *adc_info; - + unsigned int *num_stereo; /* array of combined counts + * for the mixer + */ + char **channel_names; /* array of mixer channel names */ struct snd_ak4xxx_ops ops; }; @@ -85,9 +72,9 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak); (ak)->images[(chip) * 16 + (reg)] #define snd_akm4xxx_set(ak,chip,reg,val) \ ((ak)->images[(chip) * 16 + (reg)] = (val)) -#define snd_akm4xxx_get_vol(ak,chip,reg) \ - (ak)->volumes[(chip) * 16 + (reg)] -#define snd_akm4xxx_set_vol(ak,chip,reg,val) \ - ((ak)->volumes[(chip) * 16 + (reg)] = (val)) +#define snd_akm4xxx_get_ipga(ak,chip,reg) \ + (ak)->ipga_gain[chip][(reg)-4] +#define snd_akm4xxx_set_ipga(ak,chip,reg,val) \ + ((ak)->ipga_gain[chip][(reg)-4] = (val)) #endif /* __SOUND_AK4XXX_ADDA_H */ diff --git a/trunk/include/sound/asound.h b/trunk/include/sound/asound.h index c1621c650a9a..41885f48ad91 100644 --- a/trunk/include/sound/asound.h +++ b/trunk/include/sound/asound.h @@ -688,7 +688,7 @@ struct snd_timer_tread { * * ****************************************************************************/ -#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 4) +#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 3) struct snd_ctl_card_info { int card; /* card number */ @@ -727,15 +727,10 @@ typedef int __bitwise snd_ctl_elem_iface_t; #define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1) #define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE) #define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2) /* control value may be changed without a notification */ -#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3) /* when was control changed */ -#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4) /* TLV read is possible */ -#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5) /* TLV write is possible */ -#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) -#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6) /* TLV command is possible */ +#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<2) /* when was control changed */ #define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8) /* control does actually nothing, but may be updated */ #define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9) /* write lock */ #define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10) /* write lock owner */ -#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28) /* kernel use a TLV callback */ #define SNDRV_CTL_ELEM_ACCESS_USER (1<<29) /* user space element */ #define SNDRV_CTL_ELEM_ACCESS_DINDIRECT (1<<30) /* indirect access for matrix dimensions in the info structure */ #define SNDRV_CTL_ELEM_ACCESS_INDIRECT (1<<31) /* indirect access for element value in the value structure */ @@ -823,12 +818,6 @@ struct snd_ctl_elem_value { unsigned char reserved[128-sizeof(struct timespec)]; }; -struct snd_ctl_tlv { - unsigned int numid; /* control element numeric identification */ - unsigned int length; /* in bytes aligned to 4 */ - unsigned int tlv[0]; /* first TLV */ -}; - enum { SNDRV_CTL_IOCTL_PVERSION = _IOR('U', 0x00, int), SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct snd_ctl_card_info), @@ -842,9 +831,6 @@ enum { SNDRV_CTL_IOCTL_ELEM_ADD = _IOWR('U', 0x17, struct snd_ctl_elem_info), SNDRV_CTL_IOCTL_ELEM_REPLACE = _IOWR('U', 0x18, struct snd_ctl_elem_info), SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct snd_ctl_elem_id), - SNDRV_CTL_IOCTL_TLV_READ = _IOWR('U', 0x1a, struct snd_ctl_tlv), - SNDRV_CTL_IOCTL_TLV_WRITE = _IOWR('U', 0x1b, struct snd_ctl_tlv), - SNDRV_CTL_IOCTL_TLV_COMMAND = _IOWR('U', 0x1c, struct snd_ctl_tlv), SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE = _IOWR('U', 0x20, int), SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct snd_hwdep_info), SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE = _IOR('U', 0x30, int), @@ -869,7 +855,6 @@ enum sndrv_ctl_event_type { #define SNDRV_CTL_EVENT_MASK_VALUE (1<<0) /* element value was changed */ #define SNDRV_CTL_EVENT_MASK_INFO (1<<1) /* element info was changed */ #define SNDRV_CTL_EVENT_MASK_ADD (1<<2) /* element was added */ -#define SNDRV_CTL_EVENT_MASK_TLV (1<<3) /* element TLV tree was changed */ #define SNDRV_CTL_EVENT_MASK_REMOVE (~0U) /* element was removed */ struct snd_ctl_event { diff --git a/trunk/include/sound/control.h b/trunk/include/sound/control.h index 1de148b0fd94..2489b1eb0110 100644 --- a/trunk/include/sound/control.h +++ b/trunk/include/sound/control.h @@ -30,11 +30,6 @@ struct snd_kcontrol; typedef int (snd_kcontrol_info_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_info * uinfo); typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol); typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol); -typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol, - int op_flag, /* 0=read,1=write,-1=command */ - unsigned int size, - unsigned int __user *tlv); - struct snd_kcontrol_new { snd_ctl_elem_iface_t iface; /* interface identifier */ @@ -47,10 +42,6 @@ struct snd_kcontrol_new { snd_kcontrol_info_t *info; snd_kcontrol_get_t *get; snd_kcontrol_put_t *put; - union { - snd_kcontrol_tlv_rw_t *c; - unsigned int *p; - } tlv; unsigned long private_value; }; @@ -67,10 +58,6 @@ struct snd_kcontrol { snd_kcontrol_info_t *info; snd_kcontrol_get_t *get; snd_kcontrol_put_t *put; - union { - snd_kcontrol_tlv_rw_t *c; - unsigned int *p; - } tlv; unsigned long private_value; void *private_data; void (*private_free)(struct snd_kcontrol *kcontrol); diff --git a/trunk/include/sound/core.h b/trunk/include/sound/core.h index b056ea925ecf..bab3ff457e40 100644 --- a/trunk/include/sound/core.h +++ b/trunk/include/sound/core.h @@ -25,8 +25,8 @@ #include /* wake_up() */ #include /* struct mutex */ #include /* struct rw_semaphore */ +#include /* struct workqueue_struct */ #include /* pm_message_t */ -#include /* forward declarations */ #ifdef CONFIG_PCI @@ -71,6 +71,7 @@ struct snd_device_ops { int (*dev_free)(struct snd_device *dev); int (*dev_register)(struct snd_device *dev); int (*dev_disconnect)(struct snd_device *dev); + int (*dev_unregister)(struct snd_device *dev); }; struct snd_device { @@ -130,8 +131,8 @@ struct snd_card { state */ spinlock_t files_lock; /* lock the files for this card */ int shutdown; /* this card is going down */ - int free_on_last_close; /* free in context of file_release */ wait_queue_head_t shutdown_sleep; + struct work_struct free_workq; /* for free in workqueue */ struct device *dev; #ifdef CONFIG_PM @@ -187,7 +188,6 @@ struct snd_minor { int device; /* device number */ const struct file_operations *f_ops; /* file operations */ void *private_data; /* private data for f_ops->open */ - struct class_device *class_dev; /* class device for sysfs */ }; /* sound.c */ @@ -202,8 +202,6 @@ int snd_register_device(int type, struct snd_card *card, int dev, const char *name); int snd_unregister_device(int type, struct snd_card *card, int dev); void *snd_lookup_minor_data(unsigned int minor, int type); -int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev, - const struct class_device_attribute *attr); #ifdef CONFIG_SND_OSSEMUL int snd_register_oss_device(int type, struct snd_card *card, int dev, @@ -246,7 +244,7 @@ struct snd_card *snd_card_new(int idx, const char *id, struct module *module, int extra_size); int snd_card_disconnect(struct snd_card *card); int snd_card_free(struct snd_card *card); -int snd_card_free_when_closed(struct snd_card *card); +int snd_card_free_in_thread(struct snd_card *card); int snd_card_register(struct snd_card *card); int snd_card_info_init(void); int snd_card_info_done(void); diff --git a/trunk/include/sound/emu10k1.h b/trunk/include/sound/emu10k1.h index 892e310c504d..884bbf54cd36 100644 --- a/trunk/include/sound/emu10k1.h +++ b/trunk/include/sound/emu10k1.h @@ -1524,10 +1524,6 @@ struct snd_emu10k1_fx8010_control_gpr { unsigned int value[32]; /* initial values */ unsigned int min; /* minimum range */ unsigned int max; /* maximum range */ - union { - snd_kcontrol_tlv_rw_t *c; - unsigned int *p; - } tlv; unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */ }; diff --git a/trunk/include/sound/info.h b/trunk/include/sound/info.h index 97ffc4fb9969..74f6996769c7 100644 --- a/trunk/include/sound/info.h +++ b/trunk/include/sound/info.h @@ -71,6 +71,7 @@ struct snd_info_entry { mode_t mode; long size; unsigned short content; + unsigned short disconnected: 1; union { struct snd_info_entry_text text; struct snd_info_entry_ops *ops; @@ -82,8 +83,6 @@ struct snd_info_entry { void (*private_free)(struct snd_info_entry *entry); struct proc_dir_entry *p; struct mutex access; - struct list_head children; - struct list_head list; }; #if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS) @@ -123,8 +122,8 @@ int snd_info_restore_text(struct snd_info_entry * entry); int snd_info_card_create(struct snd_card * card); int snd_info_card_register(struct snd_card * card); int snd_info_card_free(struct snd_card * card); -void snd_info_card_disconnect(struct snd_card * card); int snd_info_register(struct snd_info_entry * entry); +int snd_info_unregister(struct snd_info_entry * entry); /* for card drivers */ int snd_card_proc_new(struct snd_card *card, const char *name, struct snd_info_entry **entryp); @@ -157,8 +156,8 @@ static inline void snd_info_free_entry(struct snd_info_entry * entry) { ; } static inline int snd_info_card_create(struct snd_card * card) { return 0; } static inline int snd_info_card_register(struct snd_card * card) { return 0; } static inline int snd_info_card_free(struct snd_card * card) { return 0; } -static inline void snd_info_card_disconnect(struct snd_card * card) { } static inline int snd_info_register(struct snd_info_entry * entry) { return 0; } +static inline int snd_info_unregister(struct snd_info_entry * entry) { return 0; } static inline int snd_card_proc_new(struct snd_card *card, const char *name, struct snd_info_entry **entryp) { return -EINVAL; } diff --git a/trunk/include/sound/pcm.h b/trunk/include/sound/pcm.h index 60d40b34efc0..f84d84993a31 100644 --- a/trunk/include/sound/pcm.h +++ b/trunk/include/sound/pcm.h @@ -190,7 +190,7 @@ struct snd_pcm_ops { struct snd_pcm_file { struct snd_pcm_substream *substream; - int no_compat_mmap; + struct snd_pcm_file *next; }; struct snd_pcm_hw_rule; @@ -384,6 +384,7 @@ struct snd_pcm_substream { struct snd_info_entry *proc_prealloc_entry; #endif /* misc flags */ + unsigned int no_mmap_ctrl: 1; unsigned int hw_opened: 1; }; @@ -401,6 +402,7 @@ struct snd_pcm_str { /* -- OSS things -- */ struct snd_pcm_oss_stream oss; #endif + struct snd_pcm_file *files; #ifdef CONFIG_SND_VERBOSE_PROCFS struct snd_info_entry *proc_root; struct snd_info_entry *proc_info_entry; diff --git a/trunk/include/sound/timer.h b/trunk/include/sound/timer.h index d42c083db1da..5ece2bf541dc 100644 --- a/trunk/include/sound/timer.h +++ b/trunk/include/sound/timer.h @@ -129,6 +129,7 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer); int snd_timer_global_free(struct snd_timer *timer); int snd_timer_global_register(struct snd_timer *timer); +int snd_timer_global_unregister(struct snd_timer *timer); int snd_timer_open(struct snd_timer_instance **ti, char *owner, struct snd_timer_id *tid, unsigned int slave_id); int snd_timer_close(struct snd_timer_instance *timeri); diff --git a/trunk/include/sound/tlv.h b/trunk/include/sound/tlv.h deleted file mode 100644 index d93a96b91875..000000000000 --- a/trunk/include/sound/tlv.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef __SOUND_TLV_H -#define __SOUND_TLV_H - -/* - * Advanced Linux Sound Architecture - ALSA - Driver - * Copyright (c) 2006 by Jaroslav Kysela - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - * TLV structure is right behind the struct snd_ctl_tlv: - * unsigned int type - see SNDRV_CTL_TLVT_* - * unsigned int length - * .... data aligned to sizeof(unsigned int), use - * block_length = (length + (sizeof(unsigned int) - 1)) & - * ~(sizeof(unsigned int) - 1)) .... - */ - -#define SNDRV_CTL_TLVT_CONTAINER 0 /* one level down - group of TLVs */ -#define SNDRV_CTL_TLVT_DB_SCALE 1 /* dB scale */ -#define SNDRV_CTL_TLVT_DB_LINEAR 2 /* linear volume */ -#define SNDRV_CTL_TLVT_DB_RANGE 3 /* dB range container */ - -#define TLV_DB_SCALE_ITEM(min, step, mute) \ - SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int), \ - (min), ((step) & 0xffff) | ((mute) ? 0x10000 : 0) -#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \ - unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) } - -/* linear volume between min_dB and max_dB (.01dB unit) */ -#define TLV_DB_LINEAR_ITEM(min_dB, max_dB) \ - SNDRV_CTL_TLVT_DB_LINEAR, 2 * sizeof(unsigned int), \ - (min_dB), (max_dB) -#define DECLARE_TLV_DB_LINEAR(name, min_dB, max_dB) \ - unsigned int name[] = { TLV_DB_LINEAR_ITEM(min_dB, max_dB) } - -/* dB range container */ -/* Each item is: */ -/* The below assumes that each item TLV is 4 words like DB_SCALE or LINEAR */ -#define TLV_DB_RANGE_HEAD(num) \ - SNDRV_CTL_TLVT_DB_RANGE, 6 * (num) * sizeof(unsigned int) - -#define TLV_DB_GAIN_MUTE -9999999 - -#endif /* __SOUND_TLV_H */ diff --git a/trunk/include/sound/vx_core.h b/trunk/include/sound/vx_core.h index dbca14170615..9821a6194caa 100644 --- a/trunk/include/sound/vx_core.h +++ b/trunk/include/sound/vx_core.h @@ -128,7 +128,6 @@ struct snd_vx_hardware { unsigned int num_ins; unsigned int num_outs; unsigned int output_level_max; - unsigned int *output_level_db_scale; }; /* hwdep id string */ diff --git a/trunk/include/video/Kbuild b/trunk/include/video/Kbuild index a14f9c045b8c..76a60737cc15 100644 --- a/trunk/include/video/Kbuild +++ b/trunk/include/video/Kbuild @@ -1 +1 @@ -unifdef-y += sisfb.h +unifdef-y := sisfb.h diff --git a/trunk/init/Kconfig b/trunk/init/Kconfig index 9a7656f0b5ec..a099fc6526d9 100644 --- a/trunk/init/Kconfig +++ b/trunk/init/Kconfig @@ -182,6 +182,23 @@ config TASK_DELAY_ACCT Say N if unsure. +config SYSCTL + bool "Sysctl support" if EMBEDDED + default y + ---help--- + The sysctl interface provides a means of dynamically changing + certain kernel parameters and variables on the fly without requiring + a recompile of the kernel or reboot of the system. The primary + interface consists of a system call, but if you say Y to "/proc + file system support", a tree of modifiable sysctl entries will be + generated beneath the /proc/sys directory. They are explained in the + files in . Note that enabling this + option will enlarge the kernel by at least 8 KB. + + As it is generally a good thing, you should say Y here unless + building a kernel for install/rescue disks or your system is very + limited in memory. + config AUDIT bool "Auditing support" depends on NET @@ -244,6 +261,13 @@ config RELAY source "usr/Kconfig" +config UID16 + bool "Enable 16-bit UID system calls" if EMBEDDED + depends on ARM || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && SPARC32_COMPAT) || UML || (X86_64 && IA32_EMULATION) + default y + help + This enables the legacy 16-bit UID syscall wrappers. + config CC_OPTIMIZE_FOR_SIZE bool "Optimize for size (Look out for broken compilers!)" default y @@ -265,30 +289,6 @@ menuconfig EMBEDDED environments which can tolerate a "non-standard" kernel. Only use this if you really know what you are doing. -config UID16 - bool "Enable 16-bit UID system calls" if EMBEDDED - depends on ARM || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && SPARC32_COMPAT) || UML || (X86_64 && IA32_EMULATION) - default y - help - This enables the legacy 16-bit UID syscall wrappers. - -config SYSCTL - bool "Sysctl support" if EMBEDDED - default y - ---help--- - The sysctl interface provides a means of dynamically changing - certain kernel parameters and variables on the fly without requiring - a recompile of the kernel or reboot of the system. The primary - interface consists of a system call, but if you say Y to "/proc - file system support", a tree of modifiable sysctl entries will be - generated beneath the /proc/sys directory. They are explained in the - files in . Note that enabling this - option will enlarge the kernel by at least 8 KB. - - As it is generally a good thing, you should say Y here unless - building a kernel for install/rescue disks or your system is very - limited in memory. - config KALLSYMS bool "Load all symbols for debugging/kksymoops" if EMBEDDED default y @@ -363,6 +363,10 @@ config BASE_FULL kernel data structures. This saves memory on small machines, but may reduce performance. +config RT_MUTEXES + boolean + select PLIST + config FUTEX bool "Enable futex support" if EMBEDDED default y @@ -410,10 +414,6 @@ config VM_EVENT_COUNTERS endmenu # General setup -config RT_MUTEXES - boolean - select PLIST - config TINY_SHMEM default !SHMEM bool diff --git a/trunk/ipc/msg.c b/trunk/ipc/msg.c index 2b4fccf8ea55..cd92d342953e 100644 --- a/trunk/ipc/msg.c +++ b/trunk/ipc/msg.c @@ -1,6 +1,6 @@ /* * linux/ipc/msg.c - * Copyright (C) 1992 Krishna Balasubramanian + * Copyright (C) 1992 Krishna Balasubramanian * * Removed all the remaining kerneld mess * Catch the -EFAULT stuff properly @@ -41,24 +41,22 @@ int msg_ctlmax = MSGMAX; int msg_ctlmnb = MSGMNB; int msg_ctlmni = MSGMNI; -/* - * one msg_receiver structure for each sleeping receiver: - */ +/* one msg_receiver structure for each sleeping receiver */ struct msg_receiver { - struct list_head r_list; - struct task_struct *r_tsk; + struct list_head r_list; + struct task_struct* r_tsk; - int r_mode; - long r_msgtype; - long r_maxsize; + int r_mode; + long r_msgtype; + long r_maxsize; - volatile struct msg_msg *r_msg; + struct msg_msg* volatile r_msg; }; /* one msg_sender for each sleeping sender */ struct msg_sender { - struct list_head list; - struct task_struct *tsk; + struct list_head list; + struct task_struct* tsk; }; #define SEARCH_ANY 1 @@ -66,42 +64,45 @@ struct msg_sender { #define SEARCH_NOTEQUAL 3 #define SEARCH_LESSEQUAL 4 -static atomic_t msg_bytes = ATOMIC_INIT(0); -static atomic_t msg_hdrs = ATOMIC_INIT(0); +static atomic_t msg_bytes = ATOMIC_INIT(0); +static atomic_t msg_hdrs = ATOMIC_INIT(0); static struct ipc_ids msg_ids; -#define msg_lock(id) ((struct msg_queue *)ipc_lock(&msg_ids, id)) -#define msg_unlock(msq) ipc_unlock(&(msq)->q_perm) -#define msg_rmid(id) ((struct msg_queue *)ipc_rmid(&msg_ids, id)) -#define msg_checkid(msq, msgid) ipc_checkid(&msg_ids, &msq->q_perm, msgid) -#define msg_buildid(id, seq) ipc_buildid(&msg_ids, id, seq) +#define msg_lock(id) ((struct msg_queue*)ipc_lock(&msg_ids,id)) +#define msg_unlock(msq) ipc_unlock(&(msq)->q_perm) +#define msg_rmid(id) ((struct msg_queue*)ipc_rmid(&msg_ids,id)) +#define msg_checkid(msq, msgid) \ + ipc_checkid(&msg_ids,&msq->q_perm,msgid) +#define msg_buildid(id, seq) \ + ipc_buildid(&msg_ids, id, seq) -static void freeque(struct msg_queue *msq, int id); -static int newque(key_t key, int msgflg); +static void freeque (struct msg_queue *msq, int id); +static int newque (key_t key, int msgflg); #ifdef CONFIG_PROC_FS static int sysvipc_msg_proc_show(struct seq_file *s, void *it); #endif -void __init msg_init(void) +void __init msg_init (void) { - ipc_init_ids(&msg_ids, msg_ctlmni); + ipc_init_ids(&msg_ids,msg_ctlmni); ipc_init_proc_interface("sysvipc/msg", " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n", &msg_ids, sysvipc_msg_proc_show); } -static int newque(key_t key, int msgflg) +static int newque (key_t key, int msgflg) { + int id; + int retval; struct msg_queue *msq; - int id, retval; - msq = ipc_rcu_alloc(sizeof(*msq)); - if (!msq) + msq = ipc_rcu_alloc(sizeof(*msq)); + if (!msq) return -ENOMEM; - msq->q_perm.mode = msgflg & S_IRWXUGO; + msq->q_perm.mode = (msgflg & S_IRWXUGO); msq->q_perm.key = key; msq->q_perm.security = NULL; @@ -112,13 +113,13 @@ static int newque(key_t key, int msgflg) } id = ipc_addid(&msg_ids, &msq->q_perm, msg_ctlmni); - if (id == -1) { + if(id == -1) { security_msg_queue_free(msq); ipc_rcu_putref(msq); return -ENOSPC; } - msq->q_id = msg_buildid(id, msq->q_perm.seq); + msq->q_id = msg_buildid(id,msq->q_perm.seq); msq->q_stime = msq->q_rtime = 0; msq->q_ctime = get_seconds(); msq->q_cbytes = msq->q_qnum = 0; @@ -132,44 +133,44 @@ static int newque(key_t key, int msgflg) return msq->q_id; } -static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss) +static inline void ss_add(struct msg_queue* msq, struct msg_sender* mss) { - mss->tsk = current; - current->state = TASK_INTERRUPTIBLE; - list_add_tail(&mss->list, &msq->q_senders); + mss->tsk=current; + current->state=TASK_INTERRUPTIBLE; + list_add_tail(&mss->list,&msq->q_senders); } -static inline void ss_del(struct msg_sender *mss) +static inline void ss_del(struct msg_sender* mss) { - if (mss->list.next != NULL) + if(mss->list.next != NULL) list_del(&mss->list); } -static void ss_wakeup(struct list_head *h, int kill) +static void ss_wakeup(struct list_head* h, int kill) { struct list_head *tmp; tmp = h->next; while (tmp != h) { - struct msg_sender *mss; - - mss = list_entry(tmp, struct msg_sender, list); + struct msg_sender* mss; + + mss = list_entry(tmp,struct msg_sender,list); tmp = tmp->next; - if (kill) - mss->list.next = NULL; + if(kill) + mss->list.next=NULL; wake_up_process(mss->tsk); } } -static void expunge_all(struct msg_queue *msq, int res) +static void expunge_all(struct msg_queue* msq, int res) { struct list_head *tmp; tmp = msq->q_receivers.next; while (tmp != &msq->q_receivers) { - struct msg_receiver *msr; - - msr = list_entry(tmp, struct msg_receiver, r_list); + struct msg_receiver* msr; + + msr = list_entry(tmp,struct msg_receiver,r_list); tmp = tmp->next; msr->r_msg = NULL; wake_up_process(msr->r_tsk); @@ -177,28 +178,26 @@ static void expunge_all(struct msg_queue *msq, int res) msr->r_msg = ERR_PTR(res); } } - -/* - * freeque() wakes up waiters on the sender and receiver waiting queue, - * removes the message queue from message queue ID +/* + * freeque() wakes up waiters on the sender and receiver waiting queue, + * removes the message queue from message queue ID * array, and cleans up all the messages associated with this queue. * * msg_ids.mutex and the spinlock for this message queue is hold * before freeque() is called. msg_ids.mutex remains locked on exit. */ -static void freeque(struct msg_queue *msq, int id) +static void freeque (struct msg_queue *msq, int id) { struct list_head *tmp; - expunge_all(msq, -EIDRM); - ss_wakeup(&msq->q_senders, 1); + expunge_all(msq,-EIDRM); + ss_wakeup(&msq->q_senders,1); msq = msg_rmid(id); msg_unlock(msq); - + tmp = msq->q_messages.next; - while (tmp != &msq->q_messages) { - struct msg_msg *msg = list_entry(tmp, struct msg_msg, m_list); - + while(tmp != &msq->q_messages) { + struct msg_msg* msg = list_entry(tmp,struct msg_msg,m_list); tmp = tmp->next; atomic_dec(&msg_hdrs); free_msg(msg); @@ -208,10 +207,10 @@ static void freeque(struct msg_queue *msq, int id) ipc_rcu_putref(msq); } -asmlinkage long sys_msgget(key_t key, int msgflg) +asmlinkage long sys_msgget (key_t key, int msgflg) { - struct msg_queue *msq; int id, ret = -EPERM; + struct msg_queue *msq; mutex_lock(&msg_ids.mutex); if (key == IPC_PRIVATE) @@ -225,34 +224,31 @@ asmlinkage long sys_msgget(key_t key, int msgflg) ret = -EEXIST; } else { msq = msg_lock(id); - BUG_ON(msq == NULL); + BUG_ON(msq==NULL); if (ipcperms(&msq->q_perm, msgflg)) ret = -EACCES; else { int qid = msg_buildid(id, msq->q_perm.seq); - - ret = security_msg_queue_associate(msq, msgflg); + ret = security_msg_queue_associate(msq, msgflg); if (!ret) ret = qid; } msg_unlock(msq); } mutex_unlock(&msg_ids.mutex); - return ret; } -static inline unsigned long -copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version) +static inline unsigned long copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version) { switch(version) { case IPC_64: - return copy_to_user(buf, in, sizeof(*in)); + return copy_to_user (buf, in, sizeof(*in)); case IPC_OLD: - { + { struct msqid_ds out; - memset(&out, 0, sizeof(out)); + memset(&out,0,sizeof(out)); ipc64_perm_to_ipc_perm(&in->msg_perm, &out.msg_perm); @@ -260,18 +256,18 @@ copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version) out.msg_rtime = in->msg_rtime; out.msg_ctime = in->msg_ctime; - if (in->msg_cbytes > USHRT_MAX) + if(in->msg_cbytes > USHRT_MAX) out.msg_cbytes = USHRT_MAX; else out.msg_cbytes = in->msg_cbytes; out.msg_lcbytes = in->msg_cbytes; - if (in->msg_qnum > USHRT_MAX) + if(in->msg_qnum > USHRT_MAX) out.msg_qnum = USHRT_MAX; else out.msg_qnum = in->msg_qnum; - if (in->msg_qbytes > USHRT_MAX) + if(in->msg_qbytes > USHRT_MAX) out.msg_qbytes = USHRT_MAX; else out.msg_qbytes = in->msg_qbytes; @@ -280,8 +276,8 @@ copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version) out.msg_lspid = in->msg_lspid; out.msg_lrpid = in->msg_lrpid; - return copy_to_user(buf, &out, sizeof(out)); - } + return copy_to_user (buf, &out, sizeof(out)); + } default: return -EINVAL; } @@ -294,15 +290,14 @@ struct msq_setbuf { mode_t mode; }; -static inline unsigned long -copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version) +static inline unsigned long copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version) { switch(version) { case IPC_64: - { + { struct msqid64_ds tbuf; - if (copy_from_user(&tbuf, buf, sizeof(tbuf))) + if (copy_from_user (&tbuf, buf, sizeof (tbuf))) return -EFAULT; out->qbytes = tbuf.msg_qbytes; @@ -311,61 +306,60 @@ copy_msqid_from_user(struct msq_setbuf *out, void __user *buf, int version) out->mode = tbuf.msg_perm.mode; return 0; - } + } case IPC_OLD: - { + { struct msqid_ds tbuf_old; - if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old))) + if (copy_from_user (&tbuf_old, buf, sizeof (tbuf_old))) return -EFAULT; out->uid = tbuf_old.msg_perm.uid; out->gid = tbuf_old.msg_perm.gid; out->mode = tbuf_old.msg_perm.mode; - if (tbuf_old.msg_qbytes == 0) + if(tbuf_old.msg_qbytes == 0) out->qbytes = tbuf_old.msg_lqbytes; else out->qbytes = tbuf_old.msg_qbytes; return 0; - } + } default: return -EINVAL; } } -asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) +asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf) { - struct kern_ipc_perm *ipcp; - struct msq_setbuf setbuf; - struct msg_queue *msq; int err, version; - + struct msg_queue *msq; + struct msq_setbuf setbuf; + struct kern_ipc_perm *ipcp; + if (msqid < 0 || cmd < 0) return -EINVAL; version = ipc_parse_version(&cmd); switch (cmd) { - case IPC_INFO: - case MSG_INFO: - { + case IPC_INFO: + case MSG_INFO: + { struct msginfo msginfo; int max_id; - if (!buf) return -EFAULT; - /* - * We must not return kernel stack data. + /* We must not return kernel stack data. * due to padding, it's not enough * to set all member fields. */ + err = security_msg_queue_msgctl(NULL, cmd); if (err) return err; - memset(&msginfo, 0, sizeof(msginfo)); + memset(&msginfo,0,sizeof(msginfo)); msginfo.msgmni = msg_ctlmni; msginfo.msgmax = msg_ctlmax; msginfo.msgmnb = msg_ctlmnb; @@ -383,37 +377,36 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) } max_id = msg_ids.max_id; mutex_unlock(&msg_ids.mutex); - if (copy_to_user(buf, &msginfo, sizeof(struct msginfo))) + if (copy_to_user (buf, &msginfo, sizeof(struct msginfo))) return -EFAULT; - return (max_id < 0) ? 0 : max_id; + return (max_id < 0) ? 0: max_id; } case MSG_STAT: case IPC_STAT: { struct msqid64_ds tbuf; int success_return; - if (!buf) return -EFAULT; - if (cmd == MSG_STAT && msqid >= msg_ids.entries->size) + if(cmd == MSG_STAT && msqid >= msg_ids.entries->size) return -EINVAL; - memset(&tbuf, 0, sizeof(tbuf)); + memset(&tbuf,0,sizeof(tbuf)); msq = msg_lock(msqid); if (msq == NULL) return -EINVAL; - if (cmd == MSG_STAT) { + if(cmd == MSG_STAT) { success_return = msg_buildid(msqid, msq->q_perm.seq); } else { err = -EIDRM; - if (msg_checkid(msq, msqid)) + if (msg_checkid(msq,msqid)) goto out_unlock; success_return = 0; } err = -EACCES; - if (ipcperms(&msq->q_perm, S_IRUGO)) + if (ipcperms (&msq->q_perm, S_IRUGO)) goto out_unlock; err = security_msg_queue_msgctl(msq, cmd); @@ -437,7 +430,7 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) case IPC_SET: if (!buf) return -EFAULT; - if (copy_msqid_from_user(&setbuf, buf, version)) + if (copy_msqid_from_user (&setbuf, buf, version)) return -EFAULT; break; case IPC_RMID: @@ -448,12 +441,12 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) mutex_lock(&msg_ids.mutex); msq = msg_lock(msqid); - err = -EINVAL; + err=-EINVAL; if (msq == NULL) goto out_up; err = -EIDRM; - if (msg_checkid(msq, msqid)) + if (msg_checkid(msq,msqid)) goto out_unlock_up; ipcp = &msq->q_perm; @@ -461,16 +454,15 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) if (err) goto out_unlock_up; if (cmd==IPC_SET) { - err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid, - setbuf.mode); + err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode); if (err) goto out_unlock_up; } err = -EPERM; - if (current->euid != ipcp->cuid && + if (current->euid != ipcp->cuid && current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) - /* We _could_ check for CAP_CHOWN above, but we don't */ + /* We _could_ check for CAP_CHOWN above, but we don't */ goto out_unlock_up; err = security_msg_queue_msgctl(msq, cmd); @@ -488,22 +480,22 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) ipcp->uid = setbuf.uid; ipcp->gid = setbuf.gid; - ipcp->mode = (ipcp->mode & ~S_IRWXUGO) | - (S_IRWXUGO & setbuf.mode); + ipcp->mode = (ipcp->mode & ~S_IRWXUGO) | + (S_IRWXUGO & setbuf.mode); msq->q_ctime = get_seconds(); /* sleeping receivers might be excluded by * stricter permissions. */ - expunge_all(msq, -EAGAIN); + expunge_all(msq,-EAGAIN); /* sleeping senders might be able to send * due to a larger queue size. */ - ss_wakeup(&msq->q_senders, 0); + ss_wakeup(&msq->q_senders,0); msg_unlock(msq); break; } case IPC_RMID: - freeque(msq, msqid); + freeque (msq, msqid); break; } err = 0; @@ -518,44 +510,41 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) return err; } -static int testmsg(struct msg_msg *msg, long type, int mode) +static int testmsg(struct msg_msg* msg,long type,int mode) { switch(mode) { case SEARCH_ANY: return 1; case SEARCH_LESSEQUAL: - if (msg->m_type <=type) + if(msg->m_type <=type) return 1; break; case SEARCH_EQUAL: - if (msg->m_type == type) + if(msg->m_type == type) return 1; break; case SEARCH_NOTEQUAL: - if (msg->m_type != type) + if(msg->m_type != type) return 1; break; } return 0; } -static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg) +static inline int pipelined_send(struct msg_queue* msq, struct msg_msg* msg) { - struct list_head *tmp; + struct list_head* tmp; tmp = msq->q_receivers.next; while (tmp != &msq->q_receivers) { - struct msg_receiver *msr; - - msr = list_entry(tmp, struct msg_receiver, r_list); + struct msg_receiver* msr; + msr = list_entry(tmp,struct msg_receiver,r_list); tmp = tmp->next; - if (testmsg(msg, msr->r_msgtype, msr->r_mode) && - !security_msg_queue_msgrcv(msq, msg, msr->r_tsk, - msr->r_msgtype, msr->r_mode)) { - + if(testmsg(msg,msr->r_msgtype,msr->r_mode) && + !security_msg_queue_msgrcv(msq, msg, msr->r_tsk, msr->r_msgtype, msr->r_mode)) { list_del(&msr->r_list); - if (msr->r_maxsize < msg->m_ts) { + if(msr->r_maxsize < msg->m_ts) { msr->r_msg = NULL; wake_up_process(msr->r_tsk); smp_mb(); @@ -567,7 +556,6 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg) wake_up_process(msr->r_tsk); smp_mb(); msr->r_msg = msg; - return 1; } } @@ -575,41 +563,40 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg) return 0; } -asmlinkage long -sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) +asmlinkage long sys_msgsnd (int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) { struct msg_queue *msq; struct msg_msg *msg; long mtype; int err; - + if (msgsz > msg_ctlmax || (long) msgsz < 0 || msqid < 0) return -EINVAL; if (get_user(mtype, &msgp->mtype)) - return -EFAULT; + return -EFAULT; if (mtype < 1) return -EINVAL; msg = load_msg(msgp->mtext, msgsz); - if (IS_ERR(msg)) + if(IS_ERR(msg)) return PTR_ERR(msg); msg->m_type = mtype; msg->m_ts = msgsz; msq = msg_lock(msqid); - err = -EINVAL; - if (msq == NULL) + err=-EINVAL; + if(msq==NULL) goto out_free; err= -EIDRM; - if (msg_checkid(msq, msqid)) + if (msg_checkid(msq,msqid)) goto out_unlock_free; for (;;) { struct msg_sender s; - err = -EACCES; + err=-EACCES; if (ipcperms(&msq->q_perm, S_IWUGO)) goto out_unlock_free; @@ -617,14 +604,14 @@ sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) if (err) goto out_unlock_free; - if (msgsz + msq->q_cbytes <= msq->q_qbytes && + if(msgsz + msq->q_cbytes <= msq->q_qbytes && 1 + msq->q_qnum <= msq->q_qbytes) { break; } /* queue full, wait: */ - if (msgflg & IPC_NOWAIT) { - err = -EAGAIN; + if(msgflg&IPC_NOWAIT) { + err=-EAGAIN; goto out_unlock_free; } ss_add(msq, &s); @@ -639,9 +626,9 @@ sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) goto out_unlock_free; } ss_del(&s); - + if (signal_pending(current)) { - err = -ERESTARTNOHAND; + err=-ERESTARTNOHAND; goto out_unlock_free; } } @@ -649,47 +636,47 @@ sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) msq->q_lspid = current->tgid; msq->q_stime = get_seconds(); - if (!pipelined_send(msq, msg)) { + if(!pipelined_send(msq,msg)) { /* noone is waiting for this message, enqueue it */ - list_add_tail(&msg->m_list, &msq->q_messages); + list_add_tail(&msg->m_list,&msq->q_messages); msq->q_cbytes += msgsz; msq->q_qnum++; - atomic_add(msgsz, &msg_bytes); + atomic_add(msgsz,&msg_bytes); atomic_inc(&msg_hdrs); } - + err = 0; msg = NULL; out_unlock_free: msg_unlock(msq); out_free: - if (msg != NULL) + if(msg!=NULL) free_msg(msg); return err; } -static inline int convert_mode(long *msgtyp, int msgflg) +static inline int convert_mode(long* msgtyp, int msgflg) { - /* + /* * find message of correct type. * msgtyp = 0 => get first. * msgtyp > 0 => get first message of matching type. - * msgtyp < 0 => get message with least type must be < abs(msgtype). + * msgtyp < 0 => get message with least type must be < abs(msgtype). */ - if (*msgtyp == 0) + if(*msgtyp==0) return SEARCH_ANY; - if (*msgtyp < 0) { - *msgtyp = -*msgtyp; + if(*msgtyp<0) { + *msgtyp=-(*msgtyp); return SEARCH_LESSEQUAL; } - if (msgflg & MSG_EXCEPT) + if(msgflg & MSG_EXCEPT) return SEARCH_NOTEQUAL; return SEARCH_EQUAL; } -asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, - long msgtyp, int msgflg) +asmlinkage long sys_msgrcv (int msqid, struct msgbuf __user *msgp, size_t msgsz, + long msgtyp, int msgflg) { struct msg_queue *msq; struct msg_msg *msg; @@ -697,51 +684,44 @@ asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, if (msqid < 0 || (long) msgsz < 0) return -EINVAL; - mode = convert_mode(&msgtyp, msgflg); + mode = convert_mode(&msgtyp,msgflg); msq = msg_lock(msqid); - if (msq == NULL) + if(msq==NULL) return -EINVAL; msg = ERR_PTR(-EIDRM); - if (msg_checkid(msq, msqid)) + if (msg_checkid(msq,msqid)) goto out_unlock; for (;;) { struct msg_receiver msr_d; - struct list_head *tmp; + struct list_head* tmp; msg = ERR_PTR(-EACCES); - if (ipcperms(&msq->q_perm, S_IRUGO)) + if (ipcperms (&msq->q_perm, S_IRUGO)) goto out_unlock; msg = ERR_PTR(-EAGAIN); tmp = msq->q_messages.next; while (tmp != &msq->q_messages) { struct msg_msg *walk_msg; - - walk_msg = list_entry(tmp, struct msg_msg, m_list); - if (testmsg(walk_msg, msgtyp, mode) && - !security_msg_queue_msgrcv(msq, walk_msg, current, - msgtyp, mode)) { - + walk_msg = list_entry(tmp,struct msg_msg,m_list); + if(testmsg(walk_msg,msgtyp,mode) && + !security_msg_queue_msgrcv(msq, walk_msg, current, msgtyp, mode)) { msg = walk_msg; - if (mode == SEARCH_LESSEQUAL && - walk_msg->m_type != 1) { - msg = walk_msg; - msgtyp = walk_msg->m_type - 1; + if(mode == SEARCH_LESSEQUAL && walk_msg->m_type != 1) { + msg=walk_msg; + msgtyp=walk_msg->m_type-1; } else { - msg = walk_msg; + msg=walk_msg; break; } } tmp = tmp->next; } - if (!IS_ERR(msg)) { - /* - * Found a suitable message. - * Unlink it from the queue. - */ + if(!IS_ERR(msg)) { + /* Found a suitable message. Unlink it from the queue. */ if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) { msg = ERR_PTR(-E2BIG); goto out_unlock; @@ -751,9 +731,9 @@ asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, msq->q_rtime = get_seconds(); msq->q_lrpid = current->tgid; msq->q_cbytes -= msg->m_ts; - atomic_sub(msg->m_ts, &msg_bytes); + atomic_sub(msg->m_ts,&msg_bytes); atomic_dec(&msg_hdrs); - ss_wakeup(&msq->q_senders, 0); + ss_wakeup(&msq->q_senders,0); msg_unlock(msq); break; } @@ -762,13 +742,13 @@ asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, msg = ERR_PTR(-ENOMSG); goto out_unlock; } - list_add_tail(&msr_d.r_list, &msq->q_receivers); + list_add_tail(&msr_d.r_list,&msq->q_receivers); msr_d.r_tsk = current; msr_d.r_msgtype = msgtyp; msr_d.r_mode = mode; - if (msgflg & MSG_NOERROR) + if(msgflg & MSG_NOERROR) msr_d.r_maxsize = INT_MAX; - else + else msr_d.r_maxsize = msgsz; msr_d.r_msg = ERR_PTR(-EAGAIN); current->state = TASK_INTERRUPTIBLE; @@ -793,17 +773,17 @@ asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, * wake_up_process(). There is a race with exit(), see * ipc/mqueue.c for the details. */ - msg = (struct msg_msg*)msr_d.r_msg; + msg = (struct msg_msg*) msr_d.r_msg; while (msg == NULL) { cpu_relax(); - msg = (struct msg_msg *)msr_d.r_msg; + msg = (struct msg_msg*) msr_d.r_msg; } /* Lockless receive, part 3: * If there is a message or an error then accept it without * locking. */ - if (msg != ERR_PTR(-EAGAIN)) { + if(msg != ERR_PTR(-EAGAIN)) { rcu_read_unlock(); break; } @@ -818,7 +798,7 @@ asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, * Repeat test after acquiring the spinlock. */ msg = (struct msg_msg*)msr_d.r_msg; - if (msg != ERR_PTR(-EAGAIN)) + if(msg != ERR_PTR(-EAGAIN)) goto out_unlock; list_del(&msr_d.r_list); @@ -830,15 +810,14 @@ asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, } } if (IS_ERR(msg)) - return PTR_ERR(msg); + return PTR_ERR(msg); msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz; if (put_user (msg->m_type, &msgp->mtype) || store_msg(msgp->mtext, msg, msgsz)) { - msgsz = -EFAULT; + msgsz = -EFAULT; } free_msg(msg); - return msgsz; } @@ -848,20 +827,20 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it) struct msg_queue *msq = it; return seq_printf(s, - "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n", - msq->q_perm.key, - msq->q_id, - msq->q_perm.mode, - msq->q_cbytes, - msq->q_qnum, - msq->q_lspid, - msq->q_lrpid, - msq->q_perm.uid, - msq->q_perm.gid, - msq->q_perm.cuid, - msq->q_perm.cgid, - msq->q_stime, - msq->q_rtime, - msq->q_ctime); + "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n", + msq->q_perm.key, + msq->q_id, + msq->q_perm.mode, + msq->q_cbytes, + msq->q_qnum, + msq->q_lspid, + msq->q_lrpid, + msq->q_perm.uid, + msq->q_perm.gid, + msq->q_perm.cuid, + msq->q_perm.cgid, + msq->q_stime, + msq->q_rtime, + msq->q_ctime); } #endif diff --git a/trunk/kernel/audit.c b/trunk/kernel/audit.c index 963fd15c9621..d417ca1db79b 100644 --- a/trunk/kernel/audit.c +++ b/trunk/kernel/audit.c @@ -690,7 +690,9 @@ static const struct inotify_operations audit_inotify_ops = { /* Initialize audit support at boot time. */ static int __init audit_init(void) { +#ifdef CONFIG_AUDITSYSCALL int i; +#endif printk(KERN_INFO "audit: initializing netlink socket (%s)\n", audit_default ? "enabled" : "disabled"); @@ -715,10 +717,10 @@ static int __init audit_init(void) audit_ih = inotify_init(&audit_inotify_ops); if (IS_ERR(audit_ih)) audit_panic("cannot initialize inotify handle"); -#endif for (i = 0; i < AUDIT_INODE_BUCKETS; i++) INIT_LIST_HEAD(&audit_inode_hash[i]); +#endif return 0; } @@ -1028,9 +1030,6 @@ void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, struct sk_buff *skb; static const unsigned char *hex = "0123456789ABCDEF"; - if (!ab) - return; - BUG_ON(!ab->skb); skb = ab->skb; avail = skb_tailroom(skb); @@ -1063,9 +1062,6 @@ static void audit_log_n_string(struct audit_buffer *ab, size_t slen, unsigned char *ptr; struct sk_buff *skb; - if (!ab) - return; - BUG_ON(!ab->skb); skb = ab->skb; avail = skb_tailroom(skb); diff --git a/trunk/kernel/audit.h b/trunk/kernel/audit.h index a3370232a390..6aa33b848cf2 100644 --- a/trunk/kernel/audit.h +++ b/trunk/kernel/audit.h @@ -104,7 +104,6 @@ static inline int audit_hash_ino(u32 ino) return (ino & (AUDIT_INODE_BUCKETS-1)); } -extern int audit_match_class(int class, unsigned syscall); extern int audit_comparator(const u32 left, const u32 op, const u32 right); extern int audit_compare_dname_path(const char *dname, const char *path, int *dirlen); diff --git a/trunk/kernel/auditfilter.c b/trunk/kernel/auditfilter.c index a44879b0c72f..5b4e16276ca0 100644 --- a/trunk/kernel/auditfilter.c +++ b/trunk/kernel/auditfilter.c @@ -302,15 +302,6 @@ int __init audit_register_class(int class, unsigned *list) return 0; } -int audit_match_class(int class, unsigned syscall) -{ - if (unlikely(syscall >= AUDIT_BITMASK_SIZE * sizeof(__u32))) - return 0; - if (unlikely(class >= AUDIT_SYSCALL_CLASSES || !classes[class])) - return 0; - return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall); -} - /* Common user-space to kernel rule translation. */ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) { @@ -413,7 +404,6 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) case AUDIT_PERS: case AUDIT_ARCH: case AUDIT_MSGTYPE: - case AUDIT_PPID: case AUDIT_DEVMAJOR: case AUDIT_DEVMINOR: case AUDIT_EXIT: @@ -423,10 +413,6 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) case AUDIT_ARG2: case AUDIT_ARG3: break; - case AUDIT_PERM: - if (f->val & ~15) - goto exit_free; - break; case AUDIT_INODE: err = audit_to_inode(&entry->rule, f); if (err) @@ -456,7 +442,6 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) case AUDIT_EQUAL: break; default: - err = -EINVAL; goto exit_free; } } @@ -581,10 +566,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, entry->rule.buflen += f->val; entry->rule.filterkey = str; break; - case AUDIT_PERM: - if (f->val & ~15) - goto exit_free; - break; default: goto exit_free; } @@ -598,7 +579,6 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, case AUDIT_EQUAL: break; default: - err = -EINVAL; goto exit_free; } } @@ -931,7 +911,7 @@ static void audit_update_watch(struct audit_parent *parent, } ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); - audit_log_format(ab, "audit updated rules specifying path="); + audit_log_format(ab, "audit updated rules specifying watch="); audit_log_untrustedstring(ab, owatch->path); audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino); audit_log_end(ab); @@ -954,28 +934,19 @@ static void audit_remove_parent_watches(struct audit_parent *parent) struct audit_watch *w, *nextw; struct audit_krule *r, *nextr; struct audit_entry *e; - struct audit_buffer *ab; mutex_lock(&audit_filter_mutex); parent->flags |= AUDIT_PARENT_INVALID; list_for_each_entry_safe(w, nextw, &parent->watches, wlist) { list_for_each_entry_safe(r, nextr, &w->rules, rlist) { e = container_of(r, struct audit_entry, rule); - - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); - audit_log_format(ab, "audit implicitly removed rule path="); - audit_log_untrustedstring(ab, w->path); - if (r->filterkey) { - audit_log_format(ab, " key="); - audit_log_untrustedstring(ab, r->filterkey); - } else - audit_log_format(ab, " key=(null)"); - audit_log_format(ab, " list=%d", r->listnr); - audit_log_end(ab); - list_del(&r->rlist); list_del_rcu(&e->list); call_rcu(&e->rcu, audit_free_rule_rcu); + + audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, + "audit implicitly removed rule from list=%d\n", + AUDIT_FILTER_EXIT); } audit_remove_watch(w); } @@ -1163,14 +1134,6 @@ static inline int audit_add_rule(struct audit_entry *entry, struct audit_watch *watch = entry->rule.watch; struct nameidata *ndp, *ndw; int h, err, putnd_needed = 0; -#ifdef CONFIG_AUDITSYSCALL - int dont_count = 0; - - /* If either of these, don't count towards total */ - if (entry->rule.listnr == AUDIT_FILTER_USER || - entry->rule.listnr == AUDIT_FILTER_TYPE) - dont_count = 1; -#endif if (inode_f) { h = audit_hash_ino(inode_f->val); @@ -1211,10 +1174,6 @@ static inline int audit_add_rule(struct audit_entry *entry, } else { list_add_tail_rcu(&entry->list, list); } -#ifdef CONFIG_AUDITSYSCALL - if (!dont_count) - audit_n_rules++; -#endif mutex_unlock(&audit_filter_mutex); if (putnd_needed) @@ -1239,14 +1198,6 @@ static inline int audit_del_rule(struct audit_entry *entry, struct audit_watch *watch, *tmp_watch = entry->rule.watch; LIST_HEAD(inotify_list); int h, ret = 0; -#ifdef CONFIG_AUDITSYSCALL - int dont_count = 0; - - /* If either of these, don't count towards total */ - if (entry->rule.listnr == AUDIT_FILTER_USER || - entry->rule.listnr == AUDIT_FILTER_TYPE) - dont_count = 1; -#endif if (inode_f) { h = audit_hash_ino(inode_f->val); @@ -1284,10 +1235,6 @@ static inline int audit_del_rule(struct audit_entry *entry, list_del_rcu(&e->list); call_rcu(&e->rcu, audit_free_rule_rcu); -#ifdef CONFIG_AUDITSYSCALL - if (!dont_count) - audit_n_rules--; -#endif mutex_unlock(&audit_filter_mutex); if (!list_empty(&inotify_list)) diff --git a/trunk/kernel/auditsc.c b/trunk/kernel/auditsc.c index 1bd8827a0102..ae40ac8c39e7 100644 --- a/trunk/kernel/auditsc.c +++ b/trunk/kernel/auditsc.c @@ -85,9 +85,6 @@ extern int audit_enabled; /* Indicates that audit should log the full pathname. */ #define AUDIT_NAME_FULL -1 -/* number of audit rules */ -int audit_n_rules; - /* When fs/namei.c:getname() is called, we store the pointer in name and * we don't let putname() free it (instead we free all of the saved * pointers at syscall exit time). @@ -177,7 +174,6 @@ struct audit_aux_data_path { /* The per-task audit context. */ struct audit_context { - int dummy; /* must be the first element */ int in_syscall; /* 1 if task is in a syscall */ enum audit_state state; unsigned int serial; /* serial number for record */ @@ -209,54 +205,6 @@ struct audit_context { #endif }; -#define ACC_MODE(x) ("\004\002\006\006"[(x)&O_ACCMODE]) -static inline int open_arg(int flags, int mask) -{ - int n = ACC_MODE(flags); - if (flags & (O_TRUNC | O_CREAT)) - n |= AUDIT_PERM_WRITE; - return n & mask; -} - -static int audit_match_perm(struct audit_context *ctx, int mask) -{ - unsigned n = ctx->major; - switch (audit_classify_syscall(ctx->arch, n)) { - case 0: /* native */ - if ((mask & AUDIT_PERM_WRITE) && - audit_match_class(AUDIT_CLASS_WRITE, n)) - return 1; - if ((mask & AUDIT_PERM_READ) && - audit_match_class(AUDIT_CLASS_READ, n)) - return 1; - if ((mask & AUDIT_PERM_ATTR) && - audit_match_class(AUDIT_CLASS_CHATTR, n)) - return 1; - return 0; - case 1: /* 32bit on biarch */ - if ((mask & AUDIT_PERM_WRITE) && - audit_match_class(AUDIT_CLASS_WRITE_32, n)) - return 1; - if ((mask & AUDIT_PERM_READ) && - audit_match_class(AUDIT_CLASS_READ_32, n)) - return 1; - if ((mask & AUDIT_PERM_ATTR) && - audit_match_class(AUDIT_CLASS_CHATTR_32, n)) - return 1; - return 0; - case 2: /* open */ - return mask & ACC_MODE(ctx->argv[1]); - case 3: /* openat */ - return mask & ACC_MODE(ctx->argv[2]); - case 4: /* socketcall */ - return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND); - case 5: /* execve */ - return mask & AUDIT_PERM_EXEC; - default: - return 0; - } -} - /* Determine if any context name data matches a rule's watch data */ /* Compare a task_struct with an audit_rule. Return 1 on match, 0 * otherwise. */ @@ -445,9 +393,6 @@ static int audit_filter_rules(struct task_struct *tsk, /* ignore this field for filtering */ result = 1; break; - case AUDIT_PERM: - result = audit_match_perm(ctx, f->val); - break; } if (!result) @@ -569,7 +514,7 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, context->return_valid = return_valid; context->return_code = return_code; - if (context->in_syscall && !context->dummy && !context->auditable) { + if (context->in_syscall && !context->auditable) { enum audit_state state; state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); @@ -585,7 +530,17 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, } get_context: - + context->pid = tsk->pid; + context->ppid = sys_getppid(); /* sic. tsk == current in all cases */ + context->uid = tsk->uid; + context->gid = tsk->gid; + context->euid = tsk->euid; + context->suid = tsk->suid; + context->fsuid = tsk->fsuid; + context->egid = tsk->egid; + context->sgid = tsk->sgid; + context->fsgid = tsk->fsgid; + context->personality = tsk->personality; tsk->audit_context = NULL; return context; } @@ -794,17 +749,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts const char *tty; /* tsk == current */ - context->pid = tsk->pid; - context->ppid = sys_getppid(); /* sic. tsk == current in all cases */ - context->uid = tsk->uid; - context->gid = tsk->gid; - context->euid = tsk->euid; - context->suid = tsk->suid; - context->fsuid = tsk->fsuid; - context->egid = tsk->egid; - context->sgid = tsk->sgid; - context->fsgid = tsk->fsgid; - context->personality = tsk->personality; ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL); if (!ab) @@ -1122,8 +1066,7 @@ void audit_syscall_entry(int arch, int major, context->argv[3] = a4; state = context->state; - context->dummy = !audit_n_rules; - if (!context->dummy && (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT)) + if (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT) state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]); if (likely(state == AUDIT_DISABLED)) return; @@ -1256,18 +1199,14 @@ void audit_putname(const char *name) #endif } -/* Copy inode data into an audit_names. */ -static void audit_copy_inode(struct audit_names *name, const struct inode *inode) +static void audit_inode_context(int idx, const struct inode *inode) { - name->ino = inode->i_ino; - name->dev = inode->i_sb->s_dev; - name->mode = inode->i_mode; - name->uid = inode->i_uid; - name->gid = inode->i_gid; - name->rdev = inode->i_rdev; - selinux_get_inode_sid(inode, &name->osid); + struct audit_context *context = current->audit_context; + + selinux_get_inode_sid(inode, &context->names[idx].osid); } + /** * audit_inode - store the inode and device from a lookup * @name: name being audited @@ -1301,14 +1240,20 @@ void __audit_inode(const char *name, const struct inode *inode) ++context->ino_count; #endif } - audit_copy_inode(&context->names[idx], inode); + context->names[idx].ino = inode->i_ino; + context->names[idx].dev = inode->i_sb->s_dev; + context->names[idx].mode = inode->i_mode; + context->names[idx].uid = inode->i_uid; + context->names[idx].gid = inode->i_gid; + context->names[idx].rdev = inode->i_rdev; + audit_inode_context(idx, inode); } /** * audit_inode_child - collect inode info for created/removed objects * @dname: inode's dentry name * @inode: inode being audited - * @parent: inode of dentry parent + * @pino: inode number of dentry parent * * For syscalls that create or remove filesystem objects, audit_inode * can only collect information for the filesystem object's parent. @@ -1319,7 +1264,7 @@ void __audit_inode(const char *name, const struct inode *inode) * unsuccessful attempts. */ void __audit_inode_child(const char *dname, const struct inode *inode, - const struct inode *parent) + unsigned long pino) { int idx; struct audit_context *context = current->audit_context; @@ -1333,7 +1278,7 @@ void __audit_inode_child(const char *dname, const struct inode *inode, if (!dname) goto update_context; for (idx = 0; idx < context->name_count; idx++) - if (context->names[idx].ino == parent->i_ino) { + if (context->names[idx].ino == pino) { const char *name = context->names[idx].name; if (!name) @@ -1357,47 +1302,16 @@ void __audit_inode_child(const char *dname, const struct inode *inode, context->names[idx].name_len = AUDIT_NAME_FULL; context->names[idx].name_put = 0; /* don't call __putname() */ - if (!inode) - context->names[idx].ino = (unsigned long)-1; - else - audit_copy_inode(&context->names[idx], inode); - - /* A parent was not found in audit_names, so copy the inode data for the - * provided parent. */ - if (!found_name) { - idx = context->name_count++; -#if AUDIT_DEBUG - context->ino_count++; -#endif - audit_copy_inode(&context->names[idx], parent); - } -} - -/** - * audit_inode_update - update inode info for last collected name - * @inode: inode being audited - * - * When open() is called on an existing object with the O_CREAT flag, the inode - * data audit initially collects is incorrect. This additional hook ensures - * audit has the inode data for the actual object to be opened. - */ -void __audit_inode_update(const struct inode *inode) -{ - struct audit_context *context = current->audit_context; - int idx; - - if (!context->in_syscall || !inode) - return; - - if (context->name_count == 0) { - context->name_count++; -#if AUDIT_DEBUG - context->ino_count++; -#endif - } - idx = context->name_count - 1; - - audit_copy_inode(&context->names[idx], inode); + if (inode) { + context->names[idx].ino = inode->i_ino; + context->names[idx].dev = inode->i_sb->s_dev; + context->names[idx].mode = inode->i_mode; + context->names[idx].uid = inode->i_uid; + context->names[idx].gid = inode->i_gid; + context->names[idx].rdev = inode->i_rdev; + audit_inode_context(idx, inode); + } else + context->names[idx].ino = (unsigned long)-1; } /** @@ -1728,7 +1642,7 @@ int audit_bprm(struct linux_binprm *bprm) unsigned long p, next; void *to; - if (likely(!audit_enabled || !context || context->dummy)) + if (likely(!audit_enabled || !context)) return 0; ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p, @@ -1766,7 +1680,7 @@ int audit_socketcall(int nargs, unsigned long *args) struct audit_aux_data_socketcall *ax; struct audit_context *context = current->audit_context; - if (likely(!context || context->dummy)) + if (likely(!context)) return 0; ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL); @@ -1794,7 +1708,7 @@ int audit_sockaddr(int len, void *a) struct audit_aux_data_sockaddr *ax; struct audit_context *context = current->audit_context; - if (likely(!context || context->dummy)) + if (likely(!context)) return 0; ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL); diff --git a/trunk/kernel/cpuset.c b/trunk/kernel/cpuset.c index 4ea6f0dc2fc5..1a649f2bb9bb 100644 --- a/trunk/kernel/cpuset.c +++ b/trunk/kernel/cpuset.c @@ -816,10 +816,6 @@ static int update_cpumask(struct cpuset *cs, char *buf) struct cpuset trialcs; int retval, cpus_unchanged; - /* top_cpuset.cpus_allowed tracks cpu_online_map; it's read-only */ - if (cs == &top_cpuset) - return -EACCES; - trialcs = *cs; retval = cpulist_parse(buf, trialcs.cpus_allowed); if (retval < 0) @@ -2037,33 +2033,6 @@ int __init cpuset_init(void) return err; } -/* - * The top_cpuset tracks what CPUs and Memory Nodes are online, - * period. This is necessary in order to make cpusets transparent - * (of no affect) on systems that are actively using CPU hotplug - * but making no active use of cpusets. - * - * This handles CPU hotplug (cpuhp) events. If someday Memory - * Nodes can be hotplugged (dynamically changing node_online_map) - * then we should handle that too, perhaps in a similar way. - */ - -#ifdef CONFIG_HOTPLUG_CPU -static int cpuset_handle_cpuhp(struct notifier_block *nb, - unsigned long phase, void *cpu) -{ - mutex_lock(&manage_mutex); - mutex_lock(&callback_mutex); - - top_cpuset.cpus_allowed = cpu_online_map; - - mutex_unlock(&callback_mutex); - mutex_unlock(&manage_mutex); - - return 0; -} -#endif - /** * cpuset_init_smp - initialize cpus_allowed * @@ -2074,8 +2043,6 @@ void __init cpuset_init_smp(void) { top_cpuset.cpus_allowed = cpu_online_map; top_cpuset.mems_allowed = node_online_map; - - hotcpu_notifier(cpuset_handle_cpuhp, 0); } /** @@ -2420,7 +2387,7 @@ EXPORT_SYMBOL_GPL(cpuset_mem_spread_node); int cpuset_excl_nodes_overlap(const struct task_struct *p) { const struct cpuset *cs1, *cs2; /* my and p's cpuset ancestors */ - int overlap = 1; /* do cpusets overlap? */ + int overlap = 0; /* do cpusets overlap? */ task_lock(current); if (current->flags & PF_EXITING) { diff --git a/trunk/kernel/delayacct.c b/trunk/kernel/delayacct.c index 36752f124c6a..f05392d64267 100644 --- a/trunk/kernel/delayacct.c +++ b/trunk/kernel/delayacct.c @@ -19,15 +19,15 @@ #include #include -int delayacct_on __read_mostly = 1; /* Delay accounting turned on/off */ +int delayacct_on __read_mostly; /* Delay accounting turned on/off */ kmem_cache_t *delayacct_cache; -static int __init delayacct_setup_disable(char *str) +static int __init delayacct_setup_enable(char *str) { - delayacct_on = 0; + delayacct_on = 1; return 1; } -__setup("nodelayacct", delayacct_setup_disable); +__setup("delayacct", delayacct_setup_enable); void delayacct_init(void) { @@ -41,11 +41,24 @@ void delayacct_init(void) void __delayacct_tsk_init(struct task_struct *tsk) { + spin_lock_init(&tsk->delays_lock); + /* No need to acquire tsk->delays_lock for allocation here unless + __delayacct_tsk_init called after tsk is attached to tasklist + */ tsk->delays = kmem_cache_zalloc(delayacct_cache, SLAB_KERNEL); if (tsk->delays) spin_lock_init(&tsk->delays->lock); } +void __delayacct_tsk_exit(struct task_struct *tsk) +{ + struct task_delay_info *delays = tsk->delays; + spin_lock(&tsk->delays_lock); + tsk->delays = NULL; + spin_unlock(&tsk->delays_lock); + kmem_cache_free(delayacct_cache, delays); +} + /* * Start accounting for a delay statistic using * its starting timestamp (@start) @@ -105,6 +118,8 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) struct timespec ts; unsigned long t1,t2,t3; + spin_lock(&tsk->delays_lock); + /* Though tsk->delays accessed later, early exit avoids * unnecessary returning of other data */ @@ -146,6 +161,7 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) spin_unlock(&tsk->delays->lock); done: + spin_unlock(&tsk->delays_lock); return 0; } diff --git a/trunk/kernel/exit.c b/trunk/kernel/exit.c index d891883420f7..dba194a8d416 100644 --- a/trunk/kernel/exit.c +++ b/trunk/kernel/exit.c @@ -908,6 +908,7 @@ fastcall NORET_TYPE void do_exit(long code) audit_free(tsk); taskstats_exit_send(tsk, tidstats, group_dead, mycpu); taskstats_exit_free(tidstats); + delayacct_tsk_exit(tsk); exit_mm(tsk); @@ -1053,7 +1054,7 @@ static int eligible_child(pid_t pid, int options, struct task_struct *p) * Do not consider thread group leaders that are * in a non-empty thread group: */ - if (delay_group_leader(p)) + if (current->tgid != p->tgid && delay_group_leader(p)) return 2; if (security_task_wait(p)) diff --git a/trunk/kernel/fork.c b/trunk/kernel/fork.c index f9b014e3e700..1b0f7b1e0881 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -117,7 +117,6 @@ void __put_task_struct(struct task_struct *tsk) security_task_free(tsk); free_uid(tsk->user); put_group_info(tsk->group_info); - delayacct_tsk_free(tsk); if (!profile_handoff_task(tsk)) free_task(tsk); @@ -1012,7 +1011,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, retval = -EFAULT; if (clone_flags & CLONE_PARENT_SETTID) if (put_user(p->pid, parent_tidptr)) - goto bad_fork_cleanup_delays_binfmt; + goto bad_fork_cleanup; INIT_LIST_HEAD(&p->children); INIT_LIST_HEAD(&p->sibling); @@ -1278,8 +1277,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, bad_fork_cleanup_cpuset: #endif cpuset_exit(p); -bad_fork_cleanup_delays_binfmt: - delayacct_tsk_free(p); +bad_fork_cleanup: if (p->binfmt) module_put(p->binfmt->module); bad_fork_cleanup_put_domain: @@ -1389,10 +1387,8 @@ long do_fork(unsigned long clone_flags, if (clone_flags & CLONE_VFORK) { wait_for_completion(&vfork); - if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) { - current->ptrace_message = nr; + if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP); - } } } else { free_pid(pid); diff --git a/trunk/kernel/futex.c b/trunk/kernel/futex.c index 9d260e838cff..cf0c8e21d1ab 100644 --- a/trunk/kernel/futex.c +++ b/trunk/kernel/futex.c @@ -297,7 +297,7 @@ static int futex_handle_fault(unsigned long address, int attempt) struct vm_area_struct * vma; struct mm_struct *mm = current->mm; - if (attempt > 2 || !(vma = find_vma(mm, address)) || + if (attempt >= 2 || !(vma = find_vma(mm, address)) || vma->vm_start > address || !(vma->vm_flags & VM_WRITE)) return -EFAULT; @@ -397,7 +397,7 @@ static struct task_struct * futex_find_get_task(pid_t pid) p = NULL; goto out_unlock; } - if (p->exit_state != 0) { + if (p->state == EXIT_ZOMBIE || p->exit_state == EXIT_ZOMBIE) { p = NULL; goto out_unlock; } @@ -415,15 +415,15 @@ static struct task_struct * futex_find_get_task(pid_t pid) */ void exit_pi_state_list(struct task_struct *curr) { + struct futex_hash_bucket *hb; struct list_head *next, *head = &curr->pi_state_list; struct futex_pi_state *pi_state; - struct futex_hash_bucket *hb; union futex_key key; /* * We are a ZOMBIE and nobody can enqueue itself on * pi_state_list anymore, but we have to be careful - * versus waiters unqueueing themselves: + * versus waiters unqueueing themselfs */ spin_lock_irq(&curr->pi_lock); while (!list_empty(head)) { @@ -431,24 +431,21 @@ void exit_pi_state_list(struct task_struct *curr) next = head->next; pi_state = list_entry(next, struct futex_pi_state, list); key = pi_state->key; - hb = hash_futex(&key); spin_unlock_irq(&curr->pi_lock); + hb = hash_futex(&key); spin_lock(&hb->lock); spin_lock_irq(&curr->pi_lock); - /* - * We dropped the pi-lock, so re-check whether this - * task still owns the PI-state: - */ if (head->next != next) { spin_unlock(&hb->lock); continue; } - WARN_ON(pi_state->owner != curr); - WARN_ON(list_empty(&pi_state->list)); list_del_init(&pi_state->list); + + WARN_ON(pi_state->owner != curr); + pi_state->owner = NULL; spin_unlock_irq(&curr->pi_lock); @@ -473,7 +470,7 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me) head = &hb->chain; list_for_each_entry_safe(this, next, head, list) { - if (match_futex(&this->key, &me->key)) { + if (match_futex (&this->key, &me->key)) { /* * Another waiter already exists - bump up * the refcount and return its pi_state: @@ -485,8 +482,6 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me) if (unlikely(!pi_state)) return -EINVAL; - WARN_ON(!atomic_read(&pi_state->refcount)); - atomic_inc(&pi_state->refcount); me->pi_state = pi_state; @@ -495,13 +490,10 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me) } /* - * We are the first waiter - try to look up the real owner and attach - * the new pi_state to it, but bail out when the owner died bit is set - * and TID = 0: + * We are the first waiter - try to look up the real owner and + * attach the new pi_state to it: */ pid = uval & FUTEX_TID_MASK; - if (!pid && (uval & FUTEX_OWNER_DIED)) - return -ESRCH; p = futex_find_get_task(pid); if (!p) return -ESRCH; @@ -518,7 +510,6 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me) pi_state->key = me->key; spin_lock_irq(&p->pi_lock); - WARN_ON(!list_empty(&pi_state->list)); list_add(&pi_state->list, &p->pi_state_list); pi_state->owner = p; spin_unlock_irq(&p->pi_lock); @@ -582,29 +573,20 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) * kept enabled while there is PI state around. We must also * preserve the owner died bit.) */ - if (!(uval & FUTEX_OWNER_DIED)) { - newval = FUTEX_WAITERS | new_owner->pid; + newval = (uval & FUTEX_OWNER_DIED) | FUTEX_WAITERS | new_owner->pid; - inc_preempt_count(); - curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); - dec_preempt_count(); - if (curval == -EFAULT) - return -EFAULT; - if (curval != uval) - return -EINVAL; - } + inc_preempt_count(); + curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval); + dec_preempt_count(); - spin_lock_irq(&pi_state->owner->pi_lock); - WARN_ON(list_empty(&pi_state->list)); - list_del_init(&pi_state->list); - spin_unlock_irq(&pi_state->owner->pi_lock); + if (curval == -EFAULT) + return -EFAULT; + if (curval != uval) + return -EINVAL; - spin_lock_irq(&new_owner->pi_lock); - WARN_ON(!list_empty(&pi_state->list)); + list_del_init(&pi_state->owner->pi_state_list); list_add(&pi_state->list, &new_owner->pi_state_list); pi_state->owner = new_owner; - spin_unlock_irq(&new_owner->pi_lock); - rt_mutex_unlock(&pi_state->pi_mutex); return 0; @@ -747,10 +729,8 @@ futex_wake_op(u32 __user *uaddr1, u32 __user *uaddr2, */ if (attempt++) { if (futex_handle_fault((unsigned long)uaddr2, - attempt)) { - ret = -EFAULT; + attempt)) goto out; - } goto retry; } @@ -950,7 +930,6 @@ static int unqueue_me(struct futex_q *q) /* In the common case we don't take the spinlock, which is nice. */ retry: lock_ptr = q->lock_ptr; - barrier(); if (lock_ptr != 0) { spin_lock(lock_ptr); /* @@ -1120,10 +1099,9 @@ static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time) * if there are waiters then it will block, it does PI, etc. (Due to * races the kernel might see a 0 value of the futex too.) */ -static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, - long nsec, int trylock) +static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock, + struct hrtimer_sleeper *to) { - struct hrtimer_sleeper timeout, *to = NULL; struct task_struct *curr = current; struct futex_hash_bucket *hb; u32 uval, newval, curval; @@ -1133,13 +1111,6 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, if (refill_pi_state_cache()) return -ENOMEM; - if (sec != MAX_SCHEDULE_TIMEOUT) { - to = &timeout; - hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS); - hrtimer_init_sleeper(to, current); - to->timer.expires = ktime_set(sec, nsec); - } - q.pi_state = NULL; retry: down_read(&curr->mm->mmap_sem); @@ -1265,7 +1236,6 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, /* Owner died? */ if (q.pi_state->owner != NULL) { spin_lock_irq(&q.pi_state->owner->pi_lock); - WARN_ON(list_empty(&q.pi_state->list)); list_del_init(&q.pi_state->list); spin_unlock_irq(&q.pi_state->owner->pi_lock); } else @@ -1274,7 +1244,6 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, q.pi_state->owner = current; spin_lock_irq(¤t->pi_lock); - WARN_ON(!list_empty(&q.pi_state->list)); list_add(&q.pi_state->list, ¤t->pi_state_list); spin_unlock_irq(¤t->pi_lock); @@ -1315,7 +1284,7 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, if (!detect && ret == -EDEADLK && 0) force_sig(SIGKILL, current); - return ret != -EINTR ? ret : -ERESTARTNOINTR; + return ret; out_unlock_release_sem: queue_unlock(&q, hb); @@ -1332,10 +1301,9 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, * still holding the mmap_sem. */ if (attempt++) { - if (futex_handle_fault((unsigned long)uaddr, attempt)) { - ret = -EFAULT; + if (futex_handle_fault((unsigned long)uaddr, attempt)) goto out_unlock_release_sem; - } + goto retry_locked; } @@ -1349,6 +1317,76 @@ static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, return ret; } +/* + * Restart handler + */ +static long futex_lock_pi_restart(struct restart_block *restart) +{ + struct hrtimer_sleeper timeout, *to = NULL; + int ret; + + restart->fn = do_no_restart_syscall; + + if (restart->arg2 || restart->arg3) { + to = &timeout; + hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS); + hrtimer_init_sleeper(to, current); + to->timer.expires.tv64 = ((u64)restart->arg1 << 32) | + (u64) restart->arg0; + } + + pr_debug("lock_pi restart: %p, %d (%d)\n", + (u32 __user *)restart->arg0, current->pid); + + ret = do_futex_lock_pi((u32 __user *)restart->arg0, restart->arg1, + 0, to); + + if (ret != -EINTR) + return ret; + + restart->fn = futex_lock_pi_restart; + + /* The other values are filled in */ + return -ERESTART_RESTARTBLOCK; +} + +/* + * Called from the syscall entry below. + */ +static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec, + long nsec, int trylock) +{ + struct hrtimer_sleeper timeout, *to = NULL; + struct restart_block *restart; + int ret; + + if (sec != MAX_SCHEDULE_TIMEOUT) { + to = &timeout; + hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS); + hrtimer_init_sleeper(to, current); + to->timer.expires = ktime_set(sec, nsec); + } + + ret = do_futex_lock_pi(uaddr, detect, trylock, to); + + if (ret != -EINTR) + return ret; + + pr_debug("lock_pi interrupted: %p, %d (%d)\n", uaddr, current->pid); + + restart = ¤t_thread_info()->restart_block; + restart->fn = futex_lock_pi_restart; + restart->arg0 = (unsigned long) uaddr; + restart->arg1 = detect; + if (to) { + restart->arg2 = to->timer.expires.tv64 & 0xFFFFFFFF; + restart->arg3 = to->timer.expires.tv64 >> 32; + } else + restart->arg2 = restart->arg3 = 0; + + return -ERESTART_RESTARTBLOCK; +} + /* * Userspace attempted a TID -> 0 atomic transition, and failed. * This is the in-kernel slowpath: we look up the PI state (if any), @@ -1389,11 +1427,9 @@ static int futex_unlock_pi(u32 __user *uaddr) * again. If it succeeds then we can return without waking * anyone else up: */ - if (!(uval & FUTEX_OWNER_DIED)) { - inc_preempt_count(); - uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0); - dec_preempt_count(); - } + inc_preempt_count(); + uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0); + dec_preempt_count(); if (unlikely(uval == -EFAULT)) goto pi_faulted; @@ -1426,11 +1462,9 @@ static int futex_unlock_pi(u32 __user *uaddr) /* * No waiters - kernel unlocks the futex: */ - if (!(uval & FUTEX_OWNER_DIED)) { - ret = unlock_futex_pi(uaddr, uval); - if (ret == -EFAULT) - goto pi_faulted; - } + ret = unlock_futex_pi(uaddr, uval); + if (ret == -EFAULT) + goto pi_faulted; out_unlock: spin_unlock(&hb->lock); @@ -1447,10 +1481,9 @@ static int futex_unlock_pi(u32 __user *uaddr) * still holding the mmap_sem. */ if (attempt++) { - if (futex_handle_fault((unsigned long)uaddr, attempt)) { - ret = -EFAULT; + if (futex_handle_fault((unsigned long)uaddr, attempt)) goto out_unlock; - } + goto retry_locked; } @@ -1650,9 +1683,9 @@ sys_get_robust_list(int pid, struct robust_list_head __user **head_ptr, * Process a futex-list entry, check whether it's owned by the * dying task, and do notification if so: */ -int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi) +int handle_futex_death(u32 __user *uaddr, struct task_struct *curr) { - u32 uval, nval, mval; + u32 uval, nval; retry: if (get_user(uval, uaddr)) @@ -1669,44 +1702,20 @@ int handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi) * thread-death.) The rest of the cleanup is done in * userspace. */ - mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; - nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval); - + nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, + uval | FUTEX_OWNER_DIED); if (nval == -EFAULT) return -1; if (nval != uval) goto retry; - /* - * Wake robust non-PI futexes here. The wakeup of - * PI futexes happens in exit_pi_state(): - */ - if (!pi) { - if (uval & FUTEX_WAITERS) - futex_wake(uaddr, 1); - } + if (uval & FUTEX_WAITERS) + futex_wake(uaddr, 1); } return 0; } -/* - * Fetch a robust-list pointer. Bit 0 signals PI futexes: - */ -static inline int fetch_robust_entry(struct robust_list __user **entry, - struct robust_list __user **head, int *pi) -{ - unsigned long uentry; - - if (get_user(uentry, (unsigned long *)head)) - return -EFAULT; - - *entry = (void *)(uentry & ~1UL); - *pi = uentry & 1; - - return 0; -} - /* * Walk curr->robust_list (very carefully, it's a userspace list!) * and mark any locks found there dead, and notify any waiters. @@ -1717,14 +1726,14 @@ void exit_robust_list(struct task_struct *curr) { struct robust_list_head __user *head = curr->robust_list; struct robust_list __user *entry, *pending; - unsigned int limit = ROBUST_LIST_LIMIT, pi, pip; + unsigned int limit = ROBUST_LIST_LIMIT; unsigned long futex_offset; /* * Fetch the list head (which was registered earlier, via * sys_set_robust_list()): */ - if (fetch_robust_entry(&entry, &head->list.next, &pi)) + if (get_user(entry, &head->list.next)) return; /* * Fetch the relative futex offset: @@ -1735,11 +1744,10 @@ void exit_robust_list(struct task_struct *curr) * Fetch any possibly pending lock-add first, and handle it * if it exists: */ - if (fetch_robust_entry(&pending, &head->list_op_pending, &pip)) + if (get_user(pending, &head->list_op_pending)) return; - if (pending) - handle_futex_death((void *)pending + futex_offset, curr, pip); + handle_futex_death((void *)pending + futex_offset, curr); while (entry != &head->list) { /* @@ -1748,12 +1756,12 @@ void exit_robust_list(struct task_struct *curr) */ if (entry != pending) if (handle_futex_death((void *)entry + futex_offset, - curr, pi)) + curr)) return; /* * Fetch the next entry in the list: */ - if (fetch_robust_entry(&entry, &entry->next, &pi)) + if (get_user(entry, &entry->next)) return; /* * Avoid excessively long or circular lists: diff --git a/trunk/kernel/futex_compat.c b/trunk/kernel/futex_compat.c index c5cca3f65cb7..d1d92b441fb7 100644 --- a/trunk/kernel/futex_compat.c +++ b/trunk/kernel/futex_compat.c @@ -12,23 +12,6 @@ #include - -/* - * Fetch a robust-list pointer. Bit 0 signals PI futexes: - */ -static inline int -fetch_robust_entry(compat_uptr_t *uentry, struct robust_list __user **entry, - compat_uptr_t *head, int *pi) -{ - if (get_user(*uentry, head)) - return -EFAULT; - - *entry = compat_ptr((*uentry) & ~1); - *pi = (unsigned int)(*uentry) & 1; - - return 0; -} - /* * Walk curr->robust_list (very carefully, it's a userspace list!) * and mark any locks found there dead, and notify any waiters. @@ -39,16 +22,17 @@ void compat_exit_robust_list(struct task_struct *curr) { struct compat_robust_list_head __user *head = curr->compat_robust_list; struct robust_list __user *entry, *pending; - unsigned int limit = ROBUST_LIST_LIMIT, pi, pip; compat_uptr_t uentry, upending; + unsigned int limit = ROBUST_LIST_LIMIT; compat_long_t futex_offset; /* * Fetch the list head (which was registered earlier, via * sys_set_robust_list()): */ - if (fetch_robust_entry(&uentry, &entry, &head->list.next, &pi)) + if (get_user(uentry, &head->list.next)) return; + entry = compat_ptr(uentry); /* * Fetch the relative futex offset: */ @@ -58,11 +42,11 @@ void compat_exit_robust_list(struct task_struct *curr) * Fetch any possibly pending lock-add first, and handle it * if it exists: */ - if (fetch_robust_entry(&upending, &pending, - &head->list_op_pending, &pip)) + if (get_user(upending, &head->list_op_pending)) return; + pending = compat_ptr(upending); if (upending) - handle_futex_death((void *)pending + futex_offset, curr, pip); + handle_futex_death((void *)pending + futex_offset, curr); while (compat_ptr(uentry) != &head->list) { /* @@ -71,15 +55,15 @@ void compat_exit_robust_list(struct task_struct *curr) */ if (entry != pending) if (handle_futex_death((void *)entry + futex_offset, - curr, pi)) + curr)) return; /* * Fetch the next entry in the list: */ - if (fetch_robust_entry(&uentry, &entry, - (compat_uptr_t *)&entry->next, &pi)) + if (get_user(uentry, (compat_uptr_t *)&entry->next)) return; + entry = compat_ptr(uentry); /* * Avoid excessively long or circular lists: */ diff --git a/trunk/kernel/hrtimer.c b/trunk/kernel/hrtimer.c index 21c38a7e666b..d17766d40dab 100644 --- a/trunk/kernel/hrtimer.c +++ b/trunk/kernel/hrtimer.c @@ -187,7 +187,7 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_base *base) { struct hrtimer_base *new_base; - new_base = &__get_cpu_var(hrtimer_bases)[base->index]; + new_base = &__get_cpu_var(hrtimer_bases[base->index]); if (base != new_base) { /* @@ -835,7 +835,7 @@ static void migrate_hrtimers(int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self, +static int __devinit hrtimer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -859,7 +859,7 @@ static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata hrtimers_nb = { +static struct notifier_block __devinitdata hrtimers_nb = { .notifier_call = hrtimer_cpu_notify, }; diff --git a/trunk/kernel/irq/chip.c b/trunk/kernel/irq/chip.c index ac1f850d4937..9336f2e89e40 100644 --- a/trunk/kernel/irq/chip.c +++ b/trunk/kernel/irq/chip.c @@ -252,7 +252,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) mask_ack_irq(desc, irq); if (unlikely(desc->status & IRQ_INPROGRESS)) - goto out_unlock; + goto out; desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); kstat_cpu(cpu).irqs[irq]++; @@ -263,7 +263,7 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) action = desc->action; if (unlikely(!action || (desc->status & IRQ_DISABLED))) { desc->status |= IRQ_PENDING; - goto out_unlock; + goto out; } desc->status |= IRQ_INPROGRESS; @@ -276,9 +276,9 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) spin_lock(&desc->lock); desc->status &= ~IRQ_INPROGRESS; +out: if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) desc->chip->unmask(irq); -out_unlock: spin_unlock(&desc->lock); } diff --git a/trunk/kernel/irq/handle.c b/trunk/kernel/irq/handle.c index 48a53f68af96..fc4e906aedbd 100644 --- a/trunk/kernel/irq/handle.c +++ b/trunk/kernel/irq/handle.c @@ -20,11 +20,6 @@ /** * handle_bad_irq - handle spurious and unhandled irqs - * @irq: the interrupt number - * @desc: description of the interrupt - * @regs: pointer to a register structure - * - * Handles spurious and unhandled IRQ's. It also prints a debugmessage. */ void fastcall handle_bad_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) diff --git a/trunk/kernel/irq/manage.c b/trunk/kernel/irq/manage.c index 92be519eff26..4e461438e48b 100644 --- a/trunk/kernel/irq/manage.c +++ b/trunk/kernel/irq/manage.c @@ -137,40 +137,16 @@ EXPORT_SYMBOL(enable_irq); * @irq: interrupt to control * @on: enable/disable power management wakeup * - * Enable/disable power management wakeup mode, which is - * disabled by default. Enables and disables must match, - * just as they match for non-wakeup mode support. - * - * Wakeup mode lets this IRQ wake the system from sleep - * states like "suspend to RAM". + * Enable/disable power management wakeup mode */ int set_irq_wake(unsigned int irq, unsigned int on) { struct irq_desc *desc = irq_desc + irq; unsigned long flags; int ret = -ENXIO; - int (*set_wake)(unsigned, unsigned) = desc->chip->set_wake; - /* wakeup-capable irqs can be shared between drivers that - * don't need to have the same sleep mode behaviors. - */ spin_lock_irqsave(&desc->lock, flags); - if (on) { - if (desc->wake_depth++ == 0) - desc->status |= IRQ_WAKEUP; - else - set_wake = NULL; - } else { - if (desc->wake_depth == 0) { - printk(KERN_WARNING "Unbalanced IRQ %d " - "wake disable\n", irq); - WARN_ON(1); - } else if (--desc->wake_depth == 0) - desc->status &= ~IRQ_WAKEUP; - else - set_wake = NULL; - } - if (set_wake) + if (desc->chip->set_wake) ret = desc->chip->set_wake(irq, on); spin_unlock_irqrestore(&desc->lock, flags); return ret; diff --git a/trunk/kernel/irq/resend.c b/trunk/kernel/irq/resend.c index 35f10f7ff94a..872f91ba2ce8 100644 --- a/trunk/kernel/irq/resend.c +++ b/trunk/kernel/irq/resend.c @@ -63,7 +63,8 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq) desc->chip->enable(irq); if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { - desc->status = (status & ~IRQ_PENDING) | IRQ_REPLAY; + desc->status &= ~IRQ_PENDING; + desc->status = status | IRQ_REPLAY; if (!desc->chip || !desc->chip->retrigger || !desc->chip->retrigger(irq)) { diff --git a/trunk/kernel/kmod.c b/trunk/kernel/kmod.c index 5c470c57fb57..1d32defa38ab 100644 --- a/trunk/kernel/kmod.c +++ b/trunk/kernel/kmod.c @@ -197,12 +197,11 @@ static void __call_usermodehelper(void *data) { struct subprocess_info *sub_info = data; pid_t pid; - int wait = sub_info->wait; /* CLONE_VFORK: wait until the usermode helper has execve'd * successfully We need the data structures to stay around * until that is done. */ - if (wait) + if (sub_info->wait) pid = kernel_thread(wait_for_helper, sub_info, CLONE_FS | CLONE_FILES | SIGCHLD); else @@ -212,7 +211,7 @@ static void __call_usermodehelper(void *data) if (pid < 0) { sub_info->retval = pid; complete(sub_info->complete); - } else if (!wait) + } else if (!sub_info->wait) complete(sub_info->complete); } diff --git a/trunk/kernel/kprobes.c b/trunk/kernel/kprobes.c index 3f57dfdc8f92..64aab081153b 100644 --- a/trunk/kernel/kprobes.c +++ b/trunk/kernel/kprobes.c @@ -393,7 +393,6 @@ static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p) static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p) { copy_kprobe(p, ap); - flush_insn_slot(ap); ap->addr = p->addr; ap->pre_handler = aggr_pre_handler; ap->fault_handler = aggr_fault_handler; diff --git a/trunk/kernel/lockdep_internals.h b/trunk/kernel/lockdep_internals.h index eab043c83bb2..0d355f24fe04 100644 --- a/trunk/kernel/lockdep_internals.h +++ b/trunk/kernel/lockdep_internals.h @@ -27,7 +27,7 @@ * Stack-trace: tightly packed array of stack backtrace * addresses. Protected by the hash_lock. */ -#define MAX_STACK_TRACE_ENTRIES 262144UL +#define MAX_STACK_TRACE_ENTRIES 131072UL extern struct list_head all_lock_classes; diff --git a/trunk/kernel/panic.c b/trunk/kernel/panic.c index 8010b9b17aca..d8a0bca21233 100644 --- a/trunk/kernel/panic.c +++ b/trunk/kernel/panic.c @@ -18,7 +18,6 @@ #include #include #include -#include int panic_on_oops; int tainted; @@ -173,7 +172,7 @@ const char *print_tainted(void) void add_taint(unsigned flag) { - debug_locks = 0; /* can't trust the integrity of the kernel anymore */ + debug_locks_off(); /* can't trust the integrity of the kernel anymore */ tainted |= flag; } EXPORT_SYMBOL(add_taint); diff --git a/trunk/kernel/power/Kconfig b/trunk/kernel/power/Kconfig index 619ecabf7c58..ae44a70aae8a 100644 --- a/trunk/kernel/power/Kconfig +++ b/trunk/kernel/power/Kconfig @@ -56,7 +56,7 @@ config PM_TRACE config SOFTWARE_SUSPEND bool "Software Suspend" - depends on PM && SWAP && ((X86 && (!SMP || SUSPEND_SMP) && !X86_PAE) || ((FRV || PPC32) && !SMP)) + depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP) ---help--- Enable the possibility of suspending the machine. It doesn't need ACPI or APM. @@ -78,10 +78,6 @@ config SOFTWARE_SUSPEND For more information take a look at . - (For now, swsusp is incompatible with PAE aka HIGHMEM_64G on i386. - we need identity mapping for resume to work, and that is trivial - to get with 4MB pages, but less than trivial on PAE). - config PM_STD_PARTITION string "Default resume partition" depends on SOFTWARE_SUSPEND diff --git a/trunk/kernel/power/process.c b/trunk/kernel/power/process.c index 72e72d2c61e6..b2a5f671d6cd 100644 --- a/trunk/kernel/power/process.c +++ b/trunk/kernel/power/process.c @@ -66,25 +66,13 @@ static inline void freeze_process(struct task_struct *p) } } -static void cancel_freezing(struct task_struct *p) -{ - unsigned long flags; - - if (freezing(p)) { - pr_debug(" clean up: %s\n", p->comm); - do_not_freeze(p); - spin_lock_irqsave(&p->sighand->siglock, flags); - recalc_sigpending_tsk(p); - spin_unlock_irqrestore(&p->sighand->siglock, flags); - } -} - /* 0 = success, else # of processes that we failed to stop */ int freeze_processes(void) { int todo, nr_user, user_frozen; unsigned long start_time; struct task_struct *g, *p; + unsigned long flags; printk( "Stopping tasks: " ); start_time = jiffies; @@ -97,10 +85,6 @@ int freeze_processes(void) continue; if (frozen(p)) continue; - if (p->state == TASK_TRACED && frozen(p->parent)) { - cancel_freezing(p); - continue; - } if (p->mm && !(p->flags & PF_BORROWED_MM)) { /* The task is a user-space one. * Freeze it unless there's a vfork completion @@ -142,7 +126,13 @@ int freeze_processes(void) do_each_thread(g, p) { if (freezeable(p) && !frozen(p)) printk(KERN_ERR " %s\n", p->comm); - cancel_freezing(p); + if (freezing(p)) { + pr_debug(" clean up: %s\n", p->comm); + p->flags &= ~PF_FREEZE; + spin_lock_irqsave(&p->sighand->siglock, flags); + recalc_sigpending_tsk(p); + spin_unlock_irqrestore(&p->sighand->siglock, flags); + } } while_each_thread(g, p); read_unlock(&tasklist_lock); return todo; diff --git a/trunk/kernel/printk.c b/trunk/kernel/printk.c index 1149365e989e..65ca0688f86f 100644 --- a/trunk/kernel/printk.c +++ b/trunk/kernel/printk.c @@ -799,9 +799,6 @@ void release_console_sem(void) up(&secondary_console_sem); return; } - - console_may_schedule = 0; - for ( ; ; ) { spin_lock_irqsave(&logbuf_lock, flags); wake_klogd |= log_start - log_end; @@ -815,6 +812,7 @@ void release_console_sem(void) local_irq_restore(flags); } console_locked = 0; + console_may_schedule = 0; up(&console_sem); spin_unlock_irqrestore(&logbuf_lock, flags); if (wake_klogd && !oops_in_progress && waitqueue_active(&log_wait)) { diff --git a/trunk/kernel/rcupdate.c b/trunk/kernel/rcupdate.c index 523e46483b99..759805c9859a 100644 --- a/trunk/kernel/rcupdate.c +++ b/trunk/kernel/rcupdate.c @@ -241,16 +241,12 @@ static void rcu_do_batch(struct rcu_data *rdp) next = rdp->donelist = list->next; list->func(list); list = next; + rdp->qlen--; if (++count >= rdp->blimit) break; } - - local_irq_disable(); - rdp->qlen -= count; - local_irq_enable(); if (rdp->blimit == INT_MAX && rdp->qlen <= qlowmark) rdp->blimit = blimit; - if (!rdp->donelist) rdp->donetail = &rdp->donelist; else @@ -552,7 +548,7 @@ static void __devinit rcu_online_cpu(int cpu) tasklet_init(&per_cpu(rcu_tasklet, cpu), rcu_process_callbacks, 0UL); } -static int __cpuinit rcu_cpu_notify(struct notifier_block *self, +static int __devinit rcu_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -569,7 +565,7 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata rcu_nb = { +static struct notifier_block __devinitdata rcu_nb = { .notifier_call = rcu_cpu_notify, }; diff --git a/trunk/kernel/resource.c b/trunk/kernel/resource.c index 46286434af80..0dd3a857579e 100644 --- a/trunk/kernel/resource.c +++ b/trunk/kernel/resource.c @@ -244,7 +244,6 @@ int find_next_system_ram(struct resource *res) start = res->start; end = res->end; - BUG_ON(start >= end); read_lock(&resource_lock); for (p = iomem_resource.child; p ; p = p->sibling) { @@ -255,17 +254,15 @@ int find_next_system_ram(struct resource *res) p = NULL; break; } - if ((p->end >= start) && (p->start < end)) + if (p->start >= start) break; } read_unlock(&resource_lock); if (!p) return -1; /* copy data */ - if (res->start < p->start) - res->start = p->start; - if (res->end > p->end) - res->end = p->end; + res->start = p->start; + res->end = p->end; return 0; } #endif diff --git a/trunk/kernel/rtmutex.c b/trunk/kernel/rtmutex.c index 3e13a1e5856f..d2ef13b485e7 100644 --- a/trunk/kernel/rtmutex.c +++ b/trunk/kernel/rtmutex.c @@ -7,8 +7,6 @@ * Copyright (C) 2005-2006 Timesys Corp., Thomas Gleixner * Copyright (C) 2005 Kihon Technologies Inc., Steven Rostedt * Copyright (C) 2006 Esben Nielsen - * - * See Documentation/rt-mutex-design.txt for details. */ #include #include diff --git a/trunk/kernel/sched.c b/trunk/kernel/sched.c index a234fbee1238..b44b9a43b0fc 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -4162,8 +4162,10 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) read_unlock_irq(&tasklist_lock); return -ESRCH; } - retval = sched_setscheduler(p, policy, &lparam); + get_task_struct(p); read_unlock_irq(&tasklist_lock); + retval = sched_setscheduler(p, policy, &lparam); + put_task_struct(p); return retval; } @@ -4454,9 +4456,9 @@ asmlinkage long sys_sched_yield(void) return 0; } -static inline int __resched_legal(int expected_preempt_count) +static inline int __resched_legal(void) { - if (unlikely(preempt_count() != expected_preempt_count)) + if (unlikely(preempt_count())) return 0; if (unlikely(system_state != SYSTEM_RUNNING)) return 0; @@ -4482,7 +4484,7 @@ static void __cond_resched(void) int __sched cond_resched(void) { - if (need_resched() && __resched_legal(0)) { + if (need_resched() && __resched_legal()) { __cond_resched(); return 1; } @@ -4508,7 +4510,7 @@ int cond_resched_lock(spinlock_t *lock) ret = 1; spin_lock(lock); } - if (need_resched() && __resched_legal(1)) { + if (need_resched() && __resched_legal()) { spin_release(&lock->dep_map, 1, _THIS_IP_); _raw_spin_unlock(lock); preempt_enable_no_resched(); @@ -4524,7 +4526,7 @@ int __sched cond_resched_softirq(void) { BUG_ON(!in_softirq()); - if (need_resched() && __resched_legal(0)) { + if (need_resched() && __resched_legal()) { raw_local_irq_disable(); _local_bh_enable(); raw_local_irq_enable(); @@ -6492,12 +6494,7 @@ static int build_sched_domains(const cpumask_t *cpu_map) for (i = 0; i < MAX_NUMNODES; i++) init_numa_sched_groups_power(sched_group_nodes[i]); - if (sched_group_allnodes) { - int group = cpu_to_allnodes_group(first_cpu(*cpu_map)); - struct sched_group *sg = &sched_group_allnodes[group]; - - init_numa_sched_groups_power(sg); - } + init_numa_sched_groups_power(sched_group_allnodes); #endif /* Attach the domains */ @@ -6764,11 +6761,6 @@ void __init sched_init(void) } set_load_weight(&init_task); - -#ifdef CONFIG_RT_MUTEXES - plist_head_init(&init_task.pi_waiters, &init_task.pi_lock); -#endif - /* * The boot idle thread does lazy MMU switching as well: */ diff --git a/trunk/kernel/signal.c b/trunk/kernel/signal.c index bfdb5686fa3e..7fe874d12fae 100644 --- a/trunk/kernel/signal.c +++ b/trunk/kernel/signal.c @@ -791,31 +791,22 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) /* * Force a signal that the process can't ignore: if necessary * we unblock the signal and change any SIG_IGN to SIG_DFL. - * - * Note: If we unblock the signal, we always reset it to SIG_DFL, - * since we do not want to have a signal handler that was blocked - * be invoked when user space had explicitly blocked it. - * - * We don't want to have recursive SIGSEGV's etc, for example. */ + int force_sig_info(int sig, struct siginfo *info, struct task_struct *t) { unsigned long int flags; - int ret, blocked, ignored; - struct k_sigaction *action; + int ret; spin_lock_irqsave(&t->sighand->siglock, flags); - action = &t->sighand->action[sig-1]; - ignored = action->sa.sa_handler == SIG_IGN; - blocked = sigismember(&t->blocked, sig); - if (blocked || ignored) { - action->sa.sa_handler = SIG_DFL; - if (blocked) { - sigdelset(&t->blocked, sig); - recalc_sigpending_tsk(t); - } + if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) { + t->sighand->action[sig-1].sa.sa_handler = SIG_DFL; + } + if (sigismember(&t->blocked, sig)) { + sigdelset(&t->blocked, sig); } + recalc_sigpending_tsk(t); ret = specific_send_sig_info(sig, info, t); spin_unlock_irqrestore(&t->sighand->siglock, flags); diff --git a/trunk/kernel/softirq.c b/trunk/kernel/softirq.c index 3789ca98197c..0f08a84ae307 100644 --- a/trunk/kernel/softirq.c +++ b/trunk/kernel/softirq.c @@ -65,7 +65,6 @@ static inline void wakeup_softirqd(void) * This one is for softirq.c-internal use, * where hardirqs are disabled legitimately: */ -#ifdef CONFIG_TRACE_IRQFLAGS static void __local_bh_disable(unsigned long ip) { unsigned long flags; @@ -81,13 +80,6 @@ static void __local_bh_disable(unsigned long ip) trace_softirqs_off(ip); raw_local_irq_restore(flags); } -#else /* !CONFIG_TRACE_IRQFLAGS */ -static inline void __local_bh_disable(unsigned long ip) -{ - add_preempt_count(SOFTIRQ_OFFSET); - barrier(); -} -#endif /* CONFIG_TRACE_IRQFLAGS */ void local_bh_disable(void) { @@ -129,16 +121,12 @@ EXPORT_SYMBOL(_local_bh_enable); void local_bh_enable(void) { -#ifdef CONFIG_TRACE_IRQFLAGS unsigned long flags; WARN_ON_ONCE(in_irq()); -#endif WARN_ON_ONCE(irqs_disabled()); -#ifdef CONFIG_TRACE_IRQFLAGS local_irq_save(flags); -#endif /* * Are softirqs going to be turned on now: */ @@ -154,22 +142,18 @@ void local_bh_enable(void) do_softirq(); dec_preempt_count(); -#ifdef CONFIG_TRACE_IRQFLAGS local_irq_restore(flags); -#endif preempt_check_resched(); } EXPORT_SYMBOL(local_bh_enable); void local_bh_enable_ip(unsigned long ip) { -#ifdef CONFIG_TRACE_IRQFLAGS unsigned long flags; WARN_ON_ONCE(in_irq()); local_irq_save(flags); -#endif /* * Are softirqs going to be turned on now: */ @@ -185,9 +169,7 @@ void local_bh_enable_ip(unsigned long ip) do_softirq(); dec_preempt_count(); -#ifdef CONFIG_TRACE_IRQFLAGS local_irq_restore(flags); -#endif preempt_check_resched(); } EXPORT_SYMBOL(local_bh_enable_ip); @@ -565,7 +547,7 @@ static void takeover_tasklets(unsigned int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static int __cpuinit cpu_callback(struct notifier_block *nfb, +static int __devinit cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -605,7 +587,7 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata cpu_nfb = { +static struct notifier_block __devinitdata cpu_nfb = { .notifier_call = cpu_callback }; diff --git a/trunk/kernel/softlockup.c b/trunk/kernel/softlockup.c index 03e6a2b0b787..6b76caa22981 100644 --- a/trunk/kernel/softlockup.c +++ b/trunk/kernel/softlockup.c @@ -104,7 +104,7 @@ static int watchdog(void * __bind_cpu) /* * Create/destroy watchdog threads as CPUs come and go: */ -static int __cpuinit +static int __devinit cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { int hotcpu = (unsigned long)hcpu; @@ -142,7 +142,7 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block __cpuinitdata cpu_nfb = { +static struct notifier_block __devinitdata cpu_nfb = { .notifier_call = cpu_callback }; diff --git a/trunk/kernel/spinlock.c b/trunk/kernel/spinlock.c index fb524b009eef..bfd6ad9c0330 100644 --- a/trunk/kernel/spinlock.c +++ b/trunk/kernel/spinlock.c @@ -72,7 +72,7 @@ EXPORT_SYMBOL(_write_trylock); * not re-enabled during lock-acquire (which the preempt-spin-ops do): */ #if !defined(CONFIG_PREEMPT) || !defined(CONFIG_SMP) || \ - defined(CONFIG_DEBUG_LOCK_ALLOC) + defined(CONFIG_PROVE_LOCKING) void __lockfunc _read_lock(rwlock_t *lock) { diff --git a/trunk/kernel/stop_machine.c b/trunk/kernel/stop_machine.c index 51cacd111dbd..dcfb5d731466 100644 --- a/trunk/kernel/stop_machine.c +++ b/trunk/kernel/stop_machine.c @@ -111,6 +111,7 @@ static int stop_machine(void) /* If some failed, kill them all. */ if (ret < 0) { stopmachine_set_state(STOPMACHINE_EXIT); + up(&stopmachine_mutex); return ret; } diff --git a/trunk/kernel/taskstats.c b/trunk/kernel/taskstats.c index 2ed4040d0dc5..f45179ce028e 100644 --- a/trunk/kernel/taskstats.c +++ b/trunk/kernel/taskstats.c @@ -75,7 +75,7 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, /* * If new attributes are added, please revisit this allocation */ - skb = nlmsg_new(size, GFP_KERNEL); + skb = nlmsg_new(size); if (!skb) return -ENOMEM; @@ -121,45 +121,46 @@ static int send_reply(struct sk_buff *skb, pid_t pid) /* * Send taskstats data in @skb to listeners registered for @cpu's exit data */ -static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu) +static int send_cpu_listeners(struct sk_buff *skb, unsigned int cpu) { struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data); struct listener_list *listeners; struct listener *s, *tmp; struct sk_buff *skb_next, *skb_cur = skb; void *reply = genlmsg_data(genlhdr); - int rc, delcount = 0; + int rc, ret, delcount = 0; rc = genlmsg_end(skb, reply); if (rc < 0) { nlmsg_free(skb); - return; + return rc; } rc = 0; listeners = &per_cpu(listener_array, cpu); down_read(&listeners->sem); - list_for_each_entry(s, &listeners->list, list) { + list_for_each_entry_safe(s, tmp, &listeners->list, list) { skb_next = NULL; if (!list_is_last(&s->list, &listeners->list)) { skb_next = skb_clone(skb_cur, GFP_KERNEL); - if (!skb_next) + if (!skb_next) { + nlmsg_free(skb_cur); + rc = -ENOMEM; break; + } } - rc = genlmsg_unicast(skb_cur, s->pid); - if (rc == -ECONNREFUSED) { + ret = genlmsg_unicast(skb_cur, s->pid); + if (ret == -ECONNREFUSED) { s->valid = 0; delcount++; + rc = ret; } skb_cur = skb_next; } up_read(&listeners->sem); - if (skb_cur) - nlmsg_free(skb_cur); - if (!delcount) - return; + return rc; /* Delete invalidated entries */ down_write(&listeners->sem); @@ -170,12 +171,13 @@ static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu) } } up_write(&listeners->sem); + return rc; } static int fill_pid(pid_t pid, struct task_struct *pidtsk, struct taskstats *stats) { - int rc = 0; + int rc; struct task_struct *tsk = pidtsk; if (!pidtsk) { @@ -194,10 +196,12 @@ static int fill_pid(pid_t pid, struct task_struct *pidtsk, * Each accounting subsystem adds calls to its functions to * fill in relevant parts of struct taskstsats as follows * - * per-task-foo(stats, tsk); + * rc = per-task-foo(stats, tsk); + * if (rc) + * goto err; */ - delayacct_add_tsk(stats, tsk); + rc = delayacct_add_tsk(stats, tsk); stats->version = TASKSTATS_VERSION; /* Define err: label here if needed */ diff --git a/trunk/kernel/timer.c b/trunk/kernel/timer.c index 1d7dd6267c2d..05809c2e2fd6 100644 --- a/trunk/kernel/timer.c +++ b/trunk/kernel/timer.c @@ -84,7 +84,7 @@ typedef struct tvec_t_base_s tvec_base_t; tvec_base_t boot_tvec_bases; EXPORT_SYMBOL(boot_tvec_bases); -static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = &boot_tvec_bases; +static DEFINE_PER_CPU(tvec_base_t *, tvec_bases) = { &boot_tvec_bases }; static inline void set_running_timer(tvec_base_t *base, struct timer_list *timer) @@ -408,7 +408,7 @@ static int cascade(tvec_base_t *base, tvec_t *tv, int index) * This function cascades all vectors and executes all expired timer * vectors. */ -#define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK) +#define INDEX(N) (base->timer_jiffies >> (TVR_BITS + N * TVN_BITS)) & TVN_MASK static inline void __run_timers(tvec_base_t *base) { @@ -1324,19 +1324,46 @@ asmlinkage long sys_getpid(void) } /* - * Accessing ->real_parent is not SMP-safe, it could - * change from under us. However, we can use a stale - * value of ->real_parent under rcu_read_lock(), see - * release_task()->call_rcu(delayed_put_task_struct). + * Accessing ->group_leader->real_parent is not SMP-safe, it could + * change from under us. However, rather than getting any lock + * we can use an optimistic algorithm: get the parent + * pid, and go back and check that the parent is still + * the same. If it has changed (which is extremely unlikely + * indeed), we just try again.. + * + * NOTE! This depends on the fact that even if we _do_ + * get an old value of "parent", we can happily dereference + * the pointer (it was and remains a dereferencable kernel pointer + * no matter what): we just can't necessarily trust the result + * until we know that the parent pointer is valid. + * + * NOTE2: ->group_leader never changes from under us. */ asmlinkage long sys_getppid(void) { int pid; + struct task_struct *me = current; + struct task_struct *parent; - rcu_read_lock(); - pid = rcu_dereference(current->real_parent)->tgid; - rcu_read_unlock(); + parent = me->group_leader->real_parent; + for (;;) { + pid = parent->tgid; +#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) +{ + struct task_struct *old = parent; + /* + * Make sure we read the pid before re-reading the + * parent pointer: + */ + smp_rmb(); + parent = me->group_leader->real_parent; + if (old != parent) + continue; +} +#endif + break; + } return pid; } @@ -1661,7 +1688,7 @@ static void __devinit migrate_timers(int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static int __cpuinit timer_cpu_notify(struct notifier_block *self, +static int __devinit timer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -1681,7 +1708,7 @@ static int __cpuinit timer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata timers_nb = { +static struct notifier_block __devinitdata timers_nb = { .notifier_call = timer_cpu_notify, }; diff --git a/trunk/kernel/workqueue.c b/trunk/kernel/workqueue.c index 835fe28b87a8..eebb1d839235 100644 --- a/trunk/kernel/workqueue.c +++ b/trunk/kernel/workqueue.c @@ -68,7 +68,7 @@ struct workqueue_struct { /* All the per-cpu workqueues on the system, for hotplug cpu to add/remove threads to each one as cpus come/go. */ -static DEFINE_MUTEX(workqueue_mutex); +static DEFINE_SPINLOCK(workqueue_lock); static LIST_HEAD(workqueues); static int singlethread_cpu; @@ -93,12 +93,9 @@ static void __queue_work(struct cpu_workqueue_struct *cwq, spin_unlock_irqrestore(&cwq->lock, flags); } -/** - * queue_work - queue work on a workqueue - * @wq: workqueue to use - * @work: work to queue - * - * Returns non-zero if it was successfully added. +/* + * Queue work on a workqueue. Return non-zero if it was successfully + * added. * * We queue the work to the CPU it was submitted, but there is no * guarantee that it will be processed by that CPU. @@ -131,14 +128,6 @@ static void delayed_work_timer_fn(unsigned long __data) __queue_work(per_cpu_ptr(wq->cpu_wq, cpu), work); } -/** - * queue_delayed_work - queue work on a workqueue after delay - * @wq: workqueue to use - * @work: work to queue - * @delay: number of jiffies to wait before queueing - * - * Returns non-zero if it was successfully added. - */ int fastcall queue_delayed_work(struct workqueue_struct *wq, struct work_struct *work, unsigned long delay) { @@ -161,15 +150,6 @@ int fastcall queue_delayed_work(struct workqueue_struct *wq, } EXPORT_SYMBOL_GPL(queue_delayed_work); -/** - * queue_delayed_work_on - queue work on specific CPU after delay - * @cpu: CPU number to execute work on - * @wq: workqueue to use - * @work: work to queue - * @delay: number of jiffies to wait before queueing - * - * Returns non-zero if it was successfully added. - */ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, struct work_struct *work, unsigned long delay) { @@ -295,9 +275,8 @@ static void flush_cpu_workqueue(struct cpu_workqueue_struct *cwq) } } -/** +/* * flush_workqueue - ensure that any scheduled work has run to completion. - * @wq: workqueue to flush * * Forces execution of the workqueue and blocks until its completion. * This is typically used in driver shutdown handlers. @@ -320,10 +299,10 @@ void fastcall flush_workqueue(struct workqueue_struct *wq) } else { int cpu; - mutex_lock(&workqueue_mutex); + lock_cpu_hotplug(); for_each_online_cpu(cpu) flush_cpu_workqueue(per_cpu_ptr(wq->cpu_wq, cpu)); - mutex_unlock(&workqueue_mutex); + unlock_cpu_hotplug(); } } EXPORT_SYMBOL_GPL(flush_workqueue); @@ -371,7 +350,8 @@ struct workqueue_struct *__create_workqueue(const char *name, } wq->name = name; - mutex_lock(&workqueue_mutex); + /* We don't need the distraction of CPUs appearing and vanishing. */ + lock_cpu_hotplug(); if (singlethread) { INIT_LIST_HEAD(&wq->list); p = create_workqueue_thread(wq, singlethread_cpu); @@ -380,7 +360,9 @@ struct workqueue_struct *__create_workqueue(const char *name, else wake_up_process(p); } else { + spin_lock(&workqueue_lock); list_add(&wq->list, &workqueues); + spin_unlock(&workqueue_lock); for_each_online_cpu(cpu) { p = create_workqueue_thread(wq, cpu); if (p) { @@ -390,7 +372,7 @@ struct workqueue_struct *__create_workqueue(const char *name, destroy = 1; } } - mutex_unlock(&workqueue_mutex); + unlock_cpu_hotplug(); /* * Was there any error during startup? If yes then clean up: @@ -418,12 +400,6 @@ static void cleanup_workqueue_thread(struct workqueue_struct *wq, int cpu) kthread_stop(p); } -/** - * destroy_workqueue - safely terminate a workqueue - * @wq: target workqueue - * - * Safely destroy a workqueue. All work currently pending will be done first. - */ void destroy_workqueue(struct workqueue_struct *wq) { int cpu; @@ -431,15 +407,17 @@ void destroy_workqueue(struct workqueue_struct *wq) flush_workqueue(wq); /* We don't need the distraction of CPUs appearing and vanishing. */ - mutex_lock(&workqueue_mutex); + lock_cpu_hotplug(); if (is_single_threaded(wq)) cleanup_workqueue_thread(wq, singlethread_cpu); else { for_each_online_cpu(cpu) cleanup_workqueue_thread(wq, cpu); + spin_lock(&workqueue_lock); list_del(&wq->list); + spin_unlock(&workqueue_lock); } - mutex_unlock(&workqueue_mutex); + unlock_cpu_hotplug(); free_percpu(wq->cpu_wq); kfree(wq); } @@ -447,41 +425,18 @@ EXPORT_SYMBOL_GPL(destroy_workqueue); static struct workqueue_struct *keventd_wq; -/** - * schedule_work - put work task in global workqueue - * @work: job to be done - * - * This puts a job in the kernel-global workqueue. - */ int fastcall schedule_work(struct work_struct *work) { return queue_work(keventd_wq, work); } EXPORT_SYMBOL(schedule_work); -/** - * schedule_delayed_work - put work task in global workqueue after delay - * @work: job to be done - * @delay: number of jiffies to wait - * - * After waiting for a given time this puts a job in the kernel-global - * workqueue. - */ int fastcall schedule_delayed_work(struct work_struct *work, unsigned long delay) { return queue_delayed_work(keventd_wq, work, delay); } EXPORT_SYMBOL(schedule_delayed_work); -/** - * schedule_delayed_work_on - queue work in global workqueue on CPU after delay - * @cpu: cpu to use - * @work: job to be done - * @delay: number of jiffies to wait - * - * After waiting for a given time this puts a job in the kernel-global - * workqueue on the specified CPU. - */ int schedule_delayed_work_on(int cpu, struct work_struct *work, unsigned long delay) { @@ -510,13 +465,11 @@ int schedule_on_each_cpu(void (*func)(void *info), void *info) if (!works) return -ENOMEM; - mutex_lock(&workqueue_mutex); for_each_online_cpu(cpu) { INIT_WORK(per_cpu_ptr(works, cpu), func, info); __queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu), per_cpu_ptr(works, cpu)); } - mutex_unlock(&workqueue_mutex); flush_workqueue(keventd_wq); free_percpu(works); return 0; @@ -632,7 +585,6 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: - mutex_lock(&workqueue_mutex); /* Create a new workqueue thread for it. */ list_for_each_entry(wq, &workqueues, list) { if (!create_workqueue_thread(wq, hotcpu)) { @@ -651,7 +603,6 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, kthread_bind(cwq->thread, hotcpu); wake_up_process(cwq->thread); } - mutex_unlock(&workqueue_mutex); break; case CPU_UP_CANCELED: @@ -663,15 +614,6 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, any_online_cpu(cpu_online_map)); cleanup_workqueue_thread(wq, hotcpu); } - mutex_unlock(&workqueue_mutex); - break; - - case CPU_DOWN_PREPARE: - mutex_lock(&workqueue_mutex); - break; - - case CPU_DOWN_FAILED: - mutex_unlock(&workqueue_mutex); break; case CPU_DEAD: @@ -679,7 +621,6 @@ static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, cleanup_workqueue_thread(wq, hotcpu); list_for_each_entry(wq, &workqueues, list) take_over_work(wq, hotcpu); - mutex_unlock(&workqueue_mutex); break; } diff --git a/trunk/lib/Kconfig b/trunk/lib/Kconfig index 734ce95a93d1..f6299342b882 100644 --- a/trunk/lib/Kconfig +++ b/trunk/lib/Kconfig @@ -38,11 +38,6 @@ config LIBCRC32C require M here. See Castagnoli93. Module will be libcrc32c. -config AUDIT_GENERIC - bool - depends on AUDIT && !AUDIT_ARCH - default y - # # compression support is select'ed if needed # diff --git a/trunk/lib/Makefile b/trunk/lib/Makefile index ef1d37afbbb6..be9719ae82d0 100644 --- a/trunk/lib/Makefile +++ b/trunk/lib/Makefile @@ -49,7 +49,6 @@ obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o obj-$(CONFIG_SMP) += percpu_counter.o -obj-$(CONFIG_AUDIT_GENERIC) += audit.o obj-$(CONFIG_SWIOTLB) += swiotlb.o diff --git a/trunk/lib/audit.c b/trunk/lib/audit.c deleted file mode 100644 index 3b1289fadf06..000000000000 --- a/trunk/lib/audit.c +++ /dev/null @@ -1,55 +0,0 @@ -#include -#include -#include -#include - -static unsigned dir_class[] = { -#include -~0U -}; - -static unsigned read_class[] = { -#include -~0U -}; - -static unsigned write_class[] = { -#include -~0U -}; - -static unsigned chattr_class[] = { -#include -~0U -}; - -int audit_classify_syscall(int abi, unsigned syscall) -{ - switch(syscall) { - case __NR_open: - return 2; -#ifdef __NR_openat - case __NR_openat: - return 3; -#endif -#ifdef __NR_socketcall - case __NR_socketcall: - return 4; -#endif - case __NR_execve: - return 5; - default: - return 0; - } -} - -static int __init audit_classes_init(void) -{ - audit_register_class(AUDIT_CLASS_WRITE, write_class); - audit_register_class(AUDIT_CLASS_READ, read_class); - audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); - audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); - return 0; -} - -__initcall(audit_classes_init); diff --git a/trunk/lib/kobject_uevent.c b/trunk/lib/kobject_uevent.c index 7f20e7b857cb..2b1530fc573b 100644 --- a/trunk/lib/kobject_uevent.c +++ b/trunk/lib/kobject_uevent.c @@ -50,6 +50,10 @@ static char *action_to_string(enum kobject_action action) return "offline"; case KOBJ_ONLINE: return "online"; + case KOBJ_DOCK: + return "dock"; + case KOBJ_UNDOCK: + return "undock"; default: return NULL; } diff --git a/trunk/lib/spinlock_debug.c b/trunk/lib/spinlock_debug.c index 58c577dd82e5..3d9c4dc965ed 100644 --- a/trunk/lib/spinlock_debug.c +++ b/trunk/lib/spinlock_debug.c @@ -162,7 +162,6 @@ static void rwlock_bug(rwlock_t *lock, const char *msg) #define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg) -#if 0 /* __write_lock_debug() can lock up - maybe this can too? */ static void __read_lock_debug(rwlock_t *lock) { int print_once = 1; @@ -185,12 +184,12 @@ static void __read_lock_debug(rwlock_t *lock) } } } -#endif void _raw_read_lock(rwlock_t *lock) { RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic"); - __raw_read_lock(&lock->raw_lock); + if (unlikely(!__raw_read_trylock(&lock->raw_lock))) + __read_lock_debug(lock); } int _raw_read_trylock(rwlock_t *lock) @@ -236,7 +235,6 @@ static inline void debug_write_unlock(rwlock_t *lock) lock->owner_cpu = -1; } -#if 0 /* This can cause lockups */ static void __write_lock_debug(rwlock_t *lock) { int print_once = 1; @@ -259,12 +257,12 @@ static void __write_lock_debug(rwlock_t *lock) } } } -#endif void _raw_write_lock(rwlock_t *lock) { debug_write_lock_before(lock); - __raw_write_lock(&lock->raw_lock); + if (unlikely(!__raw_write_trylock(&lock->raw_lock))) + __write_lock_debug(lock); debug_write_lock_after(lock); } diff --git a/trunk/lib/ts_bm.c b/trunk/lib/ts_bm.c index d90822c378a4..0110e4414805 100644 --- a/trunk/lib/ts_bm.c +++ b/trunk/lib/ts_bm.c @@ -111,14 +111,15 @@ static int subpattern(u8 *pattern, int i, int j, int g) return ret; } -static void compute_prefix_tbl(struct ts_bm *bm) +static void compute_prefix_tbl(struct ts_bm *bm, const u8 *pattern, + unsigned int len) { int i, j, g; for (i = 0; i < ASIZE; i++) - bm->bad_shift[i] = bm->patlen; - for (i = 0; i < bm->patlen - 1; i++) - bm->bad_shift[bm->pattern[i]] = bm->patlen - 1 - i; + bm->bad_shift[i] = len; + for (i = 0; i < len - 1; i++) + bm->bad_shift[pattern[i]] = len - 1 - i; /* Compute the good shift array, used to match reocurrences * of a subpattern */ @@ -149,8 +150,8 @@ static struct ts_config *bm_init(const void *pattern, unsigned int len, bm = ts_config_priv(conf); bm->patlen = len; bm->pattern = (u8 *) bm->good_shift + prefix_tbl_len; + compute_prefix_tbl(bm, pattern, len); memcpy(bm->pattern, pattern, len); - compute_prefix_tbl(bm); return conf; } diff --git a/trunk/lib/zlib_inflate/inflate.c b/trunk/lib/zlib_inflate/inflate.c index fceb97c3aff7..7f922dccf1a5 100644 --- a/trunk/lib/zlib_inflate/inflate.c +++ b/trunk/lib/zlib_inflate/inflate.c @@ -347,10 +347,7 @@ int zlib_inflate(z_streamp strm, int flush) static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - /* Do not check for strm->next_out == NULL here as ppc zImage - inflates to strm->next_out = 0 */ - - if (strm == NULL || strm->state == NULL || + if (strm == NULL || strm->state == NULL || strm->next_out == NULL || (strm->next_in == NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; diff --git a/trunk/mm/fadvise.c b/trunk/mm/fadvise.c index 168c78a121bb..60a5d55e51d9 100644 --- a/trunk/mm/fadvise.c +++ b/trunk/mm/fadvise.c @@ -73,6 +73,7 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) file->f_ra.ra_pages = bdi->ra_pages * 2; break; case POSIX_FADV_WILLNEED: + case POSIX_FADV_NOREUSE: if (!mapping->a_ops->readpage) { ret = -EINVAL; break; @@ -93,8 +94,6 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) if (ret > 0) ret = 0; break; - case POSIX_FADV_NOREUSE: - break; case POSIX_FADV_DONTNEED: if (!bdi_write_congested(mapping->backing_dev_info)) filemap_flush(mapping); diff --git a/trunk/mm/filemap.c b/trunk/mm/filemap.c index b9a60c43b61a..d087fc3d3281 100644 --- a/trunk/mm/filemap.c +++ b/trunk/mm/filemap.c @@ -849,6 +849,8 @@ static void shrink_readahead_size_eio(struct file *filp, return; ra->ra_pages /= 4; + printk(KERN_WARNING "Reducing readahead size to %luK\n", + ra->ra_pages << (PAGE_CACHE_SHIFT - 10)); } /** diff --git a/trunk/mm/memory_hotplug.c b/trunk/mm/memory_hotplug.c index c37319542b70..01c9fb97c619 100644 --- a/trunk/mm/memory_hotplug.c +++ b/trunk/mm/memory_hotplug.c @@ -52,9 +52,6 @@ static int __add_section(struct zone *zone, unsigned long phys_start_pfn) int nr_pages = PAGES_PER_SECTION; int ret; - if (pfn_valid(phys_start_pfn)) - return -EEXIST; - ret = sparse_add_one_section(zone, phys_start_pfn, nr_pages); if (ret < 0) @@ -79,22 +76,15 @@ int __add_pages(struct zone *zone, unsigned long phys_start_pfn, { unsigned long i; int err = 0; - int start_sec, end_sec; - /* during initialize mem_map, align hot-added range to section */ - start_sec = pfn_to_section_nr(phys_start_pfn); - end_sec = pfn_to_section_nr(phys_start_pfn + nr_pages - 1); - for (i = start_sec; i <= end_sec; i++) { - err = __add_section(zone, i << PFN_SECTION_SHIFT); + for (i = 0; i < nr_pages; i += PAGES_PER_SECTION) { + err = __add_section(zone, phys_start_pfn + i); - /* - * EEXIST is finally dealed with by ioresource collision - * check. see add_memory() => register_memory_resource() - * Warning will be printed if there is collision. + /* We want to keep adding the rest of the + * sections if the first ones already exist */ if (err && (err != -EEXIST)) break; - err = 0; } return err; @@ -166,7 +156,7 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) res.flags = IORESOURCE_MEM; /* we just need system ram */ section_end = res.end; - while ((res.start < res.end) && (find_next_system_ram(&res) >= 0)) { + while (find_next_system_ram(&res) >= 0) { start_pfn = (unsigned long)(res.start >> PAGE_SHIFT); nr_pages = (unsigned long) ((res.end + 1 - res.start) >> PAGE_SHIFT); @@ -223,9 +213,10 @@ static void rollback_node_hotadd(int nid, pg_data_t *pgdat) } /* add this memory to iomem resource */ -static struct resource *register_memory_resource(u64 start, u64 size) +static void register_memory_resource(u64 start, u64 size) { struct resource *res; + res = kzalloc(sizeof(struct resource), GFP_KERNEL); BUG_ON(!res); @@ -237,18 +228,7 @@ static struct resource *register_memory_resource(u64 start, u64 size) printk("System RAM resource %llx - %llx cannot be added\n", (unsigned long long)res->start, (unsigned long long)res->end); kfree(res); - res = NULL; } - return res; -} - -static void release_memory_resource(struct resource *res) -{ - if (!res) - return; - release_resource(res); - kfree(res); - return; } @@ -257,13 +237,8 @@ int add_memory(int nid, u64 start, u64 size) { pg_data_t *pgdat = NULL; int new_pgdat = 0; - struct resource *res; int ret; - res = register_memory_resource(start, size); - if (!res) - return -EEXIST; - if (!node_online(nid)) { pgdat = hotadd_new_pgdat(nid, start); if (!pgdat) @@ -293,13 +268,14 @@ int add_memory(int nid, u64 start, u64 size) BUG_ON(ret); } + /* register this memory as resource */ + register_memory_resource(start, size); + return ret; error: /* rollback pgdat allocation and others */ if (new_pgdat) rollback_node_hotadd(nid, pgdat); - if (res) - release_memory_resource(res); return ret; } diff --git a/trunk/mm/mempolicy.c b/trunk/mm/mempolicy.c index a9963ceddd65..e07e27e846a2 100644 --- a/trunk/mm/mempolicy.c +++ b/trunk/mm/mempolicy.c @@ -1176,15 +1176,7 @@ static inline unsigned interleave_nid(struct mempolicy *pol, if (vma) { unsigned long off; - /* - * for small pages, there is no difference between - * shift and PAGE_SHIFT, so the bit-shift is safe. - * for huge pages, since vm_pgoff is in units of small - * pages, we need to shift off the always 0 bits to get - * a useful offset. - */ - BUG_ON(shift < PAGE_SHIFT); - off = vma->vm_pgoff >> (shift - PAGE_SHIFT); + off = vma->vm_pgoff; off += (addr - vma->vm_start) >> shift; return offset_il_node(pol, vma, off); } else diff --git a/trunk/mm/mempool.c b/trunk/mm/mempool.c index ccd8cb8cd41f..fe6e05289cc5 100644 --- a/trunk/mm/mempool.c +++ b/trunk/mm/mempool.c @@ -238,13 +238,8 @@ void * mempool_alloc(mempool_t *pool, gfp_t gfp_mask) init_wait(&wait); prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE); smp_mb(); - if (!pool->curr_nr) { - /* - * FIXME: this should be io_schedule(). The timeout is there - * as a workaround for some DM problems in 2.6.18. - */ - io_schedule_timeout(5*HZ); - } + if (!pool->curr_nr) + io_schedule(); finish_wait(&pool->wait, &wait); goto repeat_alloc; diff --git a/trunk/mm/mmap.c b/trunk/mm/mmap.c index d799d896d74a..c1868ecdbc5f 100644 --- a/trunk/mm/mmap.c +++ b/trunk/mm/mmap.c @@ -30,10 +30,6 @@ #include #include -#ifndef arch_mmap_check -#define arch_mmap_check(addr, len, flags) (0) -#endif - static void unmap_region(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev, unsigned long start, unsigned long end); @@ -64,13 +60,6 @@ pgprot_t protection_map[16] = { __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111 }; -pgprot_t vm_get_page_prot(unsigned long vm_flags) -{ - return protection_map[vm_flags & - (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]; -} -EXPORT_SYMBOL(vm_get_page_prot); - int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */ int sysctl_overcommit_ratio = 50; /* default is 50% */ int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT; @@ -924,10 +913,6 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, if (!len) return -EINVAL; - error = arch_mmap_check(addr, len, flags); - if (error) - return error; - /* Careful about overflows.. */ len = PAGE_ALIGN(len); if (!len || len > TASK_SIZE) @@ -1874,7 +1859,6 @@ unsigned long do_brk(unsigned long addr, unsigned long len) unsigned long flags; struct rb_node ** rb_link, * rb_parent; pgoff_t pgoff = addr >> PAGE_SHIFT; - int error; len = PAGE_ALIGN(len); if (!len) @@ -1883,12 +1867,6 @@ unsigned long do_brk(unsigned long addr, unsigned long len) if ((addr + len) > TASK_SIZE || (addr + len) < addr) return -EINVAL; - flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; - - error = arch_mmap_check(addr, len, flags); - if (error) - return error; - /* * mlock MCL_FUTURE? */ @@ -1929,6 +1907,8 @@ unsigned long do_brk(unsigned long addr, unsigned long len) if (security_vm_enough_memory(len >> PAGE_SHIFT)) return -ENOMEM; + flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; + /* Can we just expand an old private anonymous mapping? */ if (vma_merge(mm, prev, addr, addr + len, flags, NULL, NULL, pgoff, NULL)) diff --git a/trunk/mm/page-writeback.c b/trunk/mm/page-writeback.c index 77a0bc4e261a..e630188ccc40 100644 --- a/trunk/mm/page-writeback.c +++ b/trunk/mm/page-writeback.c @@ -802,15 +802,6 @@ int test_set_page_writeback(struct page *page) } EXPORT_SYMBOL(test_set_page_writeback); -/* - * Wakes up tasks that are being throttled due to writeback congestion - */ -void writeback_congestion_end(void) -{ - blk_congestion_end(WRITE); -} -EXPORT_SYMBOL(writeback_congestion_end); - /* * Return true if any of the pages in the mapping are marged with the * passed tag. diff --git a/trunk/mm/page_alloc.c b/trunk/mm/page_alloc.c index 3b5358a0561f..54a4f5375bba 100644 --- a/trunk/mm/page_alloc.c +++ b/trunk/mm/page_alloc.c @@ -2363,7 +2363,7 @@ int percpu_pagelist_fraction_sysctl_handler(ctl_table *table, int write, return 0; } -int hashdist = HASHDIST_DEFAULT; +__initdata int hashdist = HASHDIST_DEFAULT; #ifdef CONFIG_NUMA static int __init set_hashdist(char *str) diff --git a/trunk/mm/slab.c b/trunk/mm/slab.c index 21ba06035700..0f20843beffd 100644 --- a/trunk/mm/slab.c +++ b/trunk/mm/slab.c @@ -1106,7 +1106,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp) #endif -static int __cpuinit cpuup_callback(struct notifier_block *nfb, +static int __devinit cpuup_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -3224,7 +3224,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) EXPORT_SYMBOL(kmem_cache_alloc); /** - * kmem_cache_zalloc - Allocate an object. The memory is set to zero. + * kmem_cache_alloc - Allocate an object. The memory is set to zero. * @cache: The cache to allocate from. * @flags: See kmalloc(). * diff --git a/trunk/mm/swap.c b/trunk/mm/swap.c index 687686a61f7c..8fd095c4ae51 100644 --- a/trunk/mm/swap.c +++ b/trunk/mm/swap.c @@ -54,26 +54,6 @@ void put_page(struct page *page) } EXPORT_SYMBOL(put_page); -/** - * put_pages_list(): release a list of pages - * - * Release a list of pages which are strung together on page.lru. Currently - * used by read_cache_pages() and related error recovery code. - * - * @pages: list of pages threaded on page->lru - */ -void put_pages_list(struct list_head *pages) -{ - while (!list_empty(pages)) { - struct page *victim; - - victim = list_entry(pages->prev, struct page, lru); - list_del(&victim->lru); - page_cache_release(victim); - } -} -EXPORT_SYMBOL(put_pages_list); - /* * Writeback is about to end against a page which has been marked for immediate * reclaim. If it still appears to be reclaimable, move it to the tail of the diff --git a/trunk/mm/swapfile.c b/trunk/mm/swapfile.c index f1f5ec783781..e70d6c6d6fee 100644 --- a/trunk/mm/swapfile.c +++ b/trunk/mm/swapfile.c @@ -442,12 +442,11 @@ int swap_type_of(dev_t device) if (!(swap_info[i].flags & SWP_WRITEOK)) continue; - if (!device) { spin_unlock(&swap_lock); return i; } - inode = swap_info[i].swap_file->f_dentry->d_inode; + inode = swap_info->swap_file->f_dentry->d_inode; if (S_ISBLK(inode->i_mode) && device == MKDEV(imajor(inode), iminor(inode))) { spin_unlock(&swap_lock); diff --git a/trunk/mm/truncate.c b/trunk/mm/truncate.c index c6ab55ec6883..cf1b015df4a7 100644 --- a/trunk/mm/truncate.c +++ b/trunk/mm/truncate.c @@ -68,10 +68,10 @@ invalidate_complete_page(struct address_space *mapping, struct page *page) return 0; write_lock_irq(&mapping->tree_lock); - if (PageDirty(page)) - goto failed; - if (page_count(page) != 2) /* caller's ref + pagecache ref */ - goto failed; + if (PageDirty(page)) { + write_unlock_irq(&mapping->tree_lock); + return 0; + } BUG_ON(PagePrivate(page)); __remove_from_page_cache(page); @@ -79,9 +79,6 @@ invalidate_complete_page(struct address_space *mapping, struct page *page) ClearPageUptodate(page); page_cache_release(page); /* pagecache ref */ return 1; -failed: - write_unlock_irq(&mapping->tree_lock); - return 0; } /** diff --git a/trunk/mm/vmstat.c b/trunk/mm/vmstat.c index c1b5f4106b38..dfdf24133901 100644 --- a/trunk/mm/vmstat.c +++ b/trunk/mm/vmstat.c @@ -12,7 +12,6 @@ #include #include #include -#include void __get_zone_counts(unsigned long *active, unsigned long *inactive, unsigned long *free, struct pglist_data *pgdat) @@ -115,72 +114,17 @@ EXPORT_SYMBOL(vm_stat); #ifdef CONFIG_SMP -static int calculate_threshold(struct zone *zone) -{ - int threshold; - int mem; /* memory in 128 MB units */ - - /* - * The threshold scales with the number of processors and the amount - * of memory per zone. More memory means that we can defer updates for - * longer, more processors could lead to more contention. - * fls() is used to have a cheap way of logarithmic scaling. - * - * Some sample thresholds: - * - * Threshold Processors (fls) Zonesize fls(mem+1) - * ------------------------------------------------------------------ - * 8 1 1 0.9-1 GB 4 - * 16 2 2 0.9-1 GB 4 - * 20 2 2 1-2 GB 5 - * 24 2 2 2-4 GB 6 - * 28 2 2 4-8 GB 7 - * 32 2 2 8-16 GB 8 - * 4 2 2 <128M 1 - * 30 4 3 2-4 GB 5 - * 48 4 3 8-16 GB 8 - * 32 8 4 1-2 GB 4 - * 32 8 4 0.9-1GB 4 - * 10 16 5 <128M 1 - * 40 16 5 900M 4 - * 70 64 7 2-4 GB 5 - * 84 64 7 4-8 GB 6 - * 108 512 9 4-8 GB 6 - * 125 1024 10 8-16 GB 8 - * 125 1024 10 16-32 GB 9 - */ - - mem = zone->present_pages >> (27 - PAGE_SHIFT); - - threshold = 2 * fls(num_online_cpus()) * (1 + fls(mem)); - - /* - * Maximum threshold is 125 - */ - threshold = min(125, threshold); - - return threshold; -} +#define STAT_THRESHOLD 32 /* - * Refresh the thresholds for each zone. + * Determine pointer to currently valid differential byte given a zone and + * the item number. + * + * Preemption must be off */ -static void refresh_zone_stat_thresholds(void) +static inline s8 *diff_pointer(struct zone *zone, enum zone_stat_item item) { - struct zone *zone; - int cpu; - int threshold; - - for_each_zone(zone) { - - if (!zone->present_pages) - continue; - - threshold = calculate_threshold(zone); - - for_each_online_cpu(cpu) - zone_pcp(zone, cpu)->stat_threshold = threshold; - } + return &zone_pcp(zone, smp_processor_id())->vm_stat_diff[item]; } /* @@ -189,16 +133,17 @@ static void refresh_zone_stat_thresholds(void) void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item, int delta) { - struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); - s8 *p = pcp->vm_stat_diff + item; + s8 *p; long x; + p = diff_pointer(zone, item); x = delta + *p; - if (unlikely(x > pcp->stat_threshold || x < -pcp->stat_threshold)) { + if (unlikely(x > STAT_THRESHOLD || x < -STAT_THRESHOLD)) { zone_page_state_add(x, zone, item); x = 0; } + *p = x; } EXPORT_SYMBOL(__mod_zone_page_state); @@ -227,12 +172,10 @@ EXPORT_SYMBOL(mod_zone_page_state); * No overflow check is necessary and therefore the differential can be * incremented or decremented in place which may allow the compilers to * generate better code. + * * The increment or decrement is known and therefore one boundary check can * be omitted. * - * NOTE: These functions are very performance sensitive. Change only - * with care. - * * Some processors have inc/dec instructions that are atomic vs an interrupt. * However, the code must first determine the differential location in a zone * based on the processor number and then inc/dec the counter. There is no @@ -242,16 +185,13 @@ EXPORT_SYMBOL(mod_zone_page_state); */ static void __inc_zone_state(struct zone *zone, enum zone_stat_item item) { - struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); - s8 *p = pcp->vm_stat_diff + item; + s8 *p = diff_pointer(zone, item); (*p)++; - if (unlikely(*p > pcp->stat_threshold)) { - int overstep = pcp->stat_threshold / 2; - - zone_page_state_add(*p + overstep, zone, item); - *p = -overstep; + if (unlikely(*p > STAT_THRESHOLD)) { + zone_page_state_add(*p, zone, item); + *p = 0; } } @@ -264,16 +204,13 @@ EXPORT_SYMBOL(__inc_zone_page_state); void __dec_zone_page_state(struct page *page, enum zone_stat_item item) { struct zone *zone = page_zone(page); - struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); - s8 *p = pcp->vm_stat_diff + item; + s8 *p = diff_pointer(zone, item); (*p)--; - if (unlikely(*p < - pcp->stat_threshold)) { - int overstep = pcp->stat_threshold / 2; - - zone_page_state_add(*p - overstep, zone, item); - *p = overstep; + if (unlikely(*p < -STAT_THRESHOLD)) { + zone_page_state_add(*p, zone, item); + *p = 0; } } EXPORT_SYMBOL(__dec_zone_page_state); @@ -302,9 +239,19 @@ EXPORT_SYMBOL(inc_zone_page_state); void dec_zone_page_state(struct page *page, enum zone_stat_item item) { unsigned long flags; + struct zone *zone; + s8 *p; + zone = page_zone(page); local_irq_save(flags); - __dec_zone_page_state(page, item); + p = diff_pointer(zone, item); + + (*p)--; + + if (unlikely(*p < -STAT_THRESHOLD)) { + zone_page_state_add(*p, zone, item); + *p = 0; + } local_irq_restore(flags); } EXPORT_SYMBOL(dec_zone_page_state); @@ -578,10 +525,6 @@ static int zoneinfo_show(struct seq_file *m, void *arg) pageset->pcp[j].high, pageset->pcp[j].batch); } -#ifdef CONFIG_SMP - seq_printf(m, "\n vm stats threshold: %d", - pageset->stat_threshold); -#endif } seq_printf(m, "\n all_unreclaimable: %u" @@ -670,35 +613,3 @@ struct seq_operations vmstat_op = { #endif /* CONFIG_PROC_FS */ -#ifdef CONFIG_SMP -/* - * Use the cpu notifier to insure that the thresholds are recalculated - * when necessary. - */ -static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb, - unsigned long action, - void *hcpu) -{ - switch (action) { - case CPU_UP_PREPARE: - case CPU_UP_CANCELED: - case CPU_DEAD: - refresh_zone_stat_thresholds(); - break; - default: - break; - } - return NOTIFY_OK; -} - -static struct notifier_block __cpuinitdata vmstat_notifier = - { &vmstat_cpuup_callback, NULL, 0 }; - -int __init setup_vmstat(void) -{ - refresh_zone_stat_thresholds(); - register_cpu_notifier(&vmstat_notifier); - return 0; -} -module_init(setup_vmstat) -#endif diff --git a/trunk/net/Kconfig b/trunk/net/Kconfig index 6528a935622c..c6cec5aa5486 100644 --- a/trunk/net/Kconfig +++ b/trunk/net/Kconfig @@ -177,7 +177,7 @@ source "net/lapb/Kconfig" config NET_DIVERT bool "Frame Diverter (EXPERIMENTAL)" - depends on EXPERIMENTAL && BROKEN + depends on EXPERIMENTAL ---help--- The Frame Diverter allows you to divert packets from the network, that are not aimed at the interface receiving it (in @@ -249,11 +249,6 @@ source "net/ieee80211/Kconfig" config WIRELESS_EXT bool -source "net/netlabel/Kconfig" - -config FIB_RULES - bool - endif # if NET endmenu # Networking diff --git a/trunk/net/Makefile b/trunk/net/Makefile index ad4d14f4bb29..065796f5fb17 100644 --- a/trunk/net/Makefile +++ b/trunk/net/Makefile @@ -46,7 +46,6 @@ obj-$(CONFIG_IP_DCCP) += dccp/ obj-$(CONFIG_IP_SCTP) += sctp/ obj-$(CONFIG_IEEE80211) += ieee80211/ obj-$(CONFIG_TIPC) += tipc/ -obj-$(CONFIG_NETLABEL) += netlabel/ ifeq ($(CONFIG_NET),y) obj-$(CONFIG_SYSCTL) += sysctl_net.o diff --git a/trunk/net/atm/atm_sysfs.c b/trunk/net/atm/atm_sysfs.c index c0a4ae28fcfa..5df4b9a068bb 100644 --- a/trunk/net/atm/atm_sysfs.c +++ b/trunk/net/atm/atm_sysfs.c @@ -1,5 +1,6 @@ /* ATM driver model support. */ +#include #include #include #include diff --git a/trunk/net/atm/clip.c b/trunk/net/atm/clip.c index 7af2c411da82..7ce7bfe3fbad 100644 --- a/trunk/net/atm/clip.c +++ b/trunk/net/atm/clip.c @@ -500,11 +500,9 @@ static int clip_mkip(struct atm_vcc *vcc, int timeout) } else { unsigned int len = skb->len; - skb_get(skb); clip_push(vcc, skb); PRIV(skb->dev)->stats.rx_packets--; PRIV(skb->dev)->stats.rx_bytes -= len; - kfree_skb(skb); } return 0; } diff --git a/trunk/net/atm/mpc.c b/trunk/net/atm/mpc.c index b87c2a88bdce..00704661e83f 100644 --- a/trunk/net/atm/mpc.c +++ b/trunk/net/atm/mpc.c @@ -98,6 +98,11 @@ static struct notifier_block mpoa_notifier = { 0 }; +#ifdef CONFIG_PROC_FS +extern int mpc_proc_init(void); +extern void mpc_proc_clean(void); +#endif + struct mpoa_client *mpcs = NULL; /* FIXME */ static struct atm_mpoa_qos *qos_head = NULL; static DEFINE_TIMER(mpc_timer, NULL, 0, 0); @@ -1434,8 +1439,12 @@ static __init int atm_mpoa_init(void) { register_atm_ioctl(&atm_ioctl_ops); +#ifdef CONFIG_PROC_FS if (mpc_proc_init() != 0) printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n"); + else + printk(KERN_INFO "mpoa: /proc/mpoa initialized\n"); +#endif printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n"); @@ -1448,7 +1457,9 @@ static void __exit atm_mpoa_cleanup(void) struct atm_mpoa_qos *qos, *nextqos; struct lec_priv *priv; +#ifdef CONFIG_PROC_FS mpc_proc_clean(); +#endif del_timer(&mpc_timer); unregister_netdevice_notifier(&mpoa_notifier); diff --git a/trunk/net/atm/mpc.h b/trunk/net/atm/mpc.h index 3c7981a229e8..863ddf6079e1 100644 --- a/trunk/net/atm/mpc.h +++ b/trunk/net/atm/mpc.h @@ -50,12 +50,4 @@ int atm_mpoa_delete_qos(struct atm_mpoa_qos *qos); struct seq_file; void atm_mpoa_disp_qos(struct seq_file *m); -#ifdef CONFIG_PROC_FS -int mpc_proc_init(void); -void mpc_proc_clean(void); -#else -#define mpc_proc_init() (0) -#define mpc_proc_clean() do { } while(0) -#endif - #endif /* _MPC_H_ */ diff --git a/trunk/net/atm/proc.c b/trunk/net/atm/proc.c index 91fe5f53ff11..3f95b0886a6a 100644 --- a/trunk/net/atm/proc.c +++ b/trunk/net/atm/proc.c @@ -507,7 +507,7 @@ int __init atm_proc_init(void) goto out; } -void atm_proc_exit(void) +void __exit atm_proc_exit(void) { atm_proc_dirs_remove(); } diff --git a/trunk/net/bridge/br_forward.c b/trunk/net/bridge/br_forward.c index 191b861e5e53..6ccd32b30809 100644 --- a/trunk/net/bridge/br_forward.c +++ b/trunk/net/bridge/br_forward.c @@ -38,14 +38,13 @@ int br_dev_queue_push_xmit(struct sk_buff *skb) if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) kfree_skb(skb); else { +#ifdef CONFIG_BRIDGE_NETFILTER /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */ - if (nf_bridge_maybe_copy_header(skb)) - kfree_skb(skb); - else { - skb_push(skb, ETH_HLEN); + nf_bridge_maybe_copy_header(skb); +#endif + skb_push(skb, ETH_HLEN); - dev_queue_xmit(skb); - } + dev_queue_xmit(skb); } return 0; diff --git a/trunk/net/bridge/br_if.c b/trunk/net/bridge/br_if.c index b1211d5342f6..f55ef682ef84 100644 --- a/trunk/net/bridge/br_if.c +++ b/trunk/net/bridge/br_if.c @@ -386,17 +386,12 @@ void br_features_recompute(struct net_bridge *br) checksum = 0; if (feature & NETIF_F_GSO) - feature |= NETIF_F_GSO_SOFTWARE; + feature |= NETIF_F_TSO; feature |= NETIF_F_GSO; features &= feature; } - if (!(checksum & NETIF_F_ALL_CSUM)) - features &= ~NETIF_F_SG; - if (!(features & NETIF_F_SG)) - features &= ~NETIF_F_GSO_MASK; - br->dev->features = features | checksum | NETIF_F_LLTX | NETIF_F_GSO_ROBUST; } diff --git a/trunk/net/bridge/br_netfilter.c b/trunk/net/bridge/br_netfilter.c index ac181be13d83..05b3de888243 100644 --- a/trunk/net/bridge/br_netfilter.c +++ b/trunk/net/bridge/br_netfilter.c @@ -53,10 +53,10 @@ #ifdef CONFIG_SYSCTL static struct ctl_table_header *brnf_sysctl_header; -static int brnf_call_iptables __read_mostly = 1; -static int brnf_call_ip6tables __read_mostly = 1; -static int brnf_call_arptables __read_mostly = 1; -static int brnf_filter_vlan_tagged __read_mostly = 1; +static int brnf_call_iptables = 1; +static int brnf_call_ip6tables = 1; +static int brnf_call_arptables = 1; +static int brnf_filter_vlan_tagged = 1; #else #define brnf_filter_vlan_tagged 1 #endif @@ -127,37 +127,14 @@ static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb) static inline void nf_bridge_save_header(struct sk_buff *skb) { - int header_size = ETH_HLEN; + int header_size = 16; if (skb->protocol == htons(ETH_P_8021Q)) - header_size += VLAN_HLEN; + header_size = 18; memcpy(skb->nf_bridge->data, skb->data - header_size, header_size); } -/* - * When forwarding bridge frames, we save a copy of the original - * header before processing. - */ -int nf_bridge_copy_header(struct sk_buff *skb) -{ - int err; - int header_size = ETH_HLEN; - - if (skb->protocol == htons(ETH_P_8021Q)) - header_size += VLAN_HLEN; - - err = skb_cow(skb, header_size); - if (err) - return err; - - memcpy(skb->data - header_size, skb->nf_bridge->data, header_size); - - if (skb->protocol == htons(ETH_P_8021Q)) - __skb_push(skb, VLAN_HLEN); - return 0; -} - /* PF_BRIDGE/PRE_ROUTING *********************************************/ /* Undo the changes made for ip6tables PREROUTING and continue the * bridge PRE_ROUTING hook. */ @@ -718,6 +695,16 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, else pf = PF_INET6; +#ifdef CONFIG_NETFILTER_DEBUG + /* Sometimes we get packets with NULL ->dst here (for example, + * running a dhcp client daemon triggers this). This should now + * be fixed, but let's keep the check around. */ + if (skb->dst == NULL) { + printk(KERN_CRIT "br_netfilter: skb->dst == NULL."); + return NF_ACCEPT; + } +#endif + nf_bridge = skb->nf_bridge; nf_bridge->physoutdev = skb->dev; realindev = nf_bridge->physindev; @@ -799,7 +786,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, * keep the check just to be sure... */ if (skb->mac.raw < skb->head || skb->mac.raw + ETH_HLEN > skb->data) { printk(KERN_CRIT "br_netfilter: Argh!! br_nf_post_routing: " - "bad mac.raw pointer.\n"); + "bad mac.raw pointer."); goto print_error; } #endif @@ -817,7 +804,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, #ifdef CONFIG_NETFILTER_DEBUG if (skb->dst == NULL) { - printk(KERN_INFO "br_netfilter post_routing: skb->dst == NULL\n"); + printk(KERN_CRIT "br_netfilter: skb->dst == NULL."); goto print_error; } #endif @@ -854,7 +841,6 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, } printk(" head:%p, raw:%p, data:%p\n", skb->head, skb->mac.raw, skb->data); - dump_stack(); return NF_ACCEPT; #endif } diff --git a/trunk/net/bridge/br_netlink.c b/trunk/net/bridge/br_netlink.c index 8f661195d09d..06abb6634f5b 100644 --- a/trunk/net/bridge/br_netlink.c +++ b/trunk/net/bridge/br_netlink.c @@ -12,7 +12,6 @@ #include #include -#include #include "br_private.h" /* @@ -77,24 +76,26 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por void br_ifinfo_notify(int event, struct net_bridge_port *port) { struct sk_buff *skb; - int payload = sizeof(struct ifinfomsg) + 128; - int err = -ENOBUFS; + int err = -ENOMEM; pr_debug("bridge notify event=%d\n", event); - skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC); - if (skb == NULL) - goto errout; - - err = br_fill_ifinfo(skb, port, 0, 0, event, 0); - if (err < 0) { - kfree_skb(skb); - goto errout; - } - - err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); -errout: - if (err < 0) - rtnl_set_sk_err(RTNLGRP_LINK, err); + skb = alloc_skb(NLMSG_SPACE(sizeof(struct ifinfomsg) + 128), + GFP_ATOMIC); + if (!skb) + goto err_out; + + err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0); + if (err) + goto err_kfree; + + NETLINK_CB(skb).dst_group = RTNLGRP_LINK; + netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); + return; + +err_kfree: + kfree_skb(skb); +err_out: + netlink_set_err(rtnl, 0, RTNLGRP_LINK, err); } /* diff --git a/trunk/net/bridge/br_stp_bpdu.c b/trunk/net/bridge/br_stp_bpdu.c index 068d8afbf0a7..a7ba0cce0b46 100644 --- a/trunk/net/bridge/br_stp_bpdu.c +++ b/trunk/net/bridge/br_stp_bpdu.c @@ -121,7 +121,7 @@ void br_send_tcn_bpdu(struct net_bridge_port *p) buf[1] = 0; buf[2] = 0; buf[3] = BPDU_TYPE_TCN; - br_send_bpdu(p, buf, 4); + br_send_bpdu(p, buf, 7); } /* diff --git a/trunk/net/bridge/netfilter/ebt_ulog.c b/trunk/net/bridge/netfilter/ebt_ulog.c index 9f950db3b76f..02693a230dc1 100644 --- a/trunk/net/bridge/netfilter/ebt_ulog.c +++ b/trunk/net/bridge/netfilter/ebt_ulog.c @@ -74,9 +74,6 @@ static void ulog_send(unsigned int nlgroup) if (timer_pending(&ub->timer)) del_timer(&ub->timer); - if (!ub->skb) - return; - /* last nlmsg needs NLMSG_DONE */ if (ub->qlen > 1) ub->lastnlh->nlmsg_type = NLMSG_DONE; diff --git a/trunk/net/bridge/netfilter/ebtables.c b/trunk/net/bridge/netfilter/ebtables.c index 3df55b2bd91d..3a13ed643459 100644 --- a/trunk/net/bridge/netfilter/ebtables.c +++ b/trunk/net/bridge/netfilter/ebtables.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -32,9 +31,36 @@ /* needed for logical [in,out]-dev filtering */ #include "../br_private.h" +/* list_named_find */ +#define ASSERT_READ_LOCK(x) +#define ASSERT_WRITE_LOCK(x) +#include +#include + +#if 0 +/* use this for remote debugging + * Copyright (C) 1998 by Ori Pomerantz + * Print the string to the appropriate tty, the one + * the current task uses + */ +static void print_string(char *str) +{ + struct tty_struct *my_tty; + + /* The tty for the current task */ + my_tty = current->signal->tty; + if (my_tty != NULL) { + my_tty->driver->write(my_tty, 0, str, strlen(str)); + my_tty->driver->write(my_tty, 0, "\015\012", 2); + } +} + +#define BUGPRINT(args) print_string(args); +#else #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\ "report to author: "format, ## args) /* #define BUGPRINT(format, args...) */ +#endif #define MEMPRINT(format, args...) printk("kernel msg: ebtables "\ ": out of memory: "format, ## args) /* #define MEMPRINT(format, args...) */ @@ -273,22 +299,18 @@ static inline void * find_inlist_lock_noload(struct list_head *head, const char *name, int *error, struct mutex *mutex) { - struct { - struct list_head list; - char name[EBT_FUNCTION_MAXNAMELEN]; - } *e; + void *ret; *error = mutex_lock_interruptible(mutex); if (*error != 0) return NULL; - list_for_each_entry(e, head, list) { - if (strcmp(e->name, name) == 0) - return e; + ret = list_named_find(head, name); + if (!ret) { + *error = -ENOENT; + mutex_unlock(mutex); } - *error = -ENOENT; - mutex_unlock(mutex); - return NULL; + return ret; } #ifndef CONFIG_KMOD @@ -1042,19 +1064,15 @@ static int do_replace(void __user *user, unsigned int len) int ebt_register_target(struct ebt_target *target) { - struct ebt_target *t; int ret; ret = mutex_lock_interruptible(&ebt_mutex); if (ret != 0) return ret; - list_for_each_entry(t, &ebt_targets, list) { - if (strcmp(t->name, target->name) == 0) { - mutex_unlock(&ebt_mutex); - return -EEXIST; - } + if (!list_named_insert(&ebt_targets, target)) { + mutex_unlock(&ebt_mutex); + return -EEXIST; } - list_add(&target->list, &ebt_targets); mutex_unlock(&ebt_mutex); return 0; @@ -1063,25 +1081,21 @@ int ebt_register_target(struct ebt_target *target) void ebt_unregister_target(struct ebt_target *target) { mutex_lock(&ebt_mutex); - list_del(&target->list); + LIST_DELETE(&ebt_targets, target); mutex_unlock(&ebt_mutex); } int ebt_register_match(struct ebt_match *match) { - struct ebt_match *m; int ret; ret = mutex_lock_interruptible(&ebt_mutex); if (ret != 0) return ret; - list_for_each_entry(m, &ebt_matches, list) { - if (strcmp(m->name, match->name) == 0) { - mutex_unlock(&ebt_mutex); - return -EEXIST; - } + if (!list_named_insert(&ebt_matches, match)) { + mutex_unlock(&ebt_mutex); + return -EEXIST; } - list_add(&match->list, &ebt_matches); mutex_unlock(&ebt_mutex); return 0; @@ -1090,25 +1104,21 @@ int ebt_register_match(struct ebt_match *match) void ebt_unregister_match(struct ebt_match *match) { mutex_lock(&ebt_mutex); - list_del(&match->list); + LIST_DELETE(&ebt_matches, match); mutex_unlock(&ebt_mutex); } int ebt_register_watcher(struct ebt_watcher *watcher) { - struct ebt_watcher *w; int ret; ret = mutex_lock_interruptible(&ebt_mutex); if (ret != 0) return ret; - list_for_each_entry(w, &ebt_watchers, list) { - if (strcmp(w->name, watcher->name) == 0) { - mutex_unlock(&ebt_mutex); - return -EEXIST; - } + if (!list_named_insert(&ebt_watchers, watcher)) { + mutex_unlock(&ebt_mutex); + return -EEXIST; } - list_add(&watcher->list, &ebt_watchers); mutex_unlock(&ebt_mutex); return 0; @@ -1117,14 +1127,13 @@ int ebt_register_watcher(struct ebt_watcher *watcher) void ebt_unregister_watcher(struct ebt_watcher *watcher) { mutex_lock(&ebt_mutex); - list_del(&watcher->list); + LIST_DELETE(&ebt_watchers, watcher); mutex_unlock(&ebt_mutex); } int ebt_register_table(struct ebt_table *table) { struct ebt_table_info *newinfo; - struct ebt_table *t; int ret, i, countersize; if (!table || !table->table ||!table->table->entries || @@ -1170,12 +1179,10 @@ int ebt_register_table(struct ebt_table *table) if (ret != 0) goto free_chainstack; - list_for_each_entry(t, &ebt_tables, list) { - if (strcmp(t->name, table->name) == 0) { - ret = -EEXIST; - BUGPRINT("Table name already exists\n"); - goto free_unlock; - } + if (list_named_find(&ebt_tables, table->name)) { + ret = -EEXIST; + BUGPRINT("Table name already exists\n"); + goto free_unlock; } /* Hold a reference count if the chains aren't empty */ @@ -1183,7 +1190,7 @@ int ebt_register_table(struct ebt_table *table) ret = -ENOENT; goto free_unlock; } - list_add(&table->list, &ebt_tables); + list_prepend(&ebt_tables, table); mutex_unlock(&ebt_mutex); return 0; free_unlock: @@ -1209,7 +1216,7 @@ void ebt_unregister_table(struct ebt_table *table) return; } mutex_lock(&ebt_mutex); - list_del(&table->list); + LIST_DELETE(&ebt_tables, table); mutex_unlock(&ebt_mutex); vfree(table->private->entries); if (table->private->chainstack) { @@ -1479,7 +1486,7 @@ static int __init ebtables_init(void) int ret; mutex_lock(&ebt_mutex); - list_add(&ebt_standard_target.list, &ebt_targets); + list_named_insert(&ebt_targets, &ebt_standard_target); mutex_unlock(&ebt_mutex); if ((ret = nf_register_sockopt(&ebt_sockopts)) < 0) return ret; diff --git a/trunk/net/core/Makefile b/trunk/net/core/Makefile index 119568077dab..e9bd2467d5a9 100644 --- a/trunk/net/core/Makefile +++ b/trunk/net/core/Makefile @@ -7,7 +7,7 @@ obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \ obj-$(CONFIG_SYSCTL) += sysctl_net_core.o -obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \ +obj-y += dev.o ethtool.o dev_mcast.o dst.o \ neighbour.o rtnetlink.o utils.o link_watch.o filter.o obj-$(CONFIG_XFRM) += flow.o @@ -17,4 +17,3 @@ obj-$(CONFIG_NET_PKTGEN) += pktgen.o obj-$(CONFIG_WIRELESS_EXT) += wireless.o obj-$(CONFIG_NETPOLL) += netpoll.o obj-$(CONFIG_NET_DMA) += user_dma.o -obj-$(CONFIG_FIB_RULES) += fib_rules.o diff --git a/trunk/net/core/datagram.c b/trunk/net/core/datagram.c index f558c61aecc7..aecddcc30401 100644 --- a/trunk/net/core/datagram.c +++ b/trunk/net/core/datagram.c @@ -417,7 +417,7 @@ unsigned int __skb_checksum_complete(struct sk_buff *skb) sum = (u16)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum)); if (likely(!sum)) { - if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) + if (unlikely(skb->ip_summed == CHECKSUM_HW)) netdev_rx_csum_fault(skb->dev); skb->ip_summed = CHECKSUM_UNNECESSARY; } @@ -462,7 +462,7 @@ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, goto fault; if ((unsigned short)csum_fold(csum)) goto csum_error; - if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) + if (unlikely(skb->ip_summed == CHECKSUM_HW)) netdev_rx_csum_fault(skb->dev); iov->iov_len -= chunk; iov->iov_base += chunk; diff --git a/trunk/net/core/dev.c b/trunk/net/core/dev.c index 14de297d024d..4d2b5167d7f5 100644 --- a/trunk/net/core/dev.c +++ b/trunk/net/core/dev.c @@ -116,7 +116,6 @@ #include #include #include -#include /* * The list of packet types we will receive (as opposed to discard) @@ -633,24 +632,14 @@ struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mas * @name: name string * * Network device names need to be valid file names to - * to allow sysfs to work. We also disallow any kind of - * whitespace. + * to allow sysfs to work */ int dev_valid_name(const char *name) { - if (*name == '\0') - return 0; - if (strlen(name) >= IFNAMSIZ) - return 0; - if (!strcmp(name, ".") || !strcmp(name, "..")) - return 0; - - while (*name) { - if (*name == '/' || isspace(*name)) - return 0; - name++; - } - return 1; + return !(*name == '\0' + || !strcmp(name, ".") + || !strcmp(name, "..") + || strchr(name, '/')); } /** @@ -1168,15 +1157,20 @@ EXPORT_SYMBOL(netif_device_attach); * Invalidate hardware checksum when packet is to be mangled, and * complete checksum manually on outgoing path. */ -int skb_checksum_help(struct sk_buff *skb) +int skb_checksum_help(struct sk_buff *skb, int inward) { unsigned int csum; int ret = 0, offset = skb->h.raw - skb->data; - if (skb->ip_summed == CHECKSUM_COMPLETE) + if (inward) goto out_set_summed; if (unlikely(skb_shinfo(skb)->gso_size)) { + static int warned; + + WARN_ON(!warned); + warned = 1; + /* Let GSO fix up the checksum. */ goto out_set_summed; } @@ -1225,7 +1219,12 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) skb->mac_len = skb->nh.raw - skb->data; __skb_pull(skb, skb->mac_len); - if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) { + if (unlikely(skb->ip_summed != CHECKSUM_HW)) { + static int warned; + + WARN_ON(!warned); + warned = 1; + if (skb_header_cloned(skb) && (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) return ERR_PTR(err); @@ -1234,7 +1233,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features) rcu_read_lock(); list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) { if (ptype->type == type && !ptype->dev && ptype->gso_segment) { - if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) { + if (unlikely(skb->ip_summed != CHECKSUM_HW)) { err = ptype->gso_send_check(skb); segs = ERR_PTR(err); if (err || skb_gso_ok(skb, features)) @@ -1446,11 +1445,11 @@ int dev_queue_xmit(struct sk_buff *skb) /* If packet is not checksummed and device does not support * checksumming for this protocol, complete checksumming here. */ - if (skb->ip_summed == CHECKSUM_PARTIAL && + if (skb->ip_summed == CHECKSUM_HW && (!(dev->features & NETIF_F_GEN_CSUM) && (!(dev->features & NETIF_F_IP_CSUM) || skb->protocol != htons(ETH_P_IP)))) - if (skb_checksum_help(skb)) + if (skb_checksum_help(skb, 0)) goto out_kfree_skb; gso: @@ -1630,10 +1629,26 @@ static inline struct net_device *skb_bond(struct sk_buff *skb) struct net_device *dev = skb->dev; if (dev->master) { - if (skb_bond_should_drop(skb)) { + /* + * On bonding slaves other than the currently active + * slave, suppress duplicates except for 802.3ad + * ETH_P_SLOW and alb non-mcast/bcast. + */ + if (dev->priv_flags & IFF_SLAVE_INACTIVE) { + if (dev->master->priv_flags & IFF_MASTER_ALB) { + if (skb->pkt_type != PACKET_BROADCAST && + skb->pkt_type != PACKET_MULTICAST) + goto keep; + } + + if (dev->master->priv_flags & IFF_MASTER_8023AD && + skb->protocol == __constant_htons(ETH_P_SLOW)) + goto keep; + kfree_skb(skb); return NULL; } +keep: skb->dev = dev->master; } @@ -3193,15 +3208,13 @@ struct net_device *alloc_netdev(int sizeof_priv, const char *name, struct net_device *dev; int alloc_size; - BUG_ON(strlen(name) >= sizeof(dev->name)); - /* ensure 32-byte alignment of both the device and private area */ alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; p = kzalloc(alloc_size, GFP_KERNEL); if (!p) { - printk(KERN_ERR "alloc_netdev: Unable to allocate device.\n"); + printk(KERN_ERR "alloc_dev: Unable to allocate device.\n"); return NULL; } @@ -3416,9 +3429,12 @@ static void net_dma_rebalance(void) unsigned int cpu, i, n; struct dma_chan *chan; + lock_cpu_hotplug(); + if (net_dma_count == 0) { for_each_online_cpu(cpu) - rcu_assign_pointer(per_cpu(softnet_data, cpu).net_dma, NULL); + rcu_assign_pointer(per_cpu(softnet_data.net_dma, cpu), NULL); + unlock_cpu_hotplug(); return; } @@ -3431,13 +3447,15 @@ static void net_dma_rebalance(void) + (i < (num_online_cpus() % net_dma_count) ? 1 : 0)); while(n) { - per_cpu(softnet_data, cpu).net_dma = chan; + per_cpu(softnet_data.net_dma, cpu) = chan; cpu = next_cpu(cpu, cpu_online_map); n--; } i++; } rcu_read_unlock(); + + unlock_cpu_hotplug(); } /** diff --git a/trunk/net/core/dev_mcast.c b/trunk/net/core/dev_mcast.c index b22648d04d36..c57d887da2ef 100644 --- a/trunk/net/core/dev_mcast.c +++ b/trunk/net/core/dev_mcast.c @@ -21,7 +21,8 @@ * 2 of the License, or (at your option) any later version. */ -#include +#include +#include #include #include #include diff --git a/trunk/net/core/dst.c b/trunk/net/core/dst.c index 1a5e49da0e77..470c05bc4cb2 100644 --- a/trunk/net/core/dst.c +++ b/trunk/net/core/dst.c @@ -95,11 +95,12 @@ static void dst_run_gc(unsigned long dummy) dst_gc_timer_inc = DST_GC_INC; dst_gc_timer_expires = DST_GC_MIN; } + dst_gc_timer.expires = jiffies + dst_gc_timer_expires; #if RT_CACHE_DEBUG >= 2 printk("dst_total: %d/%d %ld\n", atomic_read(&dst_total), delayed, dst_gc_timer_expires); #endif - mod_timer(&dst_gc_timer, jiffies + dst_gc_timer_expires); + add_timer(&dst_gc_timer); out: spin_unlock(&dst_lock); diff --git a/trunk/net/core/fib_rules.c b/trunk/net/core/fib_rules.c deleted file mode 100644 index a99d87d82b7f..000000000000 --- a/trunk/net/core/fib_rules.c +++ /dev/null @@ -1,421 +0,0 @@ -/* - * net/core/fib_rules.c Generic Routing Rules - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - * Authors: Thomas Graf - */ - -#include -#include -#include -#include -#include - -static LIST_HEAD(rules_ops); -static DEFINE_SPINLOCK(rules_mod_lock); - -static void notify_rule_change(int event, struct fib_rule *rule, - struct fib_rules_ops *ops, struct nlmsghdr *nlh, - u32 pid); - -static struct fib_rules_ops *lookup_rules_ops(int family) -{ - struct fib_rules_ops *ops; - - rcu_read_lock(); - list_for_each_entry_rcu(ops, &rules_ops, list) { - if (ops->family == family) { - if (!try_module_get(ops->owner)) - ops = NULL; - rcu_read_unlock(); - return ops; - } - } - rcu_read_unlock(); - - return NULL; -} - -static void rules_ops_put(struct fib_rules_ops *ops) -{ - if (ops) - module_put(ops->owner); -} - -int fib_rules_register(struct fib_rules_ops *ops) -{ - int err = -EEXIST; - struct fib_rules_ops *o; - - if (ops->rule_size < sizeof(struct fib_rule)) - return -EINVAL; - - if (ops->match == NULL || ops->configure == NULL || - ops->compare == NULL || ops->fill == NULL || - ops->action == NULL) - return -EINVAL; - - spin_lock(&rules_mod_lock); - list_for_each_entry(o, &rules_ops, list) - if (ops->family == o->family) - goto errout; - - list_add_tail_rcu(&ops->list, &rules_ops); - err = 0; -errout: - spin_unlock(&rules_mod_lock); - - return err; -} - -EXPORT_SYMBOL_GPL(fib_rules_register); - -static void cleanup_ops(struct fib_rules_ops *ops) -{ - struct fib_rule *rule, *tmp; - - list_for_each_entry_safe(rule, tmp, ops->rules_list, list) { - list_del_rcu(&rule->list); - fib_rule_put(rule); - } -} - -int fib_rules_unregister(struct fib_rules_ops *ops) -{ - int err = 0; - struct fib_rules_ops *o; - - spin_lock(&rules_mod_lock); - list_for_each_entry(o, &rules_ops, list) { - if (o == ops) { - list_del_rcu(&o->list); - cleanup_ops(ops); - goto out; - } - } - - err = -ENOENT; -out: - spin_unlock(&rules_mod_lock); - - synchronize_rcu(); - - return err; -} - -EXPORT_SYMBOL_GPL(fib_rules_unregister); - -int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl, - int flags, struct fib_lookup_arg *arg) -{ - struct fib_rule *rule; - int err; - - rcu_read_lock(); - - list_for_each_entry_rcu(rule, ops->rules_list, list) { - if (rule->ifindex && (rule->ifindex != fl->iif)) - continue; - - if (!ops->match(rule, fl, flags)) - continue; - - err = ops->action(rule, fl, flags, arg); - if (err != -EAGAIN) { - fib_rule_get(rule); - arg->rule = rule; - goto out; - } - } - - err = -ENETUNREACH; -out: - rcu_read_unlock(); - - return err; -} - -EXPORT_SYMBOL_GPL(fib_rules_lookup); - -int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) -{ - struct fib_rule_hdr *frh = nlmsg_data(nlh); - struct fib_rules_ops *ops = NULL; - struct fib_rule *rule, *r, *last = NULL; - struct nlattr *tb[FRA_MAX+1]; - int err = -EINVAL; - - if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) - goto errout; - - ops = lookup_rules_ops(frh->family); - if (ops == NULL) { - err = EAFNOSUPPORT; - goto errout; - } - - err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy); - if (err < 0) - goto errout; - - rule = kzalloc(ops->rule_size, GFP_KERNEL); - if (rule == NULL) { - err = -ENOMEM; - goto errout; - } - - if (tb[FRA_PRIORITY]) - rule->pref = nla_get_u32(tb[FRA_PRIORITY]); - - if (tb[FRA_IFNAME]) { - struct net_device *dev; - - rule->ifindex = -1; - nla_strlcpy(rule->ifname, tb[FRA_IFNAME], IFNAMSIZ); - dev = __dev_get_by_name(rule->ifname); - if (dev) - rule->ifindex = dev->ifindex; - } - - rule->action = frh->action; - rule->flags = frh->flags; - rule->table = frh_get_table(frh, tb); - - if (!rule->pref && ops->default_pref) - rule->pref = ops->default_pref(); - - err = ops->configure(rule, skb, nlh, frh, tb); - if (err < 0) - goto errout_free; - - list_for_each_entry(r, ops->rules_list, list) { - if (r->pref > rule->pref) - break; - last = r; - } - - fib_rule_get(rule); - - if (last) - list_add_rcu(&rule->list, &last->list); - else - list_add_rcu(&rule->list, ops->rules_list); - - notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).pid); - rules_ops_put(ops); - return 0; - -errout_free: - kfree(rule); -errout: - rules_ops_put(ops); - return err; -} - -int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) -{ - struct fib_rule_hdr *frh = nlmsg_data(nlh); - struct fib_rules_ops *ops = NULL; - struct fib_rule *rule; - struct nlattr *tb[FRA_MAX+1]; - int err = -EINVAL; - - if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) - goto errout; - - ops = lookup_rules_ops(frh->family); - if (ops == NULL) { - err = EAFNOSUPPORT; - goto errout; - } - - err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy); - if (err < 0) - goto errout; - - list_for_each_entry(rule, ops->rules_list, list) { - if (frh->action && (frh->action != rule->action)) - continue; - - if (frh->table && (frh_get_table(frh, tb) != rule->table)) - continue; - - if (tb[FRA_PRIORITY] && - (rule->pref != nla_get_u32(tb[FRA_PRIORITY]))) - continue; - - if (tb[FRA_IFNAME] && - nla_strcmp(tb[FRA_IFNAME], rule->ifname)) - continue; - - if (!ops->compare(rule, frh, tb)) - continue; - - if (rule->flags & FIB_RULE_PERMANENT) { - err = -EPERM; - goto errout; - } - - list_del_rcu(&rule->list); - synchronize_rcu(); - notify_rule_change(RTM_DELRULE, rule, ops, nlh, - NETLINK_CB(skb).pid); - fib_rule_put(rule); - rules_ops_put(ops); - return 0; - } - - err = -ENOENT; -errout: - rules_ops_put(ops); - return err; -} - -static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, - u32 pid, u32 seq, int type, int flags, - struct fib_rules_ops *ops) -{ - struct nlmsghdr *nlh; - struct fib_rule_hdr *frh; - - nlh = nlmsg_put(skb, pid, seq, type, sizeof(*frh), flags); - if (nlh == NULL) - return -1; - - frh = nlmsg_data(nlh); - frh->table = rule->table; - NLA_PUT_U32(skb, FRA_TABLE, rule->table); - frh->res1 = 0; - frh->res2 = 0; - frh->action = rule->action; - frh->flags = rule->flags; - - if (rule->ifname[0]) - NLA_PUT_STRING(skb, FRA_IFNAME, rule->ifname); - - if (rule->pref) - NLA_PUT_U32(skb, FRA_PRIORITY, rule->pref); - - if (ops->fill(rule, skb, nlh, frh) < 0) - goto nla_put_failure; - - return nlmsg_end(skb, nlh); - -nla_put_failure: - return nlmsg_cancel(skb, nlh); -} - -int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family) -{ - int idx = 0; - struct fib_rule *rule; - struct fib_rules_ops *ops; - - ops = lookup_rules_ops(family); - if (ops == NULL) - return -EAFNOSUPPORT; - - rcu_read_lock(); - list_for_each_entry(rule, ops->rules_list, list) { - if (idx < cb->args[0]) - goto skip; - - if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, RTM_NEWRULE, - NLM_F_MULTI, ops) < 0) - break; -skip: - idx++; - } - rcu_read_unlock(); - cb->args[0] = idx; - rules_ops_put(ops); - - return skb->len; -} - -EXPORT_SYMBOL_GPL(fib_rules_dump); - -static void notify_rule_change(int event, struct fib_rule *rule, - struct fib_rules_ops *ops, struct nlmsghdr *nlh, - u32 pid) -{ - struct sk_buff *skb; - int err = -ENOBUFS; - - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (skb == NULL) - goto errout; - - err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops); - if (err < 0) { - kfree_skb(skb); - goto errout; - } - - err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL); -errout: - if (err < 0) - rtnl_set_sk_err(ops->nlgroup, err); -} - -static void attach_rules(struct list_head *rules, struct net_device *dev) -{ - struct fib_rule *rule; - - list_for_each_entry(rule, rules, list) { - if (rule->ifindex == -1 && - strcmp(dev->name, rule->ifname) == 0) - rule->ifindex = dev->ifindex; - } -} - -static void detach_rules(struct list_head *rules, struct net_device *dev) -{ - struct fib_rule *rule; - - list_for_each_entry(rule, rules, list) - if (rule->ifindex == dev->ifindex) - rule->ifindex = -1; -} - - -static int fib_rules_event(struct notifier_block *this, unsigned long event, - void *ptr) -{ - struct net_device *dev = ptr; - struct fib_rules_ops *ops; - - ASSERT_RTNL(); - rcu_read_lock(); - - switch (event) { - case NETDEV_REGISTER: - list_for_each_entry(ops, &rules_ops, list) - attach_rules(ops->rules_list, dev); - break; - - case NETDEV_UNREGISTER: - list_for_each_entry(ops, &rules_ops, list) - detach_rules(ops->rules_list, dev); - break; - } - - rcu_read_unlock(); - - return NOTIFY_DONE; -} - -static struct notifier_block fib_rules_notifier = { - .notifier_call = fib_rules_event, -}; - -static int __init fib_rules_init(void) -{ - return register_netdevice_notifier(&fib_rules_notifier); -} - -subsys_initcall(fib_rules_init); diff --git a/trunk/net/core/filter.c b/trunk/net/core/filter.c index 6732782a5a40..5b4486a60cf6 100644 --- a/trunk/net/core/filter.c +++ b/trunk/net/core/filter.c @@ -422,10 +422,10 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) if (!err) { struct sk_filter *old_fp; - rcu_read_lock_bh(); - old_fp = rcu_dereference(sk->sk_filter); - rcu_assign_pointer(sk->sk_filter, fp); - rcu_read_unlock_bh(); + spin_lock_bh(&sk->sk_lock.slock); + old_fp = sk->sk_filter; + sk->sk_filter = fp; + spin_unlock_bh(&sk->sk_lock.slock); fp = old_fp; } diff --git a/trunk/net/core/flow.c b/trunk/net/core/flow.c index f23e7e386543..2191af5f26ac 100644 --- a/trunk/net/core/flow.c +++ b/trunk/net/core/flow.c @@ -32,6 +32,7 @@ struct flow_cache_entry { u8 dir; struct flowi key; u32 genid; + u32 sk_sid; void *object; atomic_t *object_ref; }; @@ -164,7 +165,7 @@ static int flow_key_compare(struct flowi *key1, struct flowi *key2) return 0; } -void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, +void *flow_cache_lookup(struct flowi *key, u32 sk_sid, u16 family, u8 dir, flow_resolve_t resolver) { struct flow_cache_entry *fle, **head; @@ -188,6 +189,7 @@ void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, for (fle = *head; fle; fle = fle->next) { if (fle->family == family && fle->dir == dir && + fle->sk_sid == sk_sid && flow_key_compare(key, &fle->key) == 0) { if (fle->genid == atomic_read(&flow_cache_genid)) { void *ret = fle->object; @@ -212,6 +214,7 @@ void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, *head = fle; fle->family = family; fle->dir = dir; + fle->sk_sid = sk_sid; memcpy(&fle->key, key, sizeof(*key)); fle->object = NULL; flow_count(cpu)++; @@ -223,7 +226,7 @@ void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, void *obj; atomic_t *obj_ref; - resolver(key, family, dir, &obj, &obj_ref); + resolver(key, sk_sid, family, dir, &obj, &obj_ref); if (fle) { fle->genid = atomic_read(&flow_cache_genid); @@ -343,8 +346,12 @@ static int __init flow_cache_init(void) flow_cachep = kmem_cache_create("flow_cache", sizeof(struct flow_cache_entry), - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + + if (!flow_cachep) + panic("NET: failed to allocate flow cache slab\n"); + flow_hash_shift = 10; flow_lwm = 2 * flow_hash_size; flow_hwm = 4 * flow_hash_size; diff --git a/trunk/net/core/neighbour.c b/trunk/net/core/neighbour.c index b6c69e1463e8..7ad681f5e712 100644 --- a/trunk/net/core/neighbour.c +++ b/trunk/net/core/neighbour.c @@ -29,8 +29,6 @@ #include #include #include -#include -#include #include #include #include @@ -756,7 +754,6 @@ static void neigh_timer_handler(unsigned long arg) neigh->nud_state = NUD_STALE; neigh->updated = jiffies; neigh_suspect(neigh); - notify = 1; } } else if (state & NUD_DELAY) { if (time_before_eq(now, @@ -765,7 +762,6 @@ static void neigh_timer_handler(unsigned long arg) neigh->nud_state = NUD_REACHABLE; neigh->updated = jiffies; neigh_connect(neigh); - notify = 1; next = neigh->confirmed + neigh->parms->reachable_time; } else { NEIGH_PRINTK2("neigh %p is probed.\n", neigh); @@ -823,8 +819,6 @@ static void neigh_timer_handler(unsigned long arg) out: write_unlock(&neigh->lock); } - if (notify) - call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh); #ifdef CONFIG_ARPD if (notify && neigh->parms->app_probes) @@ -889,7 +883,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) return rc; } -static void neigh_update_hhs(struct neighbour *neigh) +static __inline__ void neigh_update_hhs(struct neighbour *neigh) { struct hh_cache *hh; void (*update)(struct hh_cache*, struct net_device*, unsigned char *) = @@ -932,7 +926,9 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, { u8 old; int err; +#ifdef CONFIG_ARPD int notify = 0; +#endif struct net_device *dev; int update_isrouter = 0; @@ -952,7 +948,9 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, neigh_suspect(neigh); neigh->nud_state = new; err = 0; +#ifdef CONFIG_ARPD notify = old & NUD_VALID; +#endif goto out; } @@ -1024,7 +1022,9 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, if (!(new & NUD_CONNECTED)) neigh->confirmed = jiffies - (neigh->parms->base_reachable_time << 1); +#ifdef CONFIG_ARPD notify = 1; +#endif } if (new == old) goto out; @@ -1056,9 +1056,6 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, (neigh->flags & ~NTF_ROUTER); } write_unlock_bh(&neigh->lock); - - if (notify) - call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh); #ifdef CONFIG_ARPD if (notify && neigh->parms->app_probes) neigh_app_notify(neigh); @@ -1339,10 +1336,14 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) neigh_rand_reach_time(tbl->parms.base_reachable_time); if (!tbl->kmem_cachep) - tbl->kmem_cachep = - kmem_cache_create(tbl->id, tbl->entry_size, 0, - SLAB_HWCACHE_ALIGN|SLAB_PANIC, - NULL, NULL); + tbl->kmem_cachep = kmem_cache_create(tbl->id, + tbl->entry_size, + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + + if (!tbl->kmem_cachep) + panic("cannot create neighbour cache"); + tbl->stats = alloc_percpu(struct neigh_statistics); if (!tbl->stats) panic("cannot create neighbour cache statistics"); @@ -1429,70 +1430,53 @@ int neigh_table_clear(struct neigh_table *tbl) kfree(tbl->phash_buckets); tbl->phash_buckets = NULL; - free_percpu(tbl->stats); - tbl->stats = NULL; - return 0; } int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { - struct ndmsg *ndm; - struct nlattr *dst_attr; + struct ndmsg *ndm = NLMSG_DATA(nlh); + struct rtattr **nda = arg; struct neigh_table *tbl; struct net_device *dev = NULL; - int err = -EINVAL; - - if (nlmsg_len(nlh) < sizeof(*ndm)) - goto out; + int err = -ENODEV; - dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST); - if (dst_attr == NULL) + if (ndm->ndm_ifindex && + (dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL) goto out; - ndm = nlmsg_data(nlh); - if (ndm->ndm_ifindex) { - dev = dev_get_by_index(ndm->ndm_ifindex); - if (dev == NULL) { - err = -ENODEV; - goto out; - } - } - read_lock(&neigh_tbl_lock); for (tbl = neigh_tables; tbl; tbl = tbl->next) { - struct neighbour *neigh; + struct rtattr *dst_attr = nda[NDA_DST - 1]; + struct neighbour *n; if (tbl->family != ndm->ndm_family) continue; read_unlock(&neigh_tbl_lock); - if (nla_len(dst_attr) < tbl->key_len) + err = -EINVAL; + if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len) goto out_dev_put; if (ndm->ndm_flags & NTF_PROXY) { - err = pneigh_delete(tbl, nla_data(dst_attr), dev); + err = pneigh_delete(tbl, RTA_DATA(dst_attr), dev); goto out_dev_put; } - if (dev == NULL) - goto out_dev_put; + if (!dev) + goto out; - neigh = neigh_lookup(tbl, nla_data(dst_attr), dev); - if (neigh == NULL) { - err = -ENOENT; - goto out_dev_put; + n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev); + if (n) { + err = neigh_update(n, NULL, NUD_FAILED, + NEIGH_UPDATE_F_OVERRIDE| + NEIGH_UPDATE_F_ADMIN); + neigh_release(n); } - - err = neigh_update(neigh, NULL, NUD_FAILED, - NEIGH_UPDATE_F_OVERRIDE | - NEIGH_UPDATE_F_ADMIN); - neigh_release(neigh); goto out_dev_put; } read_unlock(&neigh_tbl_lock); - err = -EAFNOSUPPORT; - + err = -EADDRNOTAVAIL; out_dev_put: if (dev) dev_put(dev); @@ -1502,93 +1486,76 @@ int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { - struct ndmsg *ndm; - struct nlattr *tb[NDA_MAX+1]; + struct ndmsg *ndm = NLMSG_DATA(nlh); + struct rtattr **nda = arg; struct neigh_table *tbl; struct net_device *dev = NULL; - int err; + int err = -ENODEV; - err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); - if (err < 0) + if (ndm->ndm_ifindex && + (dev = dev_get_by_index(ndm->ndm_ifindex)) == NULL) goto out; - err = -EINVAL; - if (tb[NDA_DST] == NULL) - goto out; - - ndm = nlmsg_data(nlh); - if (ndm->ndm_ifindex) { - dev = dev_get_by_index(ndm->ndm_ifindex); - if (dev == NULL) { - err = -ENODEV; - goto out; - } - - if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len) - goto out_dev_put; - } - read_lock(&neigh_tbl_lock); for (tbl = neigh_tables; tbl; tbl = tbl->next) { - int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE; - struct neighbour *neigh; - void *dst, *lladdr; + struct rtattr *lladdr_attr = nda[NDA_LLADDR - 1]; + struct rtattr *dst_attr = nda[NDA_DST - 1]; + int override = 1; + struct neighbour *n; if (tbl->family != ndm->ndm_family) continue; read_unlock(&neigh_tbl_lock); - if (nla_len(tb[NDA_DST]) < tbl->key_len) + err = -EINVAL; + if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len) goto out_dev_put; - dst = nla_data(tb[NDA_DST]); - lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL; if (ndm->ndm_flags & NTF_PROXY) { - struct pneigh_entry *pn; - err = -ENOBUFS; - pn = pneigh_lookup(tbl, dst, dev, 1); - if (pn) { - pn->flags = ndm->ndm_flags; + if (pneigh_lookup(tbl, RTA_DATA(dst_attr), dev, 1)) err = 0; - } goto out_dev_put; } - if (dev == NULL) + err = -EINVAL; + if (!dev) + goto out; + if (lladdr_attr && RTA_PAYLOAD(lladdr_attr) < dev->addr_len) goto out_dev_put; - - neigh = neigh_lookup(tbl, dst, dev); - if (neigh == NULL) { - if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { - err = -ENOENT; - goto out_dev_put; - } - neigh = __neigh_lookup_errno(tbl, dst, dev); - if (IS_ERR(neigh)) { - err = PTR_ERR(neigh); + n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev); + if (n) { + if (nlh->nlmsg_flags & NLM_F_EXCL) { + err = -EEXIST; + neigh_release(n); goto out_dev_put; } + + override = nlh->nlmsg_flags & NLM_F_REPLACE; + } else if (!(nlh->nlmsg_flags & NLM_F_CREATE)) { + err = -ENOENT; + goto out_dev_put; } else { - if (nlh->nlmsg_flags & NLM_F_EXCL) { - err = -EEXIST; - neigh_release(neigh); + n = __neigh_lookup_errno(tbl, RTA_DATA(dst_attr), dev); + if (IS_ERR(n)) { + err = PTR_ERR(n); goto out_dev_put; } - - if (!(nlh->nlmsg_flags & NLM_F_REPLACE)) - flags &= ~NEIGH_UPDATE_F_OVERRIDE; } - err = neigh_update(neigh, lladdr, ndm->ndm_state, flags); - neigh_release(neigh); + err = neigh_update(n, + lladdr_attr ? RTA_DATA(lladdr_attr) : NULL, + ndm->ndm_state, + (override ? NEIGH_UPDATE_F_OVERRIDE : 0) | + NEIGH_UPDATE_F_ADMIN); + + neigh_release(n); goto out_dev_put; } read_unlock(&neigh_tbl_lock); - err = -EAFNOSUPPORT; - + err = -EADDRNOTAVAIL; out_dev_put: if (dev) dev_put(dev); @@ -1598,59 +1565,56 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms) { - struct nlattr *nest; - - nest = nla_nest_start(skb, NDTA_PARMS); - if (nest == NULL) - return -ENOBUFS; + struct rtattr *nest = NULL; + + nest = RTA_NEST(skb, NDTA_PARMS); if (parms->dev) - NLA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex); - - NLA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)); - NLA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len); - NLA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen); - NLA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes); - NLA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes); - NLA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes); - NLA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time); - NLA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME, + RTA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex); + + RTA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)); + RTA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len); + RTA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen); + RTA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes); + RTA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes); + RTA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes); + RTA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time); + RTA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME, parms->base_reachable_time); - NLA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime); - NLA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time); - NLA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time); - NLA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay); - NLA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay); - NLA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime); + RTA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime); + RTA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time); + RTA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time); + RTA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay); + RTA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay); + RTA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime); - return nla_nest_end(skb, nest); + return RTA_NEST_END(skb, nest); -nla_put_failure: - return nla_nest_cancel(skb, nest); +rtattr_failure: + return RTA_NEST_CANCEL(skb, nest); } -static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, - u32 pid, u32 seq, int type, int flags) +static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb, + struct netlink_callback *cb) { struct nlmsghdr *nlh; struct ndtmsg *ndtmsg; - nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags); - if (nlh == NULL) - return -ENOBUFS; + nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg), + NLM_F_MULTI); - ndtmsg = nlmsg_data(nlh); + ndtmsg = NLMSG_DATA(nlh); read_lock_bh(&tbl->lock); ndtmsg->ndtm_family = tbl->family; ndtmsg->ndtm_pad1 = 0; ndtmsg->ndtm_pad2 = 0; - NLA_PUT_STRING(skb, NDTA_NAME, tbl->id); - NLA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval); - NLA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1); - NLA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2); - NLA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3); + RTA_PUT_STRING(skb, NDTA_NAME, tbl->id); + RTA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval); + RTA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1); + RTA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2); + RTA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3); { unsigned long now = jiffies; @@ -1669,7 +1633,7 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, .ndtc_proxy_qlen = tbl->proxy_queue.qlen, }; - NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc); + RTA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc); } { @@ -1694,50 +1658,55 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, ndst.ndts_forced_gc_runs += st->forced_gc_runs; } - NLA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst); + RTA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst); } BUG_ON(tbl->parms.dev); if (neightbl_fill_parms(skb, &tbl->parms) < 0) - goto nla_put_failure; + goto rtattr_failure; read_unlock_bh(&tbl->lock); - return nlmsg_end(skb, nlh); + return NLMSG_END(skb, nlh); -nla_put_failure: +rtattr_failure: read_unlock_bh(&tbl->lock); - return nlmsg_cancel(skb, nlh); + return NLMSG_CANCEL(skb, nlh); + +nlmsg_failure: + return -1; } -static int neightbl_fill_param_info(struct sk_buff *skb, - struct neigh_table *tbl, +static int neightbl_fill_param_info(struct neigh_table *tbl, struct neigh_parms *parms, - u32 pid, u32 seq, int type, - unsigned int flags) + struct sk_buff *skb, + struct netlink_callback *cb) { struct ndtmsg *ndtmsg; struct nlmsghdr *nlh; - nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags); - if (nlh == NULL) - return -ENOBUFS; + nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg), + NLM_F_MULTI); - ndtmsg = nlmsg_data(nlh); + ndtmsg = NLMSG_DATA(nlh); read_lock_bh(&tbl->lock); ndtmsg->ndtm_family = tbl->family; ndtmsg->ndtm_pad1 = 0; ndtmsg->ndtm_pad2 = 0; + RTA_PUT_STRING(skb, NDTA_NAME, tbl->id); - if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 || - neightbl_fill_parms(skb, parms) < 0) - goto errout; + if (neightbl_fill_parms(skb, parms) < 0) + goto rtattr_failure; read_unlock_bh(&tbl->lock); - return nlmsg_end(skb, nlh); -errout: + return NLMSG_END(skb, nlh); + +rtattr_failure: read_unlock_bh(&tbl->lock); - return nlmsg_cancel(skb, nlh); + return NLMSG_CANCEL(skb, nlh); + +nlmsg_failure: + return -1; } static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, @@ -1753,61 +1722,28 @@ static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl, return NULL; } -static struct nla_policy nl_neightbl_policy[NDTA_MAX+1] __read_mostly = { - [NDTA_NAME] = { .type = NLA_STRING }, - [NDTA_THRESH1] = { .type = NLA_U32 }, - [NDTA_THRESH2] = { .type = NLA_U32 }, - [NDTA_THRESH3] = { .type = NLA_U32 }, - [NDTA_GC_INTERVAL] = { .type = NLA_U64 }, - [NDTA_PARMS] = { .type = NLA_NESTED }, -}; - -static struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] __read_mostly = { - [NDTPA_IFINDEX] = { .type = NLA_U32 }, - [NDTPA_QUEUE_LEN] = { .type = NLA_U32 }, - [NDTPA_PROXY_QLEN] = { .type = NLA_U32 }, - [NDTPA_APP_PROBES] = { .type = NLA_U32 }, - [NDTPA_UCAST_PROBES] = { .type = NLA_U32 }, - [NDTPA_MCAST_PROBES] = { .type = NLA_U32 }, - [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 }, - [NDTPA_GC_STALETIME] = { .type = NLA_U64 }, - [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 }, - [NDTPA_RETRANS_TIME] = { .type = NLA_U64 }, - [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 }, - [NDTPA_PROXY_DELAY] = { .type = NLA_U64 }, - [NDTPA_LOCKTIME] = { .type = NLA_U64 }, -}; - int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { struct neigh_table *tbl; - struct ndtmsg *ndtmsg; - struct nlattr *tb[NDTA_MAX+1]; - int err; - - err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX, - nl_neightbl_policy); - if (err < 0) - goto errout; + struct ndtmsg *ndtmsg = NLMSG_DATA(nlh); + struct rtattr **tb = arg; + int err = -EINVAL; - if (tb[NDTA_NAME] == NULL) { - err = -EINVAL; - goto errout; - } + if (!tb[NDTA_NAME - 1] || !RTA_PAYLOAD(tb[NDTA_NAME - 1])) + return -EINVAL; - ndtmsg = nlmsg_data(nlh); read_lock(&neigh_tbl_lock); for (tbl = neigh_tables; tbl; tbl = tbl->next) { if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family) continue; - if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) + if (!rtattr_strcmp(tb[NDTA_NAME - 1], tbl->id)) break; } if (tbl == NULL) { err = -ENOENT; - goto errout_locked; + goto errout; } /* @@ -1816,178 +1752,165 @@ int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) */ write_lock_bh(&tbl->lock); - if (tb[NDTA_PARMS]) { - struct nlattr *tbp[NDTPA_MAX+1]; + if (tb[NDTA_THRESH1 - 1]) + tbl->gc_thresh1 = RTA_GET_U32(tb[NDTA_THRESH1 - 1]); + + if (tb[NDTA_THRESH2 - 1]) + tbl->gc_thresh2 = RTA_GET_U32(tb[NDTA_THRESH2 - 1]); + + if (tb[NDTA_THRESH3 - 1]) + tbl->gc_thresh3 = RTA_GET_U32(tb[NDTA_THRESH3 - 1]); + + if (tb[NDTA_GC_INTERVAL - 1]) + tbl->gc_interval = RTA_GET_MSECS(tb[NDTA_GC_INTERVAL - 1]); + + if (tb[NDTA_PARMS - 1]) { + struct rtattr *tbp[NDTPA_MAX]; struct neigh_parms *p; - int i, ifindex = 0; + u32 ifindex = 0; - err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS], - nl_ntbl_parm_policy); - if (err < 0) - goto errout_tbl_lock; + if (rtattr_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS - 1]) < 0) + goto rtattr_failure; - if (tbp[NDTPA_IFINDEX]) - ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]); + if (tbp[NDTPA_IFINDEX - 1]) + ifindex = RTA_GET_U32(tbp[NDTPA_IFINDEX - 1]); p = lookup_neigh_params(tbl, ifindex); if (p == NULL) { err = -ENOENT; - goto errout_tbl_lock; + goto rtattr_failure; } + + if (tbp[NDTPA_QUEUE_LEN - 1]) + p->queue_len = RTA_GET_U32(tbp[NDTPA_QUEUE_LEN - 1]); - for (i = 1; i <= NDTPA_MAX; i++) { - if (tbp[i] == NULL) - continue; + if (tbp[NDTPA_PROXY_QLEN - 1]) + p->proxy_qlen = RTA_GET_U32(tbp[NDTPA_PROXY_QLEN - 1]); - switch (i) { - case NDTPA_QUEUE_LEN: - p->queue_len = nla_get_u32(tbp[i]); - break; - case NDTPA_PROXY_QLEN: - p->proxy_qlen = nla_get_u32(tbp[i]); - break; - case NDTPA_APP_PROBES: - p->app_probes = nla_get_u32(tbp[i]); - break; - case NDTPA_UCAST_PROBES: - p->ucast_probes = nla_get_u32(tbp[i]); - break; - case NDTPA_MCAST_PROBES: - p->mcast_probes = nla_get_u32(tbp[i]); - break; - case NDTPA_BASE_REACHABLE_TIME: - p->base_reachable_time = nla_get_msecs(tbp[i]); - break; - case NDTPA_GC_STALETIME: - p->gc_staletime = nla_get_msecs(tbp[i]); - break; - case NDTPA_DELAY_PROBE_TIME: - p->delay_probe_time = nla_get_msecs(tbp[i]); - break; - case NDTPA_RETRANS_TIME: - p->retrans_time = nla_get_msecs(tbp[i]); - break; - case NDTPA_ANYCAST_DELAY: - p->anycast_delay = nla_get_msecs(tbp[i]); - break; - case NDTPA_PROXY_DELAY: - p->proxy_delay = nla_get_msecs(tbp[i]); - break; - case NDTPA_LOCKTIME: - p->locktime = nla_get_msecs(tbp[i]); - break; - } - } - } + if (tbp[NDTPA_APP_PROBES - 1]) + p->app_probes = RTA_GET_U32(tbp[NDTPA_APP_PROBES - 1]); + + if (tbp[NDTPA_UCAST_PROBES - 1]) + p->ucast_probes = + RTA_GET_U32(tbp[NDTPA_UCAST_PROBES - 1]); - if (tb[NDTA_THRESH1]) - tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]); + if (tbp[NDTPA_MCAST_PROBES - 1]) + p->mcast_probes = + RTA_GET_U32(tbp[NDTPA_MCAST_PROBES - 1]); - if (tb[NDTA_THRESH2]) - tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]); + if (tbp[NDTPA_BASE_REACHABLE_TIME - 1]) + p->base_reachable_time = + RTA_GET_MSECS(tbp[NDTPA_BASE_REACHABLE_TIME - 1]); - if (tb[NDTA_THRESH3]) - tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]); + if (tbp[NDTPA_GC_STALETIME - 1]) + p->gc_staletime = + RTA_GET_MSECS(tbp[NDTPA_GC_STALETIME - 1]); - if (tb[NDTA_GC_INTERVAL]) - tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]); + if (tbp[NDTPA_DELAY_PROBE_TIME - 1]) + p->delay_probe_time = + RTA_GET_MSECS(tbp[NDTPA_DELAY_PROBE_TIME - 1]); + + if (tbp[NDTPA_RETRANS_TIME - 1]) + p->retrans_time = + RTA_GET_MSECS(tbp[NDTPA_RETRANS_TIME - 1]); + + if (tbp[NDTPA_ANYCAST_DELAY - 1]) + p->anycast_delay = + RTA_GET_MSECS(tbp[NDTPA_ANYCAST_DELAY - 1]); + + if (tbp[NDTPA_PROXY_DELAY - 1]) + p->proxy_delay = + RTA_GET_MSECS(tbp[NDTPA_PROXY_DELAY - 1]); + + if (tbp[NDTPA_LOCKTIME - 1]) + p->locktime = RTA_GET_MSECS(tbp[NDTPA_LOCKTIME - 1]); + } err = 0; -errout_tbl_lock: +rtattr_failure: write_unlock_bh(&tbl->lock); -errout_locked: - read_unlock(&neigh_tbl_lock); errout: + read_unlock(&neigh_tbl_lock); return err; } int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) { - int family, tidx, nidx = 0; - int tbl_skip = cb->args[0]; - int neigh_skip = cb->args[1]; + int idx, family; + int s_idx = cb->args[0]; struct neigh_table *tbl; - family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; + family = ((struct rtgenmsg *)NLMSG_DATA(cb->nlh))->rtgen_family; read_lock(&neigh_tbl_lock); - for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) { + for (tbl = neigh_tables, idx = 0; tbl; tbl = tbl->next) { struct neigh_parms *p; - if (tidx < tbl_skip || (family && tbl->family != family)) + if (idx < s_idx || (family && tbl->family != family)) continue; - if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL, - NLM_F_MULTI) <= 0) + if (neightbl_fill_info(tbl, skb, cb) <= 0) break; - for (nidx = 0, p = tbl->parms.next; p; p = p->next, nidx++) { - if (nidx < neigh_skip) + for (++idx, p = tbl->parms.next; p; p = p->next, idx++) { + if (idx < s_idx) continue; - if (neightbl_fill_param_info(skb, tbl, p, - NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, - RTM_NEWNEIGHTBL, - NLM_F_MULTI) <= 0) + if (neightbl_fill_param_info(tbl, p, skb, cb) <= 0) goto out; } - neigh_skip = 0; } out: read_unlock(&neigh_tbl_lock); - cb->args[0] = tidx; - cb->args[1] = nidx; + cb->args[0] = idx; return skb->len; } -static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh, - u32 pid, u32 seq, int type, unsigned int flags) +static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n, + u32 pid, u32 seq, int event, unsigned int flags) { unsigned long now = jiffies; + unsigned char *b = skb->tail; struct nda_cacheinfo ci; - struct nlmsghdr *nlh; - struct ndmsg *ndm; + int locked = 0; + u32 probes; + struct nlmsghdr *nlh = NLMSG_NEW(skb, pid, seq, event, + sizeof(struct ndmsg), flags); + struct ndmsg *ndm = NLMSG_DATA(nlh); - nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags); - if (nlh == NULL) - return -ENOBUFS; - - ndm = nlmsg_data(nlh); - ndm->ndm_family = neigh->ops->family; + ndm->ndm_family = n->ops->family; ndm->ndm_pad1 = 0; ndm->ndm_pad2 = 0; - ndm->ndm_flags = neigh->flags; - ndm->ndm_type = neigh->type; - ndm->ndm_ifindex = neigh->dev->ifindex; - - NLA_PUT(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key); - - read_lock_bh(&neigh->lock); - ndm->ndm_state = neigh->nud_state; - if ((neigh->nud_state & NUD_VALID) && - nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, neigh->ha) < 0) { - read_unlock_bh(&neigh->lock); - goto nla_put_failure; - } - - ci.ndm_used = now - neigh->used; - ci.ndm_confirmed = now - neigh->confirmed; - ci.ndm_updated = now - neigh->updated; - ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1; - read_unlock_bh(&neigh->lock); - - NLA_PUT_U32(skb, NDA_PROBES, atomic_read(&neigh->probes)); - NLA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci); - - return nlmsg_end(skb, nlh); + ndm->ndm_flags = n->flags; + ndm->ndm_type = n->type; + ndm->ndm_ifindex = n->dev->ifindex; + RTA_PUT(skb, NDA_DST, n->tbl->key_len, n->primary_key); + read_lock_bh(&n->lock); + locked = 1; + ndm->ndm_state = n->nud_state; + if (n->nud_state & NUD_VALID) + RTA_PUT(skb, NDA_LLADDR, n->dev->addr_len, n->ha); + ci.ndm_used = now - n->used; + ci.ndm_confirmed = now - n->confirmed; + ci.ndm_updated = now - n->updated; + ci.ndm_refcnt = atomic_read(&n->refcnt) - 1; + probes = atomic_read(&n->probes); + read_unlock_bh(&n->lock); + locked = 0; + RTA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci); + RTA_PUT(skb, NDA_PROBES, sizeof(probes), &probes); + nlh->nlmsg_len = skb->tail - b; + return skb->len; -nla_put_failure: - return nlmsg_cancel(skb, nlh); +nlmsg_failure: +rtattr_failure: + if (locked) + read_unlock_bh(&n->lock); + skb_trim(skb, b - skb->data); + return -1; } @@ -2031,7 +1954,7 @@ int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) int t, family, s_t; read_lock(&neigh_tbl_lock); - family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; + family = ((struct rtgenmsg *)NLMSG_DATA(cb->nlh))->rtgen_family; s_t = cb->args[0]; for (tbl = neigh_tables, t = 0; tbl; tbl = tbl->next, t++) { @@ -2410,35 +2333,41 @@ static struct file_operations neigh_stat_seq_fops = { #endif /* CONFIG_PROC_FS */ #ifdef CONFIG_ARPD -static void __neigh_notify(struct neighbour *n, int type, int flags) +void neigh_app_ns(struct neighbour *n) { - struct sk_buff *skb; - int err = -ENOBUFS; + struct nlmsghdr *nlh; + int size = NLMSG_SPACE(sizeof(struct ndmsg) + 256); + struct sk_buff *skb = alloc_skb(size, GFP_ATOMIC); - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); - if (skb == NULL) - goto errout; + if (!skb) + return; - err = neigh_fill_info(skb, n, 0, 0, type, flags); - if (err < 0) { + if (neigh_fill_info(skb, n, 0, 0, RTM_GETNEIGH, 0) < 0) { kfree_skb(skb); - goto errout; + return; } - - err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); -errout: - if (err < 0) - rtnl_set_sk_err(RTNLGRP_NEIGH, err); -} - -void neigh_app_ns(struct neighbour *n) -{ - __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST); + nlh = (struct nlmsghdr *)skb->data; + nlh->nlmsg_flags = NLM_F_REQUEST; + NETLINK_CB(skb).dst_group = RTNLGRP_NEIGH; + netlink_broadcast(rtnl, skb, 0, RTNLGRP_NEIGH, GFP_ATOMIC); } static void neigh_app_notify(struct neighbour *n) { - __neigh_notify(n, RTM_NEWNEIGH, 0); + struct nlmsghdr *nlh; + int size = NLMSG_SPACE(sizeof(struct ndmsg) + 256); + struct sk_buff *skb = alloc_skb(size, GFP_ATOMIC); + + if (!skb) + return; + + if (neigh_fill_info(skb, n, 0, 0, RTM_NEWNEIGH, 0) < 0) { + kfree_skb(skb); + return; + } + nlh = (struct nlmsghdr *)skb->data; + NETLINK_CB(skb).dst_group = RTNLGRP_NEIGH; + netlink_broadcast(rtnl, skb, 0, RTNLGRP_NEIGH, GFP_ATOMIC); } #endif /* CONFIG_ARPD */ @@ -2452,7 +2381,7 @@ static struct neigh_sysctl_table { ctl_table neigh_neigh_dir[2]; ctl_table neigh_proto_dir[2]; ctl_table neigh_root_dir[2]; -} neigh_sysctl_template __read_mostly = { +} neigh_sysctl_template = { .neigh_vars = { { .ctl_name = NET_NEIGH_MCAST_SOLICIT, @@ -2725,6 +2654,7 @@ void neigh_sysctl_unregister(struct neigh_parms *p) #endif /* CONFIG_SYSCTL */ EXPORT_SYMBOL(__neigh_event_send); +EXPORT_SYMBOL(neigh_add); EXPORT_SYMBOL(neigh_changeaddr); EXPORT_SYMBOL(neigh_compat_output); EXPORT_SYMBOL(neigh_connected_output); @@ -2744,8 +2674,11 @@ EXPORT_SYMBOL(neigh_table_clear); EXPORT_SYMBOL(neigh_table_init); EXPORT_SYMBOL(neigh_table_init_no_netlink); EXPORT_SYMBOL(neigh_update); +EXPORT_SYMBOL(neigh_update_hhs); EXPORT_SYMBOL(pneigh_enqueue); EXPORT_SYMBOL(pneigh_lookup); +EXPORT_SYMBOL(neightbl_dump_info); +EXPORT_SYMBOL(neightbl_set); #ifdef CONFIG_ARPD EXPORT_SYMBOL(neigh_app_ns); diff --git a/trunk/net/core/netevent.c b/trunk/net/core/netevent.c deleted file mode 100644 index 35d02c38554e..000000000000 --- a/trunk/net/core/netevent.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Network event notifiers - * - * Authors: - * Tom Tucker - * Steve Wise - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Fixes: - */ - -#include -#include - -static ATOMIC_NOTIFIER_HEAD(netevent_notif_chain); - -/** - * register_netevent_notifier - register a netevent notifier block - * @nb: notifier - * - * Register a notifier to be called when a netevent occurs. - * The notifier passed is linked into the kernel structures and must - * not be reused until it has been unregistered. A negative errno code - * is returned on a failure. - */ -int register_netevent_notifier(struct notifier_block *nb) -{ - int err; - - err = atomic_notifier_chain_register(&netevent_notif_chain, nb); - return err; -} - -/** - * netevent_unregister_notifier - unregister a netevent notifier block - * @nb: notifier - * - * Unregister a notifier previously registered by - * register_neigh_notifier(). The notifier is unlinked into the - * kernel structures and may then be reused. A negative errno code - * is returned on a failure. - */ - -int unregister_netevent_notifier(struct notifier_block *nb) -{ - return atomic_notifier_chain_unregister(&netevent_notif_chain, nb); -} - -/** - * call_netevent_notifiers - call all netevent notifier blocks - * @val: value passed unmodified to notifier function - * @v: pointer passed unmodified to notifier function - * - * Call all neighbour notifier blocks. Parameters and return value - * are as for notifier_call_chain(). - */ - -int call_netevent_notifiers(unsigned long val, void *v) -{ - return atomic_notifier_call_chain(&netevent_notif_chain, val, v); -} - -EXPORT_SYMBOL_GPL(register_netevent_notifier); -EXPORT_SYMBOL_GPL(unregister_netevent_notifier); -EXPORT_SYMBOL_GPL(call_netevent_notifiers); diff --git a/trunk/net/core/netpoll.c b/trunk/net/core/netpoll.c index ead5920c26d6..471da451cd48 100644 --- a/trunk/net/core/netpoll.c +++ b/trunk/net/core/netpoll.c @@ -110,7 +110,7 @@ static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); - if (skb->ip_summed == CHECKSUM_COMPLETE && + if (skb->ip_summed == CHECKSUM_HW && !(u16)csum_fold(csum_add(psum, skb->csum))) return 0; diff --git a/trunk/net/core/pktgen.c b/trunk/net/core/pktgen.c index 72145d4a2600..67ed14ddabd2 100644 --- a/trunk/net/core/pktgen.c +++ b/trunk/net/core/pktgen.c @@ -1786,7 +1786,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) * use ipv6_get_lladdr if/when it's get exported */ - rcu_read_lock(); + read_lock(&addrconf_lock); if ((idev = __in6_dev_get(pkt_dev->odev)) != NULL) { struct inet6_ifaddr *ifp; @@ -1805,7 +1805,7 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) } read_unlock_bh(&idev->lock); } - rcu_read_unlock(); + read_unlock(&addrconf_lock); if (err) printk("pktgen: ERROR: IPv6 link address not availble.\n"); } @@ -2149,8 +2149,6 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, skb->mac.raw = ((u8 *) iph) - 14 - pkt_dev->nr_labels*sizeof(u32); skb->dev = odev; skb->pkt_type = PACKET_HOST; - skb->nh.iph = iph; - skb->h.uh = udph; if (pkt_dev->nfrags <= 0) pgh = (struct pktgen_hdr *)skb_put(skb, datalen); @@ -2462,8 +2460,6 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, skb->protocol = protocol; skb->dev = odev; skb->pkt_type = PACKET_HOST; - skb->nh.ipv6h = iph; - skb->h.uh = udph; if (pkt_dev->nfrags <= 0) pgh = (struct pktgen_hdr *)skb_put(skb, datalen); diff --git a/trunk/net/core/rtnetlink.c b/trunk/net/core/rtnetlink.c index d8e25e08cb7e..20e5bb73f147 100644 --- a/trunk/net/core/rtnetlink.c +++ b/trunk/net/core/rtnetlink.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -50,7 +49,6 @@ #include #include #include -#include #include #ifdef CONFIG_NET_WIRELESS_RTNETLINK #include @@ -58,7 +56,6 @@ #endif /* CONFIG_NET_WIRELESS_RTNETLINK */ static DEFINE_MUTEX(rtnl_mutex); -static struct sock *rtnl; void rtnl_lock(void) { @@ -96,6 +93,8 @@ int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len) return 0; } +struct sock *rtnl; + struct rtnetlink_link * rtnetlink_links[NPROTO]; static const int rtm_min[RTM_NR_FAMILIES] = @@ -103,7 +102,8 @@ static const int rtm_min[RTM_NR_FAMILIES] = [RTM_FAM(RTM_NEWLINK)] = NLMSG_LENGTH(sizeof(struct ifinfomsg)), [RTM_FAM(RTM_NEWADDR)] = NLMSG_LENGTH(sizeof(struct ifaddrmsg)), [RTM_FAM(RTM_NEWROUTE)] = NLMSG_LENGTH(sizeof(struct rtmsg)), - [RTM_FAM(RTM_NEWRULE)] = NLMSG_LENGTH(sizeof(struct fib_rule_hdr)), + [RTM_FAM(RTM_NEWNEIGH)] = NLMSG_LENGTH(sizeof(struct ndmsg)), + [RTM_FAM(RTM_NEWRULE)] = NLMSG_LENGTH(sizeof(struct rtmsg)), [RTM_FAM(RTM_NEWQDISC)] = NLMSG_LENGTH(sizeof(struct tcmsg)), [RTM_FAM(RTM_NEWTCLASS)] = NLMSG_LENGTH(sizeof(struct tcmsg)), [RTM_FAM(RTM_NEWTFILTER)] = NLMSG_LENGTH(sizeof(struct tcmsg)), @@ -111,6 +111,7 @@ static const int rtm_min[RTM_NR_FAMILIES] = [RTM_FAM(RTM_NEWPREFIX)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), [RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), [RTM_FAM(RTM_GETANYCAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), + [RTM_FAM(RTM_NEWNEIGHTBL)] = NLMSG_LENGTH(sizeof(struct ndtmsg)), }; static const int rta_max[RTM_NR_FAMILIES] = @@ -118,11 +119,13 @@ static const int rta_max[RTM_NR_FAMILIES] = [RTM_FAM(RTM_NEWLINK)] = IFLA_MAX, [RTM_FAM(RTM_NEWADDR)] = IFA_MAX, [RTM_FAM(RTM_NEWROUTE)] = RTA_MAX, - [RTM_FAM(RTM_NEWRULE)] = FRA_MAX, + [RTM_FAM(RTM_NEWNEIGH)] = NDA_MAX, + [RTM_FAM(RTM_NEWRULE)] = RTA_MAX, [RTM_FAM(RTM_NEWQDISC)] = TCA_MAX, [RTM_FAM(RTM_NEWTCLASS)] = TCA_MAX, [RTM_FAM(RTM_NEWTFILTER)] = TCA_MAX, [RTM_FAM(RTM_NEWACTION)] = TCAA_MAX, + [RTM_FAM(RTM_NEWNEIGHTBL)] = NDTA_MAX, }; void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data) @@ -165,52 +168,24 @@ int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) return err; } -int rtnl_unicast(struct sk_buff *skb, u32 pid) -{ - return nlmsg_unicast(rtnl, skb, pid); -} - -int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group, - struct nlmsghdr *nlh, gfp_t flags) -{ - int report = 0; - - if (nlh) - report = nlmsg_report(nlh); - - return nlmsg_notify(rtnl, skb, pid, group, report, flags); -} - -void rtnl_set_sk_err(u32 group, int error) -{ - netlink_set_err(rtnl, 0, group, error); -} - int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) { - struct nlattr *mx; - int i, valid = 0; - - mx = nla_nest_start(skb, RTA_METRICS); - if (mx == NULL) - return -ENOBUFS; - - for (i = 0; i < RTAX_MAX; i++) { - if (metrics[i]) { - valid++; - NLA_PUT_U32(skb, i+1, metrics[i]); - } - } + struct rtattr *mx = (struct rtattr*)skb->tail; + int i; - if (!valid) { - nla_nest_cancel(skb, mx); - return 0; + RTA_PUT(skb, RTA_METRICS, 0, NULL); + for (i=0; irta_len = skb->tail - (u8*)mx; + if (mx->rta_len == RTA_LENGTH(0)) + skb_trim(skb, (u8*)mx - skb->data); + return 0; - return nla_nest_end(skb, mx); - -nla_put_failure: - return nla_nest_cancel(skb, mx); +rtattr_failure: + skb_trim(skb, (u8*)mx - skb->data); + return -1; } @@ -241,73 +216,41 @@ static void set_operstate(struct net_device *dev, unsigned char transition) } } -static void copy_rtnl_link_stats(struct rtnl_link_stats *a, - struct net_device_stats *b) +static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, + int type, u32 pid, u32 seq, u32 change, + unsigned int flags) { - a->rx_packets = b->rx_packets; - a->tx_packets = b->tx_packets; - a->rx_bytes = b->rx_bytes; - a->tx_bytes = b->tx_bytes; - a->rx_errors = b->rx_errors; - a->tx_errors = b->tx_errors; - a->rx_dropped = b->rx_dropped; - a->tx_dropped = b->tx_dropped; - - a->multicast = b->multicast; - a->collisions = b->collisions; - - a->rx_length_errors = b->rx_length_errors; - a->rx_over_errors = b->rx_over_errors; - a->rx_crc_errors = b->rx_crc_errors; - a->rx_frame_errors = b->rx_frame_errors; - a->rx_fifo_errors = b->rx_fifo_errors; - a->rx_missed_errors = b->rx_missed_errors; - - a->tx_aborted_errors = b->tx_aborted_errors; - a->tx_carrier_errors = b->tx_carrier_errors; - a->tx_fifo_errors = b->tx_fifo_errors; - a->tx_heartbeat_errors = b->tx_heartbeat_errors; - a->tx_window_errors = b->tx_window_errors; - - a->rx_compressed = b->rx_compressed; - a->tx_compressed = b->tx_compressed; -}; + struct ifinfomsg *r; + struct nlmsghdr *nlh; + unsigned char *b = skb->tail; -static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, - void *iwbuf, int iwbuflen, int type, u32 pid, - u32 seq, u32 change, unsigned int flags) -{ - struct ifinfomsg *ifm; - struct nlmsghdr *nlh; - - nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); - if (nlh == NULL) - return -ENOBUFS; - - ifm = nlmsg_data(nlh); - ifm->ifi_family = AF_UNSPEC; - ifm->__ifi_pad = 0; - ifm->ifi_type = dev->type; - ifm->ifi_index = dev->ifindex; - ifm->ifi_flags = dev_get_flags(dev); - ifm->ifi_change = change; - - NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); - NLA_PUT_U32(skb, IFLA_TXQLEN, dev->tx_queue_len); - NLA_PUT_U32(skb, IFLA_WEIGHT, dev->weight); - NLA_PUT_U8(skb, IFLA_OPERSTATE, - netif_running(dev) ? dev->operstate : IF_OPER_DOWN); - NLA_PUT_U8(skb, IFLA_LINKMODE, dev->link_mode); - NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); - - if (dev->ifindex != dev->iflink) - NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); - - if (dev->master) - NLA_PUT_U32(skb, IFLA_MASTER, dev->master->ifindex); + nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*r), flags); + r = NLMSG_DATA(nlh); + r->ifi_family = AF_UNSPEC; + r->__ifi_pad = 0; + r->ifi_type = dev->type; + r->ifi_index = dev->ifindex; + r->ifi_flags = dev_get_flags(dev); + r->ifi_change = change; - if (dev->qdisc_sleeping) - NLA_PUT_STRING(skb, IFLA_QDISC, dev->qdisc_sleeping->ops->id); + RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name); + + if (1) { + u32 txqlen = dev->tx_queue_len; + RTA_PUT(skb, IFLA_TXQLEN, sizeof(txqlen), &txqlen); + } + + if (1) { + u32 weight = dev->weight; + RTA_PUT(skb, IFLA_WEIGHT, sizeof(weight), &weight); + } + + if (1) { + u8 operstate = netif_running(dev)?dev->operstate:IF_OPER_DOWN; + u8 link_mode = dev->link_mode; + RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate); + RTA_PUT(skb, IFLA_LINKMODE, sizeof(link_mode), &link_mode); + } if (1) { struct rtnl_link_ifmap map = { @@ -318,38 +261,58 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, .dma = dev->dma, .port = dev->if_port, }; - NLA_PUT(skb, IFLA_MAP, sizeof(map), &map); + RTA_PUT(skb, IFLA_MAP, sizeof(map), &map); } if (dev->addr_len) { - NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); - NLA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); + RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); + RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); } - if (dev->get_stats) { - struct net_device_stats *stats = dev->get_stats(dev); - if (stats) { - struct nlattr *attr; - - attr = nla_reserve(skb, IFLA_STATS, - sizeof(struct rtnl_link_stats)); - if (attr == NULL) - goto nla_put_failure; + if (1) { + u32 mtu = dev->mtu; + RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu); + } - copy_rtnl_link_stats(nla_data(attr), stats); - } + if (dev->ifindex != dev->iflink) { + u32 iflink = dev->iflink; + RTA_PUT(skb, IFLA_LINK, sizeof(iflink), &iflink); } - if (iwbuf) - NLA_PUT(skb, IFLA_WIRELESS, iwbuflen, iwbuf); + if (dev->qdisc_sleeping) + RTA_PUT(skb, IFLA_QDISC, + strlen(dev->qdisc_sleeping->ops->id) + 1, + dev->qdisc_sleeping->ops->id); + + if (dev->master) { + u32 master = dev->master->ifindex; + RTA_PUT(skb, IFLA_MASTER, sizeof(master), &master); + } - return nlmsg_end(skb, nlh); + if (dev->get_stats) { + unsigned long *stats = (unsigned long*)dev->get_stats(dev); + if (stats) { + struct rtattr *a; + __u32 *s; + int i; + int n = sizeof(struct rtnl_link_stats)/4; + + a = __RTA_PUT(skb, IFLA_STATS, n*4); + s = RTA_DATA(a); + for (i=0; inlmsg_len = skb->tail - b; + return skb->len; -nla_put_failure: - return nlmsg_cancel(skb, nlh); +nlmsg_failure: +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; } -static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) +static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) { int idx; int s_idx = cb->args[0]; @@ -359,9 +322,10 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) { if (idx < s_idx) continue; - if (rtnl_fill_ifinfo(skb, dev, NULL, 0, RTM_NEWLINK, - NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0) + if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, + NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, 0, + NLM_F_MULTI) <= 0) break; } read_unlock(&dev_base_lock); @@ -370,70 +334,52 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) return skb->len; } -static struct nla_policy ifla_policy[IFLA_MAX+1] __read_mostly = { - [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, - [IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) }, - [IFLA_MTU] = { .type = NLA_U32 }, - [IFLA_TXQLEN] = { .type = NLA_U32 }, - [IFLA_WEIGHT] = { .type = NLA_U32 }, - [IFLA_OPERSTATE] = { .type = NLA_U8 }, - [IFLA_LINKMODE] = { .type = NLA_U8 }, -}; - -static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) +static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { - struct ifinfomsg *ifm; + struct ifinfomsg *ifm = NLMSG_DATA(nlh); + struct rtattr **ida = arg; struct net_device *dev; - int err, send_addr_notify = 0, modified = 0; - struct nlattr *tb[IFLA_MAX+1]; - char ifname[IFNAMSIZ]; + int err, send_addr_notify = 0; - err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); - if (err < 0) - goto errout; - - if (tb[IFLA_IFNAME]) - nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); - else - ifname[0] = '\0'; - - err = -EINVAL; - ifm = nlmsg_data(nlh); if (ifm->ifi_index >= 0) dev = dev_get_by_index(ifm->ifi_index); - else if (tb[IFLA_IFNAME]) + else if (ida[IFLA_IFNAME - 1]) { + char ifname[IFNAMSIZ]; + + if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1], + IFNAMSIZ) >= IFNAMSIZ) + return -EINVAL; dev = dev_get_by_name(ifname); - else - goto errout; + } else + return -EINVAL; - if (dev == NULL) { - err = -ENODEV; - goto errout; - } + if (!dev) + return -ENODEV; - if (tb[IFLA_ADDRESS] && - nla_len(tb[IFLA_ADDRESS]) < dev->addr_len) - goto errout_dev; + err = -EINVAL; - if (tb[IFLA_BROADCAST] && - nla_len(tb[IFLA_BROADCAST]) < dev->addr_len) - goto errout_dev; + if (ifm->ifi_flags) + dev_change_flags(dev, ifm->ifi_flags); - if (tb[IFLA_MAP]) { + if (ida[IFLA_MAP - 1]) { struct rtnl_link_ifmap *u_map; struct ifmap k_map; if (!dev->set_config) { err = -EOPNOTSUPP; - goto errout_dev; + goto out; } if (!netif_device_present(dev)) { err = -ENODEV; - goto errout_dev; + goto out; } + + if (ida[IFLA_MAP - 1]->rta_len != RTA_LENGTH(sizeof(*u_map))) + goto out; + + u_map = RTA_DATA(ida[IFLA_MAP - 1]); - u_map = nla_data(tb[IFLA_MAP]); k_map.mem_start = (unsigned long) u_map->mem_start; k_map.mem_end = (unsigned long) u_map->mem_end; k_map.base_addr = (unsigned short) u_map->base_addr; @@ -442,175 +388,187 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) k_map.port = (unsigned char) u_map->port; err = dev->set_config(dev, &k_map); - if (err < 0) - goto errout_dev; - modified = 1; + if (err) + goto out; } - if (tb[IFLA_ADDRESS]) { - struct sockaddr *sa; - int len; - + if (ida[IFLA_ADDRESS - 1]) { if (!dev->set_mac_address) { err = -EOPNOTSUPP; - goto errout_dev; + goto out; } - if (!netif_device_present(dev)) { err = -ENODEV; - goto errout_dev; + goto out; } + if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len)) + goto out; - len = sizeof(sa_family_t) + dev->addr_len; - sa = kmalloc(len, GFP_KERNEL); - if (!sa) { - err = -ENOMEM; - goto errout_dev; - } - sa->sa_family = dev->type; - memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), - dev->addr_len); - err = dev->set_mac_address(dev, sa); - kfree(sa); + err = dev->set_mac_address(dev, RTA_DATA(ida[IFLA_ADDRESS - 1])); if (err) - goto errout_dev; + goto out; send_addr_notify = 1; - modified = 1; } - if (tb[IFLA_MTU]) { - err = dev_set_mtu(dev, nla_get_u32(tb[IFLA_MTU])); - if (err < 0) - goto errout_dev; - modified = 1; + if (ida[IFLA_BROADCAST - 1]) { + if (ida[IFLA_BROADCAST - 1]->rta_len != RTA_LENGTH(dev->addr_len)) + goto out; + memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]), + dev->addr_len); + send_addr_notify = 1; } - /* - * Interface selected by interface index but interface - * name provided implies that a name change has been - * requested. - */ - if (ifm->ifi_index >= 0 && ifname[0]) { - err = dev_change_name(dev, ifname); - if (err < 0) - goto errout_dev; - modified = 1; - } + if (ida[IFLA_MTU - 1]) { + if (ida[IFLA_MTU - 1]->rta_len != RTA_LENGTH(sizeof(u32))) + goto out; + err = dev_set_mtu(dev, *((u32 *) RTA_DATA(ida[IFLA_MTU - 1]))); + + if (err) + goto out; -#ifdef CONFIG_NET_WIRELESS_RTNETLINK - if (tb[IFLA_WIRELESS]) { - /* Call Wireless Extensions. - * Various stuff checked in there... */ - err = wireless_rtnetlink_set(dev, nla_data(tb[IFLA_WIRELESS]), - nla_len(tb[IFLA_WIRELESS])); - if (err < 0) - goto errout_dev; } -#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ - if (tb[IFLA_BROADCAST]) { - nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len); - send_addr_notify = 1; + if (ida[IFLA_TXQLEN - 1]) { + if (ida[IFLA_TXQLEN - 1]->rta_len != RTA_LENGTH(sizeof(u32))) + goto out; + + dev->tx_queue_len = *((u32 *) RTA_DATA(ida[IFLA_TXQLEN - 1])); } + if (ida[IFLA_WEIGHT - 1]) { + if (ida[IFLA_WEIGHT - 1]->rta_len != RTA_LENGTH(sizeof(u32))) + goto out; - if (ifm->ifi_flags) - dev_change_flags(dev, ifm->ifi_flags); + dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1])); + } - if (tb[IFLA_TXQLEN]) - dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]); + if (ida[IFLA_OPERSTATE - 1]) { + if (ida[IFLA_OPERSTATE - 1]->rta_len != RTA_LENGTH(sizeof(u8))) + goto out; - if (tb[IFLA_WEIGHT]) - dev->weight = nla_get_u32(tb[IFLA_WEIGHT]); + set_operstate(dev, *((u8 *) RTA_DATA(ida[IFLA_OPERSTATE - 1]))); + } - if (tb[IFLA_OPERSTATE]) - set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE])); + if (ida[IFLA_LINKMODE - 1]) { + if (ida[IFLA_LINKMODE - 1]->rta_len != RTA_LENGTH(sizeof(u8))) + goto out; - if (tb[IFLA_LINKMODE]) { write_lock_bh(&dev_base_lock); - dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]); + dev->link_mode = *((u8 *) RTA_DATA(ida[IFLA_LINKMODE - 1])); write_unlock_bh(&dev_base_lock); } - err = 0; + if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) { + char ifname[IFNAMSIZ]; + + if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1], + IFNAMSIZ) >= IFNAMSIZ) + goto out; + err = dev_change_name(dev, ifname); + if (err) + goto out; + } + +#ifdef CONFIG_NET_WIRELESS_RTNETLINK + if (ida[IFLA_WIRELESS - 1]) { -errout_dev: - if (err < 0 && modified && net_ratelimit()) - printk(KERN_WARNING "A link change request failed with " - "some changes comitted already. Interface %s may " - "have been left with an inconsistent configuration, " - "please check.\n", dev->name); + /* Call Wireless Extensions. + * Various stuff checked in there... */ + err = wireless_rtnetlink_set(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len); + if (err) + goto out; + } +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + + err = 0; +out: if (send_addr_notify) call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); dev_put(dev); -errout: return err; } -static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) +#ifdef CONFIG_NET_WIRELESS_RTNETLINK +static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg) { - struct ifinfomsg *ifm; - struct nlattr *tb[IFLA_MAX+1]; - struct net_device *dev = NULL; - struct sk_buff *nskb; - char *iw_buf = NULL, *iw = NULL; + struct ifinfomsg *ifm = NLMSG_DATA(in_nlh); + struct rtattr **ida = arg; + struct net_device *dev; + struct ifinfomsg *r; + struct nlmsghdr *nlh; + int err = -ENOBUFS; + struct sk_buff *skb; + unsigned char *b; + char *iw_buf = NULL; int iw_buf_len = 0; - int err, payload; - - err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); - if (err < 0) - goto errout; - ifm = nlmsg_data(nlh); - if (ifm->ifi_index >= 0) { + if (ifm->ifi_index >= 0) dev = dev_get_by_index(ifm->ifi_index); - if (dev == NULL) - return -ENODEV; - } else + else return -EINVAL; - + if (!dev) + return -ENODEV; #ifdef CONFIG_NET_WIRELESS_RTNETLINK - if (tb[IFLA_WIRELESS]) { + if (ida[IFLA_WIRELESS - 1]) { + /* Call Wireless Extensions. We need to know the size before * we can alloc. Various stuff checked in there... */ - err = wireless_rtnetlink_get(dev, nla_data(tb[IFLA_WIRELESS]), - nla_len(tb[IFLA_WIRELESS]), - &iw_buf, &iw_buf_len); - if (err < 0) - goto errout; - - iw += IW_EV_POINT_OFF; + err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len); + if (err) + goto out; } #endif /* CONFIG_NET_WIRELESS_RTNETLINK */ - payload = NLMSG_ALIGN(sizeof(struct ifinfomsg) + - nla_total_size(iw_buf_len)); - nskb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL); - if (nskb == NULL) { - err = -ENOBUFS; - goto errout; - } - - err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK, - NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0); - if (err <= 0) { - kfree_skb(nskb); - goto errout; - } - - err = rtnl_unicast(skb, NETLINK_CB(skb).pid); -errout: - kfree(iw_buf); + /* Create a skb big enough to include all the data. + * Some requests are way bigger than 4k... Jean II */ + skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)), + GFP_KERNEL); + if (!skb) + goto out; + b = skb->tail; + + /* Put in the message the usual good stuff */ + nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq, + RTM_NEWLINK, sizeof(*r)); + r = NLMSG_DATA(nlh); + r->ifi_family = AF_UNSPEC; + r->__ifi_pad = 0; + r->ifi_type = dev->type; + r->ifi_index = dev->ifindex; + r->ifi_flags = dev->flags; + r->ifi_change = 0; + + /* Put the wireless payload if it exist */ + if(iw_buf != NULL) + RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len, + iw_buf + IW_EV_POINT_OFF); + + nlh->nlmsg_len = skb->tail - b; + + /* Needed ? */ + NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; + + err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); + if (err > 0) + err = 0; +out: + if(iw_buf != NULL) + kfree(iw_buf); dev_put(dev); - return err; + +rtattr_failure: +nlmsg_failure: + kfree_skb(skb); + goto out; } +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ -static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) +static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb) { int idx; int s_idx = cb->family; @@ -637,22 +595,20 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) { struct sk_buff *skb; - int err = -ENOBUFS; + int size = NLMSG_SPACE(sizeof(struct ifinfomsg) + + sizeof(struct rtnl_link_ifmap) + + sizeof(struct rtnl_link_stats) + 128); - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (skb == NULL) - goto errout; + skb = alloc_skb(size, GFP_KERNEL); + if (!skb) + return; - err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0); - if (err < 0) { + if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change, 0) < 0) { kfree_skb(skb); - goto errout; + return; } - - err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); -errout: - if (err < 0) - rtnl_set_sk_err(RTNLGRP_LINK, err); + NETLINK_CB(skb).dst_group = RTNLGRP_LINK; + netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_KERNEL); } /* Protected by RTNL sempahore. */ @@ -777,19 +733,18 @@ static void rtnetlink_rcv(struct sock *sk, int len) static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] = { - [RTM_GETLINK - RTM_BASE] = { .doit = rtnl_getlink, - .dumpit = rtnl_dump_ifinfo }, - [RTM_SETLINK - RTM_BASE] = { .doit = rtnl_setlink }, - [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnl_dump_all }, - [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnl_dump_all }, + [RTM_GETLINK - RTM_BASE] = { +#ifdef CONFIG_NET_WIRELESS_RTNETLINK + .doit = do_getlink, +#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ + .dumpit = rtnetlink_dump_ifinfo }, + [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink }, + [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, + [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, [RTM_NEWNEIGH - RTM_BASE] = { .doit = neigh_add }, [RTM_DELNEIGH - RTM_BASE] = { .doit = neigh_delete }, [RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info }, -#ifdef CONFIG_FIB_RULES - [RTM_NEWRULE - RTM_BASE] = { .doit = fib_nl_newrule }, - [RTM_DELRULE - RTM_BASE] = { .doit = fib_nl_delrule }, -#endif - [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnl_dump_all }, + [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, [RTM_GETNEIGHTBL - RTM_BASE] = { .dumpit = neightbl_dump_info }, [RTM_SETNEIGHTBL - RTM_BASE] = { .doit = neightbl_set }, }; @@ -849,9 +804,7 @@ EXPORT_SYMBOL(rtattr_strlcpy); EXPORT_SYMBOL(rtattr_parse); EXPORT_SYMBOL(rtnetlink_links); EXPORT_SYMBOL(rtnetlink_put_metrics); +EXPORT_SYMBOL(rtnl); EXPORT_SYMBOL(rtnl_lock); EXPORT_SYMBOL(rtnl_trylock); EXPORT_SYMBOL(rtnl_unlock); -EXPORT_SYMBOL(rtnl_unicast); -EXPORT_SYMBOL(rtnl_notify); -EXPORT_SYMBOL(rtnl_set_sk_err); diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index c448c7f6fde2..476aa3978504 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -70,6 +70,13 @@ static kmem_cache_t *skbuff_head_cache __read_mostly; static kmem_cache_t *skbuff_fclone_cache __read_mostly; +/* + * lockdep: lock class key used by skb_queue_head_init(): + */ +struct lock_class_key skb_queue_lock_key; + +EXPORT_SYMBOL(skb_queue_lock_key); + /* * Keep out-of-line to prevent kernel bloat. * __builtin_return_address is not used because it is not always @@ -249,31 +256,6 @@ struct sk_buff *alloc_skb_from_cache(kmem_cache_t *cp, goto out; } -/** - * __netdev_alloc_skb - allocate an skbuff for rx on a specific device - * @dev: network device to receive on - * @length: length to allocate - * @gfp_mask: get_free_pages mask, passed to alloc_skb - * - * Allocate a new &sk_buff and assign it a usage count of one. The - * buffer has unspecified headroom built in. Users should allocate - * the headroom they think they need without accounting for the - * built in space. The built in space is used for optimisations. - * - * %NULL is returned if there is no free memory. - */ -struct sk_buff *__netdev_alloc_skb(struct net_device *dev, - unsigned int length, gfp_t gfp_mask) -{ - struct sk_buff *skb; - - skb = alloc_skb(length + NET_SKB_PAD, gfp_mask); - if (likely(skb)) { - skb_reserve(skb, NET_SKB_PAD); - skb->dev = dev; - } - return skb; -} static void skb_drop_list(struct sk_buff **listp) { @@ -864,11 +846,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len) unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))) return err; - i = 0; - if (offset >= len) - goto drop_pages; - - for (; i < nfrags; i++) { + for (i = 0; i < nfrags; i++) { int end = offset + skb_shinfo(skb)->frags[i].size; if (end < len) { @@ -876,9 +854,9 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len) continue; } - skb_shinfo(skb)->frags[i++].size = len - offset; + if (len > offset) + skb_shinfo(skb)->frags[i++].size = len - offset; -drop_pages: skb_shinfo(skb)->nr_frags = i; for (; i < nfrags; i++) @@ -886,7 +864,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len) if (skb_shinfo(skb)->frag_list) skb_drop_fraglist(skb); - goto done; + break; } for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp); @@ -901,7 +879,6 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len) return -ENOMEM; nfrag->next = frag->next; - kfree_skb(frag); frag = nfrag; *fragp = frag; } @@ -920,7 +897,6 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len) break; } -done: if (len > skb_headlen(skb)) { skb->data_len -= skb->len - len; skb->len = len; @@ -1397,7 +1373,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) unsigned int csum; long csstart; - if (skb->ip_summed == CHECKSUM_PARTIAL) + if (skb->ip_summed == CHECKSUM_HW) csstart = skb->h.raw - skb->data; else csstart = skb_headlen(skb); @@ -1411,7 +1387,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) csum = skb_copy_and_csum_bits(skb, csstart, to + csstart, skb->len - csstart, 0); - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { long csstuff = csstart + skb->csum; *((unsigned short *)(to + csstuff)) = csum_fold(csum); @@ -1898,10 +1874,10 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, * @len: length of data pulled * * This function performs an skb_pull on the packet and updates - * update the CHECKSUM_COMPLETE checksum. It should be used on - * receive path processing instead of skb_pull unless you know - * that the checksum difference is zero (e.g., a valid IP header) - * or you are setting ip_summed to CHECKSUM_NONE. + * update the CHECKSUM_HW checksum. It should be used on receive + * path processing instead of skb_pull unless you know that the + * checksum difference is zero (e.g., a valid IP header) or you + * are setting ip_summed to CHECKSUM_NONE. */ unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) { @@ -1994,7 +1970,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) frag = skb_shinfo(nskb)->frags; k = 0; - nskb->ip_summed = CHECKSUM_PARTIAL; + nskb->ip_summed = CHECKSUM_HW; nskb->csum = skb->csum; memcpy(skb_put(nskb, hsize), skb->data + offset, hsize); @@ -2046,14 +2022,19 @@ void __init skb_init(void) skbuff_head_cache = kmem_cache_create("skbuff_head_cache", sizeof(struct sk_buff), 0, - SLAB_HWCACHE_ALIGN|SLAB_PANIC, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if (!skbuff_head_cache) + panic("cannot create skbuff cache"); + skbuff_fclone_cache = kmem_cache_create("skbuff_fclone_cache", (2*sizeof(struct sk_buff)) + sizeof(atomic_t), 0, - SLAB_HWCACHE_ALIGN|SLAB_PANIC, + SLAB_HWCACHE_ALIGN, NULL, NULL); + if (!skbuff_fclone_cache) + panic("cannot create skbuff cache"); } EXPORT_SYMBOL(___pskb_trim); @@ -2061,7 +2042,6 @@ EXPORT_SYMBOL(__kfree_skb); EXPORT_SYMBOL(kfree_skb); EXPORT_SYMBOL(__pskb_pull_tail); EXPORT_SYMBOL(__alloc_skb); -EXPORT_SYMBOL(__netdev_alloc_skb); EXPORT_SYMBOL(pskb_copy); EXPORT_SYMBOL(pskb_expand_head); EXPORT_SYMBOL(skb_checksum); diff --git a/trunk/net/core/sock.c b/trunk/net/core/sock.c index b77e155cbe6c..51fcfbc041a7 100644 --- a/trunk/net/core/sock.c +++ b/trunk/net/core/sock.c @@ -187,13 +187,13 @@ static struct lock_class_key af_callback_keys[AF_MAX]; #define SK_RMEM_MAX (_SK_MEM_OVERHEAD * _SK_MEM_PACKETS) /* Run time adjustable parameters. */ -__u32 sysctl_wmem_max __read_mostly = SK_WMEM_MAX; -__u32 sysctl_rmem_max __read_mostly = SK_RMEM_MAX; -__u32 sysctl_wmem_default __read_mostly = SK_WMEM_MAX; -__u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX; +__u32 sysctl_wmem_max = SK_WMEM_MAX; +__u32 sysctl_rmem_max = SK_RMEM_MAX; +__u32 sysctl_wmem_default = SK_WMEM_MAX; +__u32 sysctl_rmem_default = SK_RMEM_MAX; /* Maximal space eaten by iovec or ancilliary data plus some space */ -int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); +int sysctl_optmem_max = sizeof(unsigned long)*(2*UIO_MAXIOV + 512); static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen) { @@ -247,7 +247,11 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) goto out; } - err = sk_filter(sk, skb); + /* It would be deadlock, if sock_queue_rcv_skb is used + with socket lock! We assume that users of this + function are lock free. + */ + err = sk_filter(sk, skb, 1); if (err) goto out; @@ -274,7 +278,7 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb) { int rc = NET_RX_SUCCESS; - if (sk_filter(sk, skb)) + if (sk_filter(sk, skb, 0)) goto discard_and_relse; skb->dev = NULL; @@ -602,15 +606,15 @@ int sock_setsockopt(struct socket *sock, int level, int optname, break; case SO_DETACH_FILTER: - rcu_read_lock_bh(); - filter = rcu_dereference(sk->sk_filter); + spin_lock_bh(&sk->sk_lock.slock); + filter = sk->sk_filter; if (filter) { - rcu_assign_pointer(sk->sk_filter, NULL); + sk->sk_filter = NULL; + spin_unlock_bh(&sk->sk_lock.slock); sk_filter_release(sk, filter); - rcu_read_unlock_bh(); break; } - rcu_read_unlock_bh(); + spin_unlock_bh(&sk->sk_lock.slock); ret = -ENONET; break; @@ -880,10 +884,10 @@ void sk_free(struct sock *sk) if (sk->sk_destruct) sk->sk_destruct(sk); - filter = rcu_dereference(sk->sk_filter); + filter = sk->sk_filter; if (filter) { sk_filter_release(sk, filter); - rcu_assign_pointer(sk->sk_filter, NULL); + sk->sk_filter = NULL; } sock_disable_timestamp(sk); @@ -907,7 +911,7 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority) if (newsk != NULL) { struct sk_filter *filter; - sock_copy(newsk, sk); + memcpy(newsk, sk, sk->sk_prot->obj_size); /* SANITY */ sk_node_init(&newsk->sk_node); diff --git a/trunk/net/core/utils.c b/trunk/net/core/utils.c index 2682490777de..4f96f389243d 100644 --- a/trunk/net/core/utils.c +++ b/trunk/net/core/utils.c @@ -4,7 +4,6 @@ * Authors: * net_random Alan Cox * net_ratelimit Andy Kleen - * in{4,6}_pton YOSHIFUJI Hideaki, Copyright (C)2006 USAGI/WIDE Project * * Created by Alexey Kuznetsov * @@ -131,13 +130,12 @@ void __init net_random_init(void) static int net_random_reseed(void) { int i; - unsigned long seed; + unsigned long seed[NR_CPUS]; + get_random_bytes(seed, sizeof(seed)); for_each_possible_cpu(i) { struct nrnd_state *state = &per_cpu(net_rand_state,i); - - get_random_bytes(&seed, sizeof(seed)); - __net_srandom(state, seed); + __net_srandom(state, seed[i]); } return 0; } @@ -192,215 +190,3 @@ __be32 in_aton(const char *str) } EXPORT_SYMBOL(in_aton); - -#define IN6PTON_XDIGIT 0x00010000 -#define IN6PTON_DIGIT 0x00020000 -#define IN6PTON_COLON_MASK 0x00700000 -#define IN6PTON_COLON_1 0x00100000 /* single : requested */ -#define IN6PTON_COLON_2 0x00200000 /* second : requested */ -#define IN6PTON_COLON_1_2 0x00400000 /* :: requested */ -#define IN6PTON_DOT 0x00800000 /* . */ -#define IN6PTON_DELIM 0x10000000 -#define IN6PTON_NULL 0x20000000 /* first/tail */ -#define IN6PTON_UNKNOWN 0x40000000 - -static inline int digit2bin(char c, char delim) -{ - if (c == delim || c == '\0') - return IN6PTON_DELIM; - if (c == '.') - return IN6PTON_DOT; - if (c >= '0' && c <= '9') - return (IN6PTON_DIGIT | (c - '0')); - return IN6PTON_UNKNOWN; -} - -static inline int xdigit2bin(char c, char delim) -{ - if (c == delim || c == '\0') - return IN6PTON_DELIM; - if (c == ':') - return IN6PTON_COLON_MASK; - if (c == '.') - return IN6PTON_DOT; - if (c >= '0' && c <= '9') - return (IN6PTON_XDIGIT | IN6PTON_DIGIT| (c - '0')); - if (c >= 'a' && c <= 'f') - return (IN6PTON_XDIGIT | (c - 'a' + 10)); - if (c >= 'A' && c <= 'F') - return (IN6PTON_XDIGIT | (c - 'A' + 10)); - return IN6PTON_UNKNOWN; -} - -int in4_pton(const char *src, int srclen, - u8 *dst, - char delim, const char **end) -{ - const char *s; - u8 *d; - u8 dbuf[4]; - int ret = 0; - int i; - int w = 0; - - if (srclen < 0) - srclen = strlen(src); - s = src; - d = dbuf; - i = 0; - while(1) { - int c; - c = xdigit2bin(srclen > 0 ? *s : '\0', delim); - if (!(c & (IN6PTON_DIGIT | IN6PTON_DOT | IN6PTON_DELIM))) { - goto out; - } - if (c & (IN6PTON_DOT | IN6PTON_DELIM)) { - if (w == 0) - goto out; - *d++ = w & 0xff; - w = 0; - i++; - if (c & IN6PTON_DELIM) { - if (i != 4) - goto out; - break; - } - goto cont; - } - w = (w * 10) + c; - if ((w & 0xffff) > 255) { - goto out; - } -cont: - if (i >= 4) - goto out; - s++; - srclen--; - } - ret = 1; - memcpy(dst, dbuf, sizeof(dbuf)); -out: - if (end) - *end = s; - return ret; -} - -EXPORT_SYMBOL(in4_pton); - -int in6_pton(const char *src, int srclen, - u8 *dst, - char delim, const char **end) -{ - const char *s, *tok = NULL; - u8 *d, *dc = NULL; - u8 dbuf[16]; - int ret = 0; - int i; - int state = IN6PTON_COLON_1_2 | IN6PTON_XDIGIT | IN6PTON_NULL; - int w = 0; - - memset(dbuf, 0, sizeof(dbuf)); - - s = src; - d = dbuf; - if (srclen < 0) - srclen = strlen(src); - - while (1) { - int c; - - c = xdigit2bin(srclen > 0 ? *s : '\0', delim); - if (!(c & state)) - goto out; - if (c & (IN6PTON_DELIM | IN6PTON_COLON_MASK)) { - /* process one 16-bit word */ - if (!(state & IN6PTON_NULL)) { - *d++ = (w >> 8) & 0xff; - *d++ = w & 0xff; - } - w = 0; - if (c & IN6PTON_DELIM) { - /* We've processed last word */ - break; - } - /* - * COLON_1 => XDIGIT - * COLON_2 => XDIGIT|DELIM - * COLON_1_2 => COLON_2 - */ - switch (state & IN6PTON_COLON_MASK) { - case IN6PTON_COLON_2: - dc = d; - state = IN6PTON_XDIGIT | IN6PTON_DELIM; - if (dc - dbuf >= sizeof(dbuf)) - state |= IN6PTON_NULL; - break; - case IN6PTON_COLON_1|IN6PTON_COLON_1_2: - state = IN6PTON_XDIGIT | IN6PTON_COLON_2; - break; - case IN6PTON_COLON_1: - state = IN6PTON_XDIGIT; - break; - case IN6PTON_COLON_1_2: - state = IN6PTON_COLON_2; - break; - default: - state = 0; - } - tok = s + 1; - goto cont; - } - - if (c & IN6PTON_DOT) { - ret = in4_pton(tok ? tok : s, srclen + (int)(s - tok), d, delim, &s); - if (ret > 0) { - d += 4; - break; - } - goto out; - } - - w = (w << 4) | (0xff & c); - state = IN6PTON_COLON_1 | IN6PTON_DELIM; - if (!(w & 0xf000)) { - state |= IN6PTON_XDIGIT; - } - if (!dc && d + 2 < dbuf + sizeof(dbuf)) { - state |= IN6PTON_COLON_1_2; - state &= ~IN6PTON_DELIM; - } - if (d + 2 >= dbuf + sizeof(dbuf)) { - state &= ~(IN6PTON_COLON_1|IN6PTON_COLON_1_2); - } -cont: - if ((dc && d + 4 < dbuf + sizeof(dbuf)) || - d + 4 == dbuf + sizeof(dbuf)) { - state |= IN6PTON_DOT; - } - if (d >= dbuf + sizeof(dbuf)) { - state &= ~(IN6PTON_XDIGIT|IN6PTON_COLON_MASK); - } - s++; - srclen--; - } - - i = 15; d--; - - if (dc) { - while(d >= dc) - dst[i--] = *d--; - while(i >= dc - dbuf) - dst[i--] = 0; - while(i >= 0) - dst[i--] = *d--; - } else - memcpy(dst, dbuf, sizeof(dbuf)); - - ret = 1; -out: - if (end) - *end = s; - return ret; -} - -EXPORT_SYMBOL(in6_pton); diff --git a/trunk/net/core/wireless.c b/trunk/net/core/wireless.c index 3168fca312f7..d2bc72d318f7 100644 --- a/trunk/net/core/wireless.c +++ b/trunk/net/core/wireless.c @@ -72,6 +72,7 @@ /***************************** INCLUDES *****************************/ +#include /* Not needed ??? */ #include #include /* off_t */ #include /* struct ifreq, dev_get_by_name() */ @@ -81,11 +82,9 @@ #include /* for __init */ #include /* ARPHRD_ETHER */ #include /* compare_ether_addr */ -#include #include /* Pretty obvious */ #include /* New driver API */ -#include #include /* copy_to_user() */ @@ -1843,18 +1842,6 @@ int wireless_rtnetlink_set(struct net_device * dev, */ #ifdef WE_EVENT_RTNETLINK -static struct sk_buff_head wireless_nlevent_queue; - -static void wireless_nlevent_process(unsigned long data) -{ - struct sk_buff *skb; - - while ((skb = skb_dequeue(&wireless_nlevent_queue))) - rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); -} - -static DECLARE_TASKLET(wireless_nlevent_tasklet, wireless_nlevent_process, 0); - /* ---------------------------------------------------------------- */ /* * Fill a rtnetlink message with our event data. @@ -1917,17 +1904,8 @@ static inline void rtmsg_iwinfo(struct net_device * dev, return; } NETLINK_CB(skb).dst_group = RTNLGRP_LINK; - skb_queue_tail(&wireless_nlevent_queue, skb); - tasklet_schedule(&wireless_nlevent_tasklet); -} - -static int __init wireless_nlevent_init(void) -{ - skb_queue_head_init(&wireless_nlevent_queue); - return 0; + netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); } - -subsys_initcall(wireless_nlevent_init); #endif /* WE_EVENT_RTNETLINK */ /* ---------------------------------------------------------------- */ diff --git a/trunk/net/dccp/ackvec.c b/trunk/net/dccp/ackvec.c index 4d176d33983f..8c211c58893b 100644 --- a/trunk/net/dccp/ackvec.c +++ b/trunk/net/dccp/ackvec.c @@ -142,13 +142,14 @@ struct dccp_ackvec *dccp_ackvec_alloc(const gfp_t priority) struct dccp_ackvec *av = kmem_cache_alloc(dccp_ackvec_slab, priority); if (av != NULL) { - av->dccpav_buf_head = DCCP_MAX_ACKVEC_LEN - 1; + av->dccpav_buf_head = + av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1; av->dccpav_buf_ackno = DCCP_MAX_SEQNO + 1; av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0; av->dccpav_ack_ptr = 0; av->dccpav_time.tv_sec = 0; av->dccpav_time.tv_usec = 0; - av->dccpav_vec_len = 0; + av->dccpav_sent_len = av->dccpav_vec_len = 0; INIT_LIST_HEAD(&av->dccpav_records); } @@ -352,13 +353,11 @@ static void dccp_ackvec_throw_record(struct dccp_ackvec *av, { struct dccp_ackvec_record *next; - /* sort out vector length */ - if (av->dccpav_buf_head <= avr->dccpavr_ack_ptr) - av->dccpav_vec_len = avr->dccpavr_ack_ptr - av->dccpav_buf_head; - else - av->dccpav_vec_len = DCCP_MAX_ACKVEC_LEN - 1 - - av->dccpav_buf_head - + avr->dccpavr_ack_ptr; + av->dccpav_buf_tail = avr->dccpavr_ack_ptr - 1; + if (av->dccpav_buf_tail == 0) + av->dccpav_buf_tail = DCCP_MAX_ACKVEC_LEN - 1; + + av->dccpav_vec_len -= avr->dccpavr_sent_len; /* free records */ list_for_each_entry_safe_from(avr, next, &av->dccpav_records, @@ -435,7 +434,8 @@ static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, break; found: if (between48(avr->dccpavr_ack_seqno, ackno_end_rl, ackno)) { - const u8 state = *vector & DCCP_ACKVEC_STATE_MASK; + const u8 state = (*vector & + DCCP_ACKVEC_STATE_MASK) >> 6; if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { #ifdef CONFIG_IP_DCCP_DEBUG struct dccp_sock *dp = dccp_sk(sk); diff --git a/trunk/net/dccp/ackvec.h b/trunk/net/dccp/ackvec.h index 2424effac7f6..0adf4b56c34c 100644 --- a/trunk/net/dccp/ackvec.h +++ b/trunk/net/dccp/ackvec.h @@ -54,7 +54,9 @@ struct dccp_ackvec { struct list_head dccpav_records; struct timeval dccpav_time; u8 dccpav_buf_head; + u8 dccpav_buf_tail; u8 dccpav_ack_ptr; + u8 dccpav_sent_len; u8 dccpav_vec_len; u8 dccpav_buf_nonce; u8 dccpav_ack_nonce; @@ -105,7 +107,7 @@ extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb); static inline int dccp_ackvec_pending(const struct dccp_ackvec *av) { - return av->dccpav_vec_len; + return av->dccpav_sent_len != av->dccpav_vec_len; } #else /* CONFIG_IP_DCCP_ACKVEC */ static inline int dccp_ackvec_init(void) diff --git a/trunk/net/dccp/ccids/Kconfig b/trunk/net/dccp/ccids/Kconfig index 32752f750447..ca00191628f7 100644 --- a/trunk/net/dccp/ccids/Kconfig +++ b/trunk/net/dccp/ccids/Kconfig @@ -30,14 +30,6 @@ config IP_DCCP_CCID2 If in doubt, say M. -config IP_DCCP_CCID2_DEBUG - bool "CCID2 debug" - depends on IP_DCCP_CCID2 - ---help--- - Enable CCID2 debug messages. - - If in doubt, say N. - config IP_DCCP_CCID3 tristate "CCID3 (TCP-Friendly) (EXPERIMENTAL)" depends on IP_DCCP diff --git a/trunk/net/dccp/ccids/ccid2.c b/trunk/net/dccp/ccids/ccid2.c index 457dd3db7f41..e9615627dcd6 100644 --- a/trunk/net/dccp/ccids/ccid2.c +++ b/trunk/net/dccp/ccids/ccid2.c @@ -27,6 +27,7 @@ * * BUGS: * - sequence number wrapping + * - jiffies wrapping */ #include "../ccid.h" @@ -35,7 +36,8 @@ static int ccid2_debug; -#ifdef CONFIG_IP_DCCP_CCID2_DEBUG +#undef CCID2_DEBUG +#ifdef CCID2_DEBUG #define ccid2_pr_debug(format, a...) \ do { if (ccid2_debug) \ printk(KERN_DEBUG "%s: " format, __FUNCTION__, ##a); \ @@ -44,7 +46,9 @@ static int ccid2_debug; #define ccid2_pr_debug(format, a...) #endif -#ifdef CONFIG_IP_DCCP_CCID2_DEBUG +static const int ccid2_seq_len = 128; + +#ifdef CCID2_DEBUG static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) { int len = 0; @@ -67,8 +71,8 @@ static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) /* packets are sent sequentially */ BUG_ON(seqp->ccid2s_seq <= prev->ccid2s_seq); - BUG_ON(time_before(seqp->ccid2s_sent, - prev->ccid2s_sent)); + BUG_ON(seqp->ccid2s_sent < prev->ccid2s_sent); + BUG_ON(len > ccid2_seq_len); seqp = prev; } @@ -80,57 +84,16 @@ static void ccid2_hc_tx_check_sanity(const struct ccid2_hc_tx_sock *hctx) do { seqp = seqp->ccid2s_prev; len++; + BUG_ON(len > ccid2_seq_len); } while (seqp != hctx->ccid2hctx_seqh); + BUG_ON(len != ccid2_seq_len); ccid2_pr_debug("total len=%d\n", len); - BUG_ON(len != hctx->ccid2hctx_seqbufc * CCID2_SEQBUF_LEN); } #else #define ccid2_hc_tx_check_sanity(hctx) do {} while (0) #endif -static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hctx, int num, - gfp_t gfp) -{ - struct ccid2_seq *seqp; - int i; - - /* check if we have space to preserve the pointer to the buffer */ - if (hctx->ccid2hctx_seqbufc >= (sizeof(hctx->ccid2hctx_seqbuf) / - sizeof(struct ccid2_seq*))) - return -ENOMEM; - - /* allocate buffer and initialize linked list */ - seqp = kmalloc(sizeof(*seqp) * num, gfp); - if (seqp == NULL) - return -ENOMEM; - - for (i = 0; i < (num - 1); i++) { - seqp[i].ccid2s_next = &seqp[i + 1]; - seqp[i + 1].ccid2s_prev = &seqp[i]; - } - seqp[num - 1].ccid2s_next = seqp; - seqp->ccid2s_prev = &seqp[num - 1]; - - /* This is the first allocation. Initiate the head and tail. */ - if (hctx->ccid2hctx_seqbufc == 0) - hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqt = seqp; - else { - /* link the existing list with the one we just created */ - hctx->ccid2hctx_seqh->ccid2s_next = seqp; - seqp->ccid2s_prev = hctx->ccid2hctx_seqh; - - hctx->ccid2hctx_seqt->ccid2s_prev = &seqp[num - 1]; - seqp[num - 1].ccid2s_next = hctx->ccid2hctx_seqt; - } - - /* store the original pointer to the buffer so we can free it */ - hctx->ccid2hctx_seqbuf[hctx->ccid2hctx_seqbufc] = seqp; - hctx->ccid2hctx_seqbufc++; - - return 0; -} - static int ccid2_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb, int len) { @@ -159,7 +122,7 @@ static int ccid2_hc_tx_send_packet(struct sock *sk, } } - return 1; /* XXX CCID should dequeue when ready instead of polling */ + return 100; /* XXX */ } static void ccid2_change_l_ack_ratio(struct sock *sk, int val) @@ -187,8 +150,10 @@ static void ccid2_change_l_ack_ratio(struct sock *sk, int val) dp->dccps_l_ack_ratio = val; } -static void ccid2_change_cwnd(struct ccid2_hc_tx_sock *hctx, int val) +static void ccid2_change_cwnd(struct sock *sk, int val) { + struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); + if (val == 0) val = 1; @@ -199,17 +164,6 @@ static void ccid2_change_cwnd(struct ccid2_hc_tx_sock *hctx, int val) hctx->ccid2hctx_cwnd = val; } -static void ccid2_change_srtt(struct ccid2_hc_tx_sock *hctx, long val) -{ - ccid2_pr_debug("change SRTT to %ld\n", val); - hctx->ccid2hctx_srtt = val; -} - -static void ccid2_change_pipe(struct ccid2_hc_tx_sock *hctx, long val) -{ - hctx->ccid2hctx_pipe = val; -} - static void ccid2_start_rto_timer(struct sock *sk); static void ccid2_hc_tx_rto_expire(unsigned long data) @@ -239,11 +193,11 @@ static void ccid2_hc_tx_rto_expire(unsigned long data) ccid2_start_rto_timer(sk); /* adjust pipe, cwnd etc */ - ccid2_change_pipe(hctx, 0); + hctx->ccid2hctx_pipe = 0; hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd >> 1; if (hctx->ccid2hctx_ssthresh < 2) hctx->ccid2hctx_ssthresh = 2; - ccid2_change_cwnd(hctx, 1); + ccid2_change_cwnd(sk, 1); /* clear state about stuff we sent */ hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh; @@ -278,14 +232,13 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) { struct dccp_sock *dp = dccp_sk(sk); struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); - struct ccid2_seq *next; u64 seq; ccid2_hc_tx_check_sanity(hctx); BUG_ON(!hctx->ccid2hctx_sendwait); hctx->ccid2hctx_sendwait = 0; - ccid2_change_pipe(hctx, hctx->ccid2hctx_pipe + 1); + hctx->ccid2hctx_pipe++; BUG_ON(hctx->ccid2hctx_pipe < 0); /* There is an issue. What if another packet is sent between @@ -298,24 +251,16 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) hctx->ccid2hctx_seqh->ccid2s_seq = seq; hctx->ccid2hctx_seqh->ccid2s_acked = 0; hctx->ccid2hctx_seqh->ccid2s_sent = jiffies; - - next = hctx->ccid2hctx_seqh->ccid2s_next; - /* check if we need to alloc more space */ - if (next == hctx->ccid2hctx_seqt) { - int rc; - - ccid2_pr_debug("allocating more space in history\n"); - rc = ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, GFP_KERNEL); - BUG_ON(rc); /* XXX what do we do? */ - - next = hctx->ccid2hctx_seqh->ccid2s_next; - BUG_ON(next == hctx->ccid2hctx_seqt); - } - hctx->ccid2hctx_seqh = next; + hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqh->ccid2s_next; ccid2_pr_debug("cwnd=%d pipe=%d\n", hctx->ccid2hctx_cwnd, hctx->ccid2hctx_pipe); + if (hctx->ccid2hctx_seqh == hctx->ccid2hctx_seqt) { + /* XXX allocate more space */ + WARN_ON(1); + } + hctx->ccid2hctx_sent++; /* Ack Ratio. Need to maintain a concept of how many windows we sent */ @@ -350,7 +295,7 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) if (!timer_pending(&hctx->ccid2hctx_rtotimer)) ccid2_start_rto_timer(sk); -#ifdef CONFIG_IP_DCCP_CCID2_DEBUG +#ifdef CCID2_DEBUG ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe); ccid2_pr_debug("Sent: seq=%llu\n", seq); do { @@ -453,7 +398,7 @@ static inline void ccid2_new_ack(struct sock *sk, /* increase every 2 acks */ hctx->ccid2hctx_ssacks++; if (hctx->ccid2hctx_ssacks == 2) { - ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd+1); + ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1); hctx->ccid2hctx_ssacks = 0; *maxincr = *maxincr - 1; } @@ -466,28 +411,26 @@ static inline void ccid2_new_ack(struct sock *sk, hctx->ccid2hctx_acks++; if (hctx->ccid2hctx_acks >= hctx->ccid2hctx_cwnd) { - ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd + 1); + ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd + 1); hctx->ccid2hctx_acks = 0; } } /* update RTO */ if (hctx->ccid2hctx_srtt == -1 || - time_after(jiffies, hctx->ccid2hctx_lastrtt + hctx->ccid2hctx_srtt)) { - unsigned long r = (long)jiffies - (long)seqp->ccid2s_sent; + (jiffies - hctx->ccid2hctx_lastrtt) >= hctx->ccid2hctx_srtt) { + unsigned long r = jiffies - seqp->ccid2s_sent; int s; /* first measurement */ if (hctx->ccid2hctx_srtt == -1) { ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n", r, jiffies, seqp->ccid2s_seq); - ccid2_change_srtt(hctx, r); + hctx->ccid2hctx_srtt = r; hctx->ccid2hctx_rttvar = r >> 1; } else { /* RTTVAR */ long tmp = hctx->ccid2hctx_srtt - r; - long srtt; - if (tmp < 0) tmp *= -1; @@ -497,12 +440,10 @@ static inline void ccid2_new_ack(struct sock *sk, hctx->ccid2hctx_rttvar += tmp; /* SRTT */ - srtt = hctx->ccid2hctx_srtt; - srtt *= 7; - srtt >>= 3; + hctx->ccid2hctx_srtt *= 7; + hctx->ccid2hctx_srtt >>= 3; tmp = r >> 3; - srtt += tmp; - ccid2_change_srtt(hctx, srtt); + hctx->ccid2hctx_srtt += tmp; } s = hctx->ccid2hctx_rttvar << 2; /* clock granularity is 1 when based on jiffies */ @@ -538,29 +479,13 @@ static void ccid2_hc_tx_dec_pipe(struct sock *sk) { struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); - ccid2_change_pipe(hctx, hctx->ccid2hctx_pipe-1); + hctx->ccid2hctx_pipe--; BUG_ON(hctx->ccid2hctx_pipe < 0); if (hctx->ccid2hctx_pipe == 0) ccid2_hc_tx_kill_rto_timer(sk); } -static void ccid2_congestion_event(struct ccid2_hc_tx_sock *hctx, - struct ccid2_seq *seqp) -{ - if (time_before(seqp->ccid2s_sent, hctx->ccid2hctx_last_cong)) { - ccid2_pr_debug("Multiple losses in an RTT---treating as one\n"); - return; - } - - hctx->ccid2hctx_last_cong = jiffies; - - ccid2_change_cwnd(hctx, hctx->ccid2hctx_cwnd >> 1); - hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd; - if (hctx->ccid2hctx_ssthresh < 2) - hctx->ccid2hctx_ssthresh = 2; -} - static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) { struct dccp_sock *dp = dccp_sk(sk); @@ -571,6 +496,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) unsigned char veclen; int offset = 0; int done = 0; + int loss = 0; unsigned int maxincr = 0; ccid2_hc_tx_check_sanity(hctx); @@ -656,16 +582,15 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) * run length */ while (between48(seqp->ccid2s_seq,ackno_end_rl,ackno)) { - const u8 state = *vector & - DCCP_ACKVEC_STATE_MASK; + const u8 state = (*vector & + DCCP_ACKVEC_STATE_MASK) >> 6; /* new packet received or marked */ if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED && !seqp->ccid2s_acked) { if (state == DCCP_ACKVEC_STATE_ECN_MARKED) { - ccid2_congestion_event(hctx, - seqp); + loss = 1; } else ccid2_new_ack(sk, seqp, &maxincr); @@ -717,13 +642,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* check for lost packets */ while (1) { if (!seqp->ccid2s_acked) { - ccid2_pr_debug("Packet lost: %llu\n", - seqp->ccid2s_seq); - /* XXX need to traverse from tail -> head in - * order to detect multiple congestion events in - * one ack vector. - */ - ccid2_congestion_event(hctx, seqp); + loss = 1; ccid2_hc_tx_dec_pipe(sk); } if (seqp == hctx->ccid2hctx_seqt) @@ -742,33 +661,53 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqt->ccid2s_next; } + if (loss) { + /* XXX do bit shifts guarantee a 0 as the new bit? */ + ccid2_change_cwnd(sk, hctx->ccid2hctx_cwnd >> 1); + hctx->ccid2hctx_ssthresh = hctx->ccid2hctx_cwnd; + if (hctx->ccid2hctx_ssthresh < 2) + hctx->ccid2hctx_ssthresh = 2; + } + ccid2_hc_tx_check_sanity(hctx); } static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) { struct ccid2_hc_tx_sock *hctx = ccid_priv(ccid); + int seqcount = ccid2_seq_len; + int i; - ccid2_change_cwnd(hctx, 1); - /* Initialize ssthresh to infinity. This means that we will exit the - * initial slow-start after the first packet loss. This is what we - * want. - */ - hctx->ccid2hctx_ssthresh = ~0; + /* XXX init variables with proper values */ + hctx->ccid2hctx_cwnd = 1; + hctx->ccid2hctx_ssthresh = 10; hctx->ccid2hctx_numdupack = 3; - hctx->ccid2hctx_seqbufc = 0; /* XXX init ~ to window size... */ - if (ccid2_hc_tx_alloc_seq(hctx, CCID2_SEQBUF_LEN, GFP_ATOMIC) != 0) + hctx->ccid2hctx_seqbuf = kmalloc(sizeof(*hctx->ccid2hctx_seqbuf) * + seqcount, gfp_any()); + if (hctx->ccid2hctx_seqbuf == NULL) return -ENOMEM; + for (i = 0; i < (seqcount - 1); i++) { + hctx->ccid2hctx_seqbuf[i].ccid2s_next = + &hctx->ccid2hctx_seqbuf[i + 1]; + hctx->ccid2hctx_seqbuf[i + 1].ccid2s_prev = + &hctx->ccid2hctx_seqbuf[i]; + } + hctx->ccid2hctx_seqbuf[seqcount - 1].ccid2s_next = + hctx->ccid2hctx_seqbuf; + hctx->ccid2hctx_seqbuf->ccid2s_prev = + &hctx->ccid2hctx_seqbuf[seqcount - 1]; + + hctx->ccid2hctx_seqh = hctx->ccid2hctx_seqbuf; + hctx->ccid2hctx_seqt = hctx->ccid2hctx_seqh; hctx->ccid2hctx_sent = 0; hctx->ccid2hctx_rto = 3 * HZ; - ccid2_change_srtt(hctx, -1); + hctx->ccid2hctx_srtt = -1; hctx->ccid2hctx_rttvar = -1; hctx->ccid2hctx_lastrtt = 0; hctx->ccid2hctx_rpdupack = -1; - hctx->ccid2hctx_last_cong = jiffies; hctx->ccid2hctx_rtotimer.function = &ccid2_hc_tx_rto_expire; hctx->ccid2hctx_rtotimer.data = (unsigned long)sk; @@ -781,13 +720,10 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) static void ccid2_hc_tx_exit(struct sock *sk) { struct ccid2_hc_tx_sock *hctx = ccid2_hc_tx_sk(sk); - int i; ccid2_hc_tx_kill_rto_timer(sk); - - for (i = 0; i < hctx->ccid2hctx_seqbufc; i++) - kfree(hctx->ccid2hctx_seqbuf[i]); - hctx->ccid2hctx_seqbufc = 0; + kfree(hctx->ccid2hctx_seqbuf); + hctx->ccid2hctx_seqbuf = NULL; } static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) diff --git a/trunk/net/dccp/ccids/ccid2.h b/trunk/net/dccp/ccids/ccid2.h index 5b2ef4acb300..451a87464fa5 100644 --- a/trunk/net/dccp/ccids/ccid2.h +++ b/trunk/net/dccp/ccids/ccid2.h @@ -35,9 +35,6 @@ struct ccid2_seq { struct ccid2_seq *ccid2s_next; }; -#define CCID2_SEQBUF_LEN 256 -#define CCID2_SEQBUF_MAX 128 - /** struct ccid2_hc_tx_sock - CCID2 TX half connection * * @ccid2hctx_ssacks - ACKs recv in slow start @@ -53,11 +50,10 @@ struct ccid2_hc_tx_sock { int ccid2hctx_cwnd; int ccid2hctx_ssacks; int ccid2hctx_acks; - unsigned int ccid2hctx_ssthresh; + int ccid2hctx_ssthresh; int ccid2hctx_pipe; int ccid2hctx_numdupack; - struct ccid2_seq *ccid2hctx_seqbuf[CCID2_SEQBUF_MAX]; - int ccid2hctx_seqbufc; + struct ccid2_seq *ccid2hctx_seqbuf; struct ccid2_seq *ccid2hctx_seqh; struct ccid2_seq *ccid2hctx_seqt; long ccid2hctx_rto; @@ -71,7 +67,6 @@ struct ccid2_hc_tx_sock { u64 ccid2hctx_rpseq; int ccid2hctx_rpdupack; int ccid2hctx_sendwait; - unsigned long ccid2hctx_last_cong; }; struct ccid2_hc_rx_sock { diff --git a/trunk/net/dccp/ccids/ccid3.c b/trunk/net/dccp/ccids/ccid3.c index 195aa9566228..c39bff706cfc 100644 --- a/trunk/net/dccp/ccids/ccid3.c +++ b/trunk/net/dccp/ccids/ccid3.c @@ -2,7 +2,7 @@ * net/dccp/ccids/ccid3.c * * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. - * Copyright (c) 2005-6 Ian McDonald + * Copyright (c) 2005-6 Ian McDonald * * An implementation of the DCCP protocol * @@ -342,8 +342,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, new_packet->dccphtx_ccval = DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count; - timeval_add_usecs(&hctx->ccid3hctx_t_nom, - hctx->ccid3hctx_t_ipi); } out: return rc; @@ -415,8 +413,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) case TFRC_SSTATE_NO_FBACK: case TFRC_SSTATE_FBACK: if (len > 0) { - timeval_sub_usecs(&hctx->ccid3hctx_t_nom, - hctx->ccid3hctx_t_ipi); + hctx->ccid3hctx_t_nom = now; ccid3_calc_new_t_ipi(hctx); ccid3_calc_new_delta(hctx); timeval_add_usecs(&hctx->ccid3hctx_t_nom, @@ -760,7 +757,8 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) } hcrx->ccid3hcrx_tstamp_last_feedback = now; - hcrx->ccid3hcrx_ccval_last_counter = packet->dccphrx_ccval; + hcrx->ccid3hcrx_last_counter = packet->dccphrx_ccval; + hcrx->ccid3hcrx_seqno_last_counter = packet->dccphrx_seqno; hcrx->ccid3hcrx_bytes_recv = 0; /* Convert to multiples of 10us */ @@ -784,7 +782,7 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) return 0; - DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_ccval_last_counter; + DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter; if (dccp_packet_without_ack(skb)) return 0; @@ -856,11 +854,6 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) interval = 1; } found: - if (!tail) { - LIMIT_NETDEBUG(KERN_WARNING "%s: tail is null\n", - __FUNCTION__); - return ~0; - } rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval; ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", dccp_role(sk), sk, rtt); @@ -871,20 +864,9 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta); - if (x_recv == 0) - x_recv = hcrx->ccid3hcrx_x_recv; - tmp1 = (u64)x_recv * (u64)rtt; do_div(tmp1,10000000); tmp2 = (u32)tmp1; - - if (!tmp2) { - LIMIT_NETDEBUG(KERN_WARNING "tmp2 = 0 " - "%s: x_recv = %u, rtt =%u\n", - __FUNCTION__, x_recv, rtt); - return ~0; - } - fval = (hcrx->ccid3hcrx_s * 100000) / tmp2; /* do not alter order above or you will get overflow on 32 bit */ p = tfrc_calc_x_reverse_lookup(fval); @@ -900,101 +882,31 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) { struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); - struct dccp_li_hist_entry *head; - u64 seq_temp; - if (list_empty(&hcrx->ccid3hcrx_li_hist)) { - if (!dccp_li_hist_interval_new(ccid3_li_hist, - &hcrx->ccid3hcrx_li_hist, seq_loss, win_loss)) - return; + if (seq_loss != DCCP_MAX_SEQNO + 1 && + list_empty(&hcrx->ccid3hcrx_li_hist)) { + struct dccp_li_hist_entry *li_tail; - head = list_entry(hcrx->ccid3hcrx_li_hist.next, - struct dccp_li_hist_entry, dccplih_node); - head->dccplih_interval = ccid3_hc_rx_calc_first_li(sk); - } else { - struct dccp_li_hist_entry *entry; - struct list_head *tail; - - head = list_entry(hcrx->ccid3hcrx_li_hist.next, - struct dccp_li_hist_entry, dccplih_node); - /* FIXME win count check removed as was wrong */ - /* should make this check with receive history */ - /* and compare there as per section 10.2 of RFC4342 */ - - /* new loss event detected */ - /* calculate last interval length */ - seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss); - entry = dccp_li_hist_entry_new(ccid3_li_hist, SLAB_ATOMIC); - - if (entry == NULL) { - printk(KERN_CRIT "%s: out of memory\n",__FUNCTION__); - dump_stack(); + li_tail = dccp_li_hist_interval_new(ccid3_li_hist, + &hcrx->ccid3hcrx_li_hist, + seq_loss, win_loss); + if (li_tail == NULL) return; - } - - list_add(&entry->dccplih_node, &hcrx->ccid3hcrx_li_hist); - - tail = hcrx->ccid3hcrx_li_hist.prev; - list_del(tail); - kmem_cache_free(ccid3_li_hist->dccplih_slab, tail); - - /* Create the newest interval */ - entry->dccplih_seqno = seq_loss; - entry->dccplih_interval = seq_temp; - entry->dccplih_win_count = win_loss; - } + li_tail->dccplih_interval = ccid3_hc_rx_calc_first_li(sk); + } else + LIMIT_NETDEBUG(KERN_WARNING "%s: FIXME: find end of " + "interval\n", __FUNCTION__); } -static int ccid3_hc_rx_detect_loss(struct sock *sk, - struct dccp_rx_hist_entry *packet) +static void ccid3_hc_rx_detect_loss(struct sock *sk) { struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); - struct dccp_rx_hist_entry *rx_hist = dccp_rx_hist_head(&hcrx->ccid3hcrx_hist); - u64 seqno = packet->dccphrx_seqno; - u64 tmp_seqno; - int loss = 0; - u8 ccval; - - - tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss; - - if (!rx_hist || - follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) { - hcrx->ccid3hcrx_seqno_nonloss = seqno; - hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval; - goto detect_out; - } - + u8 win_loss; + const u64 seq_loss = dccp_rx_hist_detect_loss(&hcrx->ccid3hcrx_hist, + &hcrx->ccid3hcrx_li_hist, + &win_loss); - while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno) - > TFRC_RECV_NUM_LATE_LOSS) { - loss = 1; - ccid3_hc_rx_update_li(sk, hcrx->ccid3hcrx_seqno_nonloss, - hcrx->ccid3hcrx_ccval_nonloss); - tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss; - dccp_inc_seqno(&tmp_seqno); - hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno; - dccp_inc_seqno(&tmp_seqno); - while (dccp_rx_hist_find_entry(&hcrx->ccid3hcrx_hist, - tmp_seqno, &ccval)) { - hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno; - hcrx->ccid3hcrx_ccval_nonloss = ccval; - dccp_inc_seqno(&tmp_seqno); - } - } - - /* FIXME - this code could be simplified with above while */ - /* but works at moment */ - if (follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) { - hcrx->ccid3hcrx_seqno_nonloss = seqno; - hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval; - } - -detect_out: - dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist, - &hcrx->ccid3hcrx_li_hist, packet, - hcrx->ccid3hcrx_seqno_nonloss); - return loss; + ccid3_hc_rx_update_li(sk, seq_loss, win_loss); } static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) @@ -1004,8 +916,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) struct dccp_rx_hist_entry *packet; struct timeval now; u8 win_count; - u32 p_prev, rtt_prev, r_sample, t_elapsed; - int loss; + u32 p_prev, r_sample, t_elapsed; + int ins; BUG_ON(hcrx == NULL || !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA || @@ -1020,7 +932,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) case DCCP_PKT_DATAACK: if (opt_recv->dccpor_timestamp_echo == 0) break; - rtt_prev = hcrx->ccid3hcrx_rtt; + p_prev = hcrx->ccid3hcrx_rtt; dccp_timestamp(sk, &now); timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10); r_sample = timeval_usecs(&now); @@ -1039,8 +951,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 + r_sample / 10; - if (rtt_prev != hcrx->ccid3hcrx_rtt) - ccid3_pr_debug("%s, New RTT=%uus, elapsed time=%u\n", + if (p_prev != hcrx->ccid3hcrx_rtt) + ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n", dccp_role(sk), hcrx->ccid3hcrx_rtt, opt_recv->dccpor_elapsed_time); break; @@ -1061,7 +973,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) win_count = packet->dccphrx_ccval; - loss = ccid3_hc_rx_detect_loss(sk, packet); + ins = dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist, + &hcrx->ccid3hcrx_li_hist, packet); if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK) return; @@ -1078,7 +991,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) case TFRC_RSTATE_DATA: hcrx->ccid3hcrx_bytes_recv += skb->len - dccp_hdr(skb)->dccph_doff * 4; - if (loss) + if (ins != 0) break; dccp_timestamp(sk, &now); @@ -1099,6 +1012,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n", dccp_role(sk), sk, dccp_state_name(sk->sk_state)); + ccid3_hc_rx_detect_loss(sk); p_prev = hcrx->ccid3hcrx_p; /* Calculate loss event rate */ @@ -1108,9 +1022,6 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) /* Scaling up by 1000000 as fixed decimal */ if (i_mean != 0) hcrx->ccid3hcrx_p = 1000000 / i_mean; - } else { - printk(KERN_CRIT "%s: empty loss hist\n",__FUNCTION__); - dump_stack(); } if (hcrx->ccid3hcrx_p > p_prev) { @@ -1319,7 +1230,7 @@ static __exit void ccid3_module_exit(void) } module_exit(ccid3_module_exit); -MODULE_AUTHOR("Ian McDonald , " +MODULE_AUTHOR("Ian McDonald , " "Arnaldo Carvalho de Melo "); MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID"); MODULE_LICENSE("GPL"); diff --git a/trunk/net/dccp/ccids/ccid3.h b/trunk/net/dccp/ccids/ccid3.h index 0a2cb7536d26..5ade4f668b22 100644 --- a/trunk/net/dccp/ccids/ccid3.h +++ b/trunk/net/dccp/ccids/ccid3.h @@ -1,13 +1,13 @@ /* * net/dccp/ccids/ccid3.h * - * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand. + * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. * * An implementation of the DCCP protocol * * This code has been developed by the University of Waikato WAND * research group. For further information please see http://www.wand.net.nz/ - * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz + * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz * * This code also uses code from Lulea University, rereleased as GPL by its * authors: @@ -120,10 +120,9 @@ struct ccid3_hc_rx_sock { #define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv #define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt #define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p - u64 ccid3hcrx_seqno_nonloss:48, - ccid3hcrx_ccval_nonloss:4, + u64 ccid3hcrx_seqno_last_counter:48, ccid3hcrx_state:8, - ccid3hcrx_ccval_last_counter:4; + ccid3hcrx_last_counter:4; u32 ccid3hcrx_bytes_recv; struct timeval ccid3hcrx_tstamp_last_feedback; struct timeval ccid3hcrx_tstamp_last_ack; diff --git a/trunk/net/dccp/ccids/lib/loss_interval.c b/trunk/net/dccp/ccids/lib/loss_interval.c index 906c81ab9d4f..5d7b7d864385 100644 --- a/trunk/net/dccp/ccids/lib/loss_interval.c +++ b/trunk/net/dccp/ccids/lib/loss_interval.c @@ -2,7 +2,7 @@ * net/dccp/ccids/lib/loss_interval.c * * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. - * Copyright (c) 2005-6 Ian McDonald + * Copyright (c) 2005 Ian McDonald * Copyright (c) 2005 Arnaldo Carvalho de Melo * * This program is free software; you can redistribute it and/or modify @@ -12,7 +12,6 @@ */ #include -#include #include "loss_interval.h" @@ -91,13 +90,13 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list) u32 w_tot = 0; list_for_each_entry_safe(li_entry, li_next, list, dccplih_node) { - if (li_entry->dccplih_interval != ~0) { + if (i < DCCP_LI_HIST_IVAL_F_LENGTH) { i_tot0 += li_entry->dccplih_interval * dccp_li_hist_w[i]; w_tot += dccp_li_hist_w[i]; - if (i != 0) - i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1]; } + if (i != 0) + i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1]; if (++i > DCCP_LI_HIST_IVAL_F_LENGTH) break; @@ -108,36 +107,37 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list) i_tot = max(i_tot0, i_tot1); - if (!w_tot) { - LIMIT_NETDEBUG(KERN_WARNING "%s: w_tot = 0\n", __FUNCTION__); - return 1; - } + /* FIXME: Why do we do this? -Ian McDonald */ + if (i_tot * 4 < w_tot) + i_tot = w_tot * 4; - return i_tot / w_tot; + return i_tot * 4 / w_tot; } EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean); -int dccp_li_hist_interval_new(struct dccp_li_hist *hist, - struct list_head *list, const u64 seq_loss, const u8 win_loss) +struct dccp_li_hist_entry *dccp_li_hist_interval_new(struct dccp_li_hist *hist, + struct list_head *list, + const u64 seq_loss, + const u8 win_loss) { - struct dccp_li_hist_entry *entry; + struct dccp_li_hist_entry *tail = NULL, *entry; int i; - for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) { + for (i = 0; i <= DCCP_LI_HIST_IVAL_F_LENGTH; ++i) { entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC); if (entry == NULL) { dccp_li_hist_purge(hist, list); - dump_stack(); - return 0; + return NULL; } - entry->dccplih_interval = ~0; + if (tail == NULL) + tail = entry; list_add(&entry->dccplih_node, list); } entry->dccplih_seqno = seq_loss; entry->dccplih_win_count = win_loss; - return 1; + return tail; } EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new); diff --git a/trunk/net/dccp/ccids/lib/loss_interval.h b/trunk/net/dccp/ccids/lib/loss_interval.h index 0ae85f0340b2..43bf78269d1d 100644 --- a/trunk/net/dccp/ccids/lib/loss_interval.h +++ b/trunk/net/dccp/ccids/lib/loss_interval.h @@ -4,7 +4,7 @@ * net/dccp/ccids/lib/loss_interval.h * * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. - * Copyright (c) 2005 Ian McDonald + * Copyright (c) 2005 Ian McDonald * Copyright (c) 2005 Arnaldo Carvalho de Melo * * This program is free software; you can redistribute it and/or modify it @@ -52,6 +52,9 @@ extern void dccp_li_hist_purge(struct dccp_li_hist *hist, extern u32 dccp_li_hist_calc_i_mean(struct list_head *list); -extern int dccp_li_hist_interval_new(struct dccp_li_hist *hist, - struct list_head *list, const u64 seq_loss, const u8 win_loss); +extern struct dccp_li_hist_entry * + dccp_li_hist_interval_new(struct dccp_li_hist *hist, + struct list_head *list, + const u64 seq_loss, + const u8 win_loss); #endif /* _DCCP_LI_HIST_ */ diff --git a/trunk/net/dccp/ccids/lib/packet_history.c b/trunk/net/dccp/ccids/lib/packet_history.c index b876c9c81c65..ad98d6a322eb 100644 --- a/trunk/net/dccp/ccids/lib/packet_history.c +++ b/trunk/net/dccp/ccids/lib/packet_history.c @@ -1,13 +1,13 @@ /* - * net/dccp/packet_history.c + * net/dccp/packet_history.h * - * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand. + * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. * * An implementation of the DCCP protocol * * This code has been developed by the University of Waikato WAND * research group. For further information please see http://www.wand.net.nz/ - * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz + * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz * * This code also uses code from Lulea University, rereleased as GPL by its * authors: @@ -112,27 +112,64 @@ struct dccp_rx_hist_entry * EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet); -void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, +int dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, struct list_head *rx_list, struct list_head *li_list, - struct dccp_rx_hist_entry *packet, - u64 nonloss_seqno) + struct dccp_rx_hist_entry *packet) { - struct dccp_rx_hist_entry *entry, *next; + struct dccp_rx_hist_entry *entry, *next, *iter; u8 num_later = 0; - list_add(&packet->dccphrx_node, rx_list); + iter = dccp_rx_hist_head(rx_list); + if (iter == NULL) + dccp_rx_hist_add_entry(rx_list, packet); + else { + const u64 seqno = packet->dccphrx_seqno; + + if (after48(seqno, iter->dccphrx_seqno)) + dccp_rx_hist_add_entry(rx_list, packet); + else { + if (dccp_rx_hist_entry_data_packet(iter)) + num_later = 1; + + list_for_each_entry_continue(iter, rx_list, + dccphrx_node) { + if (after48(seqno, iter->dccphrx_seqno)) { + dccp_rx_hist_add_entry(&iter->dccphrx_node, + packet); + goto trim_history; + } + + if (dccp_rx_hist_entry_data_packet(iter)) + num_later++; + if (num_later == TFRC_RECV_NUM_LATE_LOSS) { + dccp_rx_hist_entry_delete(hist, packet); + return 1; + } + } + + if (num_later < TFRC_RECV_NUM_LATE_LOSS) + dccp_rx_hist_add_entry(rx_list, packet); + /* + * FIXME: else what? should we destroy the packet + * like above? + */ + } + } + +trim_history: + /* + * Trim history (remove all packets after the NUM_LATE_LOSS + 1 + * data packets) + */ num_later = TFRC_RECV_NUM_LATE_LOSS + 1; if (!list_empty(li_list)) { list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) { if (num_later == 0) { - if (after48(nonloss_seqno, - entry->dccphrx_seqno)) { - list_del_init(&entry->dccphrx_node); - dccp_rx_hist_entry_delete(hist, entry); - } + list_del_init(&entry->dccphrx_node); + dccp_rx_hist_entry_delete(hist, entry); } else if (dccp_rx_hist_entry_data_packet(entry)) --num_later; } @@ -180,10 +217,94 @@ void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, --num_later; } } + + return 0; } EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet); +u64 dccp_rx_hist_detect_loss(struct list_head *rx_list, + struct list_head *li_list, u8 *win_loss) +{ + struct dccp_rx_hist_entry *entry, *next, *packet; + struct dccp_rx_hist_entry *a_loss = NULL; + struct dccp_rx_hist_entry *b_loss = NULL; + u64 seq_loss = DCCP_MAX_SEQNO + 1; + u8 num_later = TFRC_RECV_NUM_LATE_LOSS; + + list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) { + if (num_later == 0) { + b_loss = entry; + break; + } else if (dccp_rx_hist_entry_data_packet(entry)) + --num_later; + } + + if (b_loss == NULL) + goto out; + + num_later = 1; + list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) { + if (num_later == 0) { + a_loss = entry; + break; + } else if (dccp_rx_hist_entry_data_packet(entry)) + --num_later; + } + + if (a_loss == NULL) { + if (list_empty(li_list)) { + /* no loss event have occured yet */ + LIMIT_NETDEBUG("%s: TODO: find a lost data packet by " + "comparing to initial seqno\n", + __FUNCTION__); + goto out; + } else { + LIMIT_NETDEBUG("%s: Less than 4 data pkts in history!", + __FUNCTION__); + goto out; + } + } + + /* Locate a lost data packet */ + entry = packet = b_loss; + list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) { + u64 delta = dccp_delta_seqno(entry->dccphrx_seqno, + packet->dccphrx_seqno); + + if (delta != 0) { + if (dccp_rx_hist_entry_data_packet(packet)) + --delta; + /* + * FIXME: check this, probably this % usage is because + * in earlier drafts the ndp count was just 8 bits + * long, but now it cam be up to 24 bits long. + */ +#if 0 + if (delta % DCCP_NDP_LIMIT != + (packet->dccphrx_ndp - + entry->dccphrx_ndp) % DCCP_NDP_LIMIT) +#endif + if (delta != packet->dccphrx_ndp - entry->dccphrx_ndp) { + seq_loss = entry->dccphrx_seqno; + dccp_inc_seqno(&seq_loss); + } + } + packet = entry; + if (packet == a_loss) + break; + } +out: + if (seq_loss != DCCP_MAX_SEQNO + 1) + *win_loss = a_loss->dccphrx_ccval; + else + *win_loss = 0; /* Paranoia */ + + return seq_loss; +} + +EXPORT_SYMBOL_GPL(dccp_rx_hist_detect_loss); + struct dccp_tx_hist *dccp_tx_hist_new(const char *name) { struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); @@ -244,25 +365,6 @@ struct dccp_tx_hist_entry * EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry); -int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq, - u8 *ccval) -{ - struct dccp_rx_hist_entry *packet = NULL, *entry; - - list_for_each_entry(entry, list, dccphrx_node) - if (entry->dccphrx_seqno == seq) { - packet = entry; - break; - } - - if (packet) - *ccval = packet->dccphrx_ccval; - - return packet != NULL; -} - -EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry); - void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, struct list_head *list, struct dccp_tx_hist_entry *packet) @@ -289,7 +391,7 @@ void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list) EXPORT_SYMBOL_GPL(dccp_tx_hist_purge); -MODULE_AUTHOR("Ian McDonald , " +MODULE_AUTHOR("Ian McDonald , " "Arnaldo Carvalho de Melo "); MODULE_DESCRIPTION("DCCP TFRC library"); MODULE_LICENSE("GPL"); diff --git a/trunk/net/dccp/ccids/lib/packet_history.h b/trunk/net/dccp/ccids/lib/packet_history.h index 067cf1c85a37..673c209e4e85 100644 --- a/trunk/net/dccp/ccids/lib/packet_history.h +++ b/trunk/net/dccp/ccids/lib/packet_history.h @@ -1,13 +1,13 @@ /* * net/dccp/packet_history.h * - * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand. + * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. * * An implementation of the DCCP protocol * * This code has been developed by the University of Waikato WAND * research group. For further information please see http://www.wand.net.nz/ - * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz + * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz * * This code also uses code from Lulea University, rereleased as GPL by its * authors: @@ -106,8 +106,6 @@ static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist, extern struct dccp_tx_hist_entry * dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq); -extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq, - u8 *ccval); static inline void dccp_tx_hist_add_entry(struct list_head *list, struct dccp_tx_hist_entry *entry) @@ -166,6 +164,12 @@ static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist, extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list); +static inline void dccp_rx_hist_add_entry(struct list_head *list, + struct dccp_rx_hist_entry *entry) +{ + list_add(&entry->dccphrx_node, list); +} + static inline struct dccp_rx_hist_entry * dccp_rx_hist_head(struct list_head *list) { @@ -184,11 +188,10 @@ static inline int entry->dccphrx_type == DCCP_PKT_DATAACK; } -extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, +extern int dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, struct list_head *rx_list, struct list_head *li_list, - struct dccp_rx_hist_entry *packet, - u64 nonloss_seqno); + struct dccp_rx_hist_entry *packet); extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list, struct list_head *li_list, u8 *win_loss); diff --git a/trunk/net/dccp/ccids/lib/tfrc.h b/trunk/net/dccp/ccids/lib/tfrc.h index 45f30f59ea2a..130c4c40cfe3 100644 --- a/trunk/net/dccp/ccids/lib/tfrc.h +++ b/trunk/net/dccp/ccids/lib/tfrc.h @@ -4,7 +4,7 @@ * net/dccp/ccids/lib/tfrc.h * * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. - * Copyright (c) 2005 Ian McDonald + * Copyright (c) 2005 Ian McDonald * Copyright (c) 2005 Arnaldo Carvalho de Melo * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon * diff --git a/trunk/net/dccp/ccids/lib/tfrc_equation.c b/trunk/net/dccp/ccids/lib/tfrc_equation.c index 44076e0c6591..4fd2ebebf5a0 100644 --- a/trunk/net/dccp/ccids/lib/tfrc_equation.c +++ b/trunk/net/dccp/ccids/lib/tfrc_equation.c @@ -2,7 +2,7 @@ * net/dccp/ccids/lib/tfrc_equation.c * * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. - * Copyright (c) 2005 Ian McDonald + * Copyright (c) 2005 Ian McDonald * Copyright (c) 2005 Arnaldo Carvalho de Melo * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon * diff --git a/trunk/net/dccp/dccp.h b/trunk/net/dccp/dccp.h index 0a21be437ed3..d00a2f4ee5dd 100644 --- a/trunk/net/dccp/dccp.h +++ b/trunk/net/dccp/dccp.h @@ -5,7 +5,7 @@ * * An implementation of the DCCP protocol * Copyright (c) 2005 Arnaldo Carvalho de Melo - * Copyright (c) 2005-6 Ian McDonald + * Copyright (c) 2005 Ian McDonald * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as @@ -81,14 +81,6 @@ static inline u64 max48(const u64 seq1, const u64 seq2) return after48(seq1, seq2) ? seq1 : seq2; } -/* is seq1 next seqno after seq2 */ -static inline int follows48(const u64 seq1, const u64 seq2) -{ - int diff = (seq1 & 0xFFFF) - (seq2 & 0xFFFF); - - return diff==1; -} - enum { DCCP_MIB_NUM = 0, DCCP_MIB_ACTIVEOPENS, /* ActiveOpens */ @@ -130,7 +122,7 @@ extern void dccp_send_delayed_ack(struct sock *sk); extern void dccp_send_sync(struct sock *sk, const u64 seq, const enum dccp_pkt_type pkt_type); -extern void dccp_write_xmit(struct sock *sk, int block); +extern int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo); extern void dccp_write_space(struct sock *sk); extern void dccp_init_xmit_timers(struct sock *sk); diff --git a/trunk/net/dccp/feat.h b/trunk/net/dccp/feat.h index cee553d416ca..b44c45504fb6 100644 --- a/trunk/net/dccp/feat.h +++ b/trunk/net/dccp/feat.h @@ -27,10 +27,5 @@ extern int dccp_feat_clone(struct sock *oldsk, struct sock *newsk); extern int dccp_feat_init(struct dccp_minisock *dmsk); extern int dccp_feat_default_sequence_window; -extern int dccp_feat_default_rx_ccid; -extern int dccp_feat_default_tx_ccid; -extern int dccp_feat_default_ack_ratio; -extern int dccp_feat_default_send_ack_vector; -extern int dccp_feat_default_send_ndp_count; #endif /* _DCCP_FEAT_H */ diff --git a/trunk/net/dccp/ipv4.c b/trunk/net/dccp/ipv4.c index 9a1a76a7dc41..7f56f7e8f571 100644 --- a/trunk/net/dccp/ipv4.c +++ b/trunk/net/dccp/ipv4.c @@ -501,9 +501,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) dccp_openreq_init(req, &dp, skb); - if (security_inet_conn_request(sk, skb, req)) - goto drop_and_free; - ireq = inet_rsk(req); ireq->loc_addr = daddr; ireq->rmt_addr = saddr; @@ -608,10 +605,10 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) if (req != NULL) return dccp_check_req(sk, skb, req, prev); - nsk = inet_lookup_established(&dccp_hashinfo, - iph->saddr, dh->dccph_sport, - iph->daddr, dh->dccph_dport, - inet_iif(skb)); + nsk = __inet_lookup_established(&dccp_hashinfo, + iph->saddr, dh->dccph_sport, + iph->daddr, ntohs(dh->dccph_dport), + inet_iif(skb)); if (nsk != NULL) { if (nsk->sk_state != DCCP_TIME_WAIT) { bh_lock_sock(nsk); @@ -681,7 +678,6 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk, } }; - security_skb_classify_flow(skb, &fl); if (ip_route_output_flow(&rt, &fl, sk, 0)) { IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); return NULL; @@ -925,7 +921,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) * Look up flow ID in table and get corresponding socket */ sk = __inet_lookup(&dccp_hashinfo, skb->nh.iph->saddr, dh->dccph_sport, - skb->nh.iph->daddr, dh->dccph_dport, + skb->nh.iph->daddr, ntohs(dh->dccph_dport), inet_iif(skb)); /* diff --git a/trunk/net/dccp/ipv6.c b/trunk/net/dccp/ipv6.c index 7a47399cf31f..9f3d4d7cd0bf 100644 --- a/trunk/net/dccp/ipv6.c +++ b/trunk/net/dccp/ipv6.c @@ -201,7 +201,6 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, fl.oif = sk->sk_bound_dev_if; fl.fl_ip_dport = usin->sin6_port; fl.fl_ip_sport = inet->sport; - security_sk_classify_flow(sk, &fl); if (np->opt != NULL && np->opt->srcrt != NULL) { const struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; @@ -231,7 +230,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr, ipv6_addr_copy(&np->saddr, saddr); inet->rcv_saddr = LOOPBACK4_IPV6; - __ip6_dst_store(sk, dst, NULL, NULL); + ip6_dst_store(sk, dst, NULL); icsk->icsk_ext_hdr_len = 0; if (np->opt != NULL) @@ -323,7 +322,6 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, fl.oif = sk->sk_bound_dev_if; fl.fl_ip_dport = inet->dport; fl.fl_ip_sport = inet->sport; - security_sk_classify_flow(sk, &fl); err = ip6_dst_lookup(sk, &dst, &fl); if (err) { @@ -424,7 +422,6 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, fl.oif = ireq6->iif; fl.fl_ip_dport = inet_rsk(req)->rmt_port; fl.fl_ip_sport = inet_sk(sk)->sport; - security_req_classify_flow(req, &fl); if (dst == NULL) { opt = np->opt; @@ -569,7 +566,6 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) fl.oif = inet6_iif(rxskb); fl.fl_ip_dport = dh->dccph_dport; fl.fl_ip_sport = dh->dccph_sport; - security_skb_classify_flow(rxskb, &fl); /* sk = NULL, but it is safe for now. RST socket required. */ if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { @@ -626,7 +622,6 @@ static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb, fl.oif = inet6_iif(rxskb); fl.fl_ip_dport = dh->dccph_dport; fl.fl_ip_sport = dh->dccph_sport; - security_req_classify_flow(req, &fl); if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) { if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) { @@ -709,9 +704,6 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) dccp_openreq_init(req, &dp, skb); - if (security_inet_conn_request(sk, skb, req)) - goto drop_and_free; - ireq6 = inet6_rsk(req); ireq = inet_rsk(req); ipv6_addr_copy(&ireq6->rmt_addr, &skb->nh.ipv6h->saddr); @@ -850,7 +842,6 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, fl.oif = sk->sk_bound_dev_if; fl.fl_ip_dport = inet_rsk(req)->rmt_port; fl.fl_ip_sport = inet_sk(sk)->sport; - security_sk_classify_flow(sk, &fl); if (ip6_dst_lookup(sk, &dst, &fl)) goto out; @@ -872,7 +863,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, * comment in that function for the gory details. -acme */ - __ip6_dst_store(newsk, dst, NULL, NULL); + ip6_dst_store(newsk, dst, NULL); newsk->sk_route_caps = dst->dev->features & ~(NETIF_F_IP_CSUM | NETIF_F_TSO); newdp6 = (struct dccp6_sock *)newsk; @@ -970,7 +961,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) if (skb->protocol == htons(ETH_P_IP)) return dccp_v4_do_rcv(sk, skb); - if (sk_filter(sk, skb)) + if (sk_filter(sk, skb, 0)) goto discard; /* diff --git a/trunk/net/dccp/options.c b/trunk/net/dccp/options.c index 07a34696ac97..daf72bb671f0 100644 --- a/trunk/net/dccp/options.c +++ b/trunk/net/dccp/options.c @@ -4,7 +4,7 @@ * An implementation of the DCCP protocol * Copyright (c) 2005 Aristeu Sergio Rozanski Filho * Copyright (c) 2005 Arnaldo Carvalho de Melo - * Copyright (c) 2005 Ian McDonald + * Copyright (c) 2005 Ian McDonald * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/trunk/net/dccp/output.c b/trunk/net/dccp/output.c index 7102e3aed4ca..58669beee132 100644 --- a/trunk/net/dccp/output.c +++ b/trunk/net/dccp/output.c @@ -198,7 +198,7 @@ static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb, while (1) { prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); - if (sk->sk_err) + if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) goto do_error; if (!*timeo) goto do_nonblock; @@ -234,72 +234,37 @@ static int dccp_wait_for_ccid(struct sock *sk, struct sk_buff *skb, goto out; } -static void dccp_write_xmit_timer(unsigned long data) { - struct sock *sk = (struct sock *)data; - struct dccp_sock *dp = dccp_sk(sk); - - bh_lock_sock(sk); - if (sock_owned_by_user(sk)) - sk_reset_timer(sk, &dp->dccps_xmit_timer, jiffies+1); - else - dccp_write_xmit(sk, 0); - bh_unlock_sock(sk); - sock_put(sk); -} - -void dccp_write_xmit(struct sock *sk, int block) +int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo) { - struct dccp_sock *dp = dccp_sk(sk); - struct sk_buff *skb; - long timeo = 30000; /* If a packet is taking longer than 2 secs - we have other issues */ - - while ((skb = skb_peek(&sk->sk_write_queue))) { - int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb, + const struct dccp_sock *dp = dccp_sk(sk); + int err = ccid_hc_tx_send_packet(dp->dccps_hc_tx_ccid, sk, skb, skb->len); - if (err > 0) { - if (!block) { - sk_reset_timer(sk, &dp->dccps_xmit_timer, - msecs_to_jiffies(err)+jiffies); - break; - } else - err = dccp_wait_for_ccid(sk, skb, &timeo); - if (err) { - printk(KERN_CRIT "%s:err at dccp_wait_for_ccid" - " %d\n", __FUNCTION__, err); - dump_stack(); - } - } + if (err > 0) + err = dccp_wait_for_ccid(sk, skb, timeo); - skb_dequeue(&sk->sk_write_queue); - if (err == 0) { - struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); - const int len = skb->len; + if (err == 0) { + struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); + const int len = skb->len; - if (sk->sk_state == DCCP_PARTOPEN) { - /* See 8.1.5. Handshake Completion */ - inet_csk_schedule_ack(sk); - inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, + if (sk->sk_state == DCCP_PARTOPEN) { + /* See 8.1.5. Handshake Completion */ + inet_csk_schedule_ack(sk); + inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, inet_csk(sk)->icsk_rto, DCCP_RTO_MAX); - dcb->dccpd_type = DCCP_PKT_DATAACK; - } else if (dccp_ack_pending(sk)) - dcb->dccpd_type = DCCP_PKT_DATAACK; - else - dcb->dccpd_type = DCCP_PKT_DATA; - - err = dccp_transmit_skb(sk, skb); - ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len); - if (err) { - printk(KERN_CRIT "%s:err from " - "ccid_hc_tx_packet_sent %d\n", - __FUNCTION__, err); - dump_stack(); - } - } else - kfree(skb); - } + dcb->dccpd_type = DCCP_PKT_DATAACK; + } else if (dccp_ack_pending(sk)) + dcb->dccpd_type = DCCP_PKT_DATAACK; + else + dcb->dccpd_type = DCCP_PKT_DATA; + + err = dccp_transmit_skb(sk, skb); + ccid_hc_tx_packet_sent(dp->dccps_hc_tx_ccid, sk, 0, len); + } else + kfree_skb(skb); + + return err; } int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb) @@ -461,9 +426,6 @@ static inline void dccp_connect_init(struct sock *sk) dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss)); icsk->icsk_retransmits = 0; - init_timer(&dp->dccps_xmit_timer); - dp->dccps_xmit_timer.data = (unsigned long)sk; - dp->dccps_xmit_timer.function = dccp_write_xmit_timer; } int dccp_connect(struct sock *sk) @@ -598,10 +560,8 @@ void dccp_send_close(struct sock *sk, const int active) DCCP_PKT_CLOSE : DCCP_PKT_CLOSEREQ; if (active) { - dccp_write_xmit(sk, 1); dccp_skb_entail(sk, skb); dccp_transmit_skb(sk, skb_clone(skb, prio)); - /* FIXME do we need a retransmit timer here? */ } else dccp_transmit_skb(sk, skb); } diff --git a/trunk/net/dccp/proto.c b/trunk/net/dccp/proto.c index 962df0ea31aa..6f14bb5a28d4 100644 --- a/trunk/net/dccp/proto.c +++ b/trunk/net/dccp/proto.c @@ -662,8 +662,17 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (rc != 0) goto out_discard; - skb_queue_tail(&sk->sk_write_queue, skb); - dccp_write_xmit(sk,0); + rc = dccp_write_xmit(sk, skb, &timeo); + /* + * XXX we don't use sk_write_queue, so just discard the packet. + * Current plan however is to _use_ sk_write_queue with + * an algorith similar to tcp_sendmsg, where the main difference + * is that in DCCP we have to respect packet boundaries, so + * no coalescing of skbs. + * + * This bug was _quickly_ found & fixed by just looking at an OSTRA + * generated callgraph 8) -acme + */ out_release: release_sock(sk); return rc ? : len; @@ -837,7 +846,6 @@ static int dccp_close_state(struct sock *sk) void dccp_close(struct sock *sk, long timeout) { - struct dccp_sock *dp = dccp_sk(sk); struct sk_buff *skb; int state; @@ -854,8 +862,6 @@ void dccp_close(struct sock *sk, long timeout) goto adjudge_to_death; } - sk_stop_timer(sk, &dp->dccps_xmit_timer); - /* * We need to flush the recv. buffs. We do this only on the * descriptor close, not protocol-sourced closes, because the diff --git a/trunk/net/dccp/sysctl.c b/trunk/net/dccp/sysctl.c index 38bc157876f3..c1ba9451bc3d 100644 --- a/trunk/net/dccp/sysctl.c +++ b/trunk/net/dccp/sysctl.c @@ -11,12 +11,18 @@ #include #include -#include "feat.h" #ifndef CONFIG_SYSCTL #error This file should not be compiled without CONFIG_SYSCTL defined #endif +extern int dccp_feat_default_sequence_window; +extern int dccp_feat_default_rx_ccid; +extern int dccp_feat_default_tx_ccid; +extern int dccp_feat_default_ack_ratio; +extern int dccp_feat_default_send_ack_vector; +extern int dccp_feat_default_send_ndp_count; + static struct ctl_table dccp_default_table[] = { { .ctl_name = NET_DCCP_DEFAULT_SEQ_WINDOW, diff --git a/trunk/net/decnet/Kconfig b/trunk/net/decnet/Kconfig index 36e72cb145b0..92f2ec46fd22 100644 --- a/trunk/net/decnet/Kconfig +++ b/trunk/net/decnet/Kconfig @@ -27,7 +27,6 @@ config DECNET config DECNET_ROUTER bool "DECnet: router support (EXPERIMENTAL)" depends on DECNET && EXPERIMENTAL - select FIB_RULES ---help--- Add support for turning your DECnet Endnode into a level 1 or 2 router. This is an experimental, but functional option. If you diff --git a/trunk/net/decnet/af_decnet.c b/trunk/net/decnet/af_decnet.c index 70e027375682..5486247735f6 100644 --- a/trunk/net/decnet/af_decnet.c +++ b/trunk/net/decnet/af_decnet.c @@ -130,7 +130,6 @@ Version 0.0.6 2.1.110 07-aug-98 Eduardo Marcelo Serrat #include #include #include -#include #include #include #include diff --git a/trunk/net/decnet/dn_dev.c b/trunk/net/decnet/dn_dev.c index 01861feb608d..476455fbdb03 100644 --- a/trunk/net/decnet/dn_dev.c +++ b/trunk/net/decnet/dn_dev.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -46,7 +45,6 @@ #include #include #include -#include #include #include #include @@ -746,23 +744,20 @@ static int dn_dev_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa, static void rtmsg_ifa(int event, struct dn_ifaddr *ifa) { struct sk_buff *skb; - int payload = sizeof(struct ifaddrmsg) + 128; - int err = -ENOBUFS; + int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128); - skb = alloc_skb(nlmsg_total_size(payload), GFP_KERNEL); - if (skb == NULL) - goto errout; - - err = dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0); - if (err < 0) { + skb = alloc_skb(size, GFP_KERNEL); + if (!skb) { + netlink_set_err(rtnl, 0, RTNLGRP_DECnet_IFADDR, ENOBUFS); + return; + } + if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) { kfree_skb(skb); - goto errout; + netlink_set_err(rtnl, 0, RTNLGRP_DECnet_IFADDR, EINVAL); + return; } - - err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL); -errout: - if (err < 0) - rtnl_set_sk_err(RTNLGRP_DECnet_IFADDR, err); + NETLINK_CB(skb).dst_group = RTNLGRP_DECnet_IFADDR; + netlink_broadcast(rtnl, skb, 0, RTNLGRP_DECnet_IFADDR, GFP_KERNEL); } static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) @@ -1422,6 +1417,8 @@ static struct rtnetlink_link dnet_rtnetlink_table[RTM_NR_MSGTYPES] = [RTM_DELROUTE - RTM_BASE] = { .doit = dn_fib_rtm_delroute, }, [RTM_GETROUTE - RTM_BASE] = { .doit = dn_cache_getroute, .dumpit = dn_fib_dump, }, + [RTM_NEWRULE - RTM_BASE] = { .doit = dn_fib_rtm_newrule, }, + [RTM_DELRULE - RTM_BASE] = { .doit = dn_fib_rtm_delrule, }, [RTM_GETRULE - RTM_BASE] = { .dumpit = dn_fib_dump_rules, }, #else [RTM_GETROUTE - RTM_BASE] = { .doit = dn_cache_getroute, diff --git a/trunk/net/decnet/dn_fib.c b/trunk/net/decnet/dn_fib.c index 1cf010124ec5..fa20e2efcfc1 100644 --- a/trunk/net/decnet/dn_fib.c +++ b/trunk/net/decnet/dn_fib.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -55,9 +54,11 @@ #define endfor_nexthops(fi) } +extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb); + static DEFINE_SPINLOCK(dn_fib_multipath_lock); static struct dn_fib_info *dn_fib_info_list; -static DEFINE_SPINLOCK(dn_fib_info_lock); +static DEFINE_RWLOCK(dn_fib_info_lock); static struct { @@ -78,9 +79,6 @@ static struct [RTN_XRESOLVE] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, }; -static int dn_fib_sync_down(__le16 local, struct net_device *dev, int force); -static int dn_fib_sync_up(struct net_device *dev); - void dn_fib_free_info(struct dn_fib_info *fi) { if (fi->fib_dead == 0) { @@ -98,7 +96,7 @@ void dn_fib_free_info(struct dn_fib_info *fi) void dn_fib_release_info(struct dn_fib_info *fi) { - spin_lock(&dn_fib_info_lock); + write_lock(&dn_fib_info_lock); if (fi && --fi->fib_treeref == 0) { if (fi->fib_next) fi->fib_next->fib_prev = fi->fib_prev; @@ -109,7 +107,7 @@ void dn_fib_release_info(struct dn_fib_info *fi) fi->fib_dead = 1; dn_fib_info_put(fi); } - spin_unlock(&dn_fib_info_lock); + write_unlock(&dn_fib_info_lock); } static inline int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi) @@ -380,13 +378,13 @@ struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct dn_kern_rta fi->fib_treeref++; atomic_inc(&fi->fib_clntref); - spin_lock(&dn_fib_info_lock); + write_lock(&dn_fib_info_lock); fi->fib_next = dn_fib_info_list; fi->fib_prev = NULL; if (dn_fib_info_list) dn_fib_info_list->fib_prev = fi; dn_fib_info_list = fi; - spin_unlock(&dn_fib_info_lock); + write_unlock(&dn_fib_info_lock); return fi; err_inval: @@ -492,8 +490,7 @@ static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta) if (attr) { if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2) return -EINVAL; - if (i != RTA_MULTIPATH && i != RTA_METRICS && - i != RTA_TABLE) + if (i != RTA_MULTIPATH && i != RTA_METRICS) rta[i-1] = (struct rtattr *)RTA_DATA(attr); } } @@ -510,7 +507,7 @@ int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) if (dn_fib_check_attr(r, rta)) return -EINVAL; - tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 0); + tb = dn_fib_get_table(r->rtm_table, 0); if (tb) return tb->delete(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb)); @@ -526,13 +523,46 @@ int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) if (dn_fib_check_attr(r, rta)) return -EINVAL; - tb = dn_fib_get_table(rtm_get_table(rta, r->rtm_table), 1); + tb = dn_fib_get_table(r->rtm_table, 1); if (tb) return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb)); return -ENOBUFS; } + +int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb) +{ + int t; + int s_t; + struct dn_fib_table *tb; + + if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) && + ((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED) + return dn_cache_dump(skb, cb); + + s_t = cb->args[0]; + if (s_t == 0) + s_t = cb->args[0] = RT_MIN_TABLE; + + for(t = s_t; t <= RT_TABLE_MAX; t++) { + if (t < s_t) + continue; + if (t > s_t) + memset(&cb->args[1], 0, + sizeof(cb->args) - sizeof(cb->args[0])); + tb = dn_fib_get_table(t, 0); + if (tb == NULL) + continue; + if (tb->dump(tb, skb, cb) < 0) + break; + } + + cb->args[0] = t; + + return skb->len; +} + static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifaddr *ifa) { struct dn_fib_table *tb; @@ -652,7 +682,7 @@ static int dn_fib_dnaddr_event(struct notifier_block *this, unsigned long event, return NOTIFY_DONE; } -static int dn_fib_sync_down(__le16 local, struct net_device *dev, int force) +int dn_fib_sync_down(__le16 local, struct net_device *dev, int force) { int ret = 0; int scope = RT_SCOPE_NOWHERE; @@ -696,7 +726,7 @@ static int dn_fib_sync_down(__le16 local, struct net_device *dev, int force) } -static int dn_fib_sync_up(struct net_device *dev) +int dn_fib_sync_up(struct net_device *dev) { int ret = 0; @@ -730,6 +760,22 @@ static int dn_fib_sync_up(struct net_device *dev) return ret; } +void dn_fib_flush(void) +{ + int flushed = 0; + struct dn_fib_table *tb; + int id; + + for(id = RT_TABLE_MAX; id > 0; id--) { + if ((tb = dn_fib_get_table(id, 0)) == NULL) + continue; + flushed += tb->flush(tb); + } + + if (flushed) + dn_rt_cache_flush(-1); +} + static struct notifier_block dn_fib_dnaddr_notifier = { .notifier_call = dn_fib_dnaddr_event, }; diff --git a/trunk/net/decnet/dn_nsp_in.c b/trunk/net/decnet/dn_nsp_in.c index 72ecc6e62ec4..86f7f3b28e70 100644 --- a/trunk/net/decnet/dn_nsp_in.c +++ b/trunk/net/decnet/dn_nsp_in.c @@ -586,7 +586,7 @@ static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig goto out; } - err = sk_filter(sk, skb); + err = sk_filter(sk, skb, 0); if (err) goto out; diff --git a/trunk/net/decnet/dn_route.c b/trunk/net/decnet/dn_route.c index dd0761e3d280..1355614ec11b 100644 --- a/trunk/net/decnet/dn_route.c +++ b/trunk/net/decnet/dn_route.c @@ -80,7 +80,6 @@ #include #include #include -#include #include #include #include @@ -926,13 +925,8 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old for(dev_out = dev_base; dev_out; dev_out = dev_out->next) { if (!dev_out->dn_ptr) continue; - if (!dn_dev_islocal(dev_out, oldflp->fld_src)) - continue; - if ((dev_out->flags & IFF_LOOPBACK) && - oldflp->fld_dst && - !dn_dev_islocal(dev_out, oldflp->fld_dst)) - continue; - break; + if (dn_dev_islocal(dev_out, oldflp->fld_src)) + break; } read_unlock(&dev_base_lock); if (dev_out == NULL) @@ -1285,7 +1279,7 @@ static int dn_route_input_slow(struct sk_buff *skb) dev_hold(out_dev); if (res.r) - src_map = fl.fld_src; /* no NAT support for now */ + src_map = dn_fib_rules_policy(fl.fld_src, &res, &flags); gateway = DN_FIB_RES_GW(res); if (res.type == RTN_NAT) { @@ -1486,7 +1480,6 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, r->rtm_src_len = 0; r->rtm_tos = 0; r->rtm_table = RT_TABLE_MAIN; - RTA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN); r->rtm_type = rt->rt_type; r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; r->rtm_scope = RT_SCOPE_UNIVERSE; @@ -1611,7 +1604,9 @@ int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg) goto out_free; } - return rtnl_unicast(skb, NETLINK_CB(in_skb).pid); + err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); + + return err; out_free: kfree_skb(skb); @@ -1781,9 +1776,14 @@ void __init dn_route_init(void) { int i, goal, order; - dn_dst_ops.kmem_cachep = - kmem_cache_create("dn_dst_cache", sizeof(struct dn_route), 0, - SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); + dn_dst_ops.kmem_cachep = kmem_cache_create("dn_dst_cache", + sizeof(struct dn_route), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + + if (!dn_dst_ops.kmem_cachep) + panic("DECnet: Failed to allocate dn_dst_cache\n"); + init_timer(&dn_route_timer); dn_route_timer.function = dn_dst_check_expire; dn_route_timer.expires = jiffies + decnet_dst_gc_interval * HZ; diff --git a/trunk/net/decnet/dn_rules.c b/trunk/net/decnet/dn_rules.c index 3e0c882c90bf..6986be754ef2 100644 --- a/trunk/net/decnet/dn_rules.c +++ b/trunk/net/decnet/dn_rules.c @@ -11,213 +11,259 @@ * * * Changes: - * Steve Whitehouse - * Updated for Thomas Graf's generic rules * */ +#include #include +#include +#include #include +#include #include #include +#include #include +#include #include +#include #include #include +#include +#include #include #include #include -#include #include #include #include #include -static struct fib_rules_ops dn_fib_rules_ops; - struct dn_fib_rule { - struct fib_rule common; - unsigned char dst_len; - unsigned char src_len; - __le16 src; - __le16 srcmask; - __le16 dst; - __le16 dstmask; - __le16 srcmap; - u8 flags; + struct hlist_node r_hlist; + atomic_t r_clntref; + u32 r_preference; + unsigned char r_table; + unsigned char r_action; + unsigned char r_dst_len; + unsigned char r_src_len; + __le16 r_src; + __le16 r_srcmask; + __le16 r_dst; + __le16 r_dstmask; + __le16 r_srcmap; + u8 r_flags; #ifdef CONFIG_DECNET_ROUTE_FWMARK - u32 fwmark; - u32 fwmask; + u32 r_fwmark; #endif + int r_ifindex; + char r_ifname[IFNAMSIZ]; + int r_dead; + struct rcu_head rcu; }; static struct dn_fib_rule default_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .pref = 0x7fff, - .table = RT_TABLE_MAIN, - .action = FR_ACT_TO_TBL, - }, + .r_clntref = ATOMIC_INIT(2), + .r_preference = 0x7fff, + .r_table = RT_TABLE_MAIN, + .r_action = RTN_UNICAST }; -static LIST_HEAD(dn_fib_rules); - +static struct hlist_head dn_fib_rules; -int dn_fib_lookup(struct flowi *flp, struct dn_fib_res *res) +int dn_fib_rtm_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { - struct fib_lookup_arg arg = { - .result = res, - }; - int err; - - err = fib_rules_lookup(&dn_fib_rules_ops, flp, 0, &arg); - res->r = arg.rule; + struct rtattr **rta = arg; + struct rtmsg *rtm = NLMSG_DATA(nlh); + struct dn_fib_rule *r; + struct hlist_node *node; + int err = -ESRCH; + + hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) { + if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 2) == 0) && + rtm->rtm_src_len == r->r_src_len && + rtm->rtm_dst_len == r->r_dst_len && + (!rta[RTA_DST-1] || memcmp(RTA_DATA(rta[RTA_DST-1]), &r->r_dst, 2) == 0) && +#ifdef CONFIG_DECNET_ROUTE_FWMARK + (!rta[RTA_PROTOINFO-1] || memcmp(RTA_DATA(rta[RTA_PROTOINFO-1]), &r->r_fwmark, 4) == 0) && +#endif + (!rtm->rtm_type || rtm->rtm_type == r->r_action) && + (!rta[RTA_PRIORITY-1] || memcmp(RTA_DATA(rta[RTA_PRIORITY-1]), &r->r_preference, 4) == 0) && + (!rta[RTA_IIF-1] || rtattr_strcmp(rta[RTA_IIF-1], r->r_ifname) == 0) && + (!rtm->rtm_table || (r && rtm->rtm_table == r->r_table))) { + + err = -EPERM; + if (r == &default_rule) + break; + + hlist_del_rcu(&r->r_hlist); + r->r_dead = 1; + dn_fib_rule_put(r); + err = 0; + break; + } + } return err; } -static int dn_fib_rule_action(struct fib_rule *rule, struct flowi *flp, - int flags, struct fib_lookup_arg *arg) +static inline void dn_fib_rule_put_rcu(struct rcu_head *head) { - int err = -EAGAIN; - struct dn_fib_table *tbl; - - switch(rule->action) { - case FR_ACT_TO_TBL: - break; - - case FR_ACT_UNREACHABLE: - err = -ENETUNREACH; - goto errout; - - case FR_ACT_PROHIBIT: - err = -EACCES; - goto errout; + struct dn_fib_rule *r = container_of(head, struct dn_fib_rule, rcu); + kfree(r); +} - case FR_ACT_BLACKHOLE: - default: - err = -EINVAL; - goto errout; +void dn_fib_rule_put(struct dn_fib_rule *r) +{ + if (atomic_dec_and_test(&r->r_clntref)) { + if (r->r_dead) + call_rcu(&r->rcu, dn_fib_rule_put_rcu); + else + printk(KERN_DEBUG "Attempt to free alive dn_fib_rule\n"); } - - tbl = dn_fib_get_table(rule->table, 0); - if (tbl == NULL) - goto errout; - - err = tbl->lookup(tbl, flp, (struct dn_fib_res *)arg->result); - if (err > 0) - err = -EAGAIN; -errout: - return err; } -static struct nla_policy dn_fib_rule_policy[FRA_MAX+1] __read_mostly = { - [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, - [FRA_PRIORITY] = { .type = NLA_U32 }, - [FRA_SRC] = { .type = NLA_U16 }, - [FRA_DST] = { .type = NLA_U16 }, - [FRA_FWMARK] = { .type = NLA_U32 }, - [FRA_FWMASK] = { .type = NLA_U32 }, - [FRA_TABLE] = { .type = NLA_U32 }, -}; -static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) +int dn_fib_rtm_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { - struct dn_fib_rule *r = (struct dn_fib_rule *)rule; - u16 daddr = fl->fld_dst; - u16 saddr = fl->fld_src; - - if (((saddr ^ r->src) & r->srcmask) || - ((daddr ^ r->dst) & r->dstmask)) - return 0; + struct rtattr **rta = arg; + struct rtmsg *rtm = NLMSG_DATA(nlh); + struct dn_fib_rule *r, *new_r, *last = NULL; + struct hlist_node *node = NULL; + unsigned char table_id; + + if (rtm->rtm_src_len > 16 || rtm->rtm_dst_len > 16) + return -EINVAL; + + if (rta[RTA_IIF-1] && RTA_PAYLOAD(rta[RTA_IIF-1]) > IFNAMSIZ) + return -EINVAL; + + if (rtm->rtm_type == RTN_NAT) + return -EINVAL; + + table_id = rtm->rtm_table; + if (table_id == RT_TABLE_UNSPEC) { + struct dn_fib_table *tb; + if (rtm->rtm_type == RTN_UNICAST) { + if ((tb = dn_fib_empty_table()) == NULL) + return -ENOBUFS; + table_id = tb->n; + } + } + new_r = kzalloc(sizeof(*new_r), GFP_KERNEL); + if (!new_r) + return -ENOMEM; + + if (rta[RTA_SRC-1]) + memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 2); + if (rta[RTA_DST-1]) + memcpy(&new_r->r_dst, RTA_DATA(rta[RTA_DST-1]), 2); + if (rta[RTA_GATEWAY-1]) + memcpy(&new_r->r_srcmap, RTA_DATA(rta[RTA_GATEWAY-1]), 2); + new_r->r_src_len = rtm->rtm_src_len; + new_r->r_dst_len = rtm->rtm_dst_len; + new_r->r_srcmask = dnet_make_mask(rtm->rtm_src_len); + new_r->r_dstmask = dnet_make_mask(rtm->rtm_dst_len); #ifdef CONFIG_DECNET_ROUTE_FWMARK - if ((r->fwmark ^ fl->fld_fwmark) & r->fwmask) - return 0; + if (rta[RTA_PROTOINFO-1]) + memcpy(&new_r->r_fwmark, RTA_DATA(rta[RTA_PROTOINFO-1]), 4); #endif - - return 1; -} - -static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh, - struct nlattr **tb) -{ - int err = -EINVAL; - struct dn_fib_rule *r = (struct dn_fib_rule *)rule; - - if (frh->src_len > 16 || frh->dst_len > 16 || frh->tos) - goto errout; - - if (rule->table == RT_TABLE_UNSPEC) { - if (rule->action == FR_ACT_TO_TBL) { - struct dn_fib_table *table; - - table = dn_fib_empty_table(); - if (table == NULL) { - err = -ENOBUFS; - goto errout; - } - - rule->table = table->n; + new_r->r_action = rtm->rtm_type; + new_r->r_flags = rtm->rtm_flags; + if (rta[RTA_PRIORITY-1]) + memcpy(&new_r->r_preference, RTA_DATA(rta[RTA_PRIORITY-1]), 4); + new_r->r_table = table_id; + if (rta[RTA_IIF-1]) { + struct net_device *dev; + rtattr_strlcpy(new_r->r_ifname, rta[RTA_IIF-1], IFNAMSIZ); + new_r->r_ifindex = -1; + dev = dev_get_by_name(new_r->r_ifname); + if (dev) { + new_r->r_ifindex = dev->ifindex; + dev_put(dev); } } - if (tb[FRA_SRC]) - r->src = nla_get_u16(tb[FRA_SRC]); - - if (tb[FRA_DST]) - r->dst = nla_get_u16(tb[FRA_DST]); - -#ifdef CONFIG_DECNET_ROUTE_FWMARK - if (tb[FRA_FWMARK]) { - r->fwmark = nla_get_u32(tb[FRA_FWMARK]); - if (r->fwmark) - /* compatibility: if the mark value is non-zero all bits - * are compared unless a mask is explicitly specified. - */ - r->fwmask = 0xFFFFFFFF; + r = container_of(dn_fib_rules.first, struct dn_fib_rule, r_hlist); + if (!new_r->r_preference) { + if (r && r->r_hlist.next != NULL) { + r = container_of(r->r_hlist.next, struct dn_fib_rule, r_hlist); + if (r->r_preference) + new_r->r_preference = r->r_preference - 1; + } } - if (tb[FRA_FWMASK]) - r->fwmask = nla_get_u32(tb[FRA_FWMASK]); -#endif + hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) { + if (r->r_preference > new_r->r_preference) + break; + last = r; + } + atomic_inc(&new_r->r_clntref); - r->src_len = frh->src_len; - r->srcmask = dnet_make_mask(r->src_len); - r->dst_len = frh->dst_len; - r->dstmask = dnet_make_mask(r->dst_len); - err = 0; -errout: - return err; + if (last) + hlist_add_after_rcu(&last->r_hlist, &new_r->r_hlist); + else + hlist_add_before_rcu(&new_r->r_hlist, &r->r_hlist); + return 0; } -static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, - struct nlattr **tb) -{ - struct dn_fib_rule *r = (struct dn_fib_rule *)rule; - if (frh->src_len && (r->src_len != frh->src_len)) - return 0; +int dn_fib_lookup(const struct flowi *flp, struct dn_fib_res *res) +{ + struct dn_fib_rule *r, *policy; + struct dn_fib_table *tb; + __le16 saddr = flp->fld_src; + __le16 daddr = flp->fld_dst; + struct hlist_node *node; + int err; - if (frh->dst_len && (r->dst_len != frh->dst_len)) - return 0; + rcu_read_lock(); + hlist_for_each_entry_rcu(r, node, &dn_fib_rules, r_hlist) { + if (((saddr^r->r_src) & r->r_srcmask) || + ((daddr^r->r_dst) & r->r_dstmask) || #ifdef CONFIG_DECNET_ROUTE_FWMARK - if (tb[FRA_FWMARK] && (r->fwmark != nla_get_u32(tb[FRA_FWMARK]))) - return 0; - - if (tb[FRA_FWMASK] && (r->fwmask != nla_get_u32(tb[FRA_FWMASK]))) - return 0; + (r->r_fwmark && r->r_fwmark != flp->fld_fwmark) || #endif + (r->r_ifindex && r->r_ifindex != flp->iif)) + continue; + + switch(r->r_action) { + case RTN_UNICAST: + case RTN_NAT: + policy = r; + break; + case RTN_UNREACHABLE: + rcu_read_unlock(); + return -ENETUNREACH; + default: + case RTN_BLACKHOLE: + rcu_read_unlock(); + return -EINVAL; + case RTN_PROHIBIT: + rcu_read_unlock(); + return -EACCES; + } - if (tb[FRA_SRC] && (r->src != nla_get_u16(tb[FRA_SRC]))) - return 0; - - if (tb[FRA_DST] && (r->dst != nla_get_u16(tb[FRA_DST]))) - return 0; + if ((tb = dn_fib_get_table(r->r_table, 0)) == NULL) + continue; + err = tb->lookup(tb, flp, res); + if (err == 0) { + res->r = policy; + if (policy) + atomic_inc(&policy->r_clntref); + rcu_read_unlock(); + return 0; + } + if (err < 0 && err != -EAGAIN) { + rcu_read_unlock(); + return err; + } + } - return 1; + rcu_read_unlock(); + return -ESRCH; } unsigned dnet_addr_type(__le16 addr) @@ -225,7 +271,7 @@ unsigned dnet_addr_type(__le16 addr) struct flowi fl = { .nl_u = { .dn_u = { .daddr = addr } } }; struct dn_fib_res res; unsigned ret = RTN_UNICAST; - struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0); + struct dn_fib_table *tb = dn_fib_tables[RT_TABLE_LOCAL]; res.r = NULL; @@ -238,79 +284,142 @@ unsigned dnet_addr_type(__le16 addr) return ret; } -static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh) +__le16 dn_fib_rules_policy(__le16 saddr, struct dn_fib_res *res, unsigned *flags) { - struct dn_fib_rule *r = (struct dn_fib_rule *)rule; + struct dn_fib_rule *r = res->r; - frh->family = AF_DECnet; - frh->dst_len = r->dst_len; - frh->src_len = r->src_len; - frh->tos = 0; + if (r->r_action == RTN_NAT) { + int addrtype = dnet_addr_type(r->r_srcmap); -#ifdef CONFIG_DECNET_ROUTE_FWMARK - if (r->fwmark) - NLA_PUT_U32(skb, FRA_FWMARK, r->fwmark); - if (r->fwmask || r->fwmark) - NLA_PUT_U32(skb, FRA_FWMASK, r->fwmask); -#endif - if (r->dst_len) - NLA_PUT_U16(skb, FRA_DST, r->dst); - if (r->src_len) - NLA_PUT_U16(skb, FRA_SRC, r->src); + if (addrtype == RTN_NAT) { + saddr = (saddr&~r->r_srcmask)|r->r_srcmap; + *flags |= RTCF_SNAT; + } else if (addrtype == RTN_LOCAL || r->r_srcmap == 0) { + saddr = r->r_srcmap; + *flags |= RTCF_MASQ; + } + } + return saddr; +} - return 0; +static void dn_fib_rules_detach(struct net_device *dev) +{ + struct hlist_node *node; + struct dn_fib_rule *r; -nla_put_failure: - return -ENOBUFS; + hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) { + if (r->r_ifindex == dev->ifindex) + r->r_ifindex = -1; + } } -static u32 dn_fib_rule_default_pref(void) +static void dn_fib_rules_attach(struct net_device *dev) { - struct list_head *pos; - struct fib_rule *rule; - - if (!list_empty(&dn_fib_rules)) { - pos = dn_fib_rules.next; - if (pos->next != &dn_fib_rules) { - rule = list_entry(pos->next, struct fib_rule, list); - if (rule->pref) - return rule->pref - 1; - } - } + struct hlist_node *node; + struct dn_fib_rule *r; - return 0; + hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) { + if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0) + r->r_ifindex = dev->ifindex; + } } -int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) +static int dn_fib_rules_event(struct notifier_block *this, unsigned long event, void *ptr) { - return fib_rules_dump(skb, cb, AF_DECnet); + struct net_device *dev = ptr; + + switch(event) { + case NETDEV_UNREGISTER: + dn_fib_rules_detach(dev); + dn_fib_sync_down(0, dev, 1); + case NETDEV_REGISTER: + dn_fib_rules_attach(dev); + dn_fib_sync_up(dev); + } + + return NOTIFY_DONE; } -static struct fib_rules_ops dn_fib_rules_ops = { - .family = AF_DECnet, - .rule_size = sizeof(struct dn_fib_rule), - .action = dn_fib_rule_action, - .match = dn_fib_rule_match, - .configure = dn_fib_rule_configure, - .compare = dn_fib_rule_compare, - .fill = dn_fib_rule_fill, - .default_pref = dn_fib_rule_default_pref, - .nlgroup = RTNLGRP_DECnet_RULE, - .policy = dn_fib_rule_policy, - .rules_list = &dn_fib_rules, - .owner = THIS_MODULE, + +static struct notifier_block dn_fib_rules_notifier = { + .notifier_call = dn_fib_rules_event, }; +static int dn_fib_fill_rule(struct sk_buff *skb, struct dn_fib_rule *r, + struct netlink_callback *cb, unsigned int flags) +{ + struct rtmsg *rtm; + struct nlmsghdr *nlh; + unsigned char *b = skb->tail; + + + nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags); + rtm = NLMSG_DATA(nlh); + rtm->rtm_family = AF_DECnet; + rtm->rtm_dst_len = r->r_dst_len; + rtm->rtm_src_len = r->r_src_len; + rtm->rtm_tos = 0; +#ifdef CONFIG_DECNET_ROUTE_FWMARK + if (r->r_fwmark) + RTA_PUT(skb, RTA_PROTOINFO, 4, &r->r_fwmark); +#endif + rtm->rtm_table = r->r_table; + rtm->rtm_protocol = 0; + rtm->rtm_scope = 0; + rtm->rtm_type = r->r_action; + rtm->rtm_flags = r->r_flags; + + if (r->r_dst_len) + RTA_PUT(skb, RTA_DST, 2, &r->r_dst); + if (r->r_src_len) + RTA_PUT(skb, RTA_SRC, 2, &r->r_src); + if (r->r_ifname[0]) + RTA_PUT(skb, RTA_IIF, IFNAMSIZ, &r->r_ifname); + if (r->r_preference) + RTA_PUT(skb, RTA_PRIORITY, 4, &r->r_preference); + if (r->r_srcmap) + RTA_PUT(skb, RTA_GATEWAY, 2, &r->r_srcmap); + nlh->nlmsg_len = skb->tail - b; + return skb->len; + +nlmsg_failure: +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; +} + +int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) +{ + int idx = 0; + int s_idx = cb->args[0]; + struct dn_fib_rule *r; + struct hlist_node *node; + + rcu_read_lock(); + hlist_for_each_entry(r, node, &dn_fib_rules, r_hlist) { + if (idx < s_idx) + goto next; + if (dn_fib_fill_rule(skb, r, cb, NLM_F_MULTI) < 0) + break; +next: + idx++; + } + rcu_read_unlock(); + cb->args[0] = idx; + + return skb->len; +} + void __init dn_fib_rules_init(void) { - list_add_tail(&default_rule.common.list, &dn_fib_rules); - fib_rules_register(&dn_fib_rules_ops); + INIT_HLIST_HEAD(&dn_fib_rules); + hlist_add_head(&default_rule.r_hlist, &dn_fib_rules); + register_netdevice_notifier(&dn_fib_rules_notifier); } void __exit dn_fib_rules_cleanup(void) { - fib_rules_unregister(&dn_fib_rules_ops); + unregister_netdevice_notifier(&dn_fib_rules_notifier); } diff --git a/trunk/net/decnet/dn_table.c b/trunk/net/decnet/dn_table.c index 317904bb5896..e926c952e363 100644 --- a/trunk/net/decnet/dn_table.c +++ b/trunk/net/decnet/dn_table.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -75,9 +74,9 @@ for( ; ((f) = *(fp)) != NULL; (fp) = &(f)->fn_next) for( ; ((f) = *(fp)) != NULL && dn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_next) #define RT_TABLE_MIN 1 -#define DN_FIB_TABLE_HASHSZ 256 -static struct hlist_head dn_fib_table_hash[DN_FIB_TABLE_HASHSZ]; + static DEFINE_RWLOCK(dn_fib_tables_lock); +struct dn_fib_table *dn_fib_tables[RT_TABLE_MAX + 1]; static kmem_cache_t *dn_hash_kmem __read_mostly; static int dn_fib_hash_zombies; @@ -264,7 +263,7 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern } static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, - u32 tb_id, u8 type, u8 scope, void *dst, int dst_len, + u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, struct dn_fib_info *fi, unsigned int flags) { struct rtmsg *rtm; @@ -278,7 +277,6 @@ static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, rtm->rtm_src_len = 0; rtm->rtm_tos = 0; rtm->rtm_table = tb_id; - RTA_PUT_U32(skb, RTA_TABLE, tb_id); rtm->rtm_flags = fi->fib_flags; rtm->rtm_scope = scope; rtm->rtm_type = type; @@ -328,29 +326,29 @@ static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, } -static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id, +static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, int tb_id, struct nlmsghdr *nlh, struct netlink_skb_parms *req) { struct sk_buff *skb; u32 pid = req ? req->pid : 0; - int err = -ENOBUFS; + int size = NLMSG_SPACE(sizeof(struct rtmsg) + 256); - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (skb == NULL) - goto errout; + skb = alloc_skb(size, GFP_KERNEL); + if (!skb) + return; - err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id, - f->fn_type, f->fn_scope, &f->fn_key, z, - DN_FIB_INFO(f), 0); - if (err < 0) { + if (dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id, + f->fn_type, f->fn_scope, &f->fn_key, z, + DN_FIB_INFO(f), 0) < 0) { kfree_skb(skb); - goto errout; + return; } - - err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL); -errout: - if (err < 0) - rtnl_set_sk_err(RTNLGRP_DECnet_ROUTE, err); + NETLINK_CB(skb).dst_group = RTNLGRP_DECnet_ROUTE; + if (nlh->nlmsg_flags & NLM_F_ECHO) + atomic_inc(&skb->users); + netlink_broadcast(rtnl, skb, pid, RTNLGRP_DECnet_ROUTE, GFP_KERNEL); + if (nlh->nlmsg_flags & NLM_F_ECHO) + netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT); } static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb, @@ -361,7 +359,7 @@ static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb, { int i, s_i; - s_i = cb->args[4]; + s_i = cb->args[3]; for(i = 0; f; i++, f = f->fn_next) { if (i < s_i) continue; @@ -374,11 +372,11 @@ static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb, (f->fn_state & DN_S_ZOMBIE) ? 0 : f->fn_type, f->fn_scope, &f->fn_key, dz->dz_order, f->fn_info, NLM_F_MULTI) < 0) { - cb->args[4] = i; + cb->args[3] = i; return -1; } } - cb->args[4] = i; + cb->args[3] = i; return skb->len; } @@ -389,20 +387,20 @@ static __inline__ int dn_hash_dump_zone(struct sk_buff *skb, { int h, s_h; - s_h = cb->args[3]; + s_h = cb->args[2]; for(h = 0; h < dz->dz_divisor; h++) { if (h < s_h) continue; if (h > s_h) - memset(&cb->args[4], 0, sizeof(cb->args) - 4*sizeof(cb->args[0])); + memset(&cb->args[3], 0, sizeof(cb->args) - 3*sizeof(cb->args[0])); if (dz->dz_hash == NULL || dz->dz_hash[h] == NULL) continue; if (dn_hash_dump_bucket(skb, cb, tb, dz, dz->dz_hash[h]) < 0) { - cb->args[3] = h; + cb->args[2] = h; return -1; } } - cb->args[3] = h; + cb->args[2] = h; return skb->len; } @@ -413,63 +411,26 @@ static int dn_fib_table_dump(struct dn_fib_table *tb, struct sk_buff *skb, struct dn_zone *dz; struct dn_hash *table = (struct dn_hash *)tb->data; - s_m = cb->args[2]; + s_m = cb->args[1]; read_lock(&dn_fib_tables_lock); for(dz = table->dh_zone_list, m = 0; dz; dz = dz->dz_next, m++) { if (m < s_m) continue; if (m > s_m) - memset(&cb->args[3], 0, sizeof(cb->args) - 3*sizeof(cb->args[0])); + memset(&cb->args[2], 0, sizeof(cb->args) - 2*sizeof(cb->args[0])); if (dn_hash_dump_zone(skb, cb, tb, dz) < 0) { - cb->args[2] = m; + cb->args[1] = m; read_unlock(&dn_fib_tables_lock); return -1; } } read_unlock(&dn_fib_tables_lock); - cb->args[2] = m; + cb->args[1] = m; return skb->len; } -int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb) -{ - unsigned int h, s_h; - unsigned int e = 0, s_e; - struct dn_fib_table *tb; - struct hlist_node *node; - int dumped = 0; - - if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) && - ((struct rtmsg *)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED) - return dn_cache_dump(skb, cb); - - s_h = cb->args[0]; - s_e = cb->args[1]; - - for (h = s_h; h < DN_FIB_TABLE_HASHSZ; h++, s_h = 0) { - e = 0; - hlist_for_each_entry(tb, node, &dn_fib_table_hash[h], hlist) { - if (e < s_e) - goto next; - if (dumped) - memset(&cb->args[2], 0, sizeof(cb->args) - - 2 * sizeof(cb->args[0])); - if (tb->dump(tb, skb, cb) < 0) - goto out; - dumped = 1; -next: - e++; - } - } -out: - cb->args[1] = e; - cb->args[0] = h; - - return skb->len; -} - static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct dn_kern_rta *rta, struct nlmsghdr *n, struct netlink_skb_parms *req) { struct dn_hash *table = (struct dn_hash *)tb->data; @@ -778,11 +739,9 @@ static int dn_fib_table_lookup(struct dn_fib_table *tb, const struct flowi *flp, } -struct dn_fib_table *dn_fib_get_table(u32 n, int create) +struct dn_fib_table *dn_fib_get_table(int n, int create) { struct dn_fib_table *t; - struct hlist_node *node; - unsigned int h; if (n < RT_TABLE_MIN) return NULL; @@ -790,15 +749,8 @@ struct dn_fib_table *dn_fib_get_table(u32 n, int create) if (n > RT_TABLE_MAX) return NULL; - h = n & (DN_FIB_TABLE_HASHSZ - 1); - rcu_read_lock(); - hlist_for_each_entry_rcu(t, node, &dn_fib_table_hash[h], hlist) { - if (t->n == n) { - rcu_read_unlock(); - return t; - } - } - rcu_read_unlock(); + if (dn_fib_tables[n]) + return dn_fib_tables[n]; if (!create) return NULL; @@ -819,35 +771,31 @@ struct dn_fib_table *dn_fib_get_table(u32 n, int create) t->flush = dn_fib_table_flush; t->dump = dn_fib_table_dump; memset(t->data, 0, sizeof(struct dn_hash)); - hlist_add_head_rcu(&t->hlist, &dn_fib_table_hash[h]); + dn_fib_tables[n] = t; return t; } -struct dn_fib_table *dn_fib_empty_table(void) +static void dn_fib_del_tree(int n) { - u32 id; + struct dn_fib_table *t; - for(id = RT_TABLE_MIN; id <= RT_TABLE_MAX; id++) - if (dn_fib_get_table(id, 0) == NULL) - return dn_fib_get_table(id, 1); - return NULL; + write_lock(&dn_fib_tables_lock); + t = dn_fib_tables[n]; + dn_fib_tables[n] = NULL; + write_unlock(&dn_fib_tables_lock); + + kfree(t); } -void dn_fib_flush(void) +struct dn_fib_table *dn_fib_empty_table(void) { - int flushed = 0; - struct dn_fib_table *tb; - struct hlist_node *node; - unsigned int h; - - for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) { - hlist_for_each_entry(tb, node, &dn_fib_table_hash[h], hlist) - flushed += tb->flush(tb); - } + int id; - if (flushed) - dn_rt_cache_flush(-1); + for(id = RT_TABLE_MIN; id <= RT_TABLE_MAX; id++) + if (dn_fib_tables[id] == NULL) + return dn_fib_get_table(id, 1); + return NULL; } void __init dn_fib_table_init(void) @@ -860,17 +808,10 @@ void __init dn_fib_table_init(void) void __exit dn_fib_table_cleanup(void) { - struct dn_fib_table *t; - struct hlist_node *node, *next; - unsigned int h; + int i; - write_lock(&dn_fib_tables_lock); - for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) { - hlist_for_each_entry_safe(t, node, next, &dn_fib_table_hash[h], - hlist) { - hlist_del(&t->hlist); - kfree(t); - } - } - write_unlock(&dn_fib_tables_lock); + for (i = RT_TABLE_MIN; i <= RT_TABLE_MAX; ++i) + dn_fib_del_tree(i); + + return; } diff --git a/trunk/net/ethernet/eth.c b/trunk/net/ethernet/eth.c index 43863933f27f..387c71c584ee 100644 --- a/trunk/net/ethernet/eth.c +++ b/trunk/net/ethernet/eth.c @@ -64,79 +64,81 @@ __setup("ether=", netdev_boot_setup); -/** - * eth_header - create the Ethernet header - * @skb: buffer to alter - * @dev: source device - * @type: Ethernet type field - * @daddr: destination address (NULL leave destination address) - * @saddr: source address (NULL use device source address) - * @len: packet length (<= skb->len) - * +/* + * Create the Ethernet MAC header for an arbitrary protocol layer * - * Set the protocol type. For a packet of type ETH_P_802_3 we put the length - * in here instead. It is up to the 802.2 layer to carry protocol information. + * saddr=NULL means use device source address + * daddr=NULL means leave destination address (eg unresolved arp) */ + int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, - void *daddr, void *saddr, unsigned len) + void *daddr, void *saddr, unsigned len) { - struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); + struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN); - if (type != ETH_P_802_3) + /* + * Set the protocol type. For a packet of type ETH_P_802_3 we put the length + * in here instead. It is up to the 802.2 layer to carry protocol information. + */ + + if(type!=ETH_P_802_3) eth->h_proto = htons(type); else eth->h_proto = htons(len); /* - * Set the source hardware address. + * Set the source hardware address. */ - - if (!saddr) + + if(!saddr) saddr = dev->dev_addr; - memcpy(eth->h_source, saddr, dev->addr_len); + memcpy(eth->h_source,saddr,dev->addr_len); - if (daddr) { - memcpy(eth->h_dest, daddr, dev->addr_len); + if(daddr) + { + memcpy(eth->h_dest,daddr,dev->addr_len); return ETH_HLEN; } - + /* - * Anyway, the loopback-device should never use this function... + * Anyway, the loopback-device should never use this function... */ - if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { + if (dev->flags & (IFF_LOOPBACK|IFF_NOARP)) + { memset(eth->h_dest, 0, dev->addr_len); return ETH_HLEN; } - + return -ETH_HLEN; } -/** - * eth_rebuild_header- rebuild the Ethernet MAC header. - * @skb: socket buffer to update - * - * This is called after an ARP or IPV6 ndisc it's resolution on this - * sk_buff. We now let protocol (ARP) fill in the other fields. + +/* + * Rebuild the Ethernet MAC header. This is called after an ARP + * (or in future other address resolution) has completed on this + * sk_buff. We now let ARP fill in the other fields. * - * This routine CANNOT use cached dst->neigh! - * Really, it is used only when dst->neigh is wrong. + * This routine CANNOT use cached dst->neigh! + * Really, it is used only when dst->neigh is wrong. */ + int eth_rebuild_header(struct sk_buff *skb) { struct ethhdr *eth = (struct ethhdr *)skb->data; struct net_device *dev = skb->dev; - switch (eth->h_proto) { + switch (eth->h_proto) + { #ifdef CONFIG_INET case __constant_htons(ETH_P_IP): - return arp_find(eth->h_dest, skb); -#endif + return arp_find(eth->h_dest, skb); +#endif default: printk(KERN_DEBUG - "%s: unable to resolve type %X addresses.\n", + "%s: unable to resolve type %X addresses.\n", dev->name, (int)eth->h_proto); - + memcpy(eth->h_source, dev->dev_addr, dev->addr_len); break; } @@ -144,70 +146,62 @@ int eth_rebuild_header(struct sk_buff *skb) return 0; } -/** - * eth_type_trans - determine the packet's protocol ID. - * @skb: received socket data - * @dev: receiving network device - * - * The rule here is that we - * assume 802.3 if the type field is short enough to be a length. - * This is normal practice and works for any 'now in use' protocol. + +/* + * Determine the packet's protocol ID. The rule here is that we + * assume 802.3 if the type field is short enough to be a length. + * This is normal practice and works for any 'now in use' protocol. */ + __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) { struct ethhdr *eth; unsigned char *rawp; - + skb->mac.raw = skb->data; - skb_pull(skb, ETH_HLEN); + skb_pull(skb,ETH_HLEN); eth = eth_hdr(skb); - + if (is_multicast_ether_addr(eth->h_dest)) { if (!compare_ether_addr(eth->h_dest, dev->broadcast)) skb->pkt_type = PACKET_BROADCAST; else skb->pkt_type = PACKET_MULTICAST; } - + /* - * This ALLMULTI check should be redundant by 1.4 - * so don't forget to remove it. + * This ALLMULTI check should be redundant by 1.4 + * so don't forget to remove it. * - * Seems, you forgot to remove it. All silly devices - * seems to set IFF_PROMISC. + * Seems, you forgot to remove it. All silly devices + * seems to set IFF_PROMISC. */ - - else if (1 /*dev->flags&IFF_PROMISC */ ) { + + else if(1 /*dev->flags&IFF_PROMISC*/) { if (unlikely(compare_ether_addr(eth->h_dest, dev->dev_addr))) skb->pkt_type = PACKET_OTHERHOST; } - + if (ntohs(eth->h_proto) >= 1536) return eth->h_proto; - + rawp = skb->data; - + /* - * This is a magic hack to spot IPX packets. Older Novell breaks - * the protocol design and runs IPX over 802.3 without an 802.2 LLC - * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This - * won't work for fault tolerant netware but does for the rest. + * This is a magic hack to spot IPX packets. Older Novell breaks + * the protocol design and runs IPX over 802.3 without an 802.2 LLC + * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This + * won't work for fault tolerant netware but does for the rest. */ if (*(unsigned short *)rawp == 0xFFFF) return htons(ETH_P_802_3); - + /* - * Real 802.2 LLC + * Real 802.2 LLC */ return htons(ETH_P_802_2); } -EXPORT_SYMBOL(eth_type_trans); -/** - * eth_header_parse - extract hardware address from packet - * @skb: packet to extract header from - * @haddr: destination buffer - */ static int eth_header_parse(struct sk_buff *skb, unsigned char *haddr) { struct ethhdr *eth = eth_hdr(skb); @@ -215,20 +209,14 @@ static int eth_header_parse(struct sk_buff *skb, unsigned char *haddr) return ETH_ALEN; } -/** - * eth_header_cache - fill cache entry from neighbour - * @neigh: source neighbour - * @hh: destination cache entry - * Create an Ethernet header template from the neighbour. - */ int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh) { unsigned short type = hh->hh_type; struct ethhdr *eth; struct net_device *dev = neigh->dev; - eth = (struct ethhdr *) - (((u8 *) hh->hh_data) + (HH_DATA_OFF(sizeof(*eth)))); + eth = (struct ethhdr*) + (((u8*)hh->hh_data) + (HH_DATA_OFF(sizeof(*eth)))); if (type == __constant_htons(ETH_P_802_3)) return -1; @@ -240,47 +228,27 @@ int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh) return 0; } -/** - * eth_header_cache_update - update cache entry - * @hh: destination cache entry - * @dev: network device - * @haddr: new hardware address - * +/* * Called by Address Resolution module to notify changes in address. */ -void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev, - unsigned char *haddr) + +void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr) { - memcpy(((u8 *) hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)), + memcpy(((u8*)hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)), haddr, dev->addr_len); } -/** - * eth_mac_addr - set new Ethernet hardware address - * @dev: network device - * @p: socket address - * Change hardware address of device. - * - * This doesn't change hardware matching, so needs to be overridden - * for most real devices. - */ +EXPORT_SYMBOL(eth_type_trans); + static int eth_mac_addr(struct net_device *dev, void *p) { - struct sockaddr *addr = p; + struct sockaddr *addr=p; if (netif_running(dev)) return -EBUSY; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); return 0; } -/** - * eth_change_mtu - set new MTU size - * @dev: network device - * @new_mtu: new Maximum Transfer Unit - * - * Allow changing MTU size. Needs to be overridden for devices - * supporting jumbo frames. - */ static int eth_change_mtu(struct net_device *dev, int new_mtu) { if (new_mtu < 68 || new_mtu > ETH_DATA_LEN) @@ -289,10 +257,8 @@ static int eth_change_mtu(struct net_device *dev, int new_mtu) return 0; } -/** - * ether_setup - setup Ethernet network device - * @dev: network device - * Fill in the fields of the device structure with Ethernet-generic values. +/* + * Fill in the fields of the device structure with ethernet-generic values. */ void ether_setup(struct net_device *dev) { @@ -311,21 +277,21 @@ void ether_setup(struct net_device *dev) dev->tx_queue_len = 1000; /* Ethernet wants good queues */ dev->flags = IFF_BROADCAST|IFF_MULTICAST; - memset(dev->broadcast, 0xFF, ETH_ALEN); + memset(dev->broadcast,0xFF, ETH_ALEN); } EXPORT_SYMBOL(ether_setup); /** - * alloc_etherdev - Allocates and sets up an Ethernet device + * alloc_etherdev - Allocates and sets up an ethernet device * @sizeof_priv: Size of additional driver-private structure to be allocated - * for this Ethernet device + * for this ethernet device * - * Fill in the fields of the device structure with Ethernet-generic + * Fill in the fields of the device structure with ethernet-generic * values. Basically does everything except registering the device. * * Constructs a new net device, complete with a private data area of - * size (sizeof_priv). A 32-byte (not bit) alignment is enforced for + * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for * this private data area. */ diff --git a/trunk/net/ieee80211/Kconfig b/trunk/net/ieee80211/Kconfig index f7e84e9d13ad..dbb08528ddf5 100644 --- a/trunk/net/ieee80211/Kconfig +++ b/trunk/net/ieee80211/Kconfig @@ -58,7 +58,6 @@ config IEEE80211_CRYPT_TKIP depends on IEEE80211 && NET_RADIO select CRYPTO select CRYPTO_MICHAEL_MIC - select CRC32 ---help--- Include software based cipher suites in support of IEEE 802.11i (aka TGi, WPA, WPA2, WPA-PSK, etc.) for use with TKIP enabled diff --git a/trunk/net/ieee80211/ieee80211_crypt_ccmp.c b/trunk/net/ieee80211/ieee80211_crypt_ccmp.c index fdfe7704a469..ed90a8af1444 100644 --- a/trunk/net/ieee80211/ieee80211_crypt_ccmp.c +++ b/trunk/net/ieee80211/ieee80211_crypt_ccmp.c @@ -9,7 +9,6 @@ * more details. */ -#include #include #include #include @@ -49,7 +48,7 @@ struct ieee80211_ccmp_data { int key_idx; - struct crypto_cipher *tfm; + struct crypto_tfm *tfm; /* scratch buffers for virt_to_page() (crypto API) */ u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], @@ -57,10 +56,20 @@ struct ieee80211_ccmp_data { u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; }; -static inline void ieee80211_ccmp_aes_encrypt(struct crypto_cipher *tfm, - const u8 pt[16], u8 ct[16]) +static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm, + const u8 pt[16], u8 ct[16]) { - crypto_cipher_encrypt_one(tfm, ct, pt); + struct scatterlist src, dst; + + src.page = virt_to_page(pt); + src.offset = offset_in_page(pt); + src.length = AES_BLOCK_LEN; + + dst.page = virt_to_page(ct); + dst.offset = offset_in_page(ct); + dst.length = AES_BLOCK_LEN; + + crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN); } static void *ieee80211_ccmp_init(int key_idx) @@ -72,11 +81,10 @@ static void *ieee80211_ccmp_init(int key_idx) goto fail; priv->key_idx = key_idx; - priv->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->tfm)) { + priv->tfm = crypto_alloc_tfm("aes", 0); + if (priv->tfm == NULL) { printk(KERN_DEBUG "ieee80211_crypt_ccmp: could not allocate " "crypto API aes\n"); - priv->tfm = NULL; goto fail; } @@ -85,7 +93,7 @@ static void *ieee80211_ccmp_init(int key_idx) fail: if (priv) { if (priv->tfm) - crypto_free_cipher(priv->tfm); + crypto_free_tfm(priv->tfm); kfree(priv); } @@ -96,7 +104,7 @@ static void ieee80211_ccmp_deinit(void *priv) { struct ieee80211_ccmp_data *_priv = priv; if (_priv && _priv->tfm) - crypto_free_cipher(_priv->tfm); + crypto_free_tfm(_priv->tfm); kfree(priv); } @@ -107,7 +115,7 @@ static inline void xor_block(u8 * b, u8 * a, size_t len) b[i] ^= a[i]; } -static void ccmp_init_blocks(struct crypto_cipher *tfm, +static void ccmp_init_blocks(struct crypto_tfm *tfm, struct ieee80211_hdr_4addr *hdr, u8 * pn, size_t dlen, u8 * b0, u8 * auth, u8 * s0) { @@ -369,7 +377,7 @@ static int ieee80211_ccmp_set_key(void *key, int len, u8 * seq, void *priv) { struct ieee80211_ccmp_data *data = priv; int keyidx; - struct crypto_cipher *tfm = data->tfm; + struct crypto_tfm *tfm = data->tfm; keyidx = data->key_idx; memset(data, 0, sizeof(*data)); diff --git a/trunk/net/ieee80211/ieee80211_crypt_tkip.c b/trunk/net/ieee80211/ieee80211_crypt_tkip.c index 407a17495b61..34dba0ba545d 100644 --- a/trunk/net/ieee80211/ieee80211_crypt_tkip.c +++ b/trunk/net/ieee80211/ieee80211_crypt_tkip.c @@ -9,7 +9,6 @@ * more details. */ -#include #include #include #include @@ -53,8 +52,8 @@ struct ieee80211_tkip_data { int key_idx; - struct crypto_blkcipher *tfm_arc4; - struct crypto_hash *tfm_michael; + struct crypto_tfm *tfm_arc4; + struct crypto_tfm *tfm_michael; /* scratch buffers for virt_to_page() (crypto API) */ u8 rx_hdr[16], tx_hdr[16]; @@ -86,21 +85,17 @@ static void *ieee80211_tkip_init(int key_idx) priv->key_idx = key_idx; - priv->tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->tfm_arc4)) { + priv->tfm_arc4 = crypto_alloc_tfm("arc4", 0); + if (priv->tfm_arc4 == NULL) { printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " "crypto API arc4\n"); - priv->tfm_arc4 = NULL; goto fail; } - priv->tfm_michael = crypto_alloc_hash("michael_mic", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->tfm_michael)) { + priv->tfm_michael = crypto_alloc_tfm("michael_mic", 0); + if (priv->tfm_michael == NULL) { printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " "crypto API michael_mic\n"); - priv->tfm_michael = NULL; goto fail; } @@ -109,9 +104,9 @@ static void *ieee80211_tkip_init(int key_idx) fail: if (priv) { if (priv->tfm_michael) - crypto_free_hash(priv->tfm_michael); + crypto_free_tfm(priv->tfm_michael); if (priv->tfm_arc4) - crypto_free_blkcipher(priv->tfm_arc4); + crypto_free_tfm(priv->tfm_arc4); kfree(priv); } @@ -122,9 +117,9 @@ static void ieee80211_tkip_deinit(void *priv) { struct ieee80211_tkip_data *_priv = priv; if (_priv && _priv->tfm_michael) - crypto_free_hash(_priv->tfm_michael); + crypto_free_tfm(_priv->tfm_michael); if (_priv && _priv->tfm_arc4) - crypto_free_blkcipher(_priv->tfm_arc4); + crypto_free_tfm(_priv->tfm_arc4); kfree(priv); } @@ -323,7 +318,6 @@ static int ieee80211_tkip_hdr(struct sk_buff *skb, int hdr_len, static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct ieee80211_tkip_data *tkey = priv; - struct blkcipher_desc desc = { .tfm = tkey->tfm_arc4 }; int len; u8 rc4key[16], *pos, *icv; u32 crc; @@ -357,17 +351,18 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[2] = crc >> 16; icv[3] = crc >> 24; - crypto_blkcipher_setkey(tkey->tfm_arc4, rc4key, 16); + crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); sg.page = virt_to_page(pos); sg.offset = offset_in_page(pos); sg.length = len + 4; - return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + crypto_cipher_encrypt(tkey->tfm_arc4, &sg, &sg, len + 4); + + return 0; } static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct ieee80211_tkip_data *tkey = priv; - struct blkcipher_desc desc = { .tfm = tkey->tfm_arc4 }; u8 rc4key[16]; u8 keyidx, *pos; u32 iv32; @@ -439,18 +434,11 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) plen = skb->len - hdr_len - 12; - crypto_blkcipher_setkey(tkey->tfm_arc4, rc4key, 16); + crypto_cipher_setkey(tkey->tfm_arc4, rc4key, 16); sg.page = virt_to_page(pos); sg.offset = offset_in_page(pos); sg.length = plen + 4; - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { - if (net_ratelimit()) { - printk(KERN_DEBUG ": TKIP: failed to decrypt " - "received packet from " MAC_FMT "\n", - MAC_ARG(hdr->addr2)); - } - return -7; - } + crypto_cipher_decrypt(tkey->tfm_arc4, &sg, &sg, plen + 4); crc = ~crc32_le(~0, pos, plen); icv[0] = crc; @@ -487,7 +475,6 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr, u8 * data, size_t data_len, u8 * mic) { - struct hash_desc desc; struct scatterlist sg[2]; if (tkey->tfm_michael == NULL) { @@ -502,12 +489,12 @@ static int michael_mic(struct ieee80211_tkip_data *tkey, u8 * key, u8 * hdr, sg[1].offset = offset_in_page(data); sg[1].length = data_len; - if (crypto_hash_setkey(tkey->tfm_michael, key, 8)) - return -1; + crypto_digest_init(tkey->tfm_michael); + crypto_digest_setkey(tkey->tfm_michael, key, 8); + crypto_digest_update(tkey->tfm_michael, sg, 2); + crypto_digest_final(tkey->tfm_michael, mic); - desc.tfm = tkey->tfm_michael; - desc.flags = 0; - return crypto_hash_digest(&desc, sg, data_len + 16, mic); + return 0; } static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr) @@ -631,8 +618,8 @@ static int ieee80211_tkip_set_key(void *key, int len, u8 * seq, void *priv) { struct ieee80211_tkip_data *tkey = priv; int keyidx; - struct crypto_hash *tfm = tkey->tfm_michael; - struct crypto_blkcipher *tfm2 = tkey->tfm_arc4; + struct crypto_tfm *tfm = tkey->tfm_michael; + struct crypto_tfm *tfm2 = tkey->tfm_arc4; keyidx = tkey->key_idx; memset(tkey, 0, sizeof(*tkey)); diff --git a/trunk/net/ieee80211/ieee80211_crypt_wep.c b/trunk/net/ieee80211/ieee80211_crypt_wep.c index 3d46d3efe1dd..0ebf235f6939 100644 --- a/trunk/net/ieee80211/ieee80211_crypt_wep.c +++ b/trunk/net/ieee80211/ieee80211_crypt_wep.c @@ -9,7 +9,6 @@ * more details. */ -#include #include #include #include @@ -33,7 +32,7 @@ struct prism2_wep_data { u8 key[WEP_KEY_LEN + 1]; u8 key_len; u8 key_idx; - struct crypto_blkcipher *tfm; + struct crypto_tfm *tfm; }; static void *prism2_wep_init(int keyidx) @@ -45,11 +44,10 @@ static void *prism2_wep_init(int keyidx) goto fail; priv->key_idx = keyidx; - priv->tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->tfm)) { + priv->tfm = crypto_alloc_tfm("arc4", 0); + if (priv->tfm == NULL) { printk(KERN_DEBUG "ieee80211_crypt_wep: could not allocate " "crypto API arc4\n"); - priv->tfm = NULL; goto fail; } @@ -61,7 +59,7 @@ static void *prism2_wep_init(int keyidx) fail: if (priv) { if (priv->tfm) - crypto_free_blkcipher(priv->tfm); + crypto_free_tfm(priv->tfm); kfree(priv); } return NULL; @@ -71,7 +69,7 @@ static void prism2_wep_deinit(void *priv) { struct prism2_wep_data *_priv = priv; if (_priv && _priv->tfm) - crypto_free_blkcipher(_priv->tfm); + crypto_free_tfm(_priv->tfm); kfree(priv); } @@ -122,7 +120,6 @@ static int prism2_wep_build_iv(struct sk_buff *skb, int hdr_len, static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct prism2_wep_data *wep = priv; - struct blkcipher_desc desc = { .tfm = wep->tfm }; u32 crc, klen, len; u8 *pos, *icv; struct scatterlist sg; @@ -154,11 +151,13 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) icv[2] = crc >> 16; icv[3] = crc >> 24; - crypto_blkcipher_setkey(wep->tfm, key, klen); + crypto_cipher_setkey(wep->tfm, key, klen); sg.page = virt_to_page(pos); sg.offset = offset_in_page(pos); sg.length = len + 4; - return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4); + + return 0; } /* Perform WEP decryption on given buffer. Buffer includes whole WEP part of @@ -171,7 +170,6 @@ static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) { struct prism2_wep_data *wep = priv; - struct blkcipher_desc desc = { .tfm = wep->tfm }; u32 crc, klen, plen; u8 key[WEP_KEY_LEN + 3]; u8 keyidx, *pos, icv[4]; @@ -196,12 +194,11 @@ static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) /* Apply RC4 to data and compute CRC32 over decrypted data */ plen = skb->len - hdr_len - 8; - crypto_blkcipher_setkey(wep->tfm, key, klen); + crypto_cipher_setkey(wep->tfm, key, klen); sg.page = virt_to_page(pos); sg.offset = offset_in_page(pos); sg.length = plen + 4; - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) - return -7; + crypto_cipher_decrypt(wep->tfm, &sg, &sg, plen + 4); crc = ~crc32_le(~0, pos, plen); icv[0] = crc; diff --git a/trunk/net/ieee80211/softmac/ieee80211softmac_auth.c b/trunk/net/ieee80211/softmac/ieee80211softmac_auth.c index 4cef39e171d0..ebc33ca6e692 100644 --- a/trunk/net/ieee80211/softmac/ieee80211softmac_auth.c +++ b/trunk/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -116,16 +116,6 @@ ieee80211softmac_auth_queue(void *data) kfree(auth); } -/* Sends a response to an auth challenge (for shared key auth). */ -static void -ieee80211softmac_auth_challenge_response(void *_aq) -{ - struct ieee80211softmac_auth_queue_item *aq = _aq; - - /* Send our response */ - ieee80211softmac_send_mgt_frame(aq->mac, aq->net, IEEE80211_STYPE_AUTH, aq->state); -} - /* Handle the auth response from the AP * This should be registered with ieee80211 as handle_auth */ @@ -207,30 +197,24 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE: /* Check to make sure we have a challenge IE */ data = (u8 *)auth->info_element; - if (*data++ != MFIE_TYPE_CHALLENGE) { + if(*data++ != MFIE_TYPE_CHALLENGE){ printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n"); break; } /* Save the challenge */ spin_lock_irqsave(&mac->lock, flags); net->challenge_len = *data++; - if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN) + if(net->challenge_len > WLAN_AUTH_CHALLENGE_LEN) net->challenge_len = WLAN_AUTH_CHALLENGE_LEN; - if (net->challenge != NULL) + if(net->challenge != NULL) kfree(net->challenge); net->challenge = kmalloc(net->challenge_len, GFP_ATOMIC); memcpy(net->challenge, data, net->challenge_len); aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; - - /* We reuse the work struct from the auth request here. - * It is safe to do so as each one is per-request, and - * at this point (dealing with authentication response) - * we have obviously already sent the initial auth - * request. */ - cancel_delayed_work(&aq->work); - INIT_WORK(&aq->work, &ieee80211softmac_auth_challenge_response, (void *)aq); - schedule_work(&aq->work); spin_unlock_irqrestore(&mac->lock, flags); + + /* Send our response */ + ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state); return 0; case IEEE80211SOFTMAC_AUTH_SHARED_PASS: kfree(net->challenge); diff --git a/trunk/net/ipv4/Kconfig b/trunk/net/ipv4/Kconfig index 1650b64415aa..8514106761b0 100644 --- a/trunk/net/ipv4/Kconfig +++ b/trunk/net/ipv4/Kconfig @@ -88,7 +88,6 @@ config IP_FIB_HASH config IP_MULTIPLE_TABLES bool "IP: policy routing" depends on IP_ADVANCED_ROUTER - select FIB_RULES ---help--- Normally, a router decides what to do with a received packet based solely on the packet's final destination address. If you say Y here, @@ -387,7 +386,6 @@ config INET_ESP select CRYPTO select CRYPTO_HMAC select CRYPTO_MD5 - select CRYPTO_CBC select CRYPTO_SHA1 select CRYPTO_DES ---help--- diff --git a/trunk/net/ipv4/Makefile b/trunk/net/ipv4/Makefile index f66049e28aeb..4878fc5be85f 100644 --- a/trunk/net/ipv4/Makefile +++ b/trunk/net/ipv4/Makefile @@ -47,7 +47,6 @@ obj-$(CONFIG_TCP_CONG_VEGAS) += tcp_vegas.o obj-$(CONFIG_TCP_CONG_VENO) += tcp_veno.o obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o -obj-$(CONFIG_NETLABEL) += cipso_ipv4.o obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ xfrm4_output.o diff --git a/trunk/net/ipv4/af_inet.c b/trunk/net/ipv4/af_inet.c index fdd89e37b9aa..c84a32070f8d 100644 --- a/trunk/net/ipv4/af_inet.c +++ b/trunk/net/ipv4/af_inet.c @@ -67,6 +67,7 @@ * 2 of the License, or (at your option) any later version. */ +#include #include #include #include @@ -391,7 +392,7 @@ int inet_release(struct socket *sock) } /* It is off by default, see below. */ -int sysctl_ip_nonlocal_bind __read_mostly; +int sysctl_ip_nonlocal_bind; int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { @@ -987,7 +988,7 @@ void inet_unregister_protosw(struct inet_protosw *p) * Shall we try to damage output packets if routing dev changes? */ -int sysctl_ip_dynaddr __read_mostly; +int sysctl_ip_dynaddr; static int inet_sk_reselect_saddr(struct sock *sk) { @@ -1073,7 +1074,6 @@ int inet_sk_rebuild_header(struct sock *sk) }, }; - security_sk_classify_flow(sk, &fl); err = ip_route_output_flow(&rt, &fl, sk, 0); } if (!err) @@ -1254,7 +1254,10 @@ static int __init inet_init(void) struct list_head *r; int rc = -EINVAL; - BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)); + if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) { + printk(KERN_CRIT "%s: panic\n", __FUNCTION__); + goto out; + } rc = proto_register(&tcp_prot, 1); if (rc) diff --git a/trunk/net/ipv4/ah4.c b/trunk/net/ipv4/ah4.c index 99542977e47e..1366bc6ce6a5 100644 --- a/trunk/net/ipv4/ah4.c +++ b/trunk/net/ipv4/ah4.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -35,7 +34,7 @@ static int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr) switch (*optptr) { case IPOPT_SEC: case 0x85: /* Some "Extended Security" crap. */ - case IPOPT_CIPSO: + case 0x86: /* Another "Commercial Security" crap. */ case IPOPT_RA: case 0x80|21: /* RFC1770 */ break; @@ -98,10 +97,7 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb) ah->spi = x->id.spi; ah->seq_no = htonl(++x->replay.oseq); xfrm_aevent_doreplay(x); - err = ah_mac_digest(ahp, skb, ah->auth_data); - if (err) - goto error; - memcpy(ah->auth_data, ahp->work_icv, ahp->icv_trunc_len); + ahp->icv(ahp, skb, ah->auth_data); top_iph->tos = iph->tos; top_iph->ttl = iph->ttl; @@ -123,7 +119,6 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) { int ah_hlen; int ihl; - int err = -EINVAL; struct iphdr *iph; struct ip_auth_hdr *ah; struct ah_data *ahp; @@ -171,11 +166,8 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); skb_push(skb, ihl); - err = ah_mac_digest(ahp, skb, ah->auth_data); - if (err) - goto out; - err = -EINVAL; - if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) { + ahp->icv(ahp, skb, ah->auth_data); + if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { x->stats.integrity_failed++; goto out; } @@ -187,7 +179,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) return 0; out: - return err; + return -EINVAL; } static void ah4_err(struct sk_buff *skb, u32 info) @@ -212,7 +204,6 @@ static int ah_init_state(struct xfrm_state *x) { struct ah_data *ahp = NULL; struct xfrm_algo_desc *aalg_desc; - struct crypto_hash *tfm; if (!x->aalg) goto error; @@ -230,27 +221,24 @@ static int ah_init_state(struct xfrm_state *x) ahp->key = x->aalg->alg_key; ahp->key_len = (x->aalg->alg_key_len+7)/8; - tfm = crypto_alloc_hash(x->aalg->alg_name, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) - goto error; - - ahp->tfm = tfm; - if (crypto_hash_setkey(tfm, ahp->key, ahp->key_len)) + ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); + if (!ahp->tfm) goto error; + ahp->icv = ah_hmac_digest; /* * Lookup the algorithm description maintained by xfrm_algo, * verify crypto transform properties, and store information * we need for AH processing. This lookup cannot fail here - * after a successful crypto_alloc_hash(). + * after a successful crypto_alloc_tfm(). */ aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); BUG_ON(!aalg_desc); if (aalg_desc->uinfo.auth.icv_fullbits/8 != - crypto_hash_digestsize(tfm)) { + crypto_tfm_alg_digestsize(ahp->tfm)) { printk(KERN_INFO "AH: %s digestsize %u != %hu\n", - x->aalg->alg_name, crypto_hash_digestsize(tfm), + x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm), aalg_desc->uinfo.auth.icv_fullbits/8); goto error; } @@ -265,7 +253,7 @@ static int ah_init_state(struct xfrm_state *x) goto error; x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + ahp->icv_trunc_len); - if (x->props.mode == XFRM_MODE_TUNNEL) + if (x->props.mode) x->props.header_len += sizeof(struct iphdr); x->data = ahp; @@ -274,7 +262,7 @@ static int ah_init_state(struct xfrm_state *x) error: if (ahp) { kfree(ahp->work_icv); - crypto_free_hash(ahp->tfm); + crypto_free_tfm(ahp->tfm); kfree(ahp); } return -EINVAL; @@ -289,7 +277,7 @@ static void ah_destroy(struct xfrm_state *x) kfree(ahp->work_icv); ahp->work_icv = NULL; - crypto_free_hash(ahp->tfm); + crypto_free_tfm(ahp->tfm); ahp->tfm = NULL; kfree(ahp); } diff --git a/trunk/net/ipv4/cipso_ipv4.c b/trunk/net/ipv4/cipso_ipv4.c deleted file mode 100644 index 80a2a0911b49..000000000000 --- a/trunk/net/ipv4/cipso_ipv4.c +++ /dev/null @@ -1,1607 +0,0 @@ -/* - * CIPSO - Commercial IP Security Option - * - * This is an implementation of the CIPSO 2.2 protocol as specified in - * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in - * FIPS-188, copies of both documents can be found in the Documentation - * directory. While CIPSO never became a full IETF RFC standard many vendors - * have chosen to adopt the protocol and over the years it has become a - * de-facto standard for labeled networking. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct cipso_v4_domhsh_entry { - char *domain; - u32 valid; - struct list_head list; - struct rcu_head rcu; -}; - -/* List of available DOI definitions */ -/* XXX - Updates should be minimal so having a single lock for the - * cipso_v4_doi_list and the cipso_v4_doi_list->dom_list should be - * okay. */ -/* XXX - This currently assumes a minimal number of different DOIs in use, - * if in practice there are a lot of different DOIs this list should - * probably be turned into a hash table or something similar so we - * can do quick lookups. */ -static DEFINE_SPINLOCK(cipso_v4_doi_list_lock); -static struct list_head cipso_v4_doi_list = LIST_HEAD_INIT(cipso_v4_doi_list); - -/* Label mapping cache */ -int cipso_v4_cache_enabled = 1; -int cipso_v4_cache_bucketsize = 10; -#define CIPSO_V4_CACHE_BUCKETBITS 7 -#define CIPSO_V4_CACHE_BUCKETS (1 << CIPSO_V4_CACHE_BUCKETBITS) -#define CIPSO_V4_CACHE_REORDERLIMIT 10 -struct cipso_v4_map_cache_bkt { - spinlock_t lock; - u32 size; - struct list_head list; -}; -struct cipso_v4_map_cache_entry { - u32 hash; - unsigned char *key; - size_t key_len; - - struct netlbl_lsm_cache lsm_data; - - u32 activity; - struct list_head list; -}; -static struct cipso_v4_map_cache_bkt *cipso_v4_cache = NULL; - -/* Restricted bitmap (tag #1) flags */ -int cipso_v4_rbm_optfmt = 0; -int cipso_v4_rbm_strictvalid = 1; - -/* - * Helper Functions - */ - -/** - * cipso_v4_bitmap_walk - Walk a bitmap looking for a bit - * @bitmap: the bitmap - * @bitmap_len: length in bits - * @offset: starting offset - * @state: if non-zero, look for a set (1) bit else look for a cleared (0) bit - * - * Description: - * Starting at @offset, walk the bitmap from left to right until either the - * desired bit is found or we reach the end. Return the bit offset, -1 if - * not found, or -2 if error. - */ -static int cipso_v4_bitmap_walk(const unsigned char *bitmap, - u32 bitmap_len, - u32 offset, - u8 state) -{ - u32 bit_spot; - u32 byte_offset; - unsigned char bitmask; - unsigned char byte; - - /* gcc always rounds to zero when doing integer division */ - byte_offset = offset / 8; - byte = bitmap[byte_offset]; - bit_spot = offset; - bitmask = 0x80 >> (offset % 8); - - while (bit_spot < bitmap_len) { - if ((state && (byte & bitmask) == bitmask) || - (state == 0 && (byte & bitmask) == 0)) - return bit_spot; - - bit_spot++; - bitmask >>= 1; - if (bitmask == 0) { - byte = bitmap[++byte_offset]; - bitmask = 0x80; - } - } - - return -1; -} - -/** - * cipso_v4_bitmap_setbit - Sets a single bit in a bitmap - * @bitmap: the bitmap - * @bit: the bit - * @state: if non-zero, set the bit (1) else clear the bit (0) - * - * Description: - * Set a single bit in the bitmask. Returns zero on success, negative values - * on error. - */ -static void cipso_v4_bitmap_setbit(unsigned char *bitmap, - u32 bit, - u8 state) -{ - u32 byte_spot; - u8 bitmask; - - /* gcc always rounds to zero when doing integer division */ - byte_spot = bit / 8; - bitmask = 0x80 >> (bit % 8); - if (state) - bitmap[byte_spot] |= bitmask; - else - bitmap[byte_spot] &= ~bitmask; -} - -/** - * cipso_v4_doi_domhsh_free - Frees a domain list entry - * @entry: the entry's RCU field - * - * Description: - * This function is designed to be used as a callback to the call_rcu() - * function so that the memory allocated to a domain list entry can be released - * safely. - * - */ -static void cipso_v4_doi_domhsh_free(struct rcu_head *entry) -{ - struct cipso_v4_domhsh_entry *ptr; - - ptr = container_of(entry, struct cipso_v4_domhsh_entry, rcu); - kfree(ptr->domain); - kfree(ptr); -} - -/** - * cipso_v4_cache_entry_free - Frees a cache entry - * @entry: the entry to free - * - * Description: - * This function frees the memory associated with a cache entry. - * - */ -static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry) -{ - if (entry->lsm_data.free) - entry->lsm_data.free(entry->lsm_data.data); - kfree(entry->key); - kfree(entry); -} - -/** - * cipso_v4_map_cache_hash - Hashing function for the CIPSO cache - * @key: the hash key - * @key_len: the length of the key in bytes - * - * Description: - * The CIPSO tag hashing function. Returns a 32-bit hash value. - * - */ -static u32 cipso_v4_map_cache_hash(const unsigned char *key, u32 key_len) -{ - return jhash(key, key_len, 0); -} - -/* - * Label Mapping Cache Functions - */ - -/** - * cipso_v4_cache_init - Initialize the CIPSO cache - * - * Description: - * Initializes the CIPSO label mapping cache, this function should be called - * before any of the other functions defined in this file. Returns zero on - * success, negative values on error. - * - */ -static int cipso_v4_cache_init(void) -{ - u32 iter; - - cipso_v4_cache = kcalloc(CIPSO_V4_CACHE_BUCKETS, - sizeof(struct cipso_v4_map_cache_bkt), - GFP_KERNEL); - if (cipso_v4_cache == NULL) - return -ENOMEM; - - for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) { - spin_lock_init(&cipso_v4_cache[iter].lock); - cipso_v4_cache[iter].size = 0; - INIT_LIST_HEAD(&cipso_v4_cache[iter].list); - } - - return 0; -} - -/** - * cipso_v4_cache_invalidate - Invalidates the current CIPSO cache - * - * Description: - * Invalidates and frees any entries in the CIPSO cache. Returns zero on - * success and negative values on failure. - * - */ -void cipso_v4_cache_invalidate(void) -{ - struct cipso_v4_map_cache_entry *entry, *tmp_entry; - u32 iter; - - for (iter = 0; iter < CIPSO_V4_CACHE_BUCKETS; iter++) { - spin_lock(&cipso_v4_cache[iter].lock); - list_for_each_entry_safe(entry, - tmp_entry, - &cipso_v4_cache[iter].list, list) { - list_del(&entry->list); - cipso_v4_cache_entry_free(entry); - } - cipso_v4_cache[iter].size = 0; - spin_unlock(&cipso_v4_cache[iter].lock); - } - - return; -} - -/** - * cipso_v4_cache_check - Check the CIPSO cache for a label mapping - * @key: the buffer to check - * @key_len: buffer length in bytes - * @secattr: the security attribute struct to use - * - * Description: - * This function checks the cache to see if a label mapping already exists for - * the given key. If there is a match then the cache is adjusted and the - * @secattr struct is populated with the correct LSM security attributes. The - * cache is adjusted in the following manner if the entry is not already the - * first in the cache bucket: - * - * 1. The cache entry's activity counter is incremented - * 2. The previous (higher ranking) entry's activity counter is decremented - * 3. If the difference between the two activity counters is geater than - * CIPSO_V4_CACHE_REORDERLIMIT the two entries are swapped - * - * Returns zero on success, -ENOENT for a cache miss, and other negative values - * on error. - * - */ -static int cipso_v4_cache_check(const unsigned char *key, - u32 key_len, - struct netlbl_lsm_secattr *secattr) -{ - u32 bkt; - struct cipso_v4_map_cache_entry *entry; - struct cipso_v4_map_cache_entry *prev_entry = NULL; - u32 hash; - - if (!cipso_v4_cache_enabled) - return -ENOENT; - - hash = cipso_v4_map_cache_hash(key, key_len); - bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); - spin_lock(&cipso_v4_cache[bkt].lock); - list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) { - if (entry->hash == hash && - entry->key_len == key_len && - memcmp(entry->key, key, key_len) == 0) { - entry->activity += 1; - secattr->cache.free = entry->lsm_data.free; - secattr->cache.data = entry->lsm_data.data; - if (prev_entry == NULL) { - spin_unlock(&cipso_v4_cache[bkt].lock); - return 0; - } - - if (prev_entry->activity > 0) - prev_entry->activity -= 1; - if (entry->activity > prev_entry->activity && - entry->activity - prev_entry->activity > - CIPSO_V4_CACHE_REORDERLIMIT) { - __list_del(entry->list.prev, entry->list.next); - __list_add(&entry->list, - prev_entry->list.prev, - &prev_entry->list); - } - - spin_unlock(&cipso_v4_cache[bkt].lock); - return 0; - } - prev_entry = entry; - } - spin_unlock(&cipso_v4_cache[bkt].lock); - - return -ENOENT; -} - -/** - * cipso_v4_cache_add - Add an entry to the CIPSO cache - * @skb: the packet - * @secattr: the packet's security attributes - * - * Description: - * Add a new entry into the CIPSO label mapping cache. Add the new entry to - * head of the cache bucket's list, if the cache bucket is out of room remove - * the last entry in the list first. It is important to note that there is - * currently no checking for duplicate keys. Returns zero on success, - * negative values on failure. - * - */ -int cipso_v4_cache_add(const struct sk_buff *skb, - const struct netlbl_lsm_secattr *secattr) -{ - int ret_val = -EPERM; - u32 bkt; - struct cipso_v4_map_cache_entry *entry = NULL; - struct cipso_v4_map_cache_entry *old_entry = NULL; - unsigned char *cipso_ptr; - u32 cipso_ptr_len; - - if (!cipso_v4_cache_enabled || cipso_v4_cache_bucketsize <= 0) - return 0; - - cipso_ptr = CIPSO_V4_OPTPTR(skb); - cipso_ptr_len = cipso_ptr[1]; - - entry = kzalloc(sizeof(*entry), GFP_ATOMIC); - if (entry == NULL) - return -ENOMEM; - entry->key = kmalloc(cipso_ptr_len, GFP_ATOMIC); - if (entry->key == NULL) { - ret_val = -ENOMEM; - goto cache_add_failure; - } - memcpy(entry->key, cipso_ptr, cipso_ptr_len); - entry->key_len = cipso_ptr_len; - entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len); - entry->lsm_data.free = secattr->cache.free; - entry->lsm_data.data = secattr->cache.data; - - bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); - spin_lock(&cipso_v4_cache[bkt].lock); - if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) { - list_add(&entry->list, &cipso_v4_cache[bkt].list); - cipso_v4_cache[bkt].size += 1; - } else { - old_entry = list_entry(cipso_v4_cache[bkt].list.prev, - struct cipso_v4_map_cache_entry, list); - list_del(&old_entry->list); - list_add(&entry->list, &cipso_v4_cache[bkt].list); - cipso_v4_cache_entry_free(old_entry); - } - spin_unlock(&cipso_v4_cache[bkt].lock); - - return 0; - -cache_add_failure: - if (entry) - cipso_v4_cache_entry_free(entry); - return ret_val; -} - -/* - * DOI List Functions - */ - -/** - * cipso_v4_doi_search - Searches for a DOI definition - * @doi: the DOI to search for - * - * Description: - * Search the DOI definition list for a DOI definition with a DOI value that - * matches @doi. The caller is responsibile for calling rcu_read_[un]lock(). - * Returns a pointer to the DOI definition on success and NULL on failure. - */ -static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi) -{ - struct cipso_v4_doi *iter; - - list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list) - if (iter->doi == doi && iter->valid) - return iter; - return NULL; -} - -/** - * cipso_v4_doi_add - Add a new DOI to the CIPSO protocol engine - * @doi_def: the DOI structure - * - * Description: - * The caller defines a new DOI for use by the CIPSO engine and calls this - * function to add it to the list of acceptable domains. The caller must - * ensure that the mapping table specified in @doi_def->map meets all of the - * requirements of the mapping type (see cipso_ipv4.h for details). Returns - * zero on success and non-zero on failure. - * - */ -int cipso_v4_doi_add(struct cipso_v4_doi *doi_def) -{ - if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN) - return -EINVAL; - - doi_def->valid = 1; - INIT_RCU_HEAD(&doi_def->rcu); - INIT_LIST_HEAD(&doi_def->dom_list); - - rcu_read_lock(); - if (cipso_v4_doi_search(doi_def->doi) != NULL) - goto doi_add_failure_rlock; - spin_lock(&cipso_v4_doi_list_lock); - if (cipso_v4_doi_search(doi_def->doi) != NULL) - goto doi_add_failure_slock; - list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list); - spin_unlock(&cipso_v4_doi_list_lock); - rcu_read_unlock(); - - return 0; - -doi_add_failure_slock: - spin_unlock(&cipso_v4_doi_list_lock); -doi_add_failure_rlock: - rcu_read_unlock(); - return -EEXIST; -} - -/** - * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine - * @doi: the DOI value - * @callback: the DOI cleanup/free callback - * - * Description: - * Removes a DOI definition from the CIPSO engine, @callback is called to - * free any memory. The NetLabel routines will be called to release their own - * LSM domain mappings as well as our own domain list. Returns zero on - * success and negative values on failure. - * - */ -int cipso_v4_doi_remove(u32 doi, void (*callback) (struct rcu_head * head)) -{ - struct cipso_v4_doi *doi_def; - struct cipso_v4_domhsh_entry *dom_iter; - - rcu_read_lock(); - if (cipso_v4_doi_search(doi) != NULL) { - spin_lock(&cipso_v4_doi_list_lock); - doi_def = cipso_v4_doi_search(doi); - if (doi_def == NULL) { - spin_unlock(&cipso_v4_doi_list_lock); - rcu_read_unlock(); - return -ENOENT; - } - doi_def->valid = 0; - list_del_rcu(&doi_def->list); - spin_unlock(&cipso_v4_doi_list_lock); - list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list) - if (dom_iter->valid) - netlbl_domhsh_remove(dom_iter->domain); - cipso_v4_cache_invalidate(); - rcu_read_unlock(); - - call_rcu(&doi_def->rcu, callback); - return 0; - } - rcu_read_unlock(); - - return -ENOENT; -} - -/** - * cipso_v4_doi_getdef - Returns a pointer to a valid DOI definition - * @doi: the DOI value - * - * Description: - * Searches for a valid DOI definition and if one is found it is returned to - * the caller. Otherwise NULL is returned. The caller must ensure that - * rcu_read_lock() is held while accessing the returned definition. - * - */ -struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi) -{ - return cipso_v4_doi_search(doi); -} - -/** - * cipso_v4_doi_dump_all - Dump all the CIPSO DOI definitions into a sk_buff - * @headroom: the amount of headroom to allocate for the sk_buff - * - * Description: - * Dump a list of all the configured DOI values into a sk_buff. The returned - * sk_buff has room at the front of the sk_buff for @headroom bytes. See - * net/netlabel/netlabel_cipso_v4.h for the LISTALL message format. This - * function may fail if another process is changing the DOI list at the same - * time. Returns a pointer to a sk_buff on success, NULL on error. - * - */ -struct sk_buff *cipso_v4_doi_dump_all(size_t headroom) -{ - struct sk_buff *skb = NULL; - struct cipso_v4_doi *iter; - u32 doi_cnt = 0; - ssize_t buf_len; - - buf_len = NETLBL_LEN_U32; - rcu_read_lock(); - list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list) - if (iter->valid) { - doi_cnt += 1; - buf_len += 2 * NETLBL_LEN_U32; - } - - skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); - if (skb == NULL) - goto doi_dump_all_failure; - - if (nla_put_u32(skb, NLA_U32, doi_cnt) != 0) - goto doi_dump_all_failure; - buf_len -= NETLBL_LEN_U32; - list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list) - if (iter->valid) { - if (buf_len < 2 * NETLBL_LEN_U32) - goto doi_dump_all_failure; - if (nla_put_u32(skb, NLA_U32, iter->doi) != 0) - goto doi_dump_all_failure; - if (nla_put_u32(skb, NLA_U32, iter->type) != 0) - goto doi_dump_all_failure; - buf_len -= 2 * NETLBL_LEN_U32; - } - rcu_read_unlock(); - - return skb; - -doi_dump_all_failure: - rcu_read_unlock(); - kfree(skb); - return NULL; -} - -/** - * cipso_v4_doi_dump - Dump a CIPSO DOI definition into a sk_buff - * @doi: the DOI value - * @headroom: the amount of headroom to allocate for the sk_buff - * - * Description: - * Lookup the DOI definition matching @doi and dump it's contents into a - * sk_buff. The returned sk_buff has room at the front of the sk_buff for - * @headroom bytes. See net/netlabel/netlabel_cipso_v4.h for the LIST message - * format. This function may fail if another process is changing the DOI list - * at the same time. Returns a pointer to a sk_buff on success, NULL on error. - * - */ -struct sk_buff *cipso_v4_doi_dump(u32 doi, size_t headroom) -{ - struct sk_buff *skb = NULL; - struct cipso_v4_doi *iter; - u32 tag_cnt = 0; - u32 lvl_cnt = 0; - u32 cat_cnt = 0; - ssize_t buf_len; - ssize_t tmp; - - rcu_read_lock(); - iter = cipso_v4_doi_getdef(doi); - if (iter == NULL) - goto doi_dump_failure; - buf_len = NETLBL_LEN_U32; - switch (iter->type) { - case CIPSO_V4_MAP_PASS: - buf_len += NETLBL_LEN_U32; - while(tag_cnt < CIPSO_V4_TAG_MAXCNT && - iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) { - tag_cnt += 1; - buf_len += NETLBL_LEN_U8; - } - break; - case CIPSO_V4_MAP_STD: - buf_len += 3 * NETLBL_LEN_U32; - while (tag_cnt < CIPSO_V4_TAG_MAXCNT && - iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) { - tag_cnt += 1; - buf_len += NETLBL_LEN_U8; - } - for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++) - if (iter->map.std->lvl.local[tmp] != - CIPSO_V4_INV_LVL) { - lvl_cnt += 1; - buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U8; - } - for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++) - if (iter->map.std->cat.local[tmp] != - CIPSO_V4_INV_CAT) { - cat_cnt += 1; - buf_len += NETLBL_LEN_U32 + NETLBL_LEN_U16; - } - break; - } - - skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); - if (skb == NULL) - goto doi_dump_failure; - - if (nla_put_u32(skb, NLA_U32, iter->type) != 0) - goto doi_dump_failure; - buf_len -= NETLBL_LEN_U32; - if (iter != cipso_v4_doi_getdef(doi)) - goto doi_dump_failure; - switch (iter->type) { - case CIPSO_V4_MAP_PASS: - if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0) - goto doi_dump_failure; - buf_len -= NETLBL_LEN_U32; - for (tmp = 0; - tmp < CIPSO_V4_TAG_MAXCNT && - iter->tags[tmp] != CIPSO_V4_TAG_INVALID; - tmp++) { - if (buf_len < NETLBL_LEN_U8) - goto doi_dump_failure; - if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0) - goto doi_dump_failure; - buf_len -= NETLBL_LEN_U8; - } - break; - case CIPSO_V4_MAP_STD: - if (nla_put_u32(skb, NLA_U32, tag_cnt) != 0) - goto doi_dump_failure; - if (nla_put_u32(skb, NLA_U32, lvl_cnt) != 0) - goto doi_dump_failure; - if (nla_put_u32(skb, NLA_U32, cat_cnt) != 0) - goto doi_dump_failure; - buf_len -= 3 * NETLBL_LEN_U32; - for (tmp = 0; - tmp < CIPSO_V4_TAG_MAXCNT && - iter->tags[tmp] != CIPSO_V4_TAG_INVALID; - tmp++) { - if (buf_len < NETLBL_LEN_U8) - goto doi_dump_failure; - if (nla_put_u8(skb, NLA_U8, iter->tags[tmp]) != 0) - goto doi_dump_failure; - buf_len -= NETLBL_LEN_U8; - } - for (tmp = 0; tmp < iter->map.std->lvl.local_size; tmp++) - if (iter->map.std->lvl.local[tmp] != - CIPSO_V4_INV_LVL) { - if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U8) - goto doi_dump_failure; - if (nla_put_u32(skb, NLA_U32, tmp) != 0) - goto doi_dump_failure; - if (nla_put_u8(skb, - NLA_U8, - iter->map.std->lvl.local[tmp]) != 0) - goto doi_dump_failure; - buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U8; - } - for (tmp = 0; tmp < iter->map.std->cat.local_size; tmp++) - if (iter->map.std->cat.local[tmp] != - CIPSO_V4_INV_CAT) { - if (buf_len < NETLBL_LEN_U32 + NETLBL_LEN_U16) - goto doi_dump_failure; - if (nla_put_u32(skb, NLA_U32, tmp) != 0) - goto doi_dump_failure; - if (nla_put_u16(skb, - NLA_U16, - iter->map.std->cat.local[tmp]) != 0) - goto doi_dump_failure; - buf_len -= NETLBL_LEN_U32 + NETLBL_LEN_U16; - } - break; - } - rcu_read_unlock(); - - return skb; - -doi_dump_failure: - rcu_read_unlock(); - kfree(skb); - return NULL; -} - -/** - * cipso_v4_doi_domhsh_add - Adds a domain entry to a DOI definition - * @doi_def: the DOI definition - * @domain: the domain to add - * - * Description: - * Adds the @domain to the the DOI specified by @doi_def, this function - * should only be called by external functions (i.e. NetLabel). This function - * does allocate memory. Returns zero on success, negative values on failure. - * - */ -int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain) -{ - struct cipso_v4_domhsh_entry *iter; - struct cipso_v4_domhsh_entry *new_dom; - - new_dom = kzalloc(sizeof(*new_dom), GFP_KERNEL); - if (new_dom == NULL) - return -ENOMEM; - if (domain) { - new_dom->domain = kstrdup(domain, GFP_KERNEL); - if (new_dom->domain == NULL) { - kfree(new_dom); - return -ENOMEM; - } - } - new_dom->valid = 1; - INIT_RCU_HEAD(&new_dom->rcu); - - rcu_read_lock(); - spin_lock(&cipso_v4_doi_list_lock); - list_for_each_entry_rcu(iter, &doi_def->dom_list, list) - if (iter->valid && - ((domain != NULL && iter->domain != NULL && - strcmp(iter->domain, domain) == 0) || - (domain == NULL && iter->domain == NULL))) { - spin_unlock(&cipso_v4_doi_list_lock); - rcu_read_unlock(); - kfree(new_dom->domain); - kfree(new_dom); - return -EEXIST; - } - list_add_tail_rcu(&new_dom->list, &doi_def->dom_list); - spin_unlock(&cipso_v4_doi_list_lock); - rcu_read_unlock(); - - return 0; -} - -/** - * cipso_v4_doi_domhsh_remove - Removes a domain entry from a DOI definition - * @doi_def: the DOI definition - * @domain: the domain to remove - * - * Description: - * Removes the @domain from the DOI specified by @doi_def, this function - * should only be called by external functions (i.e. NetLabel). Returns zero - * on success and negative values on error. - * - */ -int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def, - const char *domain) -{ - struct cipso_v4_domhsh_entry *iter; - - rcu_read_lock(); - spin_lock(&cipso_v4_doi_list_lock); - list_for_each_entry_rcu(iter, &doi_def->dom_list, list) - if (iter->valid && - ((domain != NULL && iter->domain != NULL && - strcmp(iter->domain, domain) == 0) || - (domain == NULL && iter->domain == NULL))) { - iter->valid = 0; - list_del_rcu(&iter->list); - spin_unlock(&cipso_v4_doi_list_lock); - rcu_read_unlock(); - call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free); - - return 0; - } - spin_unlock(&cipso_v4_doi_list_lock); - rcu_read_unlock(); - - return -ENOENT; -} - -/* - * Label Mapping Functions - */ - -/** - * cipso_v4_map_lvl_valid - Checks to see if the given level is understood - * @doi_def: the DOI definition - * @level: the level to check - * - * Description: - * Checks the given level against the given DOI definition and returns a - * negative value if the level does not have a valid mapping and a zero value - * if the level is defined by the DOI. - * - */ -static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def, u8 level) -{ - switch (doi_def->type) { - case CIPSO_V4_MAP_PASS: - return 0; - case CIPSO_V4_MAP_STD: - if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL) - return 0; - break; - } - - return -EFAULT; -} - -/** - * cipso_v4_map_lvl_hton - Perform a level mapping from the host to the network - * @doi_def: the DOI definition - * @host_lvl: the host MLS level - * @net_lvl: the network/CIPSO MLS level - * - * Description: - * Perform a label mapping to translate a local MLS level to the correct - * CIPSO level using the given DOI definition. Returns zero on success, - * negative values otherwise. - * - */ -static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def, - u32 host_lvl, - u32 *net_lvl) -{ - switch (doi_def->type) { - case CIPSO_V4_MAP_PASS: - *net_lvl = host_lvl; - return 0; - case CIPSO_V4_MAP_STD: - if (host_lvl < doi_def->map.std->lvl.local_size) { - *net_lvl = doi_def->map.std->lvl.local[host_lvl]; - return 0; - } - break; - } - - return -EINVAL; -} - -/** - * cipso_v4_map_lvl_ntoh - Perform a level mapping from the network to the host - * @doi_def: the DOI definition - * @net_lvl: the network/CIPSO MLS level - * @host_lvl: the host MLS level - * - * Description: - * Perform a label mapping to translate a CIPSO level to the correct local MLS - * level using the given DOI definition. Returns zero on success, negative - * values otherwise. - * - */ -static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def, - u32 net_lvl, - u32 *host_lvl) -{ - struct cipso_v4_std_map_tbl *map_tbl; - - switch (doi_def->type) { - case CIPSO_V4_MAP_PASS: - *host_lvl = net_lvl; - return 0; - case CIPSO_V4_MAP_STD: - map_tbl = doi_def->map.std; - if (net_lvl < map_tbl->lvl.cipso_size && - map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) { - *host_lvl = doi_def->map.std->lvl.cipso[net_lvl]; - return 0; - } - break; - } - - return -EINVAL; -} - -/** - * cipso_v4_map_cat_rbm_valid - Checks to see if the category bitmap is valid - * @doi_def: the DOI definition - * @bitmap: category bitmap - * @bitmap_len: bitmap length in bytes - * - * Description: - * Checks the given category bitmap against the given DOI definition and - * returns a negative value if any of the categories in the bitmap do not have - * a valid mapping and a zero value if all of the categories are valid. - * - */ -static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def, - const unsigned char *bitmap, - u32 bitmap_len) -{ - int cat = -1; - u32 bitmap_len_bits = bitmap_len * 8; - u32 cipso_cat_size = doi_def->map.std->cat.cipso_size; - u32 *cipso_array = doi_def->map.std->cat.cipso; - - switch (doi_def->type) { - case CIPSO_V4_MAP_PASS: - return 0; - case CIPSO_V4_MAP_STD: - for (;;) { - cat = cipso_v4_bitmap_walk(bitmap, - bitmap_len_bits, - cat + 1, - 1); - if (cat < 0) - break; - if (cat >= cipso_cat_size || - cipso_array[cat] >= CIPSO_V4_INV_CAT) - return -EFAULT; - } - - if (cat == -1) - return 0; - break; - } - - return -EFAULT; -} - -/** - * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network - * @doi_def: the DOI definition - * @host_cat: the category bitmap in host format - * @host_cat_len: the length of the host's category bitmap in bytes - * @net_cat: the zero'd out category bitmap in network/CIPSO format - * @net_cat_len: the length of the CIPSO bitmap in bytes - * - * Description: - * Perform a label mapping to translate a local MLS category bitmap to the - * correct CIPSO bitmap using the given DOI definition. Returns the minimum - * size in bytes of the network bitmap on success, negative values otherwise. - * - */ -static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def, - const unsigned char *host_cat, - u32 host_cat_len, - unsigned char *net_cat, - u32 net_cat_len) -{ - int host_spot = -1; - u32 net_spot; - u32 net_spot_max = 0; - u32 host_clen_bits = host_cat_len * 8; - u32 net_clen_bits = net_cat_len * 8; - u32 host_cat_size = doi_def->map.std->cat.local_size; - u32 *host_cat_array = doi_def->map.std->cat.local; - - switch (doi_def->type) { - case CIPSO_V4_MAP_PASS: - net_spot_max = host_cat_len - 1; - while (net_spot_max > 0 && host_cat[net_spot_max] == 0) - net_spot_max--; - if (net_spot_max > net_cat_len) - return -EINVAL; - memcpy(net_cat, host_cat, net_spot_max); - return net_spot_max; - case CIPSO_V4_MAP_STD: - for (;;) { - host_spot = cipso_v4_bitmap_walk(host_cat, - host_clen_bits, - host_spot + 1, - 1); - if (host_spot < 0) - break; - if (host_spot >= host_cat_size) - return -EPERM; - - net_spot = host_cat_array[host_spot]; - if (net_spot >= net_clen_bits) - return -ENOSPC; - cipso_v4_bitmap_setbit(net_cat, net_spot, 1); - - if (net_spot > net_spot_max) - net_spot_max = net_spot; - } - - if (host_spot == -2) - return -EFAULT; - - if (++net_spot_max % 8) - return net_spot_max / 8 + 1; - return net_spot_max / 8; - } - - return -EINVAL; -} - -/** - * cipso_v4_map_cat_rbm_ntoh - Perform a category mapping from network to host - * @doi_def: the DOI definition - * @net_cat: the category bitmap in network/CIPSO format - * @net_cat_len: the length of the CIPSO bitmap in bytes - * @host_cat: the zero'd out category bitmap in host format - * @host_cat_len: the length of the host's category bitmap in bytes - * - * Description: - * Perform a label mapping to translate a CIPSO bitmap to the correct local - * MLS category bitmap using the given DOI definition. Returns the minimum - * size in bytes of the host bitmap on success, negative values otherwise. - * - */ -static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def, - const unsigned char *net_cat, - u32 net_cat_len, - unsigned char *host_cat, - u32 host_cat_len) -{ - u32 host_spot; - u32 host_spot_max = 0; - int net_spot = -1; - u32 net_clen_bits = net_cat_len * 8; - u32 host_clen_bits = host_cat_len * 8; - u32 net_cat_size = doi_def->map.std->cat.cipso_size; - u32 *net_cat_array = doi_def->map.std->cat.cipso; - - switch (doi_def->type) { - case CIPSO_V4_MAP_PASS: - if (net_cat_len > host_cat_len) - return -EINVAL; - memcpy(host_cat, net_cat, net_cat_len); - return net_cat_len; - case CIPSO_V4_MAP_STD: - for (;;) { - net_spot = cipso_v4_bitmap_walk(net_cat, - net_clen_bits, - net_spot + 1, - 1); - if (net_spot < 0) - break; - if (net_spot >= net_cat_size || - net_cat_array[net_spot] >= CIPSO_V4_INV_CAT) - return -EPERM; - - host_spot = net_cat_array[net_spot]; - if (host_spot >= host_clen_bits) - return -ENOSPC; - cipso_v4_bitmap_setbit(host_cat, host_spot, 1); - - if (host_spot > host_spot_max) - host_spot_max = host_spot; - } - - if (net_spot == -2) - return -EFAULT; - - if (++host_spot_max % 8) - return host_spot_max / 8 + 1; - return host_spot_max / 8; - } - - return -EINVAL; -} - -/* - * Protocol Handling Functions - */ - -#define CIPSO_V4_HDR_LEN 6 - -/** - * cipso_v4_gentag_hdr - Generate a CIPSO option header - * @doi_def: the DOI definition - * @len: the total tag length in bytes - * @buf: the CIPSO option buffer - * - * Description: - * Write a CIPSO header into the beginning of @buffer. Return zero on success, - * negative values on failure. - * - */ -static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, - u32 len, - unsigned char *buf) -{ - if (CIPSO_V4_HDR_LEN + len > 40) - return -ENOSPC; - - buf[0] = IPOPT_CIPSO; - buf[1] = CIPSO_V4_HDR_LEN + len; - *(u32 *)&buf[2] = htonl(doi_def->doi); - - return 0; -} - -#define CIPSO_V4_TAG1_CAT_LEN 30 - -/** - * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1) - * @doi_def: the DOI definition - * @secattr: the security attributes - * @buffer: the option buffer - * @buffer_len: length of buffer in bytes - * - * Description: - * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The - * actual buffer length may be larger than the indicated size due to - * translation between host and network category bitmaps. Returns zero on - * success, negative values on failure. - * - */ -static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, - const struct netlbl_lsm_secattr *secattr, - unsigned char **buffer, - u32 *buffer_len) -{ - int ret_val = -EPERM; - unsigned char *buf = NULL; - u32 buf_len; - u32 level; - - if (secattr->mls_cat) { - buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN, - GFP_ATOMIC); - if (buf == NULL) - return -ENOMEM; - - ret_val = cipso_v4_map_cat_rbm_hton(doi_def, - secattr->mls_cat, - secattr->mls_cat_len, - &buf[CIPSO_V4_HDR_LEN + 4], - CIPSO_V4_TAG1_CAT_LEN); - if (ret_val < 0) - goto gentag_failure; - - /* This will send packets using the "optimized" format when - * possibile as specified in section 3.4.2.6 of the - * CIPSO draft. */ - if (cipso_v4_rbm_optfmt && (ret_val > 0 && ret_val < 10)) - ret_val = 10; - - buf_len = 4 + ret_val; - } else { - buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC); - if (buf == NULL) - return -ENOMEM; - buf_len = 4; - } - - ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level); - if (ret_val != 0) - goto gentag_failure; - - ret_val = cipso_v4_gentag_hdr(doi_def, buf_len, buf); - if (ret_val != 0) - goto gentag_failure; - - buf[CIPSO_V4_HDR_LEN] = 0x01; - buf[CIPSO_V4_HDR_LEN + 1] = buf_len; - buf[CIPSO_V4_HDR_LEN + 3] = level; - - *buffer = buf; - *buffer_len = CIPSO_V4_HDR_LEN + buf_len; - - return 0; - -gentag_failure: - kfree(buf); - return ret_val; -} - -/** - * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag - * @doi_def: the DOI definition - * @tag: the CIPSO tag - * @secattr: the security attributes - * - * Description: - * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security - * attributes in @secattr. Return zero on success, negatives values on - * failure. - * - */ -static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, - const unsigned char *tag, - struct netlbl_lsm_secattr *secattr) -{ - int ret_val; - u8 tag_len = tag[1]; - u32 level; - - ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level); - if (ret_val != 0) - return ret_val; - secattr->mls_lvl = level; - secattr->mls_lvl_vld = 1; - - if (tag_len > 4) { - switch (doi_def->type) { - case CIPSO_V4_MAP_PASS: - secattr->mls_cat_len = tag_len - 4; - break; - case CIPSO_V4_MAP_STD: - secattr->mls_cat_len = - doi_def->map.std->cat.local_size; - break; - } - secattr->mls_cat = kzalloc(secattr->mls_cat_len, GFP_ATOMIC); - if (secattr->mls_cat == NULL) - return -ENOMEM; - - ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def, - &tag[4], - tag_len - 4, - secattr->mls_cat, - secattr->mls_cat_len); - if (ret_val < 0) { - kfree(secattr->mls_cat); - return ret_val; - } - secattr->mls_cat_len = ret_val; - } - - return 0; -} - -/** - * cipso_v4_validate - Validate a CIPSO option - * @option: the start of the option, on error it is set to point to the error - * - * Description: - * This routine is called to validate a CIPSO option, it checks all of the - * fields to ensure that they are at least valid, see the draft snippet below - * for details. If the option is valid then a zero value is returned and - * the value of @option is unchanged. If the option is invalid then a - * non-zero value is returned and @option is adjusted to point to the - * offending portion of the option. From the IETF draft ... - * - * "If any field within the CIPSO options, such as the DOI identifier, is not - * recognized the IP datagram is discarded and an ICMP 'parameter problem' - * (type 12) is generated and returned. The ICMP code field is set to 'bad - * parameter' (code 0) and the pointer is set to the start of the CIPSO field - * that is unrecognized." - * - */ -int cipso_v4_validate(unsigned char **option) -{ - unsigned char *opt = *option; - unsigned char *tag; - unsigned char opt_iter; - unsigned char err_offset = 0; - u8 opt_len; - u8 tag_len; - struct cipso_v4_doi *doi_def = NULL; - u32 tag_iter; - - /* caller already checks for length values that are too large */ - opt_len = opt[1]; - if (opt_len < 8) { - err_offset = 1; - goto validate_return; - } - - rcu_read_lock(); - doi_def = cipso_v4_doi_getdef(ntohl(*((u32 *)&opt[2]))); - if (doi_def == NULL) { - err_offset = 2; - goto validate_return_locked; - } - - opt_iter = 6; - tag = opt + opt_iter; - while (opt_iter < opt_len) { - for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];) - if (doi_def->tags[tag_iter] == CIPSO_V4_TAG_INVALID || - ++tag_iter == CIPSO_V4_TAG_MAXCNT) { - err_offset = opt_iter; - goto validate_return_locked; - } - - tag_len = tag[1]; - if (tag_len > (opt_len - opt_iter)) { - err_offset = opt_iter + 1; - goto validate_return_locked; - } - - switch (tag[0]) { - case CIPSO_V4_TAG_RBITMAP: - if (tag_len < 4) { - err_offset = opt_iter + 1; - goto validate_return_locked; - } - - /* We are already going to do all the verification - * necessary at the socket layer so from our point of - * view it is safe to turn these checks off (and less - * work), however, the CIPSO draft says we should do - * all the CIPSO validations here but it doesn't - * really specify _exactly_ what we need to validate - * ... so, just make it a sysctl tunable. */ - if (cipso_v4_rbm_strictvalid) { - if (cipso_v4_map_lvl_valid(doi_def, - tag[3]) < 0) { - err_offset = opt_iter + 3; - goto validate_return_locked; - } - if (tag_len > 4 && - cipso_v4_map_cat_rbm_valid(doi_def, - &tag[4], - tag_len - 4) < 0) { - err_offset = opt_iter + 4; - goto validate_return_locked; - } - } - break; - default: - err_offset = opt_iter; - goto validate_return_locked; - } - - tag += tag_len; - opt_iter += tag_len; - } - -validate_return_locked: - rcu_read_unlock(); -validate_return: - *option = opt + err_offset; - return err_offset; -} - -/** - * cipso_v4_error - Send the correct reponse for a bad packet - * @skb: the packet - * @error: the error code - * @gateway: CIPSO gateway flag - * - * Description: - * Based on the error code given in @error, send an ICMP error message back to - * the originating host. From the IETF draft ... - * - * "If the contents of the CIPSO [option] are valid but the security label is - * outside of the configured host or port label range, the datagram is - * discarded and an ICMP 'destination unreachable' (type 3) is generated and - * returned. The code field of the ICMP is set to 'communication with - * destination network administratively prohibited' (code 9) or to - * 'communication with destination host administratively prohibited' - * (code 10). The value of the code is dependent on whether the originator - * of the ICMP message is acting as a CIPSO host or a CIPSO gateway. The - * recipient of the ICMP message MUST be able to handle either value. The - * same procedure is performed if a CIPSO [option] can not be added to an - * IP packet because it is too large to fit in the IP options area." - * - * "If the error is triggered by receipt of an ICMP message, the message is - * discarded and no response is permitted (consistent with general ICMP - * processing rules)." - * - */ -void cipso_v4_error(struct sk_buff *skb, int error, u32 gateway) -{ - if (skb->nh.iph->protocol == IPPROTO_ICMP || error != -EACCES) - return; - - if (gateway) - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0); - else - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0); -} - -/** - * cipso_v4_socket_setattr - Add a CIPSO option to a socket - * @sock: the socket - * @doi_def: the CIPSO DOI to use - * @secattr: the specific security attributes of the socket - * - * Description: - * Set the CIPSO option on the given socket using the DOI definition and - * security attributes passed to the function. This function requires - * exclusive access to @sock->sk, which means it either needs to be in the - * process of being created or locked via lock_sock(sock->sk). Returns zero on - * success and negative values on failure. - * - */ -int cipso_v4_socket_setattr(const struct socket *sock, - const struct cipso_v4_doi *doi_def, - const struct netlbl_lsm_secattr *secattr) -{ - int ret_val = -EPERM; - u32 iter; - unsigned char *buf = NULL; - u32 buf_len = 0; - u32 opt_len; - struct ip_options *opt = NULL; - struct sock *sk; - struct inet_sock *sk_inet; - struct inet_connection_sock *sk_conn; - - /* In the case of sock_create_lite(), the sock->sk field is not - * defined yet but it is not a problem as the only users of these - * "lite" PF_INET sockets are functions which do an accept() call - * afterwards so we will label the socket as part of the accept(). */ - sk = sock->sk; - if (sk == NULL) - return 0; - - /* XXX - This code assumes only one tag per CIPSO option which isn't - * really a good assumption to make but since we only support the MAC - * tags right now it is a safe assumption. */ - iter = 0; - do { - switch (doi_def->tags[iter]) { - case CIPSO_V4_TAG_RBITMAP: - ret_val = cipso_v4_gentag_rbm(doi_def, - secattr, - &buf, - &buf_len); - break; - default: - ret_val = -EPERM; - goto socket_setattr_failure; - } - - iter++; - } while (ret_val != 0 && - iter < CIPSO_V4_TAG_MAXCNT && - doi_def->tags[iter] != CIPSO_V4_TAG_INVALID); - if (ret_val != 0) - goto socket_setattr_failure; - - /* We can't use ip_options_get() directly because it makes a call to - * ip_options_get_alloc() which allocates memory with GFP_KERNEL and - * we can't block here. */ - opt_len = (buf_len + 3) & ~3; - opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC); - if (opt == NULL) { - ret_val = -ENOMEM; - goto socket_setattr_failure; - } - memcpy(opt->__data, buf, buf_len); - opt->optlen = opt_len; - opt->is_data = 1; - kfree(buf); - buf = NULL; - ret_val = ip_options_compile(opt, NULL); - if (ret_val != 0) - goto socket_setattr_failure; - - sk_inet = inet_sk(sk); - if (sk_inet->is_icsk) { - sk_conn = inet_csk(sk); - if (sk_inet->opt) - sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen; - sk_conn->icsk_ext_hdr_len += opt->optlen; - sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie); - } - opt = xchg(&sk_inet->opt, opt); - kfree(opt); - - return 0; - -socket_setattr_failure: - kfree(buf); - kfree(opt); - return ret_val; -} - -/** - * cipso_v4_socket_getattr - Get the security attributes from a socket - * @sock: the socket - * @secattr: the security attributes - * - * Description: - * Query @sock to see if there is a CIPSO option attached to the socket and if - * there is return the CIPSO security attributes in @secattr. Returns zero on - * success and negative values on failure. - * - */ -int cipso_v4_socket_getattr(const struct socket *sock, - struct netlbl_lsm_secattr *secattr) -{ - int ret_val = -ENOMSG; - struct sock *sk; - struct inet_sock *sk_inet; - unsigned char *cipso_ptr; - u32 doi; - struct cipso_v4_doi *doi_def; - - sk = sock->sk; - lock_sock(sk); - sk_inet = inet_sk(sk); - if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0) - goto socket_getattr_return; - cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso - - sizeof(struct iphdr); - ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr); - if (ret_val == 0) - goto socket_getattr_return; - - doi = ntohl(*(u32 *)&cipso_ptr[2]); - rcu_read_lock(); - doi_def = cipso_v4_doi_getdef(doi); - if (doi_def == NULL) { - rcu_read_unlock(); - goto socket_getattr_return; - } - switch (cipso_ptr[6]) { - case CIPSO_V4_TAG_RBITMAP: - ret_val = cipso_v4_parsetag_rbm(doi_def, - &cipso_ptr[6], - secattr); - break; - } - rcu_read_unlock(); - -socket_getattr_return: - release_sock(sk); - return ret_val; -} - -/** - * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option - * @skb: the packet - * @secattr: the security attributes - * - * Description: - * Parse the given packet's CIPSO option and return the security attributes. - * Returns zero on success and negative values on failure. - * - */ -int cipso_v4_skbuff_getattr(const struct sk_buff *skb, - struct netlbl_lsm_secattr *secattr) -{ - int ret_val = -ENOMSG; - unsigned char *cipso_ptr; - u32 doi; - struct cipso_v4_doi *doi_def; - - if (!CIPSO_V4_OPTEXIST(skb)) - return -ENOMSG; - cipso_ptr = CIPSO_V4_OPTPTR(skb); - if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0) - return 0; - - doi = ntohl(*(u32 *)&cipso_ptr[2]); - rcu_read_lock(); - doi_def = cipso_v4_doi_getdef(doi); - if (doi_def == NULL) - goto skbuff_getattr_return; - switch (cipso_ptr[6]) { - case CIPSO_V4_TAG_RBITMAP: - ret_val = cipso_v4_parsetag_rbm(doi_def, - &cipso_ptr[6], - secattr); - break; - } - -skbuff_getattr_return: - rcu_read_unlock(); - return ret_val; -} - -/* - * Setup Functions - */ - -/** - * cipso_v4_init - Initialize the CIPSO module - * - * Description: - * Initialize the CIPSO module and prepare it for use. Returns zero on success - * and negative values on failure. - * - */ -static int __init cipso_v4_init(void) -{ - int ret_val; - - ret_val = cipso_v4_cache_init(); - if (ret_val != 0) - panic("Failed to initialize the CIPSO/IPv4 cache (%d)\n", - ret_val); - - return 0; -} - -subsys_initcall(cipso_v4_init); diff --git a/trunk/net/ipv4/devinet.c b/trunk/net/ipv4/devinet.c index 8e8d1f17d77a..a6cc31d911eb 100644 --- a/trunk/net/ipv4/devinet.c +++ b/trunk/net/ipv4/devinet.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include @@ -63,7 +62,6 @@ #include #include #include -#include struct ipv4_devconf ipv4_devconf = { .accept_redirects = 1, @@ -80,15 +78,7 @@ static struct ipv4_devconf ipv4_devconf_dflt = { .accept_source_route = 1, }; -static struct nla_policy ifa_ipv4_policy[IFA_MAX+1] __read_mostly = { - [IFA_LOCAL] = { .type = NLA_U32 }, - [IFA_ADDRESS] = { .type = NLA_U32 }, - [IFA_BROADCAST] = { .type = NLA_U32 }, - [IFA_ANYCAST] = { .type = NLA_U32 }, - [IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, -}; - -static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32); +static void rtmsg_ifa(int event, struct in_ifaddr *); static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, @@ -239,8 +229,8 @@ int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b) return 0; } -static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, - int destroy, struct nlmsghdr *nlh, u32 pid) +static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, + int destroy) { struct in_ifaddr *promote = NULL; struct in_ifaddr *ifa, *ifa1 = *ifap; @@ -273,7 +263,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, if (!do_promote) { *ifap1 = ifa->ifa_next; - rtmsg_ifa(RTM_DELADDR, ifa, nlh, pid); + rtmsg_ifa(RTM_DELADDR, ifa); blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa); inet_free_ifa(ifa); @@ -298,7 +288,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, is valid, it will try to restore deleted routes... Grr. So that, this order is correct. */ - rtmsg_ifa(RTM_DELADDR, ifa1, nlh, pid); + rtmsg_ifa(RTM_DELADDR, ifa1); blocking_notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa1); if (promote) { @@ -310,7 +300,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, } promote->ifa_flags &= ~IFA_F_SECONDARY; - rtmsg_ifa(RTM_NEWADDR, promote, nlh, pid); + rtmsg_ifa(RTM_NEWADDR, promote); blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote); for (ifa = promote->ifa_next; ifa; ifa = ifa->ifa_next) { @@ -329,14 +319,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, } } -static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, - int destroy) -{ - __inet_del_ifa(in_dev, ifap, destroy, NULL, 0); -} - -static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, - u32 pid) +static int inet_insert_ifa(struct in_ifaddr *ifa) { struct in_device *in_dev = ifa->ifa_dev; struct in_ifaddr *ifa1, **ifap, **last_primary; @@ -381,17 +364,12 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh, /* Send message first, then call notifier. Notifier will trigger FIB update, so that listeners of netlink will know about new ifaddr */ - rtmsg_ifa(RTM_NEWADDR, ifa, nlh, pid); + rtmsg_ifa(RTM_NEWADDR, ifa); blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa); return 0; } -static int inet_insert_ifa(struct in_ifaddr *ifa) -{ - return __inet_insert_ifa(ifa, NULL, 0); -} - static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa) { struct in_device *in_dev = __in_dev_get_rtnl(dev); @@ -443,134 +421,87 @@ struct in_ifaddr *inet_ifa_byprefix(struct in_device *in_dev, u32 prefix, static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { - struct nlattr *tb[IFA_MAX+1]; + struct rtattr **rta = arg; struct in_device *in_dev; - struct ifaddrmsg *ifm; + struct ifaddrmsg *ifm = NLMSG_DATA(nlh); struct in_ifaddr *ifa, **ifap; - int err = -EINVAL; ASSERT_RTNL(); - err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy); - if (err < 0) - goto errout; - - ifm = nlmsg_data(nlh); - in_dev = inetdev_by_index(ifm->ifa_index); - if (in_dev == NULL) { - err = -ENODEV; - goto errout; - } - + if ((in_dev = inetdev_by_index(ifm->ifa_index)) == NULL) + goto out; __in_dev_put(in_dev); for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { - if (tb[IFA_LOCAL] && - ifa->ifa_local != nla_get_u32(tb[IFA_LOCAL])) - continue; - - if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label)) - continue; - - if (tb[IFA_ADDRESS] && - (ifm->ifa_prefixlen != ifa->ifa_prefixlen || - !inet_ifa_match(nla_get_u32(tb[IFA_ADDRESS]), ifa))) + if ((rta[IFA_LOCAL - 1] && + memcmp(RTA_DATA(rta[IFA_LOCAL - 1]), + &ifa->ifa_local, 4)) || + (rta[IFA_LABEL - 1] && + rtattr_strcmp(rta[IFA_LABEL - 1], ifa->ifa_label)) || + (rta[IFA_ADDRESS - 1] && + (ifm->ifa_prefixlen != ifa->ifa_prefixlen || + !inet_ifa_match(*(u32*)RTA_DATA(rta[IFA_ADDRESS - 1]), + ifa)))) continue; - - __inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).pid); + inet_del_ifa(in_dev, ifap, 1); return 0; } - - err = -EADDRNOTAVAIL; -errout: - return err; +out: + return -EADDRNOTAVAIL; } -static struct in_ifaddr *rtm_to_ifaddr(struct nlmsghdr *nlh) +static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { - struct nlattr *tb[IFA_MAX+1]; - struct in_ifaddr *ifa; - struct ifaddrmsg *ifm; + struct rtattr **rta = arg; struct net_device *dev; struct in_device *in_dev; - int err = -EINVAL; + struct ifaddrmsg *ifm = NLMSG_DATA(nlh); + struct in_ifaddr *ifa; + int rc = -EINVAL; - err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv4_policy); - if (err < 0) - goto errout; + ASSERT_RTNL(); - ifm = nlmsg_data(nlh); - if (ifm->ifa_prefixlen > 32 || tb[IFA_LOCAL] == NULL) - goto errout; + if (ifm->ifa_prefixlen > 32 || !rta[IFA_LOCAL - 1]) + goto out; - dev = __dev_get_by_index(ifm->ifa_index); - if (dev == NULL) { - err = -ENODEV; - goto errout; - } + rc = -ENODEV; + if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL) + goto out; - in_dev = __in_dev_get_rtnl(dev); - if (in_dev == NULL) { + rc = -ENOBUFS; + if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) { in_dev = inetdev_init(dev); - if (in_dev == NULL) { - err = -ENOBUFS; - goto errout; - } - } - - ifa = inet_alloc_ifa(); - if (ifa == NULL) { - /* - * A potential indev allocation can be left alive, it stays - * assigned to its device and is destroy with it. - */ - err = -ENOBUFS; - goto errout; + if (!in_dev) + goto out; } - in_dev_hold(in_dev); - - if (tb[IFA_ADDRESS] == NULL) - tb[IFA_ADDRESS] = tb[IFA_LOCAL]; + if ((ifa = inet_alloc_ifa()) == NULL) + goto out; + if (!rta[IFA_ADDRESS - 1]) + rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1]; + memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL - 1]), 4); + memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS - 1]), 4); ifa->ifa_prefixlen = ifm->ifa_prefixlen; ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen); + if (rta[IFA_BROADCAST - 1]) + memcpy(&ifa->ifa_broadcast, + RTA_DATA(rta[IFA_BROADCAST - 1]), 4); + if (rta[IFA_ANYCAST - 1]) + memcpy(&ifa->ifa_anycast, RTA_DATA(rta[IFA_ANYCAST - 1]), 4); ifa->ifa_flags = ifm->ifa_flags; ifa->ifa_scope = ifm->ifa_scope; - ifa->ifa_dev = in_dev; - - ifa->ifa_local = nla_get_u32(tb[IFA_LOCAL]); - ifa->ifa_address = nla_get_u32(tb[IFA_ADDRESS]); - - if (tb[IFA_BROADCAST]) - ifa->ifa_broadcast = nla_get_u32(tb[IFA_BROADCAST]); - - if (tb[IFA_ANYCAST]) - ifa->ifa_anycast = nla_get_u32(tb[IFA_ANYCAST]); - - if (tb[IFA_LABEL]) - nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ); + in_dev_hold(in_dev); + ifa->ifa_dev = in_dev; + if (rta[IFA_LABEL - 1]) + rtattr_strlcpy(ifa->ifa_label, rta[IFA_LABEL - 1], IFNAMSIZ); else memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); - return ifa; - -errout: - return ERR_PTR(err); -} - -static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) -{ - struct in_ifaddr *ifa; - - ASSERT_RTNL(); - - ifa = rtm_to_ifaddr(nlh); - if (IS_ERR(ifa)) - return PTR_ERR(ifa); - - return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).pid); + rc = inet_insert_ifa(ifa); +out: + return rc; } /* @@ -1125,37 +1056,32 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, { struct ifaddrmsg *ifm; struct nlmsghdr *nlh; + unsigned char *b = skb->tail; - nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags); - if (nlh == NULL) - return -ENOBUFS; - - ifm = nlmsg_data(nlh); + nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); + ifm = NLMSG_DATA(nlh); ifm->ifa_family = AF_INET; ifm->ifa_prefixlen = ifa->ifa_prefixlen; ifm->ifa_flags = ifa->ifa_flags|IFA_F_PERMANENT; ifm->ifa_scope = ifa->ifa_scope; ifm->ifa_index = ifa->ifa_dev->dev->ifindex; - if (ifa->ifa_address) - NLA_PUT_U32(skb, IFA_ADDRESS, ifa->ifa_address); - + RTA_PUT(skb, IFA_ADDRESS, 4, &ifa->ifa_address); if (ifa->ifa_local) - NLA_PUT_U32(skb, IFA_LOCAL, ifa->ifa_local); - + RTA_PUT(skb, IFA_LOCAL, 4, &ifa->ifa_local); if (ifa->ifa_broadcast) - NLA_PUT_U32(skb, IFA_BROADCAST, ifa->ifa_broadcast); - + RTA_PUT(skb, IFA_BROADCAST, 4, &ifa->ifa_broadcast); if (ifa->ifa_anycast) - NLA_PUT_U32(skb, IFA_ANYCAST, ifa->ifa_anycast); - + RTA_PUT(skb, IFA_ANYCAST, 4, &ifa->ifa_anycast); if (ifa->ifa_label[0]) - NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label); - - return nlmsg_end(skb, nlh); + RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label); + nlh->nlmsg_len = skb->tail - b; + return skb->len; -nla_put_failure: - return nlmsg_cancel(skb, nlh); +nlmsg_failure: +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; } static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) @@ -1201,27 +1127,19 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) return skb->len; } -static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh, - u32 pid) +static void rtmsg_ifa(int event, struct in_ifaddr* ifa) { - struct sk_buff *skb; - u32 seq = nlh ? nlh->nlmsg_seq : 0; - int err = -ENOBUFS; - - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); - if (skb == NULL) - goto errout; + int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + 128); + struct sk_buff *skb = alloc_skb(size, GFP_KERNEL); - err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0); - if (err < 0) { + if (!skb) + netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, ENOBUFS); + else if (inet_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) { kfree_skb(skb); - goto errout; + netlink_set_err(rtnl, 0, RTNLGRP_IPV4_IFADDR, EINVAL); + } else { + netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_IFADDR, GFP_KERNEL); } - - err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); -errout: - if (err < 0) - rtnl_set_sk_err(RTNLGRP_IPV4_IFADDR, err); } static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = { @@ -1233,7 +1151,9 @@ static struct rtnetlink_link inet_rtnetlink_table[RTM_NR_MSGTYPES] = { [RTM_GETROUTE - RTM_BASE] = { .doit = inet_rtm_getroute, .dumpit = inet_dump_fib, }, #ifdef CONFIG_IP_MULTIPLE_TABLES - [RTM_GETRULE - RTM_BASE] = { .dumpit = fib4_rules_dump, }, + [RTM_NEWRULE - RTM_BASE] = { .doit = inet_rtm_newrule, }, + [RTM_DELRULE - RTM_BASE] = { .doit = inet_rtm_delrule, }, + [RTM_GETRULE - RTM_BASE] = { .dumpit = inet_dump_rules, }, #endif }; diff --git a/trunk/net/ipv4/esp4.c b/trunk/net/ipv4/esp4.c index 13b29360d102..fc2f8ce441de 100644 --- a/trunk/net/ipv4/esp4.c +++ b/trunk/net/ipv4/esp4.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -17,8 +16,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) int err; struct iphdr *top_iph; struct ip_esp_hdr *esph; - struct crypto_blkcipher *tfm; - struct blkcipher_desc desc; + struct crypto_tfm *tfm; struct esp_data *esp; struct sk_buff *trailer; int blksize; @@ -38,9 +36,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) esp = x->data; alen = esp->auth.icv_trunc_len; tfm = esp->conf.tfm; - desc.tfm = tfm; - desc.flags = 0; - blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); + blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4); clen = ALIGN(clen + 2, blksize); if (esp->conf.padlen) clen = ALIGN(clen, esp->conf.padlen); @@ -95,13 +91,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) esph->seq_no = htonl(++x->replay.oseq); xfrm_aevent_doreplay(x); - if (esp->conf.ivlen) { - if (unlikely(!esp->conf.ivinitted)) { - get_random_bytes(esp->conf.ivec, esp->conf.ivlen); - esp->conf.ivinitted = 1; - } - crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen); - } + if (esp->conf.ivlen) + crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); do { struct scatterlist *sg = &esp->sgbuf[0]; @@ -112,27 +103,26 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) goto error; } skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); - err = crypto_blkcipher_encrypt(&desc, sg, sg, clen); + crypto_cipher_encrypt(tfm, sg, sg, clen); if (unlikely(sg != &esp->sgbuf[0])) kfree(sg); } while (0); - if (unlikely(err)) - goto error; - if (esp->conf.ivlen) { - memcpy(esph->enc_data, esp->conf.ivec, esp->conf.ivlen); - crypto_blkcipher_get_iv(tfm, esp->conf.ivec, esp->conf.ivlen); + memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); + crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); } if (esp->auth.icv_full_len) { - err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data, - sizeof(*esph) + esp->conf.ivlen + clen); - memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen); + esp->auth.icv(esp, skb, (u8*)esph-skb->data, + sizeof(struct ip_esp_hdr) + esp->conf.ivlen+clen, trailer->tail); + pskb_put(skb, trailer, alen); } ip_send_check(top_iph); + err = 0; + error: return err; } @@ -147,10 +137,8 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) struct iphdr *iph; struct ip_esp_hdr *esph; struct esp_data *esp = x->data; - struct crypto_blkcipher *tfm = esp->conf.tfm; - struct blkcipher_desc desc = { .tfm = tfm }; struct sk_buff *trailer; - int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); + int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); int alen = esp->auth.icv_trunc_len; int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; int nfrags; @@ -158,7 +146,6 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) u8 nexthdr[2]; struct scatterlist *sg; int padlen; - int err; if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr))) goto out; @@ -168,16 +155,15 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) /* If integrity check is required, do this. */ if (esp->auth.icv_full_len) { - u8 sum[alen]; - - err = esp_mac_digest(esp, skb, 0, skb->len - alen); - if (err) - goto out; + u8 sum[esp->auth.icv_full_len]; + u8 sum1[alen]; + + esp->auth.icv(esp, skb, 0, skb->len-alen, sum); - if (skb_copy_bits(skb, skb->len - alen, sum, alen)) + if (skb_copy_bits(skb, skb->len-alen, sum1, alen)) BUG(); - if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { + if (unlikely(memcmp(sum, sum1, alen))) { x->stats.integrity_failed++; goto out; } @@ -192,7 +178,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) /* Get ivec. This can be wrong, check against another impls. */ if (esp->conf.ivlen) - crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen); + crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm)); sg = &esp->sgbuf[0]; @@ -202,11 +188,9 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) goto out; } skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen); - err = crypto_blkcipher_decrypt(&desc, sg, sg, elen); + crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); if (unlikely(sg != &esp->sgbuf[0])) kfree(sg); - if (unlikely(err)) - return err; if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) BUG(); @@ -253,7 +237,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) * as per draft-ietf-ipsec-udp-encaps-06, * section 3.1.2 */ - if (x->props.mode == XFRM_MODE_TRANSPORT) + if (!x->props.mode) skb->ip_summed = CHECKSUM_UNNECESSARY; } @@ -270,9 +254,9 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) { struct esp_data *esp = x->data; - u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); + u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); - if (x->props.mode == XFRM_MODE_TUNNEL) { + if (x->props.mode) { mtu = ALIGN(mtu + 2, blksize); } else { /* The worst case. */ @@ -309,11 +293,11 @@ static void esp_destroy(struct xfrm_state *x) if (!esp) return; - crypto_free_blkcipher(esp->conf.tfm); + crypto_free_tfm(esp->conf.tfm); esp->conf.tfm = NULL; kfree(esp->conf.ivec); esp->conf.ivec = NULL; - crypto_free_hash(esp->auth.tfm); + crypto_free_tfm(esp->auth.tfm); esp->auth.tfm = NULL; kfree(esp->auth.work_icv); esp->auth.work_icv = NULL; @@ -323,7 +307,6 @@ static void esp_destroy(struct xfrm_state *x) static int esp_init_state(struct xfrm_state *x) { struct esp_data *esp = NULL; - struct crypto_blkcipher *tfm; /* null auth and encryption can have zero length keys */ if (x->aalg) { @@ -339,27 +322,22 @@ static int esp_init_state(struct xfrm_state *x) if (x->aalg) { struct xfrm_algo_desc *aalg_desc; - struct crypto_hash *hash; esp->auth.key = x->aalg->alg_key; esp->auth.key_len = (x->aalg->alg_key_len+7)/8; - hash = crypto_alloc_hash(x->aalg->alg_name, 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(hash)) - goto error; - - esp->auth.tfm = hash; - if (crypto_hash_setkey(hash, esp->auth.key, esp->auth.key_len)) + esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); + if (esp->auth.tfm == NULL) goto error; + esp->auth.icv = esp_hmac_digest; aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); BUG_ON(!aalg_desc); if (aalg_desc->uinfo.auth.icv_fullbits/8 != - crypto_hash_digestsize(hash)) { + crypto_tfm_alg_digestsize(esp->auth.tfm)) { NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n", x->aalg->alg_name, - crypto_hash_digestsize(hash), + crypto_tfm_alg_digestsize(esp->auth.tfm), aalg_desc->uinfo.auth.icv_fullbits/8); goto error; } @@ -373,22 +351,24 @@ static int esp_init_state(struct xfrm_state *x) } esp->conf.key = x->ealg->alg_key; esp->conf.key_len = (x->ealg->alg_key_len+7)/8; - tfm = crypto_alloc_blkcipher(x->ealg->alg_name, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) + if (x->props.ealgo == SADB_EALG_NULL) + esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB); + else + esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC); + if (esp->conf.tfm == NULL) goto error; - esp->conf.tfm = tfm; - esp->conf.ivlen = crypto_blkcipher_ivsize(tfm); + esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm); esp->conf.padlen = 0; if (esp->conf.ivlen) { esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); if (unlikely(esp->conf.ivec == NULL)) goto error; - esp->conf.ivinitted = 0; + get_random_bytes(esp->conf.ivec, esp->conf.ivlen); } - if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len)) + if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len)) goto error; x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen; - if (x->props.mode == XFRM_MODE_TUNNEL) + if (x->props.mode) x->props.header_len += sizeof(struct iphdr); if (x->encap) { struct xfrm_encap_tmpl *encap = x->encap; diff --git a/trunk/net/ipv4/fib_frontend.c b/trunk/net/ipv4/fib_frontend.c index cfb527c060e4..ba2a70745a63 100644 --- a/trunk/net/ipv4/fib_frontend.c +++ b/trunk/net/ipv4/fib_frontend.c @@ -32,12 +32,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include @@ -52,67 +50,48 @@ #ifndef CONFIG_IP_MULTIPLE_TABLES +#define RT_TABLE_MIN RT_TABLE_MAIN + struct fib_table *ip_fib_local_table; struct fib_table *ip_fib_main_table; -#define FIB_TABLE_HASHSZ 1 -static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ]; - #else -#define FIB_TABLE_HASHSZ 256 -static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ]; +#define RT_TABLE_MIN 1 -struct fib_table *fib_new_table(u32 id) +struct fib_table *fib_tables[RT_TABLE_MAX+1]; + +struct fib_table *__fib_new_table(int id) { struct fib_table *tb; - unsigned int h; - if (id == 0) - id = RT_TABLE_MAIN; - tb = fib_get_table(id); - if (tb) - return tb; tb = fib_hash_init(id); if (!tb) return NULL; - h = id & (FIB_TABLE_HASHSZ - 1); - hlist_add_head_rcu(&tb->tb_hlist, &fib_table_hash[h]); + fib_tables[id] = tb; return tb; } -struct fib_table *fib_get_table(u32 id) -{ - struct fib_table *tb; - struct hlist_node *node; - unsigned int h; - if (id == 0) - id = RT_TABLE_MAIN; - h = id & (FIB_TABLE_HASHSZ - 1); - rcu_read_lock(); - hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb_hlist) { - if (tb->tb_id == id) { - rcu_read_unlock(); - return tb; - } - } - rcu_read_unlock(); - return NULL; -} #endif /* CONFIG_IP_MULTIPLE_TABLES */ + static void fib_flush(void) { int flushed = 0; +#ifdef CONFIG_IP_MULTIPLE_TABLES struct fib_table *tb; - struct hlist_node *node; - unsigned int h; + int id; - for (h = 0; h < FIB_TABLE_HASHSZ; h++) { - hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist) - flushed += tb->tb_flush(tb); + for (id = RT_TABLE_MAX; id>0; id--) { + if ((tb = fib_get_table(id))==NULL) + continue; + flushed += tb->tb_flush(tb); } +#else /* CONFIG_IP_MULTIPLE_TABLES */ + flushed += ip_fib_main_table->tb_flush(ip_fib_main_table); + flushed += ip_fib_local_table->tb_flush(ip_fib_local_table); +#endif /* CONFIG_IP_MULTIPLE_TABLES */ if (flushed) rt_cache_flush(-1); @@ -253,190 +232,42 @@ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, #ifndef CONFIG_IP_NOSIOCRT -static inline u32 sk_extract_addr(struct sockaddr *addr) -{ - return ((struct sockaddr_in *) addr)->sin_addr.s_addr; -} - -static int put_rtax(struct nlattr *mx, int len, int type, u32 value) -{ - struct nlattr *nla; - - nla = (struct nlattr *) ((char *) mx + len); - nla->nla_type = type; - nla->nla_len = nla_attr_size(4); - *(u32 *) nla_data(nla) = value; - - return len + nla_total_size(4); -} - -static int rtentry_to_fib_config(int cmd, struct rtentry *rt, - struct fib_config *cfg) -{ - u32 addr; - int plen; - - memset(cfg, 0, sizeof(*cfg)); - - if (rt->rt_dst.sa_family != AF_INET) - return -EAFNOSUPPORT; - - /* - * Check mask for validity: - * a) it must be contiguous. - * b) destination must have all host bits clear. - * c) if application forgot to set correct family (AF_INET), - * reject request unless it is absolutely clear i.e. - * both family and mask are zero. - */ - plen = 32; - addr = sk_extract_addr(&rt->rt_dst); - if (!(rt->rt_flags & RTF_HOST)) { - u32 mask = sk_extract_addr(&rt->rt_genmask); - - if (rt->rt_genmask.sa_family != AF_INET) { - if (mask || rt->rt_genmask.sa_family) - return -EAFNOSUPPORT; - } - - if (bad_mask(mask, addr)) - return -EINVAL; - - plen = inet_mask_len(mask); - } - - cfg->fc_dst_len = plen; - cfg->fc_dst = addr; - - if (cmd != SIOCDELRT) { - cfg->fc_nlflags = NLM_F_CREATE; - cfg->fc_protocol = RTPROT_BOOT; - } - - if (rt->rt_metric) - cfg->fc_priority = rt->rt_metric - 1; - - if (rt->rt_flags & RTF_REJECT) { - cfg->fc_scope = RT_SCOPE_HOST; - cfg->fc_type = RTN_UNREACHABLE; - return 0; - } - - cfg->fc_scope = RT_SCOPE_NOWHERE; - cfg->fc_type = RTN_UNICAST; - - if (rt->rt_dev) { - char *colon; - struct net_device *dev; - char devname[IFNAMSIZ]; - - if (copy_from_user(devname, rt->rt_dev, IFNAMSIZ-1)) - return -EFAULT; - - devname[IFNAMSIZ-1] = 0; - colon = strchr(devname, ':'); - if (colon) - *colon = 0; - dev = __dev_get_by_name(devname); - if (!dev) - return -ENODEV; - cfg->fc_oif = dev->ifindex; - if (colon) { - struct in_ifaddr *ifa; - struct in_device *in_dev = __in_dev_get_rtnl(dev); - if (!in_dev) - return -ENODEV; - *colon = ':'; - for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) - if (strcmp(ifa->ifa_label, devname) == 0) - break; - if (ifa == NULL) - return -ENODEV; - cfg->fc_prefsrc = ifa->ifa_local; - } - } - - addr = sk_extract_addr(&rt->rt_gateway); - if (rt->rt_gateway.sa_family == AF_INET && addr) { - cfg->fc_gw = addr; - if (rt->rt_flags & RTF_GATEWAY && - inet_addr_type(addr) == RTN_UNICAST) - cfg->fc_scope = RT_SCOPE_UNIVERSE; - } - - if (cmd == SIOCDELRT) - return 0; - - if (rt->rt_flags & RTF_GATEWAY && !cfg->fc_gw) - return -EINVAL; - - if (cfg->fc_scope == RT_SCOPE_NOWHERE) - cfg->fc_scope = RT_SCOPE_LINK; - - if (rt->rt_flags & (RTF_MTU | RTF_WINDOW | RTF_IRTT)) { - struct nlattr *mx; - int len = 0; - - mx = kzalloc(3 * nla_total_size(4), GFP_KERNEL); - if (mx == NULL) - return -ENOMEM; - - if (rt->rt_flags & RTF_MTU) - len = put_rtax(mx, len, RTAX_ADVMSS, rt->rt_mtu - 40); - - if (rt->rt_flags & RTF_WINDOW) - len = put_rtax(mx, len, RTAX_WINDOW, rt->rt_window); - - if (rt->rt_flags & RTF_IRTT) - len = put_rtax(mx, len, RTAX_RTT, rt->rt_irtt << 3); - - cfg->fc_mx = mx; - cfg->fc_mx_len = len; - } - - return 0; -} - /* * Handle IP routing ioctl calls. These are used to manipulate the routing tables */ int ip_rt_ioctl(unsigned int cmd, void __user *arg) { - struct fib_config cfg; - struct rtentry rt; int err; + struct kern_rta rta; + struct rtentry r; + struct { + struct nlmsghdr nlh; + struct rtmsg rtm; + } req; switch (cmd) { case SIOCADDRT: /* Add a route */ case SIOCDELRT: /* Delete a route */ if (!capable(CAP_NET_ADMIN)) return -EPERM; - - if (copy_from_user(&rt, arg, sizeof(rt))) + if (copy_from_user(&r, arg, sizeof(struct rtentry))) return -EFAULT; - rtnl_lock(); - err = rtentry_to_fib_config(cmd, &rt, &cfg); + err = fib_convert_rtentry(cmd, &req.nlh, &req.rtm, &rta, &r); if (err == 0) { - struct fib_table *tb; - if (cmd == SIOCDELRT) { - tb = fib_get_table(cfg.fc_table); + struct fib_table *tb = fib_get_table(req.rtm.rtm_table); + err = -ESRCH; if (tb) - err = tb->tb_delete(tb, &cfg); - else - err = -ESRCH; + err = tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL); } else { - tb = fib_new_table(cfg.fc_table); + struct fib_table *tb = fib_new_table(req.rtm.rtm_table); + err = -ENOBUFS; if (tb) - err = tb->tb_insert(tb, &cfg); - else - err = -ENOBUFS; + err = tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL); } - - /* allocated by rtentry_to_fib_config() */ - kfree(cfg.fc_mx); + kfree(rta.rta_mx); } rtnl_unlock(); return err; @@ -453,169 +284,77 @@ int ip_rt_ioctl(unsigned int cmd, void *arg) #endif -struct nla_policy rtm_ipv4_policy[RTA_MAX+1] __read_mostly = { - [RTA_DST] = { .type = NLA_U32 }, - [RTA_SRC] = { .type = NLA_U32 }, - [RTA_IIF] = { .type = NLA_U32 }, - [RTA_OIF] = { .type = NLA_U32 }, - [RTA_GATEWAY] = { .type = NLA_U32 }, - [RTA_PRIORITY] = { .type = NLA_U32 }, - [RTA_PREFSRC] = { .type = NLA_U32 }, - [RTA_METRICS] = { .type = NLA_NESTED }, - [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) }, - [RTA_PROTOINFO] = { .type = NLA_U32 }, - [RTA_FLOW] = { .type = NLA_U32 }, - [RTA_MP_ALGO] = { .type = NLA_U32 }, -}; - -static int rtm_to_fib_config(struct sk_buff *skb, struct nlmsghdr *nlh, - struct fib_config *cfg) +static int inet_check_attr(struct rtmsg *r, struct rtattr **rta) { - struct nlattr *attr; - int err, remaining; - struct rtmsg *rtm; - - err = nlmsg_validate(nlh, sizeof(*rtm), RTA_MAX, rtm_ipv4_policy); - if (err < 0) - goto errout; - - memset(cfg, 0, sizeof(*cfg)); - - rtm = nlmsg_data(nlh); - cfg->fc_family = rtm->rtm_family; - cfg->fc_dst_len = rtm->rtm_dst_len; - cfg->fc_src_len = rtm->rtm_src_len; - cfg->fc_tos = rtm->rtm_tos; - cfg->fc_table = rtm->rtm_table; - cfg->fc_protocol = rtm->rtm_protocol; - cfg->fc_scope = rtm->rtm_scope; - cfg->fc_type = rtm->rtm_type; - cfg->fc_flags = rtm->rtm_flags; - cfg->fc_nlflags = nlh->nlmsg_flags; - - cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid; - cfg->fc_nlinfo.nlh = nlh; - - nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) { - switch (attr->nla_type) { - case RTA_DST: - cfg->fc_dst = nla_get_u32(attr); - break; - case RTA_SRC: - cfg->fc_src = nla_get_u32(attr); - break; - case RTA_OIF: - cfg->fc_oif = nla_get_u32(attr); - break; - case RTA_GATEWAY: - cfg->fc_gw = nla_get_u32(attr); - break; - case RTA_PRIORITY: - cfg->fc_priority = nla_get_u32(attr); - break; - case RTA_PREFSRC: - cfg->fc_prefsrc = nla_get_u32(attr); - break; - case RTA_METRICS: - cfg->fc_mx = nla_data(attr); - cfg->fc_mx_len = nla_len(attr); - break; - case RTA_MULTIPATH: - cfg->fc_mp = nla_data(attr); - cfg->fc_mp_len = nla_len(attr); - break; - case RTA_FLOW: - cfg->fc_flow = nla_get_u32(attr); - break; - case RTA_MP_ALGO: - cfg->fc_mp_alg = nla_get_u32(attr); - break; - case RTA_TABLE: - cfg->fc_table = nla_get_u32(attr); - break; + int i; + + for (i=1; i<=RTA_MAX; i++, rta++) { + struct rtattr *attr = *rta; + if (attr) { + if (RTA_PAYLOAD(attr) < 4) + return -EINVAL; + if (i != RTA_MULTIPATH && i != RTA_METRICS) + *rta = (struct rtattr*)RTA_DATA(attr); } } - return 0; -errout: - return err; } int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) { - struct fib_config cfg; - struct fib_table *tb; - int err; - - err = rtm_to_fib_config(skb, nlh, &cfg); - if (err < 0) - goto errout; + struct fib_table * tb; + struct rtattr **rta = arg; + struct rtmsg *r = NLMSG_DATA(nlh); - tb = fib_get_table(cfg.fc_table); - if (tb == NULL) { - err = -ESRCH; - goto errout; - } + if (inet_check_attr(r, rta)) + return -EINVAL; - err = tb->tb_delete(tb, &cfg); -errout: - return err; + tb = fib_get_table(r->rtm_table); + if (tb) + return tb->tb_delete(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb)); + return -ESRCH; } int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) { - struct fib_config cfg; - struct fib_table *tb; - int err; - - err = rtm_to_fib_config(skb, nlh, &cfg); - if (err < 0) - goto errout; + struct fib_table * tb; + struct rtattr **rta = arg; + struct rtmsg *r = NLMSG_DATA(nlh); - tb = fib_new_table(cfg.fc_table); - if (tb == NULL) { - err = -ENOBUFS; - goto errout; - } + if (inet_check_attr(r, rta)) + return -EINVAL; - err = tb->tb_insert(tb, &cfg); -errout: - return err; + tb = fib_new_table(r->rtm_table); + if (tb) + return tb->tb_insert(tb, r, (struct kern_rta*)rta, nlh, &NETLINK_CB(skb)); + return -ENOBUFS; } int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) { - unsigned int h, s_h; - unsigned int e = 0, s_e; + int t; + int s_t; struct fib_table *tb; - struct hlist_node *node; - int dumped = 0; - if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) && - ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED) + if (NLMSG_PAYLOAD(cb->nlh, 0) >= sizeof(struct rtmsg) && + ((struct rtmsg*)NLMSG_DATA(cb->nlh))->rtm_flags&RTM_F_CLONED) return ip_rt_dump(skb, cb); - s_h = cb->args[0]; - s_e = cb->args[1]; - - for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) { - e = 0; - hlist_for_each_entry(tb, node, &fib_table_hash[h], tb_hlist) { - if (e < s_e) - goto next; - if (dumped) - memset(&cb->args[2], 0, sizeof(cb->args) - - 2 * sizeof(cb->args[0])); - if (tb->tb_dump(tb, skb, cb) < 0) - goto out; - dumped = 1; -next: - e++; - } + s_t = cb->args[0]; + if (s_t == 0) + s_t = cb->args[0] = RT_TABLE_MIN; + + for (t=s_t; t<=RT_TABLE_MAX; t++) { + if (t < s_t) continue; + if (t > s_t) + memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0])); + if ((tb = fib_get_table(t))==NULL) + continue; + if (tb->tb_dump(tb, skb, cb) < 0) + break; } -out: - cb->args[1] = e; - cb->args[0] = h; + + cb->args[0] = t; return skb->len; } @@ -627,19 +366,17 @@ int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) only when netlink is already locked. */ -static void fib_magic(int cmd, int type, u32 dst, int dst_len, - struct in_ifaddr *ifa) +static void fib_magic(int cmd, int type, u32 dst, int dst_len, struct in_ifaddr *ifa) { - struct fib_table *tb; - struct fib_config cfg = { - .fc_protocol = RTPROT_KERNEL, - .fc_type = type, - .fc_dst = dst, - .fc_dst_len = dst_len, - .fc_prefsrc = ifa->ifa_local, - .fc_oif = ifa->ifa_dev->dev->ifindex, - .fc_nlflags = NLM_F_CREATE | NLM_F_APPEND, - }; + struct fib_table * tb; + struct { + struct nlmsghdr nlh; + struct rtmsg rtm; + } req; + struct kern_rta rta; + + memset(&req.rtm, 0, sizeof(req.rtm)); + memset(&rta, 0, sizeof(rta)); if (type == RTN_UNICAST) tb = fib_new_table(RT_TABLE_MAIN); @@ -649,17 +386,26 @@ static void fib_magic(int cmd, int type, u32 dst, int dst_len, if (tb == NULL) return; - cfg.fc_table = tb->tb_id; + req.nlh.nlmsg_len = sizeof(req); + req.nlh.nlmsg_type = cmd; + req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND; + req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_seq = 0; - if (type != RTN_LOCAL) - cfg.fc_scope = RT_SCOPE_LINK; - else - cfg.fc_scope = RT_SCOPE_HOST; + req.rtm.rtm_dst_len = dst_len; + req.rtm.rtm_table = tb->tb_id; + req.rtm.rtm_protocol = RTPROT_KERNEL; + req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST); + req.rtm.rtm_type = type; + + rta.rta_dst = &dst; + rta.rta_prefsrc = &ifa->ifa_local; + rta.rta_oif = &ifa->ifa_dev->dev->ifindex; if (cmd == RTM_NEWROUTE) - tb->tb_insert(tb, &cfg); + tb->tb_insert(tb, &req.rtm, &rta, &req.nlh, NULL); else - tb->tb_delete(tb, &cfg); + tb->tb_delete(tb, &req.rtm, &rta, &req.nlh, NULL); } void fib_add_ifaddr(struct in_ifaddr *ifa) @@ -906,17 +652,11 @@ static struct notifier_block fib_netdev_notifier = { void __init ip_fib_init(void) { - unsigned int i; - - for (i = 0; i < FIB_TABLE_HASHSZ; i++) - INIT_HLIST_HEAD(&fib_table_hash[i]); #ifndef CONFIG_IP_MULTIPLE_TABLES ip_fib_local_table = fib_hash_init(RT_TABLE_LOCAL); - hlist_add_head_rcu(&ip_fib_local_table->tb_hlist, &fib_table_hash[0]); ip_fib_main_table = fib_hash_init(RT_TABLE_MAIN); - hlist_add_head_rcu(&ip_fib_main_table->tb_hlist, &fib_table_hash[0]); #else - fib4_rules_init(); + fib_rules_init(); #endif register_netdevice_notifier(&fib_netdev_notifier); diff --git a/trunk/net/ipv4/fib_hash.c b/trunk/net/ipv4/fib_hash.c index 88133b383dc5..72c633b357cf 100644 --- a/trunk/net/ipv4/fib_hash.c +++ b/trunk/net/ipv4/fib_hash.c @@ -379,39 +379,42 @@ static struct fib_node *fib_find_node(struct fn_zone *fz, u32 key) return NULL; } -static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) +static int +fn_hash_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta, + struct nlmsghdr *n, struct netlink_skb_parms *req) { struct fn_hash *table = (struct fn_hash *) tb->tb_data; struct fib_node *new_f, *f; struct fib_alias *fa, *new_fa; struct fn_zone *fz; struct fib_info *fi; - u8 tos = cfg->fc_tos; + int z = r->rtm_dst_len; + int type = r->rtm_type; + u8 tos = r->rtm_tos; u32 key; int err; - if (cfg->fc_dst_len > 32) + if (z > 32) return -EINVAL; - - fz = table->fn_zones[cfg->fc_dst_len]; - if (!fz && !(fz = fn_new_zone(table, cfg->fc_dst_len))) + fz = table->fn_zones[z]; + if (!fz && !(fz = fn_new_zone(table, z))) return -ENOBUFS; key = 0; - if (cfg->fc_dst) { - if (cfg->fc_dst & ~FZ_MASK(fz)) + if (rta->rta_dst) { + u32 dst; + memcpy(&dst, rta->rta_dst, 4); + if (dst & ~FZ_MASK(fz)) return -EINVAL; - key = fz_key(cfg->fc_dst, fz); + key = fz_key(dst, fz); } - fi = fib_create_info(cfg); - if (IS_ERR(fi)) - return PTR_ERR(fi); + if ((fi = fib_create_info(r, rta, n, &err)) == NULL) + return err; if (fz->fz_nent > (fz->fz_divisor<<1) && fz->fz_divisor < FZ_MAX_DIVISOR && - (cfg->fc_dst_len == 32 || - (1 << cfg->fc_dst_len) > fz->fz_divisor)) + (z==32 || (1< fz->fz_divisor)) fn_rehash_zone(fz); f = fib_find_node(fz, key); @@ -437,18 +440,18 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) struct fib_alias *fa_orig; err = -EEXIST; - if (cfg->fc_nlflags & NLM_F_EXCL) + if (n->nlmsg_flags & NLM_F_EXCL) goto out; - if (cfg->fc_nlflags & NLM_F_REPLACE) { + if (n->nlmsg_flags & NLM_F_REPLACE) { struct fib_info *fi_drop; u8 state; write_lock_bh(&fib_hash_lock); fi_drop = fa->fa_info; fa->fa_info = fi; - fa->fa_type = cfg->fc_type; - fa->fa_scope = cfg->fc_scope; + fa->fa_type = type; + fa->fa_scope = r->rtm_scope; state = fa->fa_state; fa->fa_state &= ~FA_S_ACCESSED; fib_hash_genid++; @@ -471,17 +474,17 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) break; if (fa->fa_info->fib_priority != fi->fib_priority) break; - if (fa->fa_type == cfg->fc_type && - fa->fa_scope == cfg->fc_scope && + if (fa->fa_type == type && + fa->fa_scope == r->rtm_scope && fa->fa_info == fi) goto out; } - if (!(cfg->fc_nlflags & NLM_F_APPEND)) + if (!(n->nlmsg_flags & NLM_F_APPEND)) fa = fa_orig; } err = -ENOENT; - if (!(cfg->fc_nlflags & NLM_F_CREATE)) + if (!(n->nlmsg_flags&NLM_F_CREATE)) goto out; err = -ENOBUFS; @@ -503,8 +506,8 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) new_fa->fa_info = fi; new_fa->fa_tos = tos; - new_fa->fa_type = cfg->fc_type; - new_fa->fa_scope = cfg->fc_scope; + new_fa->fa_type = type; + new_fa->fa_scope = r->rtm_scope; new_fa->fa_state = 0; /* @@ -523,8 +526,7 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) fz->fz_nent++; rt_cache_flush(-1); - rtmsg_fib(RTM_NEWROUTE, key, new_fa, cfg->fc_dst_len, tb->tb_id, - &cfg->fc_nlinfo); + rtmsg_fib(RTM_NEWROUTE, key, new_fa, z, tb->tb_id, n, req); return 0; out_free_new_fa: @@ -535,25 +537,30 @@ static int fn_hash_insert(struct fib_table *tb, struct fib_config *cfg) } -static int fn_hash_delete(struct fib_table *tb, struct fib_config *cfg) +static int +fn_hash_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta, + struct nlmsghdr *n, struct netlink_skb_parms *req) { struct fn_hash *table = (struct fn_hash*)tb->tb_data; struct fib_node *f; struct fib_alias *fa, *fa_to_delete; + int z = r->rtm_dst_len; struct fn_zone *fz; u32 key; + u8 tos = r->rtm_tos; - if (cfg->fc_dst_len > 32) + if (z > 32) return -EINVAL; - - if ((fz = table->fn_zones[cfg->fc_dst_len]) == NULL) + if ((fz = table->fn_zones[z]) == NULL) return -ESRCH; key = 0; - if (cfg->fc_dst) { - if (cfg->fc_dst & ~FZ_MASK(fz)) + if (rta->rta_dst) { + u32 dst; + memcpy(&dst, rta->rta_dst, 4); + if (dst & ~FZ_MASK(fz)) return -EINVAL; - key = fz_key(cfg->fc_dst, fz); + key = fz_key(dst, fz); } f = fib_find_node(fz, key); @@ -561,7 +568,7 @@ static int fn_hash_delete(struct fib_table *tb, struct fib_config *cfg) if (!f) fa = NULL; else - fa = fib_find_alias(&f->fn_alias, cfg->fc_tos, 0); + fa = fib_find_alias(&f->fn_alias, tos, 0); if (!fa) return -ESRCH; @@ -570,16 +577,16 @@ static int fn_hash_delete(struct fib_table *tb, struct fib_config *cfg) list_for_each_entry_continue(fa, &f->fn_alias, fa_list) { struct fib_info *fi = fa->fa_info; - if (fa->fa_tos != cfg->fc_tos) + if (fa->fa_tos != tos) break; - if ((!cfg->fc_type || - fa->fa_type == cfg->fc_type) && - (cfg->fc_scope == RT_SCOPE_NOWHERE || - fa->fa_scope == cfg->fc_scope) && - (!cfg->fc_protocol || - fi->fib_protocol == cfg->fc_protocol) && - fib_nh_match(cfg, fi) == 0) { + if ((!r->rtm_type || + fa->fa_type == r->rtm_type) && + (r->rtm_scope == RT_SCOPE_NOWHERE || + fa->fa_scope == r->rtm_scope) && + (!r->rtm_protocol || + fi->fib_protocol == r->rtm_protocol) && + fib_nh_match(r, n, rta, fi) == 0) { fa_to_delete = fa; break; } @@ -589,8 +596,7 @@ static int fn_hash_delete(struct fib_table *tb, struct fib_config *cfg) int kill_fn; fa = fa_to_delete; - rtmsg_fib(RTM_DELROUTE, key, fa, cfg->fc_dst_len, - tb->tb_id, &cfg->fc_nlinfo); + rtmsg_fib(RTM_DELROUTE, key, fa, z, tb->tb_id, n, req); kill_fn = 0; write_lock_bh(&fib_hash_lock); @@ -678,7 +684,7 @@ fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb, struct fib_node *f; int i, s_i; - s_i = cb->args[4]; + s_i = cb->args[3]; i = 0; hlist_for_each_entry(f, node, head, fn_hash) { struct fib_alias *fa; @@ -693,19 +699,19 @@ fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb, tb->tb_id, fa->fa_type, fa->fa_scope, - f->fn_key, + &f->fn_key, fz->fz_order, fa->fa_tos, fa->fa_info, NLM_F_MULTI) < 0) { - cb->args[4] = i; + cb->args[3] = i; return -1; } next: i++; } } - cb->args[4] = i; + cb->args[3] = i; return skb->len; } @@ -716,21 +722,21 @@ fn_hash_dump_zone(struct sk_buff *skb, struct netlink_callback *cb, { int h, s_h; - s_h = cb->args[3]; + s_h = cb->args[2]; for (h=0; h < fz->fz_divisor; h++) { if (h < s_h) continue; if (h > s_h) - memset(&cb->args[4], 0, - sizeof(cb->args) - 4*sizeof(cb->args[0])); + memset(&cb->args[3], 0, + sizeof(cb->args) - 3*sizeof(cb->args[0])); if (fz->fz_hash == NULL || hlist_empty(&fz->fz_hash[h])) continue; if (fn_hash_dump_bucket(skb, cb, tb, fz, &fz->fz_hash[h])<0) { - cb->args[3] = h; + cb->args[2] = h; return -1; } } - cb->args[3] = h; + cb->args[2] = h; return skb->len; } @@ -740,28 +746,28 @@ static int fn_hash_dump(struct fib_table *tb, struct sk_buff *skb, struct netlin struct fn_zone *fz; struct fn_hash *table = (struct fn_hash*)tb->tb_data; - s_m = cb->args[2]; + s_m = cb->args[1]; read_lock(&fib_hash_lock); for (fz = table->fn_zone_list, m=0; fz; fz = fz->fz_next, m++) { if (m < s_m) continue; if (m > s_m) - memset(&cb->args[3], 0, - sizeof(cb->args) - 3*sizeof(cb->args[0])); + memset(&cb->args[2], 0, + sizeof(cb->args) - 2*sizeof(cb->args[0])); if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) { - cb->args[2] = m; + cb->args[1] = m; read_unlock(&fib_hash_lock); return -1; } } read_unlock(&fib_hash_lock); - cb->args[2] = m; + cb->args[1] = m; return skb->len; } #ifdef CONFIG_IP_MULTIPLE_TABLES -struct fib_table * fib_hash_init(u32 id) +struct fib_table * fib_hash_init(int id) #else -struct fib_table * __init fib_hash_init(u32 id) +struct fib_table * __init fib_hash_init(int id) #endif { struct fib_table *tb; diff --git a/trunk/net/ipv4/fib_lookup.h b/trunk/net/ipv4/fib_lookup.h index fd6f7769f8ab..ef6609ea0eb7 100644 --- a/trunk/net/ipv4/fib_lookup.h +++ b/trunk/net/ipv4/fib_lookup.h @@ -23,14 +23,19 @@ extern int fib_semantic_match(struct list_head *head, struct fib_result *res, __u32 zone, __u32 mask, int prefixlen); extern void fib_release_info(struct fib_info *); -extern struct fib_info *fib_create_info(struct fib_config *cfg); -extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi); +extern struct fib_info *fib_create_info(const struct rtmsg *r, + struct kern_rta *rta, + const struct nlmsghdr *, + int *err); +extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *, + struct kern_rta *rta, struct fib_info *fi); extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, - u32 tb_id, u8 type, u8 scope, u32 dst, + u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos, struct fib_info *fi, unsigned int); extern void rtmsg_fib(int event, u32 key, struct fib_alias *fa, - int dst_len, u32 tb_id, struct nl_info *info); + int z, int tb_id, + struct nlmsghdr *n, struct netlink_skb_parms *req); extern struct fib_alias *fib_find_alias(struct list_head *fah, u8 tos, u32 prio); extern int fib_detect_death(struct fib_info *fi, int order, diff --git a/trunk/net/ipv4/fib_rules.c b/trunk/net/ipv4/fib_rules.c index 52b2adae4f22..79b04718bdfd 100644 --- a/trunk/net/ipv4/fib_rules.c +++ b/trunk/net/ipv4/fib_rules.c @@ -5,8 +5,9 @@ * * IPv4 Forwarding Information Base: policy rules. * + * Version: $Id: fib_rules.c,v 1.17 2001/10/31 21:55:54 davem Exp $ + * * Authors: Alexey Kuznetsov, - * Thomas Graf * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,350 +19,463 @@ * Marc Boucher : routing by fwmark */ +#include +#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#include #include -#include #include #include #include + #include +#include #include #include +#include #include -#include -static struct fib_rules_ops fib4_rules_ops; +#define FRprintk(a...) -struct fib4_rule +struct fib_rule { - struct fib_rule common; - u8 dst_len; - u8 src_len; - u8 tos; - u32 src; - u32 srcmask; - u32 dst; - u32 dstmask; + struct hlist_node hlist; + atomic_t r_clntref; + u32 r_preference; + unsigned char r_table; + unsigned char r_action; + unsigned char r_dst_len; + unsigned char r_src_len; + u32 r_src; + u32 r_srcmask; + u32 r_dst; + u32 r_dstmask; + u32 r_srcmap; + u8 r_flags; + u8 r_tos; #ifdef CONFIG_IP_ROUTE_FWMARK - u32 fwmark; - u32 fwmask; + u32 r_fwmark; #endif + int r_ifindex; #ifdef CONFIG_NET_CLS_ROUTE - u32 tclassid; + __u32 r_tclassid; #endif + char r_ifname[IFNAMSIZ]; + int r_dead; + struct rcu_head rcu; }; -static struct fib4_rule default_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .pref = 0x7FFF, - .table = RT_TABLE_DEFAULT, - .action = FR_ACT_TO_TBL, - }, +static struct fib_rule default_rule = { + .r_clntref = ATOMIC_INIT(2), + .r_preference = 0x7FFF, + .r_table = RT_TABLE_DEFAULT, + .r_action = RTN_UNICAST, }; -static struct fib4_rule main_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .pref = 0x7FFE, - .table = RT_TABLE_MAIN, - .action = FR_ACT_TO_TBL, - }, +static struct fib_rule main_rule = { + .r_clntref = ATOMIC_INIT(2), + .r_preference = 0x7FFE, + .r_table = RT_TABLE_MAIN, + .r_action = RTN_UNICAST, }; -static struct fib4_rule local_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .table = RT_TABLE_LOCAL, - .action = FR_ACT_TO_TBL, - .flags = FIB_RULE_PERMANENT, - }, +static struct fib_rule local_rule = { + .r_clntref = ATOMIC_INIT(2), + .r_table = RT_TABLE_LOCAL, + .r_action = RTN_UNICAST, }; -static LIST_HEAD(fib4_rules); +static struct hlist_head fib_rules; -#ifdef CONFIG_NET_CLS_ROUTE -u32 fib_rules_tclass(struct fib_result *res) -{ - return res->r ? ((struct fib4_rule *) res->r)->tclassid : 0; -} -#endif - -int fib_lookup(struct flowi *flp, struct fib_result *res) -{ - struct fib_lookup_arg arg = { - .result = res, - }; - int err; +/* writer func called from netlink -- rtnl_sem hold*/ - err = fib_rules_lookup(&fib4_rules_ops, flp, 0, &arg); - res->r = arg.rule; +static void rtmsg_rule(int, struct fib_rule *); +int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) +{ + struct rtattr **rta = arg; + struct rtmsg *rtm = NLMSG_DATA(nlh); + struct fib_rule *r; + struct hlist_node *node; + int err = -ESRCH; + + hlist_for_each_entry(r, node, &fib_rules, hlist) { + if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 4) == 0) && + rtm->rtm_src_len == r->r_src_len && + rtm->rtm_dst_len == r->r_dst_len && + (!rta[RTA_DST-1] || memcmp(RTA_DATA(rta[RTA_DST-1]), &r->r_dst, 4) == 0) && + rtm->rtm_tos == r->r_tos && +#ifdef CONFIG_IP_ROUTE_FWMARK + (!rta[RTA_PROTOINFO-1] || memcmp(RTA_DATA(rta[RTA_PROTOINFO-1]), &r->r_fwmark, 4) == 0) && +#endif + (!rtm->rtm_type || rtm->rtm_type == r->r_action) && + (!rta[RTA_PRIORITY-1] || memcmp(RTA_DATA(rta[RTA_PRIORITY-1]), &r->r_preference, 4) == 0) && + (!rta[RTA_IIF-1] || rtattr_strcmp(rta[RTA_IIF-1], r->r_ifname) == 0) && + (!rtm->rtm_table || (r && rtm->rtm_table == r->r_table))) { + err = -EPERM; + if (r == &local_rule) + break; + + hlist_del_rcu(&r->hlist); + r->r_dead = 1; + rtmsg_rule(RTM_DELRULE, r); + fib_rule_put(r); + err = 0; + break; + } + } return err; } -static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp, - int flags, struct fib_lookup_arg *arg) -{ - int err = -EAGAIN; - struct fib_table *tbl; +/* Allocate new unique table id */ - switch (rule->action) { - case FR_ACT_TO_TBL: - break; +static struct fib_table *fib_empty_table(void) +{ + int id; - case FR_ACT_UNREACHABLE: - err = -ENETUNREACH; - goto errout; + for (id = 1; id <= RT_TABLE_MAX; id++) + if (fib_tables[id] == NULL) + return __fib_new_table(id); + return NULL; +} - case FR_ACT_PROHIBIT: - err = -EACCES; - goto errout; +static inline void fib_rule_put_rcu(struct rcu_head *head) +{ + struct fib_rule *r = container_of(head, struct fib_rule, rcu); + kfree(r); +} - case FR_ACT_BLACKHOLE: - default: - err = -EINVAL; - goto errout; +void fib_rule_put(struct fib_rule *r) +{ + if (atomic_dec_and_test(&r->r_clntref)) { + if (r->r_dead) + call_rcu(&r->rcu, fib_rule_put_rcu); + else + printk("Freeing alive rule %p\n", r); } - - if ((tbl = fib_get_table(rule->table)) == NULL) - goto errout; - - err = tbl->tb_lookup(tbl, flp, (struct fib_result *) arg->result); - if (err > 0) - err = -EAGAIN; -errout: - return err; } +/* writer func called from netlink -- rtnl_sem hold*/ -void fib_select_default(const struct flowi *flp, struct fib_result *res) +int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) { - if (res->r && res->r->action == FR_ACT_TO_TBL && - FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) { - struct fib_table *tb; - if ((tb = fib_get_table(res->r->table)) != NULL) - tb->tb_select_default(tb, flp, res); + struct rtattr **rta = arg; + struct rtmsg *rtm = NLMSG_DATA(nlh); + struct fib_rule *r, *new_r, *last = NULL; + struct hlist_node *node = NULL; + unsigned char table_id; + + if (rtm->rtm_src_len > 32 || rtm->rtm_dst_len > 32 || + (rtm->rtm_tos & ~IPTOS_TOS_MASK)) + return -EINVAL; + + if (rta[RTA_IIF-1] && RTA_PAYLOAD(rta[RTA_IIF-1]) > IFNAMSIZ) + return -EINVAL; + + table_id = rtm->rtm_table; + if (table_id == RT_TABLE_UNSPEC) { + struct fib_table *table; + if (rtm->rtm_type == RTN_UNICAST) { + if ((table = fib_empty_table()) == NULL) + return -ENOBUFS; + table_id = table->tb_id; + } } -} -static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) -{ - struct fib4_rule *r = (struct fib4_rule *) rule; - u32 daddr = fl->fl4_dst; - u32 saddr = fl->fl4_src; + new_r = kzalloc(sizeof(*new_r), GFP_KERNEL); + if (!new_r) + return -ENOMEM; + + if (rta[RTA_SRC-1]) + memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 4); + if (rta[RTA_DST-1]) + memcpy(&new_r->r_dst, RTA_DATA(rta[RTA_DST-1]), 4); + if (rta[RTA_GATEWAY-1]) + memcpy(&new_r->r_srcmap, RTA_DATA(rta[RTA_GATEWAY-1]), 4); + new_r->r_src_len = rtm->rtm_src_len; + new_r->r_dst_len = rtm->rtm_dst_len; + new_r->r_srcmask = inet_make_mask(rtm->rtm_src_len); + new_r->r_dstmask = inet_make_mask(rtm->rtm_dst_len); + new_r->r_tos = rtm->rtm_tos; +#ifdef CONFIG_IP_ROUTE_FWMARK + if (rta[RTA_PROTOINFO-1]) + memcpy(&new_r->r_fwmark, RTA_DATA(rta[RTA_PROTOINFO-1]), 4); +#endif + new_r->r_action = rtm->rtm_type; + new_r->r_flags = rtm->rtm_flags; + if (rta[RTA_PRIORITY-1]) + memcpy(&new_r->r_preference, RTA_DATA(rta[RTA_PRIORITY-1]), 4); + new_r->r_table = table_id; + if (rta[RTA_IIF-1]) { + struct net_device *dev; + rtattr_strlcpy(new_r->r_ifname, rta[RTA_IIF-1], IFNAMSIZ); + new_r->r_ifindex = -1; + dev = __dev_get_by_name(new_r->r_ifname); + if (dev) + new_r->r_ifindex = dev->ifindex; + } +#ifdef CONFIG_NET_CLS_ROUTE + if (rta[RTA_FLOW-1]) + memcpy(&new_r->r_tclassid, RTA_DATA(rta[RTA_FLOW-1]), 4); +#endif + r = container_of(fib_rules.first, struct fib_rule, hlist); - if (((saddr ^ r->src) & r->srcmask) || - ((daddr ^ r->dst) & r->dstmask)) - return 0; + if (!new_r->r_preference) { + if (r && r->hlist.next != NULL) { + r = container_of(r->hlist.next, struct fib_rule, hlist); + if (r->r_preference) + new_r->r_preference = r->r_preference - 1; + } + } - if (r->tos && (r->tos != fl->fl4_tos)) - return 0; + hlist_for_each_entry(r, node, &fib_rules, hlist) { + if (r->r_preference > new_r->r_preference) + break; + last = r; + } + atomic_inc(&new_r->r_clntref); -#ifdef CONFIG_IP_ROUTE_FWMARK - if ((r->fwmark ^ fl->fl4_fwmark) & r->fwmask) - return 0; -#endif + if (last) + hlist_add_after_rcu(&last->hlist, &new_r->hlist); + else + hlist_add_before_rcu(&new_r->hlist, &r->hlist); - return 1; + rtmsg_rule(RTM_NEWRULE, new_r); + return 0; } -static struct fib_table *fib_empty_table(void) +#ifdef CONFIG_NET_CLS_ROUTE +u32 fib_rules_tclass(struct fib_result *res) { - u32 id; - - for (id = 1; id <= RT_TABLE_MAX; id++) - if (fib_get_table(id) == NULL) - return fib_new_table(id); - return NULL; + if (res->r) + return res->r->r_tclassid; + return 0; } +#endif -static struct nla_policy fib4_rule_policy[FRA_MAX+1] __read_mostly = { - [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, - [FRA_PRIORITY] = { .type = NLA_U32 }, - [FRA_SRC] = { .type = NLA_U32 }, - [FRA_DST] = { .type = NLA_U32 }, - [FRA_FWMARK] = { .type = NLA_U32 }, - [FRA_FWMASK] = { .type = NLA_U32 }, - [FRA_FLOW] = { .type = NLA_U32 }, - [FRA_TABLE] = { .type = NLA_U32 }, -}; +/* callers should hold rtnl semaphore */ -static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh, - struct nlattr **tb) +static void fib_rules_detach(struct net_device *dev) { - int err = -EINVAL; - struct fib4_rule *rule4 = (struct fib4_rule *) rule; - - if (frh->src_len > 32 || frh->dst_len > 32 || - (frh->tos & ~IPTOS_TOS_MASK)) - goto errout; - - if (rule->table == RT_TABLE_UNSPEC) { - if (rule->action == FR_ACT_TO_TBL) { - struct fib_table *table; + struct hlist_node *node; + struct fib_rule *r; - table = fib_empty_table(); - if (table == NULL) { - err = -ENOBUFS; - goto errout; - } + hlist_for_each_entry(r, node, &fib_rules, hlist) { + if (r->r_ifindex == dev->ifindex) + r->r_ifindex = -1; - rule->table = table->tb_id; - } } +} - if (tb[FRA_SRC]) - rule4->src = nla_get_u32(tb[FRA_SRC]); +/* callers should hold rtnl semaphore */ - if (tb[FRA_DST]) - rule4->dst = nla_get_u32(tb[FRA_DST]); +static void fib_rules_attach(struct net_device *dev) +{ + struct hlist_node *node; + struct fib_rule *r; -#ifdef CONFIG_IP_ROUTE_FWMARK - if (tb[FRA_FWMARK]) { - rule4->fwmark = nla_get_u32(tb[FRA_FWMARK]); - if (rule4->fwmark) - /* compatibility: if the mark value is non-zero all bits - * are compared unless a mask is explicitly specified. - */ - rule4->fwmask = 0xFFFFFFFF; + hlist_for_each_entry(r, node, &fib_rules, hlist) { + if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0) + r->r_ifindex = dev->ifindex; } - - if (tb[FRA_FWMASK]) - rule4->fwmask = nla_get_u32(tb[FRA_FWMASK]); -#endif - -#ifdef CONFIG_NET_CLS_ROUTE - if (tb[FRA_FLOW]) - rule4->tclassid = nla_get_u32(tb[FRA_FLOW]); -#endif - - rule4->src_len = frh->src_len; - rule4->srcmask = inet_make_mask(rule4->src_len); - rule4->dst_len = frh->dst_len; - rule4->dstmask = inet_make_mask(rule4->dst_len); - rule4->tos = frh->tos; - - err = 0; -errout: - return err; } -static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, - struct nlattr **tb) +int fib_lookup(const struct flowi *flp, struct fib_result *res) { - struct fib4_rule *rule4 = (struct fib4_rule *) rule; + int err; + struct fib_rule *r, *policy; + struct fib_table *tb; + struct hlist_node *node; - if (frh->src_len && (rule4->src_len != frh->src_len)) - return 0; + u32 daddr = flp->fl4_dst; + u32 saddr = flp->fl4_src; - if (frh->dst_len && (rule4->dst_len != frh->dst_len)) - return 0; +FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ", + NIPQUAD(flp->fl4_dst), NIPQUAD(flp->fl4_src)); - if (frh->tos && (rule4->tos != frh->tos)) - return 0; + rcu_read_lock(); + hlist_for_each_entry_rcu(r, node, &fib_rules, hlist) { + if (((saddr^r->r_src) & r->r_srcmask) || + ((daddr^r->r_dst) & r->r_dstmask) || + (r->r_tos && r->r_tos != flp->fl4_tos) || #ifdef CONFIG_IP_ROUTE_FWMARK - if (tb[FRA_FWMARK] && (rule4->fwmark != nla_get_u32(tb[FRA_FWMARK]))) - return 0; - - if (tb[FRA_FWMASK] && (rule4->fwmask != nla_get_u32(tb[FRA_FWMASK]))) - return 0; + (r->r_fwmark && r->r_fwmark != flp->fl4_fwmark) || #endif + (r->r_ifindex && r->r_ifindex != flp->iif)) + continue; + +FRprintk("tb %d r %d ", r->r_table, r->r_action); + switch (r->r_action) { + case RTN_UNICAST: + policy = r; + break; + case RTN_UNREACHABLE: + rcu_read_unlock(); + return -ENETUNREACH; + default: + case RTN_BLACKHOLE: + rcu_read_unlock(); + return -EINVAL; + case RTN_PROHIBIT: + rcu_read_unlock(); + return -EACCES; + } -#ifdef CONFIG_NET_CLS_ROUTE - if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW]))) - return 0; -#endif + if ((tb = fib_get_table(r->r_table)) == NULL) + continue; + err = tb->tb_lookup(tb, flp, res); + if (err == 0) { + res->r = policy; + if (policy) + atomic_inc(&policy->r_clntref); + rcu_read_unlock(); + return 0; + } + if (err < 0 && err != -EAGAIN) { + rcu_read_unlock(); + return err; + } + } +FRprintk("FAILURE\n"); + rcu_read_unlock(); + return -ENETUNREACH; +} - if (tb[FRA_SRC] && (rule4->src != nla_get_u32(tb[FRA_SRC]))) - return 0; +void fib_select_default(const struct flowi *flp, struct fib_result *res) +{ + if (res->r && res->r->r_action == RTN_UNICAST && + FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) { + struct fib_table *tb; + if ((tb = fib_get_table(res->r->r_table)) != NULL) + tb->tb_select_default(tb, flp, res); + } +} - if (tb[FRA_DST] && (rule4->dst != nla_get_u32(tb[FRA_DST]))) - return 0; +static int fib_rules_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct net_device *dev = ptr; - return 1; + if (event == NETDEV_UNREGISTER) + fib_rules_detach(dev); + else if (event == NETDEV_REGISTER) + fib_rules_attach(dev); + return NOTIFY_DONE; } -static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh) -{ - struct fib4_rule *rule4 = (struct fib4_rule *) rule; - frh->family = AF_INET; - frh->dst_len = rule4->dst_len; - frh->src_len = rule4->src_len; - frh->tos = rule4->tos; +static struct notifier_block fib_rules_notifier = { + .notifier_call =fib_rules_event, +}; +static __inline__ int inet_fill_rule(struct sk_buff *skb, + struct fib_rule *r, + u32 pid, u32 seq, int event, + unsigned int flags) +{ + struct rtmsg *rtm; + struct nlmsghdr *nlh; + unsigned char *b = skb->tail; + + nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags); + rtm = NLMSG_DATA(nlh); + rtm->rtm_family = AF_INET; + rtm->rtm_dst_len = r->r_dst_len; + rtm->rtm_src_len = r->r_src_len; + rtm->rtm_tos = r->r_tos; #ifdef CONFIG_IP_ROUTE_FWMARK - if (rule4->fwmark) - NLA_PUT_U32(skb, FRA_FWMARK, rule4->fwmark); - - if (rule4->fwmask || rule4->fwmark) - NLA_PUT_U32(skb, FRA_FWMASK, rule4->fwmask); + if (r->r_fwmark) + RTA_PUT(skb, RTA_PROTOINFO, 4, &r->r_fwmark); #endif - - if (rule4->dst_len) - NLA_PUT_U32(skb, FRA_DST, rule4->dst); - - if (rule4->src_len) - NLA_PUT_U32(skb, FRA_SRC, rule4->src); - + rtm->rtm_table = r->r_table; + rtm->rtm_protocol = 0; + rtm->rtm_scope = 0; + rtm->rtm_type = r->r_action; + rtm->rtm_flags = r->r_flags; + + if (r->r_dst_len) + RTA_PUT(skb, RTA_DST, 4, &r->r_dst); + if (r->r_src_len) + RTA_PUT(skb, RTA_SRC, 4, &r->r_src); + if (r->r_ifname[0]) + RTA_PUT(skb, RTA_IIF, IFNAMSIZ, &r->r_ifname); + if (r->r_preference) + RTA_PUT(skb, RTA_PRIORITY, 4, &r->r_preference); + if (r->r_srcmap) + RTA_PUT(skb, RTA_GATEWAY, 4, &r->r_srcmap); #ifdef CONFIG_NET_CLS_ROUTE - if (rule4->tclassid) - NLA_PUT_U32(skb, FRA_FLOW, rule4->tclassid); + if (r->r_tclassid) + RTA_PUT(skb, RTA_FLOW, 4, &r->r_tclassid); #endif - return 0; + nlh->nlmsg_len = skb->tail - b; + return skb->len; -nla_put_failure: - return -ENOBUFS; +nlmsg_failure: +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; } -int fib4_rules_dump(struct sk_buff *skb, struct netlink_callback *cb) +/* callers should hold rtnl semaphore */ + +static void rtmsg_rule(int event, struct fib_rule *r) { - return fib_rules_dump(skb, cb, AF_INET); + int size = NLMSG_SPACE(sizeof(struct rtmsg) + 128); + struct sk_buff *skb = alloc_skb(size, GFP_KERNEL); + + if (!skb) + netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, ENOBUFS); + else if (inet_fill_rule(skb, r, 0, 0, event, 0) < 0) { + kfree_skb(skb); + netlink_set_err(rtnl, 0, RTNLGRP_IPV4_RULE, EINVAL); + } else { + netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV4_RULE, GFP_KERNEL); + } } -static u32 fib4_rule_default_pref(void) +int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) { - struct list_head *pos; - struct fib_rule *rule; - - if (!list_empty(&fib4_rules)) { - pos = fib4_rules.next; - if (pos->next != &fib4_rules) { - rule = list_entry(pos->next, struct fib_rule, list); - if (rule->pref) - return rule->pref - 1; - } + int idx = 0; + int s_idx = cb->args[0]; + struct fib_rule *r; + struct hlist_node *node; + + rcu_read_lock(); + hlist_for_each_entry(r, node, &fib_rules, hlist) { + if (idx < s_idx) + goto next; + if (inet_fill_rule(skb, r, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, + RTM_NEWRULE, NLM_F_MULTI) < 0) + break; +next: + idx++; } + rcu_read_unlock(); + cb->args[0] = idx; - return 0; + return skb->len; } -static struct fib_rules_ops fib4_rules_ops = { - .family = AF_INET, - .rule_size = sizeof(struct fib4_rule), - .action = fib4_rule_action, - .match = fib4_rule_match, - .configure = fib4_rule_configure, - .compare = fib4_rule_compare, - .fill = fib4_rule_fill, - .default_pref = fib4_rule_default_pref, - .nlgroup = RTNLGRP_IPV4_RULE, - .policy = fib4_rule_policy, - .rules_list = &fib4_rules, - .owner = THIS_MODULE, -}; - -void __init fib4_rules_init(void) +void __init fib_rules_init(void) { - list_add_tail(&local_rule.common.list, &fib4_rules); - list_add_tail(&main_rule.common.list, &fib4_rules); - list_add_tail(&default_rule.common.list, &fib4_rules); - - fib_rules_register(&fib4_rules_ops); + INIT_HLIST_HEAD(&fib_rules); + hlist_add_head(&local_rule.hlist, &fib_rules); + hlist_add_after(&local_rule.hlist, &main_rule.hlist); + hlist_add_after(&main_rule.hlist, &default_rule.hlist); + register_netdevice_notifier(&fib_rules_notifier); } diff --git a/trunk/net/ipv4/fib_semantics.c b/trunk/net/ipv4/fib_semantics.c index 2ead09543f68..9be53a8e72c3 100644 --- a/trunk/net/ipv4/fib_semantics.c +++ b/trunk/net/ipv4/fib_semantics.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -43,14 +44,12 @@ #include #include #include -#include -#include #include "fib_lookup.h" #define FSprintk(a...) -static DEFINE_SPINLOCK(fib_info_lock); +static DEFINE_RWLOCK(fib_info_lock); static struct hlist_head *fib_info_hash; static struct hlist_head *fib_info_laddrhash; static unsigned int fib_hash_size; @@ -160,7 +159,7 @@ void free_fib_info(struct fib_info *fi) void fib_release_info(struct fib_info *fi) { - spin_lock_bh(&fib_info_lock); + write_lock(&fib_info_lock); if (fi && --fi->fib_treeref == 0) { hlist_del(&fi->fib_hash); if (fi->fib_prefsrc) @@ -173,7 +172,7 @@ void fib_release_info(struct fib_info *fi) fi->fib_dead = 1; fib_info_put(fi); } - spin_unlock_bh(&fib_info_lock); + write_unlock(&fib_info_lock); } static __inline__ int nh_comp(const struct fib_info *fi, const struct fib_info *ofi) @@ -255,7 +254,7 @@ int ip_fib_check_default(u32 gw, struct net_device *dev) struct fib_nh *nh; unsigned int hash; - spin_lock(&fib_info_lock); + read_lock(&fib_info_lock); hash = fib_devindex_hashfn(dev->ifindex); head = &fib_info_devhash[hash]; @@ -263,41 +262,41 @@ int ip_fib_check_default(u32 gw, struct net_device *dev) if (nh->nh_dev == dev && nh->nh_gw == gw && !(nh->nh_flags&RTNH_F_DEAD)) { - spin_unlock(&fib_info_lock); + read_unlock(&fib_info_lock); return 0; } } - spin_unlock(&fib_info_lock); + read_unlock(&fib_info_lock); return -1; } void rtmsg_fib(int event, u32 key, struct fib_alias *fa, - int dst_len, u32 tb_id, struct nl_info *info) + int z, int tb_id, + struct nlmsghdr *n, struct netlink_skb_parms *req) { struct sk_buff *skb; - int payload = sizeof(struct rtmsg) + 256; - u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0; - int err = -ENOBUFS; - - skb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL); - if (skb == NULL) - goto errout; - - err = fib_dump_info(skb, info->pid, seq, event, tb_id, - fa->fa_type, fa->fa_scope, key, dst_len, - fa->fa_tos, fa->fa_info, 0); - if (err < 0) { + u32 pid = req ? req->pid : n->nlmsg_pid; + int size = NLMSG_SPACE(sizeof(struct rtmsg)+256); + + skb = alloc_skb(size, GFP_KERNEL); + if (!skb) + return; + + if (fib_dump_info(skb, pid, n->nlmsg_seq, event, tb_id, + fa->fa_type, fa->fa_scope, &key, z, + fa->fa_tos, + fa->fa_info, 0) < 0) { kfree_skb(skb); - goto errout; + return; } - - err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE, - info->nlh, GFP_KERNEL); -errout: - if (err < 0) - rtnl_set_sk_err(RTNLGRP_IPV4_ROUTE, err); + NETLINK_CB(skb).dst_group = RTNLGRP_IPV4_ROUTE; + if (n->nlmsg_flags&NLM_F_ECHO) + atomic_inc(&skb->users); + netlink_broadcast(rtnl, skb, pid, RTNLGRP_IPV4_ROUTE, GFP_KERNEL); + if (n->nlmsg_flags&NLM_F_ECHO) + netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT); } /* Return the first fib alias matching TOS with @@ -343,100 +342,102 @@ int fib_detect_death(struct fib_info *fi, int order, #ifdef CONFIG_IP_ROUTE_MULTIPATH -static int fib_count_nexthops(struct rtnexthop *rtnh, int remaining) +static u32 fib_get_attr32(struct rtattr *attr, int attrlen, int type) +{ + while (RTA_OK(attr,attrlen)) { + if (attr->rta_type == type) + return *(u32*)RTA_DATA(attr); + attr = RTA_NEXT(attr, attrlen); + } + return 0; +} + +static int +fib_count_nexthops(struct rtattr *rta) { int nhs = 0; + struct rtnexthop *nhp = RTA_DATA(rta); + int nhlen = RTA_PAYLOAD(rta); - while (rtnh_ok(rtnh, remaining)) { + while (nhlen >= (int)sizeof(struct rtnexthop)) { + if ((nhlen -= nhp->rtnh_len) < 0) + return 0; nhs++; - rtnh = rtnh_next(rtnh, &remaining); - } - - /* leftover implies invalid nexthop configuration, discard it */ - return remaining > 0 ? 0 : nhs; + nhp = RTNH_NEXT(nhp); + }; + return nhs; } -static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh, - int remaining, struct fib_config *cfg) +static int +fib_get_nhs(struct fib_info *fi, const struct rtattr *rta, const struct rtmsg *r) { - change_nexthops(fi) { - int attrlen; + struct rtnexthop *nhp = RTA_DATA(rta); + int nhlen = RTA_PAYLOAD(rta); - if (!rtnh_ok(rtnh, remaining)) + change_nexthops(fi) { + int attrlen = nhlen - sizeof(struct rtnexthop); + if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0) return -EINVAL; - - nh->nh_flags = (cfg->fc_flags & ~0xFF) | rtnh->rtnh_flags; - nh->nh_oif = rtnh->rtnh_ifindex; - nh->nh_weight = rtnh->rtnh_hops + 1; - - attrlen = rtnh_attrlen(rtnh); - if (attrlen > 0) { - struct nlattr *nla, *attrs = rtnh_attrs(rtnh); - - nla = nla_find(attrs, attrlen, RTA_GATEWAY); - nh->nh_gw = nla ? nla_get_u32(nla) : 0; + nh->nh_flags = (r->rtm_flags&~0xFF) | nhp->rtnh_flags; + nh->nh_oif = nhp->rtnh_ifindex; + nh->nh_weight = nhp->rtnh_hops + 1; + if (attrlen) { + nh->nh_gw = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_GATEWAY); #ifdef CONFIG_NET_CLS_ROUTE - nla = nla_find(attrs, attrlen, RTA_FLOW); - nh->nh_tclassid = nla ? nla_get_u32(nla) : 0; + nh->nh_tclassid = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_FLOW); #endif } - - rtnh = rtnh_next(rtnh, &remaining); + nhp = RTNH_NEXT(nhp); } endfor_nexthops(fi); - return 0; } #endif -int fib_nh_match(struct fib_config *cfg, struct fib_info *fi) +int fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct kern_rta *rta, + struct fib_info *fi) { #ifdef CONFIG_IP_ROUTE_MULTIPATH - struct rtnexthop *rtnh; - int remaining; + struct rtnexthop *nhp; + int nhlen; #endif - if (cfg->fc_priority && cfg->fc_priority != fi->fib_priority) + if (rta->rta_priority && + *rta->rta_priority != fi->fib_priority) return 1; - if (cfg->fc_oif || cfg->fc_gw) { - if ((!cfg->fc_oif || cfg->fc_oif == fi->fib_nh->nh_oif) && - (!cfg->fc_gw || cfg->fc_gw == fi->fib_nh->nh_gw)) + if (rta->rta_oif || rta->rta_gw) { + if ((!rta->rta_oif || *rta->rta_oif == fi->fib_nh->nh_oif) && + (!rta->rta_gw || memcmp(rta->rta_gw, &fi->fib_nh->nh_gw, 4) == 0)) return 0; return 1; } #ifdef CONFIG_IP_ROUTE_MULTIPATH - if (cfg->fc_mp == NULL) + if (rta->rta_mp == NULL) return 0; - - rtnh = cfg->fc_mp; - remaining = cfg->fc_mp_len; + nhp = RTA_DATA(rta->rta_mp); + nhlen = RTA_PAYLOAD(rta->rta_mp); for_nexthops(fi) { - int attrlen; + int attrlen = nhlen - sizeof(struct rtnexthop); + u32 gw; - if (!rtnh_ok(rtnh, remaining)) + if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0) return -EINVAL; - - if (rtnh->rtnh_ifindex && rtnh->rtnh_ifindex != nh->nh_oif) + if (nhp->rtnh_ifindex && nhp->rtnh_ifindex != nh->nh_oif) return 1; - - attrlen = rtnh_attrlen(rtnh); - if (attrlen < 0) { - struct nlattr *nla, *attrs = rtnh_attrs(rtnh); - - nla = nla_find(attrs, attrlen, RTA_GATEWAY); - if (nla && nla_get_u32(nla) != nh->nh_gw) + if (attrlen) { + gw = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_GATEWAY); + if (gw && gw != nh->nh_gw) return 1; #ifdef CONFIG_NET_CLS_ROUTE - nla = nla_find(attrs, attrlen, RTA_FLOW); - if (nla && nla_get_u32(nla) != nh->nh_tclassid) + gw = fib_get_attr32(RTNH_DATA(nhp), attrlen, RTA_FLOW); + if (gw && gw != nh->nh_tclassid) return 1; #endif } - - rtnh = rtnh_next(rtnh, &remaining); + nhp = RTNH_NEXT(nhp); } endfor_nexthops(fi); #endif return 0; @@ -487,8 +488,7 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi) |-> {local prefix} (terminal node) */ -static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, - struct fib_nh *nh) +static int fib_check_nh(const struct rtmsg *r, struct fib_info *fi, struct fib_nh *nh) { int err; @@ -502,7 +502,7 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, if (nh->nh_flags&RTNH_F_ONLINK) { struct net_device *dev; - if (cfg->fc_scope >= RT_SCOPE_LINK) + if (r->rtm_scope >= RT_SCOPE_LINK) return -EINVAL; if (inet_addr_type(nh->nh_gw) != RTN_UNICAST) return -EINVAL; @@ -516,15 +516,10 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, return 0; } { - struct flowi fl = { - .nl_u = { - .ip4_u = { - .daddr = nh->nh_gw, - .scope = cfg->fc_scope + 1, - }, - }, - .oif = nh->nh_oif, - }; + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = nh->nh_gw, + .scope = r->rtm_scope + 1 } }, + .oif = nh->nh_oif }; /* It is not necessary, but requires a bit of thinking */ if (fl.fl4_scope < RT_SCOPE_LINK) @@ -603,7 +598,7 @@ static void fib_hash_move(struct hlist_head *new_info_hash, unsigned int old_size = fib_hash_size; unsigned int i, bytes; - spin_lock_bh(&fib_info_lock); + write_lock(&fib_info_lock); old_info_hash = fib_info_hash; old_laddrhash = fib_info_laddrhash; fib_hash_size = new_size; @@ -644,35 +639,46 @@ static void fib_hash_move(struct hlist_head *new_info_hash, } fib_info_laddrhash = new_laddrhash; - spin_unlock_bh(&fib_info_lock); + write_unlock(&fib_info_lock); bytes = old_size * sizeof(struct hlist_head *); fib_hash_free(old_info_hash, bytes); fib_hash_free(old_laddrhash, bytes); } -struct fib_info *fib_create_info(struct fib_config *cfg) +struct fib_info * +fib_create_info(const struct rtmsg *r, struct kern_rta *rta, + const struct nlmsghdr *nlh, int *errp) { int err; struct fib_info *fi = NULL; struct fib_info *ofi; +#ifdef CONFIG_IP_ROUTE_MULTIPATH int nhs = 1; +#else + const int nhs = 1; +#endif +#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED + u32 mp_alg = IP_MP_ALG_NONE; +#endif /* Fast check to catch the most weird cases */ - if (fib_props[cfg->fc_type].scope > cfg->fc_scope) + if (fib_props[r->rtm_type].scope > r->rtm_scope) goto err_inval; #ifdef CONFIG_IP_ROUTE_MULTIPATH - if (cfg->fc_mp) { - nhs = fib_count_nexthops(cfg->fc_mp, cfg->fc_mp_len); + if (rta->rta_mp) { + nhs = fib_count_nexthops(rta->rta_mp); if (nhs == 0) goto err_inval; } #endif #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - if (cfg->fc_mp_alg) { - if (cfg->fc_mp_alg < IP_MP_ALG_NONE || - cfg->fc_mp_alg > IP_MP_ALG_MAX) + if (rta->rta_mp_alg) { + mp_alg = *rta->rta_mp_alg; + + if (mp_alg < IP_MP_ALG_NONE || + mp_alg > IP_MP_ALG_MAX) goto err_inval; } #endif @@ -708,42 +714,43 @@ struct fib_info *fib_create_info(struct fib_config *cfg) goto failure; fib_info_cnt++; - fi->fib_protocol = cfg->fc_protocol; - fi->fib_flags = cfg->fc_flags; - fi->fib_priority = cfg->fc_priority; - fi->fib_prefsrc = cfg->fc_prefsrc; + fi->fib_protocol = r->rtm_protocol; fi->fib_nhs = nhs; change_nexthops(fi) { nh->nh_parent = fi; } endfor_nexthops(fi) - if (cfg->fc_mx) { - struct nlattr *nla; - int remaining; - - nla_for_each_attr(nla, cfg->fc_mx, cfg->fc_mx_len, remaining) { - int type = nla->nla_type; - - if (type) { - if (type > RTAX_MAX) + fi->fib_flags = r->rtm_flags; + if (rta->rta_priority) + fi->fib_priority = *rta->rta_priority; + if (rta->rta_mx) { + int attrlen = RTA_PAYLOAD(rta->rta_mx); + struct rtattr *attr = RTA_DATA(rta->rta_mx); + + while (RTA_OK(attr, attrlen)) { + unsigned flavor = attr->rta_type; + if (flavor) { + if (flavor > RTAX_MAX) goto err_inval; - fi->fib_metrics[type - 1] = nla_get_u32(nla); + fi->fib_metrics[flavor-1] = *(unsigned*)RTA_DATA(attr); } + attr = RTA_NEXT(attr, attrlen); } } + if (rta->rta_prefsrc) + memcpy(&fi->fib_prefsrc, rta->rta_prefsrc, 4); - if (cfg->fc_mp) { + if (rta->rta_mp) { #ifdef CONFIG_IP_ROUTE_MULTIPATH - err = fib_get_nhs(fi, cfg->fc_mp, cfg->fc_mp_len, cfg); - if (err != 0) + if ((err = fib_get_nhs(fi, rta->rta_mp, r)) != 0) goto failure; - if (cfg->fc_oif && fi->fib_nh->nh_oif != cfg->fc_oif) + if (rta->rta_oif && fi->fib_nh->nh_oif != *rta->rta_oif) goto err_inval; - if (cfg->fc_gw && fi->fib_nh->nh_gw != cfg->fc_gw) + if (rta->rta_gw && memcmp(&fi->fib_nh->nh_gw, rta->rta_gw, 4)) goto err_inval; #ifdef CONFIG_NET_CLS_ROUTE - if (cfg->fc_flow && fi->fib_nh->nh_tclassid != cfg->fc_flow) + if (rta->rta_flow && memcmp(&fi->fib_nh->nh_tclassid, rta->rta_flow, 4)) goto err_inval; #endif #else @@ -751,32 +758,34 @@ struct fib_info *fib_create_info(struct fib_config *cfg) #endif } else { struct fib_nh *nh = fi->fib_nh; - - nh->nh_oif = cfg->fc_oif; - nh->nh_gw = cfg->fc_gw; - nh->nh_flags = cfg->fc_flags; + if (rta->rta_oif) + nh->nh_oif = *rta->rta_oif; + if (rta->rta_gw) + memcpy(&nh->nh_gw, rta->rta_gw, 4); #ifdef CONFIG_NET_CLS_ROUTE - nh->nh_tclassid = cfg->fc_flow; + if (rta->rta_flow) + memcpy(&nh->nh_tclassid, rta->rta_flow, 4); #endif + nh->nh_flags = r->rtm_flags; #ifdef CONFIG_IP_ROUTE_MULTIPATH nh->nh_weight = 1; #endif } #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - fi->fib_mp_alg = cfg->fc_mp_alg; + fi->fib_mp_alg = mp_alg; #endif - if (fib_props[cfg->fc_type].error) { - if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp) + if (fib_props[r->rtm_type].error) { + if (rta->rta_gw || rta->rta_oif || rta->rta_mp) goto err_inval; goto link_it; } - if (cfg->fc_scope > RT_SCOPE_HOST) + if (r->rtm_scope > RT_SCOPE_HOST) goto err_inval; - if (cfg->fc_scope == RT_SCOPE_HOST) { + if (r->rtm_scope == RT_SCOPE_HOST) { struct fib_nh *nh = fi->fib_nh; /* Local address is added. */ @@ -789,14 +798,14 @@ struct fib_info *fib_create_info(struct fib_config *cfg) goto failure; } else { change_nexthops(fi) { - if ((err = fib_check_nh(cfg, fi, nh)) != 0) + if ((err = fib_check_nh(r, fi, nh)) != 0) goto failure; } endfor_nexthops(fi) } if (fi->fib_prefsrc) { - if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst || - fi->fib_prefsrc != cfg->fc_dst) + if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL || + memcmp(&fi->fib_prefsrc, rta->rta_dst, 4)) if (inet_addr_type(fi->fib_prefsrc) != RTN_LOCAL) goto err_inval; } @@ -811,7 +820,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) fi->fib_treeref++; atomic_inc(&fi->fib_clntref); - spin_lock_bh(&fib_info_lock); + write_lock(&fib_info_lock); hlist_add_head(&fi->fib_hash, &fib_info_hash[fib_info_hashfn(fi)]); if (fi->fib_prefsrc) { @@ -830,19 +839,19 @@ struct fib_info *fib_create_info(struct fib_config *cfg) head = &fib_info_devhash[hash]; hlist_add_head(&nh->nh_hash, head); } endfor_nexthops(fi) - spin_unlock_bh(&fib_info_lock); + write_unlock(&fib_info_lock); return fi; err_inval: err = -EINVAL; failure: + *errp = err; if (fi) { fi->fib_dead = 1; free_fib_info(fi); } - - return ERR_PTR(err); + return NULL; } /* Note! fib_semantic_match intentionally uses RCU list functions. */ @@ -928,89 +937,224 @@ u32 __fib_res_prefsrc(struct fib_result *res) return inet_select_addr(FIB_RES_DEV(*res), FIB_RES_GW(*res), res->scope); } -int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, - u32 tb_id, u8 type, u8 scope, u32 dst, int dst_len, u8 tos, - struct fib_info *fi, unsigned int flags) +int +fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, + u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos, + struct fib_info *fi, unsigned int flags) { - struct nlmsghdr *nlh; struct rtmsg *rtm; + struct nlmsghdr *nlh; + unsigned char *b = skb->tail; - nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags); - if (nlh == NULL) - return -ENOBUFS; - - rtm = nlmsg_data(nlh); + nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags); + rtm = NLMSG_DATA(nlh); rtm->rtm_family = AF_INET; rtm->rtm_dst_len = dst_len; rtm->rtm_src_len = 0; rtm->rtm_tos = tos; rtm->rtm_table = tb_id; - NLA_PUT_U32(skb, RTA_TABLE, tb_id); rtm->rtm_type = type; rtm->rtm_flags = fi->fib_flags; rtm->rtm_scope = scope; - rtm->rtm_protocol = fi->fib_protocol; - if (rtm->rtm_dst_len) - NLA_PUT_U32(skb, RTA_DST, dst); - + RTA_PUT(skb, RTA_DST, 4, dst); + rtm->rtm_protocol = fi->fib_protocol; if (fi->fib_priority) - NLA_PUT_U32(skb, RTA_PRIORITY, fi->fib_priority); - + RTA_PUT(skb, RTA_PRIORITY, 4, &fi->fib_priority); if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0) - goto nla_put_failure; - + goto rtattr_failure; if (fi->fib_prefsrc) - NLA_PUT_U32(skb, RTA_PREFSRC, fi->fib_prefsrc); - + RTA_PUT(skb, RTA_PREFSRC, 4, &fi->fib_prefsrc); if (fi->fib_nhs == 1) { if (fi->fib_nh->nh_gw) - NLA_PUT_U32(skb, RTA_GATEWAY, fi->fib_nh->nh_gw); - + RTA_PUT(skb, RTA_GATEWAY, 4, &fi->fib_nh->nh_gw); if (fi->fib_nh->nh_oif) - NLA_PUT_U32(skb, RTA_OIF, fi->fib_nh->nh_oif); + RTA_PUT(skb, RTA_OIF, sizeof(int), &fi->fib_nh->nh_oif); #ifdef CONFIG_NET_CLS_ROUTE if (fi->fib_nh[0].nh_tclassid) - NLA_PUT_U32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid); + RTA_PUT(skb, RTA_FLOW, 4, &fi->fib_nh[0].nh_tclassid); #endif } #ifdef CONFIG_IP_ROUTE_MULTIPATH if (fi->fib_nhs > 1) { - struct rtnexthop *rtnh; - struct nlattr *mp; - - mp = nla_nest_start(skb, RTA_MULTIPATH); - if (mp == NULL) - goto nla_put_failure; + struct rtnexthop *nhp; + struct rtattr *mp_head; + if (skb_tailroom(skb) <= RTA_SPACE(0)) + goto rtattr_failure; + mp_head = (struct rtattr*)skb_put(skb, RTA_SPACE(0)); for_nexthops(fi) { - rtnh = nla_reserve_nohdr(skb, sizeof(*rtnh)); - if (rtnh == NULL) - goto nla_put_failure; - - rtnh->rtnh_flags = nh->nh_flags & 0xFF; - rtnh->rtnh_hops = nh->nh_weight - 1; - rtnh->rtnh_ifindex = nh->nh_oif; - + if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4)) + goto rtattr_failure; + nhp = (struct rtnexthop*)skb_put(skb, RTA_ALIGN(sizeof(*nhp))); + nhp->rtnh_flags = nh->nh_flags & 0xFF; + nhp->rtnh_hops = nh->nh_weight-1; + nhp->rtnh_ifindex = nh->nh_oif; if (nh->nh_gw) - NLA_PUT_U32(skb, RTA_GATEWAY, nh->nh_gw); + RTA_PUT(skb, RTA_GATEWAY, 4, &nh->nh_gw); #ifdef CONFIG_NET_CLS_ROUTE if (nh->nh_tclassid) - NLA_PUT_U32(skb, RTA_FLOW, nh->nh_tclassid); + RTA_PUT(skb, RTA_FLOW, 4, &nh->nh_tclassid); #endif - /* length of rtnetlink header + attributes */ - rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *) rtnh; + nhp->rtnh_len = skb->tail - (unsigned char*)nhp; } endfor_nexthops(fi); - - nla_nest_end(skb, mp); + mp_head->rta_type = RTA_MULTIPATH; + mp_head->rta_len = skb->tail - (u8*)mp_head; } #endif - return nlmsg_end(skb, nlh); + nlh->nlmsg_len = skb->tail - b; + return skb->len; + +nlmsg_failure: +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; +} + +#ifndef CONFIG_IP_NOSIOCRT + +int +fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm, + struct kern_rta *rta, struct rtentry *r) +{ + int plen; + u32 *ptr; + + memset(rtm, 0, sizeof(*rtm)); + memset(rta, 0, sizeof(*rta)); + + if (r->rt_dst.sa_family != AF_INET) + return -EAFNOSUPPORT; + + /* Check mask for validity: + a) it must be contiguous. + b) destination must have all host bits clear. + c) if application forgot to set correct family (AF_INET), + reject request unless it is absolutely clear i.e. + both family and mask are zero. + */ + plen = 32; + ptr = &((struct sockaddr_in*)&r->rt_dst)->sin_addr.s_addr; + if (!(r->rt_flags&RTF_HOST)) { + u32 mask = ((struct sockaddr_in*)&r->rt_genmask)->sin_addr.s_addr; + if (r->rt_genmask.sa_family != AF_INET) { + if (mask || r->rt_genmask.sa_family) + return -EAFNOSUPPORT; + } + if (bad_mask(mask, *ptr)) + return -EINVAL; + plen = inet_mask_len(mask); + } + + nl->nlmsg_flags = NLM_F_REQUEST; + nl->nlmsg_pid = 0; + nl->nlmsg_seq = 0; + nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm)); + if (cmd == SIOCDELRT) { + nl->nlmsg_type = RTM_DELROUTE; + nl->nlmsg_flags = 0; + } else { + nl->nlmsg_type = RTM_NEWROUTE; + nl->nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE; + rtm->rtm_protocol = RTPROT_BOOT; + } -nla_put_failure: - return nlmsg_cancel(skb, nlh); + rtm->rtm_dst_len = plen; + rta->rta_dst = ptr; + + if (r->rt_metric) { + *(u32*)&r->rt_pad3 = r->rt_metric - 1; + rta->rta_priority = (u32*)&r->rt_pad3; + } + if (r->rt_flags&RTF_REJECT) { + rtm->rtm_scope = RT_SCOPE_HOST; + rtm->rtm_type = RTN_UNREACHABLE; + return 0; + } + rtm->rtm_scope = RT_SCOPE_NOWHERE; + rtm->rtm_type = RTN_UNICAST; + + if (r->rt_dev) { + char *colon; + struct net_device *dev; + char devname[IFNAMSIZ]; + + if (copy_from_user(devname, r->rt_dev, IFNAMSIZ-1)) + return -EFAULT; + devname[IFNAMSIZ-1] = 0; + colon = strchr(devname, ':'); + if (colon) + *colon = 0; + dev = __dev_get_by_name(devname); + if (!dev) + return -ENODEV; + rta->rta_oif = &dev->ifindex; + if (colon) { + struct in_ifaddr *ifa; + struct in_device *in_dev = __in_dev_get_rtnl(dev); + if (!in_dev) + return -ENODEV; + *colon = ':'; + for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) + if (strcmp(ifa->ifa_label, devname) == 0) + break; + if (ifa == NULL) + return -ENODEV; + rta->rta_prefsrc = &ifa->ifa_local; + } + } + + ptr = &((struct sockaddr_in*)&r->rt_gateway)->sin_addr.s_addr; + if (r->rt_gateway.sa_family == AF_INET && *ptr) { + rta->rta_gw = ptr; + if (r->rt_flags&RTF_GATEWAY && inet_addr_type(*ptr) == RTN_UNICAST) + rtm->rtm_scope = RT_SCOPE_UNIVERSE; + } + + if (cmd == SIOCDELRT) + return 0; + + if (r->rt_flags&RTF_GATEWAY && rta->rta_gw == NULL) + return -EINVAL; + + if (rtm->rtm_scope == RT_SCOPE_NOWHERE) + rtm->rtm_scope = RT_SCOPE_LINK; + + if (r->rt_flags&(RTF_MTU|RTF_WINDOW|RTF_IRTT)) { + struct rtattr *rec; + struct rtattr *mx = kmalloc(RTA_LENGTH(3*RTA_LENGTH(4)), GFP_KERNEL); + if (mx == NULL) + return -ENOMEM; + rta->rta_mx = mx; + mx->rta_type = RTA_METRICS; + mx->rta_len = RTA_LENGTH(0); + if (r->rt_flags&RTF_MTU) { + rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len)); + rec->rta_type = RTAX_ADVMSS; + rec->rta_len = RTA_LENGTH(4); + mx->rta_len += RTA_LENGTH(4); + *(u32*)RTA_DATA(rec) = r->rt_mtu - 40; + } + if (r->rt_flags&RTF_WINDOW) { + rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len)); + rec->rta_type = RTAX_WINDOW; + rec->rta_len = RTA_LENGTH(4); + mx->rta_len += RTA_LENGTH(4); + *(u32*)RTA_DATA(rec) = r->rt_window; + } + if (r->rt_flags&RTF_IRTT) { + rec = (void*)((char*)mx + RTA_ALIGN(mx->rta_len)); + rec->rta_type = RTAX_RTT; + rec->rta_len = RTA_LENGTH(4); + mx->rta_len += RTA_LENGTH(4); + *(u32*)RTA_DATA(rec) = r->rt_irtt<<3; + } + } + return 0; } +#endif + /* Update FIB if: - local address disappeared -> we must delete all the entries diff --git a/trunk/net/ipv4/fib_trie.c b/trunk/net/ipv4/fib_trie.c index 9c3ff6ba6e21..23fb9d9768e3 100644 --- a/trunk/net/ipv4/fib_trie.c +++ b/trunk/net/ipv4/fib_trie.c @@ -1124,14 +1124,17 @@ fib_insert_node(struct trie *t, int *err, u32 key, int plen) return fa_head; } -static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) +static int +fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta, + struct nlmsghdr *nlhdr, struct netlink_skb_parms *req) { struct trie *t = (struct trie *) tb->tb_data; struct fib_alias *fa, *new_fa; struct list_head *fa_head = NULL; struct fib_info *fi; - int plen = cfg->fc_dst_len; - u8 tos = cfg->fc_tos; + int plen = r->rtm_dst_len; + int type = r->rtm_type; + u8 tos = r->rtm_tos; u32 key, mask; int err; struct leaf *l; @@ -1139,9 +1142,13 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) if (plen > 32) return -EINVAL; - key = ntohl(cfg->fc_dst); + key = 0; + if (rta->rta_dst) + memcpy(&key, rta->rta_dst, 4); + + key = ntohl(key); - pr_debug("Insert table=%u %08x/%d\n", tb->tb_id, key, plen); + pr_debug("Insert table=%d %08x/%d\n", tb->tb_id, key, plen); mask = ntohl(inet_make_mask(plen)); @@ -1150,11 +1157,10 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) key = key & mask; - fi = fib_create_info(cfg); - if (IS_ERR(fi)) { - err = PTR_ERR(fi); + fi = fib_create_info(r, rta, nlhdr, &err); + + if (!fi) goto err; - } l = fib_find_node(t, key); fa = NULL; @@ -1179,10 +1185,10 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) struct fib_alias *fa_orig; err = -EEXIST; - if (cfg->fc_nlflags & NLM_F_EXCL) + if (nlhdr->nlmsg_flags & NLM_F_EXCL) goto out; - if (cfg->fc_nlflags & NLM_F_REPLACE) { + if (nlhdr->nlmsg_flags & NLM_F_REPLACE) { struct fib_info *fi_drop; u8 state; @@ -1194,8 +1200,8 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) fi_drop = fa->fa_info; new_fa->fa_tos = fa->fa_tos; new_fa->fa_info = fi; - new_fa->fa_type = cfg->fc_type; - new_fa->fa_scope = cfg->fc_scope; + new_fa->fa_type = type; + new_fa->fa_scope = r->rtm_scope; state = fa->fa_state; new_fa->fa_state &= ~FA_S_ACCESSED; @@ -1218,17 +1224,17 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) break; if (fa->fa_info->fib_priority != fi->fib_priority) break; - if (fa->fa_type == cfg->fc_type && - fa->fa_scope == cfg->fc_scope && + if (fa->fa_type == type && + fa->fa_scope == r->rtm_scope && fa->fa_info == fi) { goto out; } } - if (!(cfg->fc_nlflags & NLM_F_APPEND)) + if (!(nlhdr->nlmsg_flags & NLM_F_APPEND)) fa = fa_orig; } err = -ENOENT; - if (!(cfg->fc_nlflags & NLM_F_CREATE)) + if (!(nlhdr->nlmsg_flags & NLM_F_CREATE)) goto out; err = -ENOBUFS; @@ -1238,8 +1244,8 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) new_fa->fa_info = fi; new_fa->fa_tos = tos; - new_fa->fa_type = cfg->fc_type; - new_fa->fa_scope = cfg->fc_scope; + new_fa->fa_type = type; + new_fa->fa_scope = r->rtm_scope; new_fa->fa_state = 0; /* * Insert new entry to the list. @@ -1256,8 +1262,7 @@ static int fn_trie_insert(struct fib_table *tb, struct fib_config *cfg) (fa ? &fa->fa_list : fa_head)); rt_cache_flush(-1); - rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, - &cfg->fc_nlinfo); + rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req); succeeded: return 0; @@ -1276,18 +1281,18 @@ static inline int check_leaf(struct trie *t, struct leaf *l, struct fib_result *res) { int err, i; - __be32 mask; + t_key mask; struct leaf_info *li; struct hlist_head *hhead = &l->list; struct hlist_node *node; hlist_for_each_entry_rcu(li, node, hhead, hlist) { i = li->plen; - mask = inet_make_mask(i); - if (l->key != (key & ntohl(mask))) + mask = ntohl(inet_make_mask(i)); + if (l->key != (key & mask)) continue; - if ((err = fib_semantic_match(&li->falh, flp, res, htonl(l->key), mask, i)) <= 0) { + if ((err = fib_semantic_match(&li->falh, flp, res, l->key, mask, i)) <= 0) { *plen = i; #ifdef CONFIG_IP_FIB_TRIE_STATS t->stats.semantic_match_passed++; @@ -1543,21 +1548,28 @@ static int trie_leaf_remove(struct trie *t, t_key key) return 1; } -static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg) +static int +fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta, + struct nlmsghdr *nlhdr, struct netlink_skb_parms *req) { struct trie *t = (struct trie *) tb->tb_data; u32 key, mask; - int plen = cfg->fc_dst_len; - u8 tos = cfg->fc_tos; + int plen = r->rtm_dst_len; + u8 tos = r->rtm_tos; struct fib_alias *fa, *fa_to_delete; struct list_head *fa_head; struct leaf *l; struct leaf_info *li; + if (plen > 32) return -EINVAL; - key = ntohl(cfg->fc_dst); + key = 0; + if (rta->rta_dst) + memcpy(&key, rta->rta_dst, 4); + + key = ntohl(key); mask = ntohl(inet_make_mask(plen)); if (key & ~mask) @@ -1586,12 +1598,13 @@ static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg) if (fa->fa_tos != tos) break; - if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) && - (cfg->fc_scope == RT_SCOPE_NOWHERE || - fa->fa_scope == cfg->fc_scope) && - (!cfg->fc_protocol || - fi->fib_protocol == cfg->fc_protocol) && - fib_nh_match(cfg, fi) == 0) { + if ((!r->rtm_type || + fa->fa_type == r->rtm_type) && + (r->rtm_scope == RT_SCOPE_NOWHERE || + fa->fa_scope == r->rtm_scope) && + (!r->rtm_protocol || + fi->fib_protocol == r->rtm_protocol) && + fib_nh_match(r, nlhdr, rta, fi) == 0) { fa_to_delete = fa; break; } @@ -1601,8 +1614,7 @@ static int fn_trie_delete(struct fib_table *tb, struct fib_config *cfg) return -ESRCH; fa = fa_to_delete; - rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, - &cfg->fc_nlinfo); + rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req); l = fib_find_node(t, key); li = find_leaf_info(l, plen); @@ -1836,7 +1848,7 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fi u32 xkey = htonl(key); - s_i = cb->args[4]; + s_i = cb->args[3]; i = 0; /* rcu_read_lock is hold by caller */ @@ -1854,16 +1866,16 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fi tb->tb_id, fa->fa_type, fa->fa_scope, - xkey, + &xkey, plen, fa->fa_tos, fa->fa_info, 0) < 0) { - cb->args[4] = i; + cb->args[3] = i; return -1; } i++; } - cb->args[4] = i; + cb->args[3] = i; return skb->len; } @@ -1874,14 +1886,14 @@ static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, str struct list_head *fa_head; struct leaf *l = NULL; - s_h = cb->args[3]; + s_h = cb->args[2]; for (h = 0; (l = nextleaf(t, l)) != NULL; h++) { if (h < s_h) continue; if (h > s_h) - memset(&cb->args[4], 0, - sizeof(cb->args) - 4*sizeof(cb->args[0])); + memset(&cb->args[3], 0, + sizeof(cb->args) - 3*sizeof(cb->args[0])); fa_head = get_fa_head(l, plen); @@ -1892,11 +1904,11 @@ static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, str continue; if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb)<0) { - cb->args[3] = h; + cb->args[2] = h; return -1; } } - cb->args[3] = h; + cb->args[2] = h; return skb->len; } @@ -1905,23 +1917,23 @@ static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, struct netlin int m, s_m; struct trie *t = (struct trie *) tb->tb_data; - s_m = cb->args[2]; + s_m = cb->args[1]; rcu_read_lock(); for (m = 0; m <= 32; m++) { if (m < s_m) continue; if (m > s_m) - memset(&cb->args[3], 0, - sizeof(cb->args) - 3*sizeof(cb->args[0])); + memset(&cb->args[2], 0, + sizeof(cb->args) - 2*sizeof(cb->args[0])); if (fn_trie_dump_plen(t, 32-m, tb, skb, cb)<0) { - cb->args[2] = m; + cb->args[1] = m; goto out; } } rcu_read_unlock(); - cb->args[2] = m; + cb->args[1] = m; return skb->len; out: rcu_read_unlock(); @@ -1931,9 +1943,9 @@ static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, struct netlin /* Fix more generic FIB names for init later */ #ifdef CONFIG_IP_MULTIPLE_TABLES -struct fib_table * fib_hash_init(u32 id) +struct fib_table * fib_hash_init(int id) #else -struct fib_table * __init fib_hash_init(u32 id) +struct fib_table * __init fib_hash_init(int id) #endif { struct fib_table *tb; diff --git a/trunk/net/ipv4/icmp.c b/trunk/net/ipv4/icmp.c index c2ad07e48ab4..4c86ac3d882d 100644 --- a/trunk/net/ipv4/icmp.c +++ b/trunk/net/ipv4/icmp.c @@ -187,11 +187,11 @@ struct icmp_err icmp_err_convert[] = { }; /* Control parameters for ECHO replies. */ -int sysctl_icmp_echo_ignore_all __read_mostly; -int sysctl_icmp_echo_ignore_broadcasts __read_mostly = 1; +int sysctl_icmp_echo_ignore_all; +int sysctl_icmp_echo_ignore_broadcasts = 1; /* Control parameter - ignore bogus broadcast responses? */ -int sysctl_icmp_ignore_bogus_error_responses __read_mostly = 1; +int sysctl_icmp_ignore_bogus_error_responses = 1; /* * Configurable global rate limit. @@ -205,9 +205,9 @@ int sysctl_icmp_ignore_bogus_error_responses __read_mostly = 1; * time exceeded (11), parameter problem (12) */ -int sysctl_icmp_ratelimit __read_mostly = 1 * HZ; -int sysctl_icmp_ratemask __read_mostly = 0x1818; -int sysctl_icmp_errors_use_inbound_ifaddr __read_mostly; +int sysctl_icmp_ratelimit = 1 * HZ; +int sysctl_icmp_ratemask = 0x1818; +int sysctl_icmp_errors_use_inbound_ifaddr; /* * ICMP control array. This specifies what to do with each ICMP. @@ -406,7 +406,6 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) .saddr = rt->rt_spec_dst, .tos = RT_TOS(skb->nh.iph->tos) } }, .proto = IPPROTO_ICMP }; - security_skb_classify_flow(skb, &fl); if (ip_route_output_key(&rt, &fl)) goto out_unlock; } @@ -561,7 +560,6 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info) } } }; - security_skb_classify_flow(skb_in, &fl); if (ip_route_output_key(&rt, &fl)) goto out_unlock; } @@ -930,7 +928,7 @@ int icmp_rcv(struct sk_buff *skb) ICMP_INC_STATS_BH(ICMP_MIB_INMSGS); switch (skb->ip_summed) { - case CHECKSUM_COMPLETE: + case CHECKSUM_HW: if (!(u16)csum_fold(skb->csum)) break; /* fall through */ diff --git a/trunk/net/ipv4/igmp.c b/trunk/net/ipv4/igmp.c index 58be8227b0cb..9f4b752f5a33 100644 --- a/trunk/net/ipv4/igmp.c +++ b/trunk/net/ipv4/igmp.c @@ -931,7 +931,7 @@ int igmp_rcv(struct sk_buff *skb) goto drop; switch (skb->ip_summed) { - case CHECKSUM_COMPLETE: + case CHECKSUM_HW: if (!(u16)csum_fold(skb->csum)) break; /* fall through */ @@ -1397,8 +1397,8 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr) /* * Join a socket to a group */ -int sysctl_igmp_max_memberships __read_mostly = IP_MAX_MEMBERSHIPS; -int sysctl_igmp_max_msf __read_mostly = IP_MAX_MSF; +int sysctl_igmp_max_memberships = IP_MAX_MEMBERSHIPS; +int sysctl_igmp_max_msf = IP_MAX_MSF; static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode, @@ -1793,35 +1793,29 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr) struct in_device *in_dev; u32 group = imr->imr_multiaddr.s_addr; u32 ifindex; - int ret = -EADDRNOTAVAIL; rtnl_lock(); in_dev = ip_mc_find_dev(imr); + if (!in_dev) { + rtnl_unlock(); + return -ENODEV; + } ifindex = imr->imr_ifindex; for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) { - if (iml->multi.imr_multiaddr.s_addr != group) - continue; - if (ifindex) { - if (iml->multi.imr_ifindex != ifindex) - continue; - } else if (imr->imr_address.s_addr && imr->imr_address.s_addr != - iml->multi.imr_address.s_addr) - continue; - - (void) ip_mc_leave_src(sk, iml, in_dev); + if (iml->multi.imr_multiaddr.s_addr == group && + iml->multi.imr_ifindex == ifindex) { + (void) ip_mc_leave_src(sk, iml, in_dev); - *imlp = iml->next; + *imlp = iml->next; - if (in_dev) ip_mc_dec_group(in_dev, group); - rtnl_unlock(); - sock_kfree_s(sk, iml, sizeof(*iml)); - return 0; + rtnl_unlock(); + sock_kfree_s(sk, iml, sizeof(*iml)); + return 0; + } } - if (!in_dev) - ret = -ENODEV; rtnl_unlock(); - return ret; + return -EADDRNOTAVAIL; } int ip_mc_source(int add, int omode, struct sock *sk, struct @@ -2205,13 +2199,13 @@ void ip_mc_drop_socket(struct sock *sk) struct in_device *in_dev; inet->mc_list = iml->next; - in_dev = inetdev_by_index(iml->multi.imr_ifindex); - (void) ip_mc_leave_src(sk, iml, in_dev); - if (in_dev != NULL) { + if ((in_dev = inetdev_by_index(iml->multi.imr_ifindex)) != NULL) { + (void) ip_mc_leave_src(sk, iml, in_dev); ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr); in_dev_put(in_dev); } sock_kfree_s(sk, iml, sizeof(*iml)); + } rtnl_unlock(); } diff --git a/trunk/net/ipv4/inet_connection_sock.c b/trunk/net/ipv4/inet_connection_sock.c index 07204391d083..e50a1bfd7ccc 100644 --- a/trunk/net/ipv4/inet_connection_sock.c +++ b/trunk/net/ipv4/inet_connection_sock.c @@ -327,7 +327,6 @@ struct dst_entry* inet_csk_route_req(struct sock *sk, { .sport = inet_sk(sk)->sport, .dport = ireq->rmt_port } } }; - security_req_classify_flow(req, &fl); if (ip_route_output_flow(&rt, &fl, sk, 0)) { IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES); return NULL; @@ -510,8 +509,6 @@ struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req, /* Deinitialize accept_queue to trap illegal accesses. */ memset(&newicsk->icsk_accept_queue, 0, sizeof(newicsk->icsk_accept_queue)); - - security_inet_csk_clone(newsk, req); } return newsk; } diff --git a/trunk/net/ipv4/inet_hashtables.c b/trunk/net/ipv4/inet_hashtables.c index fb296c9a7f3f..95fac5532994 100644 --- a/trunk/net/ipv4/inet_hashtables.c +++ b/trunk/net/ipv4/inet_hashtables.c @@ -124,10 +124,8 @@ EXPORT_SYMBOL(inet_listen_wlock); * remote address for the connection. So always assume those are both * wildcarded during the search since they can never be otherwise. */ -static struct sock *inet_lookup_listener_slow(const struct hlist_head *head, - const u32 daddr, - const unsigned short hnum, - const int dif) +struct sock *__inet_lookup_listener(const struct hlist_head *head, const u32 daddr, + const unsigned short hnum, const int dif) { struct sock *result = NULL, *sk; const struct hlist_node *node; @@ -161,33 +159,6 @@ static struct sock *inet_lookup_listener_slow(const struct hlist_head *head, return result; } -/* Optimize the common listener case. */ -struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo, - const u32 daddr, const unsigned short hnum, - const int dif) -{ - struct sock *sk = NULL; - const struct hlist_head *head; - - read_lock(&hashinfo->lhash_lock); - head = &hashinfo->listening_hash[inet_lhashfn(hnum)]; - if (!hlist_empty(head)) { - const struct inet_sock *inet = inet_sk((sk = __sk_head(head))); - - if (inet->num == hnum && !sk->sk_node.next && - (!inet->rcv_saddr || inet->rcv_saddr == daddr) && - (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) && - !sk->sk_bound_dev_if) - goto sherry_cache; - sk = inet_lookup_listener_slow(head, daddr, hnum, dif); - } - if (sk) { -sherry_cache: - sock_hold(sk); - } - read_unlock(&hashinfo->lhash_lock); - return sk; -} EXPORT_SYMBOL_GPL(__inet_lookup_listener); /* called with local bh disabled */ diff --git a/trunk/net/ipv4/inetpeer.c b/trunk/net/ipv4/inetpeer.c index a675602ef295..03ff62ebcfeb 100644 --- a/trunk/net/ipv4/inetpeer.c +++ b/trunk/net/ipv4/inetpeer.c @@ -126,9 +126,12 @@ void __init inet_initpeers(void) peer_cachep = kmem_cache_create("inet_peer_cache", sizeof(struct inet_peer), - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + if (!peer_cachep) + panic("cannot create inet_peer_cache"); + /* All the timers, started at system startup tend to synchronize. Perturb it a bit. */ diff --git a/trunk/net/ipv4/ip_fragment.c b/trunk/net/ipv4/ip_fragment.c index 165d72859ddf..b84b53a47526 100644 --- a/trunk/net/ipv4/ip_fragment.c +++ b/trunk/net/ipv4/ip_fragment.c @@ -54,15 +54,15 @@ * even the most extreme cases without allowing an attacker to measurably * harm machine performance. */ -int sysctl_ipfrag_high_thresh __read_mostly = 256*1024; -int sysctl_ipfrag_low_thresh __read_mostly = 192*1024; +int sysctl_ipfrag_high_thresh = 256*1024; +int sysctl_ipfrag_low_thresh = 192*1024; -int sysctl_ipfrag_max_dist __read_mostly = 64; +int sysctl_ipfrag_max_dist = 64; /* Important NOTE! Fragment queue must be destroyed before MSL expires. * RFC791 is wrong proposing to prolongate timer each fragment arrival by TTL. */ -int sysctl_ipfrag_time __read_mostly = IP_FRAG_TIME; +int sysctl_ipfrag_time = IP_FRAG_TIME; struct ipfrag_skb_cb { @@ -130,7 +130,7 @@ static unsigned int ipqhashfn(u16 id, u32 saddr, u32 daddr, u8 prot) } static struct timer_list ipfrag_secret_timer; -int sysctl_ipfrag_secret_interval __read_mostly = 10 * 60 * HZ; +int sysctl_ipfrag_secret_interval = 10 * 60 * HZ; static void ipfrag_secret_rebuild(unsigned long dummy) { @@ -665,7 +665,7 @@ static struct sk_buff *ip_frag_reasm(struct ipq *qp, struct net_device *dev) head->len += fp->len; if (head->ip_summed != fp->ip_summed) head->ip_summed = CHECKSUM_NONE; - else if (head->ip_summed == CHECKSUM_COMPLETE) + else if (head->ip_summed == CHECKSUM_HW) head->csum = csum_add(head->csum, fp->csum); head->truesize += fp->truesize; atomic_sub(fp->truesize, &ip_frag_mem); diff --git a/trunk/net/ipv4/ip_gre.c b/trunk/net/ipv4/ip_gre.c index f5fba051df3d..0f9b3a31997b 100644 --- a/trunk/net/ipv4/ip_gre.c +++ b/trunk/net/ipv4/ip_gre.c @@ -393,8 +393,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) int code = skb->h.icmph->code; int rel_type = 0; int rel_code = 0; - __be32 rel_info = 0; - __u32 n = 0; + int rel_info = 0; u16 flags; int grehlen = (iph->ihl<<2) + 4; struct sk_buff *skb2; @@ -423,16 +422,14 @@ static void ipgre_err(struct sk_buff *skb, u32 info) default: return; case ICMP_PARAMETERPROB: - n = ntohl(skb->h.icmph->un.gateway) >> 24; - if (n < (iph->ihl<<2)) + if (skb->h.icmph->un.gateway < (iph->ihl<<2)) return; /* So... This guy found something strange INSIDE encapsulated packet. Well, he is fool, but what can we do ? */ rel_type = ICMP_PARAMETERPROB; - n -= grehlen; - rel_info = htonl(n << 24); + rel_info = skb->h.icmph->un.gateway - grehlen; break; case ICMP_DEST_UNREACH: @@ -443,14 +440,13 @@ static void ipgre_err(struct sk_buff *skb, u32 info) return; case ICMP_FRAG_NEEDED: /* And it is the only really necessary thing :-) */ - n = ntohs(skb->h.icmph->un.frag.mtu); - if (n < grehlen+68) + rel_info = ntohs(skb->h.icmph->un.frag.mtu); + if (rel_info < grehlen+68) return; - n -= grehlen; + rel_info -= grehlen; /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ - if (n > ntohs(eiph->tot_len)) + if (rel_info > ntohs(eiph->tot_len)) return; - rel_info = htonl(n); break; default: /* All others are translated to HOST_UNREACH. @@ -512,11 +508,12 @@ static void ipgre_err(struct sk_buff *skb, u32 info) /* change mtu on this route */ if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { - if (n > dst_mtu(skb2->dst)) { + if (rel_info > dst_mtu(skb2->dst)) { kfree_skb(skb2); return; } - skb2->dst->ops->update_pmtu(skb2->dst, n); + skb2->dst->ops->update_pmtu(skb2->dst, rel_info); + rel_info = htonl(rel_info); } else if (type == ICMP_TIME_EXCEEDED) { struct ip_tunnel *t = netdev_priv(skb2->dev); if (t->parms.iph.ttl) { @@ -579,7 +576,7 @@ static int ipgre_rcv(struct sk_buff *skb) if (flags&GRE_CSUM) { switch (skb->ip_summed) { - case CHECKSUM_COMPLETE: + case CHECKSUM_HW: csum = (u16)csum_fold(skb->csum); if (!csum) break; @@ -587,7 +584,7 @@ static int ipgre_rcv(struct sk_buff *skb) case CHECKSUM_NONE: skb->csum = 0; csum = __skb_checksum_complete(skb); - skb->ip_summed = CHECKSUM_COMPLETE; + skb->ip_summed = CHECKSUM_HW; } offset += 4; } diff --git a/trunk/net/ipv4/ip_options.c b/trunk/net/ipv4/ip_options.c index e7437c091326..406056edc02b 100644 --- a/trunk/net/ipv4/ip_options.c +++ b/trunk/net/ipv4/ip_options.c @@ -24,7 +24,6 @@ #include #include #include -#include /* * Write options to IP header, record destination address to @@ -195,13 +194,6 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) dopt->is_strictroute = sopt->is_strictroute; } } - if (sopt->cipso) { - optlen = sptr[sopt->cipso+1]; - dopt->cipso = dopt->optlen+sizeof(struct iphdr); - memcpy(dptr, sptr+sopt->cipso, optlen); - dptr += optlen; - dopt->optlen += optlen; - } while (dopt->optlen & 3) { *dptr++ = IPOPT_END; dopt->optlen++; @@ -442,17 +434,6 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb) if (optptr[2] == 0 && optptr[3] == 0) opt->router_alert = optptr - iph; break; - case IPOPT_CIPSO: - if (opt->cipso) { - pp_ptr = optptr; - goto error; - } - opt->cipso = optptr - iph; - if (cipso_v4_validate(&optptr)) { - pp_ptr = optptr; - goto error; - } - break; case IPOPT_SEC: case IPOPT_SID: default: @@ -525,6 +506,7 @@ static int ip_options_get_finish(struct ip_options **optp, opt->__data[optlen++] = IPOPT_END; opt->optlen = optlen; opt->is_data = 1; + opt->is_setbyuser = 1; if (optlen && ip_options_compile(opt, NULL)) { kfree(opt); return -EINVAL; diff --git a/trunk/net/ipv4/ip_output.c b/trunk/net/ipv4/ip_output.c index 97aee76fb746..7c9f9a6421b8 100644 --- a/trunk/net/ipv4/ip_output.c +++ b/trunk/net/ipv4/ip_output.c @@ -83,7 +83,7 @@ #include #include -int sysctl_ip_default_ttl __read_mostly = IPDEFTTL; +int sysctl_ip_default_ttl = IPDEFTTL; /* Generate a checksum for an outgoing IP datagram. */ __inline__ void ip_send_check(struct iphdr *iph) @@ -328,7 +328,6 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok) * keep trying until route appears or the connection times * itself out. */ - security_sk_classify_flow(sk, &fl); if (ip_route_output_flow(&rt, &fl, sk, 0)) goto no_route; } @@ -426,7 +425,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) int ptr; struct net_device *dev; struct sk_buff *skb2; - unsigned int mtu, hlen, left, len, ll_rs, pad; + unsigned int mtu, hlen, left, len, ll_rs; int offset; __be16 not_last_frag; struct rtable *rt = (struct rtable*)skb->dst; @@ -441,7 +440,6 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) iph = skb->nh.iph; if (unlikely((iph->frag_off & htons(IP_DF)) && !skb->local_df)) { - IP_INC_STATS(IPSTATS_MIB_FRAGFAILS); icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(dst_mtu(&rt->u.dst))); kfree_skb(skb); @@ -528,8 +526,6 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) err = output(skb); - if (!err) - IP_INC_STATS(IPSTATS_MIB_FRAGCREATES); if (err || !frag) break; @@ -556,13 +552,14 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) left = skb->len - hlen; /* Space per frame */ ptr = raw + hlen; /* Where to start from */ +#ifdef CONFIG_BRIDGE_NETFILTER /* for bridged IP traffic encapsulated inside f.e. a vlan header, - * we need to make room for the encapsulating header - */ - pad = nf_bridge_pad(skb); - ll_rs = LL_RESERVED_SPACE_EXTRA(rt->u.dst.dev, pad); - mtu -= pad; - + * we need to make room for the encapsulating header */ + ll_rs = LL_RESERVED_SPACE_EXTRA(rt->u.dst.dev, nf_bridge_pad(skb)); + mtu -= nf_bridge_pad(skb); +#else + ll_rs = LL_RESERVED_SPACE(rt->u.dst.dev); +#endif /* * Fragment the datagram. */ @@ -652,6 +649,9 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) /* * Put this fragment into the sending queue. */ + + IP_INC_STATS(IPSTATS_MIB_FRAGCREATES); + iph->tot_len = htons(len + hlen); ip_send_check(iph); @@ -659,8 +659,6 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*)) err = output(skb2); if (err) goto fail; - - IP_INC_STATS(IPSTATS_MIB_FRAGCREATES); } kfree_skb(skb); IP_INC_STATS(IPSTATS_MIB_FRAGOKS); @@ -679,7 +677,7 @@ ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk { struct iovec *iov = from; - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { if (memcpy_fromiovecend(to, iov, offset, len) < 0) return -EFAULT; } else { @@ -735,7 +733,7 @@ static inline int ip_ufo_append_data(struct sock *sk, /* initialize protocol header pointer */ skb->h.raw = skb->data + fragheaderlen; - skb->ip_summed = CHECKSUM_PARTIAL; + skb->ip_summed = CHECKSUM_HW; skb->csum = 0; sk->sk_sndmsg_off = 0; } @@ -843,7 +841,7 @@ int ip_append_data(struct sock *sk, length + fragheaderlen <= mtu && rt->u.dst.dev->features & NETIF_F_ALL_CSUM && !exthdrlen) - csummode = CHECKSUM_PARTIAL; + csummode = CHECKSUM_HW; inet->cork.length += length; if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && @@ -948,7 +946,7 @@ int ip_append_data(struct sock *sk, skb_prev->csum = csum_sub(skb_prev->csum, skb->csum); data += fraggap; - pskb_trim_unique(skb_prev, maxfraglen); + skb_trim(skb_prev, maxfraglen); } copy = datalen - transhdrlen - fraggap; @@ -1143,7 +1141,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, data, fraggap, 0); skb_prev->csum = csum_sub(skb_prev->csum, skb->csum); - pskb_trim_unique(skb_prev, maxfraglen); + skb_trim(skb_prev, maxfraglen); } /* @@ -1366,7 +1364,6 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar { .sport = skb->h.th->dest, .dport = skb->h.th->source } }, .proto = sk->sk_protocol }; - security_skb_classify_flow(skb, &fl); if (ip_route_output_key(&rt, &fl)) return; } diff --git a/trunk/net/ipv4/ip_sockglue.c b/trunk/net/ipv4/ip_sockglue.c index 2d05c4133d3e..84f43a3c9098 100644 --- a/trunk/net/ipv4/ip_sockglue.c +++ b/trunk/net/ipv4/ip_sockglue.c @@ -112,19 +112,14 @@ static void ip_cmsg_recv_retopts(struct msghdr *msg, struct sk_buff *skb) static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb) { char *secdata; - u32 seclen, secid; + u32 seclen; int err; - err = security_socket_getpeersec_dgram(NULL, skb, &secid); - if (err) - return; - - err = security_secid_to_secctx(secid, &secdata, &seclen); + err = security_socket_getpeersec_dgram(skb, &secdata, &seclen); if (err) return; put_cmsg(msg, SOL_IP, SCM_SECURITY, seclen, secdata); - security_release_secctx(secdata, seclen); } diff --git a/trunk/net/ipv4/ipcomp.c b/trunk/net/ipv4/ipcomp.c index 17342430a843..a0c28b2b756e 100644 --- a/trunk/net/ipv4/ipcomp.c +++ b/trunk/net/ipv4/ipcomp.c @@ -32,7 +32,7 @@ struct ipcomp_tfms { struct list_head list; - struct crypto_comp **tfms; + struct crypto_tfm **tfms; int users; }; @@ -46,7 +46,7 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb) int err, plen, dlen; struct ipcomp_data *ipcd = x->data; u8 *start, *scratch; - struct crypto_comp *tfm; + struct crypto_tfm *tfm; int cpu; plen = skb->len; @@ -107,7 +107,7 @@ static int ipcomp_compress(struct xfrm_state *x, struct sk_buff *skb) struct iphdr *iph = skb->nh.iph; struct ipcomp_data *ipcd = x->data; u8 *start, *scratch; - struct crypto_comp *tfm; + struct crypto_tfm *tfm; int cpu; ihlen = iph->ihl * 4; @@ -176,7 +176,7 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb) return 0; out_ok: - if (x->props.mode == XFRM_MODE_TUNNEL) + if (x->props.mode) ip_send_check(iph); return 0; } @@ -216,7 +216,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x) t->id.daddr.a4 = x->id.daddr.a4; memcpy(&t->sel, &x->sel, sizeof(t->sel)); t->props.family = AF_INET; - t->props.mode = XFRM_MODE_TUNNEL; + t->props.mode = 1; t->props.saddr.a4 = x->props.saddr.a4; t->props.flags = x->props.flags; @@ -302,7 +302,7 @@ static void **ipcomp_alloc_scratches(void) return scratches; } -static void ipcomp_free_tfms(struct crypto_comp **tfms) +static void ipcomp_free_tfms(struct crypto_tfm **tfms) { struct ipcomp_tfms *pos; int cpu; @@ -324,28 +324,28 @@ static void ipcomp_free_tfms(struct crypto_comp **tfms) return; for_each_possible_cpu(cpu) { - struct crypto_comp *tfm = *per_cpu_ptr(tfms, cpu); - crypto_free_comp(tfm); + struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu); + crypto_free_tfm(tfm); } free_percpu(tfms); } -static struct crypto_comp **ipcomp_alloc_tfms(const char *alg_name) +static struct crypto_tfm **ipcomp_alloc_tfms(const char *alg_name) { struct ipcomp_tfms *pos; - struct crypto_comp **tfms; + struct crypto_tfm **tfms; int cpu; /* This can be any valid CPU ID so we don't need locking. */ cpu = raw_smp_processor_id(); list_for_each_entry(pos, &ipcomp_tfms_list, list) { - struct crypto_comp *tfm; + struct crypto_tfm *tfm; tfms = pos->tfms; tfm = *per_cpu_ptr(tfms, cpu); - if (!strcmp(crypto_comp_name(tfm), alg_name)) { + if (!strcmp(crypto_tfm_alg_name(tfm), alg_name)) { pos->users++; return tfms; } @@ -359,13 +359,12 @@ static struct crypto_comp **ipcomp_alloc_tfms(const char *alg_name) INIT_LIST_HEAD(&pos->list); list_add(&pos->list, &ipcomp_tfms_list); - pos->tfms = tfms = alloc_percpu(struct crypto_comp *); + pos->tfms = tfms = alloc_percpu(struct crypto_tfm *); if (!tfms) goto error; for_each_possible_cpu(cpu) { - struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0, - CRYPTO_ALG_ASYNC); + struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0); if (!tfm) goto error; *per_cpu_ptr(tfms, cpu) = tfm; @@ -416,7 +415,7 @@ static int ipcomp_init_state(struct xfrm_state *x) goto out; x->props.header_len = 0; - if (x->props.mode == XFRM_MODE_TUNNEL) + if (x->props.mode) x->props.header_len += sizeof(struct iphdr); mutex_lock(&ipcomp_resource_mutex); @@ -428,7 +427,7 @@ static int ipcomp_init_state(struct xfrm_state *x) goto error; mutex_unlock(&ipcomp_resource_mutex); - if (x->props.mode == XFRM_MODE_TUNNEL) { + if (x->props.mode) { err = ipcomp_tunnel_attach(x); if (err) goto error_tunnel; diff --git a/trunk/net/ipv4/ipconfig.c b/trunk/net/ipv4/ipconfig.c index 1fbb38415b19..cb8a92f18ef6 100644 --- a/trunk/net/ipv4/ipconfig.c +++ b/trunk/net/ipv4/ipconfig.c @@ -31,6 +31,7 @@ * -- Josef Siemes , Aug 2002 */ +#include #include #include #include diff --git a/trunk/net/ipv4/ipip.c b/trunk/net/ipv4/ipip.c index 0c4556529228..76ab50b0d6ef 100644 --- a/trunk/net/ipv4/ipip.c +++ b/trunk/net/ipv4/ipip.c @@ -341,8 +341,7 @@ static int ipip_err(struct sk_buff *skb, u32 info) int code = skb->h.icmph->code; int rel_type = 0; int rel_code = 0; - __be32 rel_info = 0; - __u32 n = 0; + int rel_info = 0; struct sk_buff *skb2; struct flowi fl; struct rtable *rt; @@ -355,15 +354,14 @@ static int ipip_err(struct sk_buff *skb, u32 info) default: return 0; case ICMP_PARAMETERPROB: - n = ntohl(skb->h.icmph->un.gateway) >> 24; - if (n < hlen) + if (skb->h.icmph->un.gateway < hlen) return 0; /* So... This guy found something strange INSIDE encapsulated packet. Well, he is fool, but what can we do ? */ rel_type = ICMP_PARAMETERPROB; - rel_info = htonl((n - hlen) << 24); + rel_info = skb->h.icmph->un.gateway - hlen; break; case ICMP_DEST_UNREACH: @@ -374,14 +372,13 @@ static int ipip_err(struct sk_buff *skb, u32 info) return 0; case ICMP_FRAG_NEEDED: /* And it is the only really necessary thing :-) */ - n = ntohs(skb->h.icmph->un.frag.mtu); - if (n < hlen+68) + rel_info = ntohs(skb->h.icmph->un.frag.mtu); + if (rel_info < hlen+68) return 0; - n -= hlen; + rel_info -= hlen; /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ - if (n > ntohs(eiph->tot_len)) + if (rel_info > ntohs(eiph->tot_len)) return 0; - rel_info = htonl(n); break; default: /* All others are translated to HOST_UNREACH. @@ -443,11 +440,12 @@ static int ipip_err(struct sk_buff *skb, u32 info) /* change mtu on this route */ if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { - if (n > dst_mtu(skb2->dst)) { + if (rel_info > dst_mtu(skb2->dst)) { kfree_skb(skb2); return 0; } - skb2->dst->ops->update_pmtu(skb2->dst, n); + skb2->dst->ops->update_pmtu(skb2->dst, rel_info); + rel_info = htonl(rel_info); } else if (type == ICMP_TIME_EXCEEDED) { struct ip_tunnel *t = netdev_priv(skb2->dev); if (t->parms.iph.ttl) { diff --git a/trunk/net/ipv4/ipmr.c b/trunk/net/ipv4/ipmr.c index ba49588da242..85893eef6b16 100644 --- a/trunk/net/ipv4/ipmr.c +++ b/trunk/net/ipv4/ipmr.c @@ -312,8 +312,7 @@ static void ipmr_destroy_unres(struct mfc_cache *c) e = NLMSG_DATA(nlh); e->error = -ETIMEDOUT; memset(&e->msg, 0, sizeof(e->msg)); - - rtnl_unicast(skb, NETLINK_CB(skb).pid); + netlink_unicast(rtnl, skb, NETLINK_CB(skb).dst_pid, MSG_DONTWAIT); } else kfree_skb(skb); } @@ -513,6 +512,7 @@ static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c) while((skb=__skb_dequeue(&uc->mfc_un.unres.unresolved))) { if (skb->nh.iph->version == 0) { + int err; struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct iphdr)); if (ipmr_fill_mroute(skb, c, NLMSG_DATA(nlh)) > 0) { @@ -525,8 +525,7 @@ static void ipmr_cache_resolve(struct mfc_cache *uc, struct mfc_cache *c) e->error = -EMSGSIZE; memset(&e->msg, 0, sizeof(e->msg)); } - - rtnl_unicast(skb, NETLINK_CB(skb).pid); + err = netlink_unicast(rtnl, skb, NETLINK_CB(skb).dst_pid, MSG_DONTWAIT); } else ip_mr_forward(skb, c, 0); } @@ -1900,8 +1899,11 @@ void __init ip_mr_init(void) { mrt_cachep = kmem_cache_create("ip_mrt_cache", sizeof(struct mfc_cache), - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + if (!mrt_cachep) + panic("cannot allocate ip_mrt_cache"); + init_timer(&ipmr_expire_timer); ipmr_expire_timer.function=ipmr_expire_process; register_netdevice_notifier(&ip_mr_notifier); diff --git a/trunk/net/ipv4/ipvs/ip_vs_ftp.c b/trunk/net/ipv4/ipvs/ip_vs_ftp.c index 37fafb1fbcff..a19a33ceb811 100644 --- a/trunk/net/ipv4/ipvs/ip_vs_ftp.c +++ b/trunk/net/ipv4/ipvs/ip_vs_ftp.c @@ -46,7 +46,14 @@ */ static int ports[IP_VS_APP_MAX_PORTS] = {21, 0}; module_param_array(ports, int, NULL, 0); -MODULE_PARM_DESC(ports, "Ports to monitor for FTP control commands"); + +/* + * Debug level + */ +#ifdef CONFIG_IP_VS_DEBUG +static int debug=0; +module_param(debug, int, 0); +#endif /* Dummy variable */ @@ -170,7 +177,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, &start, &end) != 1) return 1; - IP_VS_DBG(7, "PASV response (%u.%u.%u.%u:%d) -> " + IP_VS_DBG(1-debug, "PASV response (%u.%u.%u.%u:%d) -> " "%u.%u.%u.%u:%d detected\n", NIPQUAD(from), ntohs(port), NIPQUAD(cp->caddr), 0); @@ -273,7 +280,7 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, while (data <= data_limit - 6) { if (strnicmp(data, "PASV\r\n", 6) == 0) { /* Passive mode on */ - IP_VS_DBG(7, "got PASV at %zd of %zd\n", + IP_VS_DBG(1-debug, "got PASV at %zd of %zd\n", data - data_start, data_limit - data_start); cp->app_data = &ip_vs_ftp_pasv; @@ -295,7 +302,7 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, &start, &end) != 1) return 1; - IP_VS_DBG(7, "PORT %u.%u.%u.%u:%d detected\n", + IP_VS_DBG(1-debug, "PORT %u.%u.%u.%u:%d detected\n", NIPQUAD(to), ntohs(port)); /* Passive mode off */ @@ -304,7 +311,7 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp, /* * Now update or create a connection entry for it */ - IP_VS_DBG(7, "protocol %s %u.%u.%u.%u:%d %u.%u.%u.%u:%d\n", + IP_VS_DBG(1-debug, "protocol %s %u.%u.%u.%u:%d %u.%u.%u.%u:%d\n", ip_vs_proto_name(iph->protocol), NIPQUAD(to), ntohs(port), NIPQUAD(cp->vaddr), 0); @@ -365,17 +372,11 @@ static int __init ip_vs_ftp_init(void) for (i=0; i 0xffff) { - IP_VS_WARNING("ip_vs_ftp: Ignoring invalid " - "configuration port[%d] = %d\n", - i, ports[i]); - continue; - } ret = register_ip_vs_app_inc(app, app->protocol, ports[i]); if (ret) break; - IP_VS_INFO("%s: loaded support on port[%d] = %d\n", - app->name, i, ports[i]); + IP_VS_DBG(1-debug, "%s: loaded support on port[%d] = %d\n", + app->name, i, ports[i]); } if (ret) diff --git a/trunk/net/ipv4/ipvs/ip_vs_proto_tcp.c b/trunk/net/ipv4/ipvs/ip_vs_proto_tcp.c index 820e8318d10d..bc28b1160a3a 100644 --- a/trunk/net/ipv4/ipvs/ip_vs_proto_tcp.c +++ b/trunk/net/ipv4/ipvs/ip_vs_proto_tcp.c @@ -151,7 +151,7 @@ tcp_snat_handler(struct sk_buff **pskb, /* Only port and addr are changed, do fast csum update */ tcp_fast_csum_update(tcph, cp->daddr, cp->vaddr, cp->dport, cp->vport); - if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) + if ((*pskb)->ip_summed == CHECKSUM_HW) (*pskb)->ip_summed = CHECKSUM_NONE; } else { /* full checksum calculation */ @@ -204,7 +204,7 @@ tcp_dnat_handler(struct sk_buff **pskb, /* Only port and addr are changed, do fast csum update */ tcp_fast_csum_update(tcph, cp->vaddr, cp->daddr, cp->vport, cp->dport); - if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) + if ((*pskb)->ip_summed == CHECKSUM_HW) (*pskb)->ip_summed = CHECKSUM_NONE; } else { /* full checksum calculation */ @@ -229,7 +229,7 @@ tcp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) switch (skb->ip_summed) { case CHECKSUM_NONE: skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0); - case CHECKSUM_COMPLETE: + case CHECKSUM_HW: if (csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr, skb->len - tcphoff, skb->nh.iph->protocol, skb->csum)) { @@ -239,7 +239,7 @@ tcp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) } break; default: - /* No need to checksum. */ + /* CHECKSUM_UNNECESSARY */ break; } diff --git a/trunk/net/ipv4/ipvs/ip_vs_proto_udp.c b/trunk/net/ipv4/ipvs/ip_vs_proto_udp.c index 90c8166c0ec1..89d9175d8f28 100644 --- a/trunk/net/ipv4/ipvs/ip_vs_proto_udp.c +++ b/trunk/net/ipv4/ipvs/ip_vs_proto_udp.c @@ -161,7 +161,7 @@ udp_snat_handler(struct sk_buff **pskb, /* Only port and addr are changed, do fast csum update */ udp_fast_csum_update(udph, cp->daddr, cp->vaddr, cp->dport, cp->vport); - if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) + if ((*pskb)->ip_summed == CHECKSUM_HW) (*pskb)->ip_summed = CHECKSUM_NONE; } else { /* full checksum calculation */ @@ -216,7 +216,7 @@ udp_dnat_handler(struct sk_buff **pskb, /* Only port and addr are changed, do fast csum update */ udp_fast_csum_update(udph, cp->vaddr, cp->daddr, cp->vport, cp->dport); - if ((*pskb)->ip_summed == CHECKSUM_COMPLETE) + if ((*pskb)->ip_summed == CHECKSUM_HW) (*pskb)->ip_summed = CHECKSUM_NONE; } else { /* full checksum calculation */ @@ -250,7 +250,7 @@ udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) case CHECKSUM_NONE: skb->csum = skb_checksum(skb, udphoff, skb->len - udphoff, 0); - case CHECKSUM_COMPLETE: + case CHECKSUM_HW: if (csum_tcpudp_magic(skb->nh.iph->saddr, skb->nh.iph->daddr, skb->len - udphoff, @@ -262,7 +262,7 @@ udp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp) } break; default: - /* No need to checksum. */ + /* CHECKSUM_UNNECESSARY */ break; } } diff --git a/trunk/net/ipv4/netfilter.c b/trunk/net/ipv4/netfilter.c index f88347de21a9..6a9e34b794bc 100644 --- a/trunk/net/ipv4/netfilter.c +++ b/trunk/net/ipv4/netfilter.c @@ -168,7 +168,7 @@ unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, unsigned int csum = 0; switch (skb->ip_summed) { - case CHECKSUM_COMPLETE: + case CHECKSUM_HW: if (hook != NF_IP_PRE_ROUTING && hook != NF_IP_LOCAL_IN) break; if ((protocol == 0 && !(u16)csum_fold(skb->csum)) || diff --git a/trunk/net/ipv4/netfilter/Kconfig b/trunk/net/ipv4/netfilter/Kconfig index a55b8ff70ded..ef0b5aac5838 100644 --- a/trunk/net/ipv4/netfilter/Kconfig +++ b/trunk/net/ipv4/netfilter/Kconfig @@ -278,6 +278,17 @@ config IP_NF_MATCH_ECN To compile it as a module, choose M here. If unsure, say N. +config IP_NF_MATCH_DSCP + tristate "DSCP match support" + depends on IP_NF_IPTABLES + help + This option adds a `DSCP' match, which allows you to match against + the IPv4 header DSCP field (DSCP codepoint). + + The DSCP codepoint can have any value between 0x0 and 0x4f. + + To compile it as a module, choose M here. If unsure, say N. + config IP_NF_MATCH_AH tristate "AH match support" depends on IP_NF_IPTABLES @@ -557,6 +568,17 @@ config IP_NF_TARGET_ECN To compile it as a module, choose M here. If unsure, say N. +config IP_NF_TARGET_DSCP + tristate "DSCP target support" + depends on IP_NF_MANGLE + help + This option adds a `DSCP' match, which allows you to match against + the IPv4 header DSCP field (DSCP codepoint). + + The DSCP codepoint can have any value between 0x0 and 0x4f. + + To compile it as a module, choose M here. If unsure, say N. + config IP_NF_TARGET_TTL tristate 'TTL target support' depends on IP_NF_MANGLE diff --git a/trunk/net/ipv4/netfilter/Makefile b/trunk/net/ipv4/netfilter/Makefile index 09aaed1a8063..3ded4a3af59c 100644 --- a/trunk/net/ipv4/netfilter/Makefile +++ b/trunk/net/ipv4/netfilter/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o +obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o @@ -67,6 +68,7 @@ obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o +obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o diff --git a/trunk/net/ipv4/netfilter/arp_tables.c b/trunk/net/ipv4/netfilter/arp_tables.c index 85f0d73ebfb4..80c73ca90116 100644 --- a/trunk/net/ipv4/netfilter/arp_tables.c +++ b/trunk/net/ipv4/netfilter/arp_tables.c @@ -56,6 +56,8 @@ do { \ #define ARP_NF_ASSERT(x) #endif +#include + static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, char *hdr_addr, int len) { @@ -206,7 +208,8 @@ static unsigned int arpt_error(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { if (net_ratelimit()) printk("arp_tables: error: '%s'\n", (char *)targinfo); @@ -223,7 +226,8 @@ unsigned int arpt_do_table(struct sk_buff **pskb, unsigned int hook, const struct net_device *in, const struct net_device *out, - struct arpt_table *table) + struct arpt_table *table, + void *userdata) { static const char nulldevname[IFNAMSIZ]; unsigned int verdict = NF_DROP; @@ -232,7 +236,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb, struct arpt_entry *e, *back; const char *indev, *outdev; void *table_base; - struct xt_table_info *private; + struct xt_table_info *private = table->private; /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + @@ -244,7 +248,6 @@ unsigned int arpt_do_table(struct sk_buff **pskb, outdev = out ? out->name : nulldevname; read_lock_bh(&table->lock); - private = table->private; table_base = (void *)private->entries[smp_processor_id()]; e = get_entry(table_base, private->hook_entry[hook]); back = get_entry(table_base, private->underflow[hook]); @@ -298,7 +301,8 @@ unsigned int arpt_do_table(struct sk_buff **pskb, in, out, hook, t->u.kernel.target, - t->data); + t->data, + userdata); /* Target might have changed stuff. */ arp = (*pskb)->nh.arph; @@ -485,10 +489,12 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i if (t->u.kernel.target == &arpt_standard_target) { if (!standard_check(t, size)) { ret = -EINVAL; - goto err; + goto out; } } else if (t->u.kernel.target->checkentry && !t->u.kernel.target->checkentry(name, e, target, t->data, + t->u.target_size + - sizeof(*t), e->comefrom)) { duprintf("arp_tables: check failed for `%s'.\n", t->u.kernel.target->name); @@ -555,7 +561,8 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) t = arpt_get_target(e); if (t->u.kernel.target->destroy) - t->u.kernel.target->destroy(t->u.kernel.target, t->data); + t->u.kernel.target->destroy(t->u.kernel.target, t->data, + t->u.target_size - sizeof(*t)); module_put(t->u.kernel.target->me); return 0; } @@ -1163,34 +1170,21 @@ static int __init arp_tables_init(void) { int ret; - ret = xt_proto_init(NF_ARP); - if (ret < 0) - goto err1; + xt_proto_init(NF_ARP); /* Noone else will be downing sem now, so we won't sleep */ - ret = xt_register_target(&arpt_standard_target); - if (ret < 0) - goto err2; - ret = xt_register_target(&arpt_error_target); - if (ret < 0) - goto err3; + xt_register_target(&arpt_standard_target); + xt_register_target(&arpt_error_target); /* Register setsockopt */ ret = nf_register_sockopt(&arpt_sockopts); - if (ret < 0) - goto err4; + if (ret < 0) { + duprintf("Unable to register sockopts.\n"); + return ret; + } printk("arp_tables: (C) 2002 David S. Miller\n"); return 0; - -err4: - xt_unregister_target(&arpt_error_target); -err3: - xt_unregister_target(&arpt_standard_target); -err2: - xt_proto_fini(NF_ARP); -err1: - return ret; } static void __exit arp_tables_fini(void) diff --git a/trunk/net/ipv4/netfilter/arpt_mangle.c b/trunk/net/ipv4/netfilter/arpt_mangle.c index d12b1df252a1..a58325c1ceb9 100644 --- a/trunk/net/ipv4/netfilter/arpt_mangle.c +++ b/trunk/net/ipv4/netfilter/arpt_mangle.c @@ -11,7 +11,7 @@ static unsigned int target(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, void *userinfo) { const struct arpt_mangle *mangle = targinfo; struct arphdr *arp; @@ -67,7 +67,7 @@ target(struct sk_buff **pskb, static int checkentry(const char *tablename, const void *e, const struct xt_target *target, - void *targinfo, unsigned int hook_mask) + void *targinfo, unsigned int targinfosize, unsigned int hook_mask) { const struct arpt_mangle *mangle = targinfo; diff --git a/trunk/net/ipv4/netfilter/arptable_filter.c b/trunk/net/ipv4/netfilter/arptable_filter.c index 7edea2a1696c..d7c472faa53b 100644 --- a/trunk/net/ipv4/netfilter/arptable_filter.c +++ b/trunk/net/ipv4/netfilter/arptable_filter.c @@ -155,7 +155,7 @@ static unsigned int arpt_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return arpt_do_table(pskb, hook, in, out, &packet_filter); + return arpt_do_table(pskb, hook, in, out, &packet_filter, NULL); } static struct nf_hook_ops arpt_ops[] = { diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_core.c b/trunk/net/ipv4/netfilter/ip_conntrack_core.c index c432b3163609..aa459177c3f8 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_core.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_core.c @@ -47,6 +47,7 @@ #include #include #include +#include #define IP_CONNTRACK_VERSION "2.4" @@ -63,17 +64,17 @@ atomic_t ip_conntrack_count = ATOMIC_INIT(0); void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack) = NULL; LIST_HEAD(ip_conntrack_expect_list); -struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO] __read_mostly; +struct ip_conntrack_protocol *ip_ct_protos[MAX_IP_CT_PROTO]; static LIST_HEAD(helpers); -unsigned int ip_conntrack_htable_size __read_mostly = 0; -int ip_conntrack_max __read_mostly; -struct list_head *ip_conntrack_hash __read_mostly; +unsigned int ip_conntrack_htable_size = 0; +int ip_conntrack_max; +struct list_head *ip_conntrack_hash; static kmem_cache_t *ip_conntrack_cachep __read_mostly; static kmem_cache_t *ip_conntrack_expect_cachep __read_mostly; struct ip_conntrack ip_conntrack_untracked; -unsigned int ip_ct_log_invalid __read_mostly; +unsigned int ip_ct_log_invalid; static LIST_HEAD(unconfirmed); -static int ip_conntrack_vmalloc __read_mostly; +static int ip_conntrack_vmalloc; static unsigned int ip_conntrack_next_id; static unsigned int ip_conntrack_expect_next_id; @@ -293,10 +294,15 @@ void ip_ct_remove_expectations(struct ip_conntrack *ct) static void clean_from_lists(struct ip_conntrack *ct) { + unsigned int ho, hr; + DEBUGP("clean_from_lists(%p)\n", ct); ASSERT_WRITE_LOCK(&ip_conntrack_lock); - list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); - list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list); + + ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); + LIST_DELETE(&ip_conntrack_hash[ho], &ct->tuplehash[IP_CT_DIR_ORIGINAL]); + LIST_DELETE(&ip_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]); /* Destroy all pending expectations */ ip_ct_remove_expectations(ct); @@ -307,7 +313,6 @@ destroy_conntrack(struct nf_conntrack *nfct) { struct ip_conntrack *ct = (struct ip_conntrack *)nfct; struct ip_conntrack_protocol *proto; - struct ip_conntrack_helper *helper; DEBUGP("destroy_conntrack(%p)\n", ct); IP_NF_ASSERT(atomic_read(&nfct->use) == 0); @@ -316,10 +321,6 @@ destroy_conntrack(struct nf_conntrack *nfct) ip_conntrack_event(IPCT_DESTROY, ct); set_bit(IPS_DYING_BIT, &ct->status); - helper = ct->helper; - if (helper && helper->destroy) - helper->destroy(ct); - /* To make sure we don't get any weird locking issues here: * destroy_conntrack() MUST NOT be called with a write lock * to ip_conntrack_lock!!! -HW */ @@ -366,6 +367,16 @@ static void death_by_timeout(unsigned long ul_conntrack) ip_conntrack_put(ct); } +static inline int +conntrack_tuple_cmp(const struct ip_conntrack_tuple_hash *i, + const struct ip_conntrack_tuple *tuple, + const struct ip_conntrack *ignored_conntrack) +{ + ASSERT_READ_LOCK(&ip_conntrack_lock); + return tuplehash_to_ctrack(i) != ignored_conntrack + && ip_ct_tuple_equal(tuple, &i->tuple); +} + struct ip_conntrack_tuple_hash * __ip_conntrack_find(const struct ip_conntrack_tuple *tuple, const struct ip_conntrack *ignored_conntrack) @@ -375,8 +386,7 @@ __ip_conntrack_find(const struct ip_conntrack_tuple *tuple, ASSERT_READ_LOCK(&ip_conntrack_lock); list_for_each_entry(h, &ip_conntrack_hash[hash], list) { - if (tuplehash_to_ctrack(h) != ignored_conntrack && - ip_ct_tuple_equal(tuple, &h->tuple)) { + if (conntrack_tuple_cmp(h, tuple, ignored_conntrack)) { CONNTRACK_STAT_INC(found); return h; } @@ -407,10 +417,10 @@ static void __ip_conntrack_hash_insert(struct ip_conntrack *ct, unsigned int repl_hash) { ct->id = ++ip_conntrack_next_id; - list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list, - &ip_conntrack_hash[hash]); - list_add(&ct->tuplehash[IP_CT_DIR_REPLY].list, - &ip_conntrack_hash[repl_hash]); + list_prepend(&ip_conntrack_hash[hash], + &ct->tuplehash[IP_CT_DIR_ORIGINAL].list); + list_prepend(&ip_conntrack_hash[repl_hash], + &ct->tuplehash[IP_CT_DIR_REPLY].list); } void ip_conntrack_hash_insert(struct ip_conntrack *ct) @@ -430,7 +440,6 @@ int __ip_conntrack_confirm(struct sk_buff **pskb) { unsigned int hash, repl_hash; - struct ip_conntrack_tuple_hash *h; struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; @@ -461,43 +470,43 @@ __ip_conntrack_confirm(struct sk_buff **pskb) /* See if there's one in the list already, including reverse: NAT could have grabbed it without realizing, since we're not in the hash. If there is, we lost race. */ - list_for_each_entry(h, &ip_conntrack_hash[hash], list) - if (ip_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, - &h->tuple)) - goto out; - list_for_each_entry(h, &ip_conntrack_hash[repl_hash], list) - if (ip_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, - &h->tuple)) - goto out; - - /* Remove from unconfirmed list */ - list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); + if (!LIST_FIND(&ip_conntrack_hash[hash], + conntrack_tuple_cmp, + struct ip_conntrack_tuple_hash *, + &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, NULL) + && !LIST_FIND(&ip_conntrack_hash[repl_hash], + conntrack_tuple_cmp, + struct ip_conntrack_tuple_hash *, + &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) { + /* Remove from unconfirmed list */ + list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); - __ip_conntrack_hash_insert(ct, hash, repl_hash); - /* Timer relative to confirmation time, not original - setting time, otherwise we'd get timer wrap in - weird delay cases. */ - ct->timeout.expires += jiffies; - add_timer(&ct->timeout); - atomic_inc(&ct->ct_general.use); - set_bit(IPS_CONFIRMED_BIT, &ct->status); - CONNTRACK_STAT_INC(insert); - write_unlock_bh(&ip_conntrack_lock); - if (ct->helper) - ip_conntrack_event_cache(IPCT_HELPER, *pskb); + __ip_conntrack_hash_insert(ct, hash, repl_hash); + /* Timer relative to confirmation time, not original + setting time, otherwise we'd get timer wrap in + weird delay cases. */ + ct->timeout.expires += jiffies; + add_timer(&ct->timeout); + atomic_inc(&ct->ct_general.use); + set_bit(IPS_CONFIRMED_BIT, &ct->status); + CONNTRACK_STAT_INC(insert); + write_unlock_bh(&ip_conntrack_lock); + if (ct->helper) + ip_conntrack_event_cache(IPCT_HELPER, *pskb); #ifdef CONFIG_IP_NF_NAT_NEEDED - if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || - test_bit(IPS_DST_NAT_DONE_BIT, &ct->status)) - ip_conntrack_event_cache(IPCT_NATINFO, *pskb); + if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || + test_bit(IPS_DST_NAT_DONE_BIT, &ct->status)) + ip_conntrack_event_cache(IPCT_NATINFO, *pskb); #endif - ip_conntrack_event_cache(master_ct(ct) ? - IPCT_RELATED : IPCT_NEW, *pskb); + ip_conntrack_event_cache(master_ct(ct) ? + IPCT_RELATED : IPCT_NEW, *pskb); - return NF_ACCEPT; + return NF_ACCEPT; + } -out: CONNTRACK_STAT_INC(insert_failed); write_unlock_bh(&ip_conntrack_lock); + return NF_DROP; } @@ -518,21 +527,23 @@ ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple, /* There's a small race here where we may free a just-assured connection. Too bad: we're in trouble anyway. */ +static inline int unreplied(const struct ip_conntrack_tuple_hash *i) +{ + return !(test_bit(IPS_ASSURED_BIT, &tuplehash_to_ctrack(i)->status)); +} + static int early_drop(struct list_head *chain) { /* Traverse backwards: gives us oldest, which is roughly LRU */ struct ip_conntrack_tuple_hash *h; - struct ip_conntrack *ct = NULL, *tmp; + struct ip_conntrack *ct = NULL; int dropped = 0; read_lock_bh(&ip_conntrack_lock); - list_for_each_entry_reverse(h, chain, list) { - tmp = tuplehash_to_ctrack(h); - if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) { - ct = tmp; - atomic_inc(&ct->ct_general.use); - break; - } + h = LIST_FIND_B(chain, unreplied, struct ip_conntrack_tuple_hash *); + if (h) { + ct = tuplehash_to_ctrack(h); + atomic_inc(&ct->ct_general.use); } read_unlock_bh(&ip_conntrack_lock); @@ -548,16 +559,18 @@ static int early_drop(struct list_head *chain) return dropped; } +static inline int helper_cmp(const struct ip_conntrack_helper *i, + const struct ip_conntrack_tuple *rtuple) +{ + return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask); +} + static struct ip_conntrack_helper * __ip_conntrack_helper_find( const struct ip_conntrack_tuple *tuple) { - struct ip_conntrack_helper *h; - - list_for_each_entry(h, &helpers, list) { - if (ip_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask)) - return h; - } - return NULL; + return LIST_FIND(&helpers, helper_cmp, + struct ip_conntrack_helper *, + tuple); } struct ip_conntrack_helper * @@ -627,15 +640,11 @@ struct ip_conntrack *ip_conntrack_alloc(struct ip_conntrack_tuple *orig, ip_conntrack_hash_rnd_initted = 1; } - /* We don't want any race condition at early drop stage */ - atomic_inc(&ip_conntrack_count); - if (ip_conntrack_max - && atomic_read(&ip_conntrack_count) > ip_conntrack_max) { + && atomic_read(&ip_conntrack_count) >= ip_conntrack_max) { unsigned int hash = hash_conntrack(orig); /* Try dropping from this hash chain. */ if (!early_drop(&ip_conntrack_hash[hash])) { - atomic_dec(&ip_conntrack_count); if (net_ratelimit()) printk(KERN_WARNING "ip_conntrack: table full, dropping" @@ -647,7 +656,6 @@ struct ip_conntrack *ip_conntrack_alloc(struct ip_conntrack_tuple *orig, conntrack = kmem_cache_alloc(ip_conntrack_cachep, GFP_ATOMIC); if (!conntrack) { DEBUGP("Can't allocate conntrack.\n"); - atomic_dec(&ip_conntrack_count); return ERR_PTR(-ENOMEM); } @@ -661,6 +669,8 @@ struct ip_conntrack *ip_conntrack_alloc(struct ip_conntrack_tuple *orig, conntrack->timeout.data = (unsigned long)conntrack; conntrack->timeout.function = death_by_timeout; + atomic_inc(&ip_conntrack_count); + return conntrack; } @@ -1052,7 +1062,7 @@ int ip_conntrack_helper_register(struct ip_conntrack_helper *me) { BUG_ON(me->timeout == 0); write_lock_bh(&ip_conntrack_lock); - list_add(&me->list, &helpers); + list_prepend(&helpers, me); write_unlock_bh(&ip_conntrack_lock); return 0; @@ -1071,24 +1081,24 @@ __ip_conntrack_helper_find_byname(const char *name) return NULL; } -static inline void unhelp(struct ip_conntrack_tuple_hash *i, - const struct ip_conntrack_helper *me) +static inline int unhelp(struct ip_conntrack_tuple_hash *i, + const struct ip_conntrack_helper *me) { if (tuplehash_to_ctrack(i)->helper == me) { ip_conntrack_event(IPCT_HELPER, tuplehash_to_ctrack(i)); tuplehash_to_ctrack(i)->helper = NULL; } + return 0; } void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me) { unsigned int i; - struct ip_conntrack_tuple_hash *h; struct ip_conntrack_expect *exp, *tmp; /* Need write lock here, to delete helper. */ write_lock_bh(&ip_conntrack_lock); - list_del(&me->list); + LIST_DELETE(&helpers, me); /* Get rid of expectations */ list_for_each_entry_safe(exp, tmp, &ip_conntrack_expect_list, list) { @@ -1098,12 +1108,10 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me) } } /* Get rid of expecteds, set helpers to NULL. */ - list_for_each_entry(h, &unconfirmed, list) - unhelp(h, me); - for (i = 0; i < ip_conntrack_htable_size; i++) { - list_for_each_entry(h, &ip_conntrack_hash[i], list) - unhelp(h, me); - } + LIST_FIND_W(&unconfirmed, unhelp, struct ip_conntrack_tuple_hash*, me); + for (i = 0; i < ip_conntrack_htable_size; i++) + LIST_FIND_W(&ip_conntrack_hash[i], unhelp, + struct ip_conntrack_tuple_hash *, me); write_unlock_bh(&ip_conntrack_lock); /* Someone could be still looking at the helper in a bh. */ @@ -1229,43 +1237,46 @@ static void ip_conntrack_attach(struct sk_buff *nskb, struct sk_buff *skb) nf_conntrack_get(nskb->nfct); } +static inline int +do_iter(const struct ip_conntrack_tuple_hash *i, + int (*iter)(struct ip_conntrack *i, void *data), + void *data) +{ + return iter(tuplehash_to_ctrack(i), data); +} + /* Bring out ya dead! */ -static struct ip_conntrack * +static struct ip_conntrack_tuple_hash * get_next_corpse(int (*iter)(struct ip_conntrack *i, void *data), void *data, unsigned int *bucket) { - struct ip_conntrack_tuple_hash *h; - struct ip_conntrack *ct; + struct ip_conntrack_tuple_hash *h = NULL; write_lock_bh(&ip_conntrack_lock); for (; *bucket < ip_conntrack_htable_size; (*bucket)++) { - list_for_each_entry(h, &ip_conntrack_hash[*bucket], list) { - ct = tuplehash_to_ctrack(h); - if (iter(ct, data)) - goto found; - } - } - list_for_each_entry(h, &unconfirmed, list) { - ct = tuplehash_to_ctrack(h); - if (iter(ct, data)) - goto found; + h = LIST_FIND_W(&ip_conntrack_hash[*bucket], do_iter, + struct ip_conntrack_tuple_hash *, iter, data); + if (h) + break; } + if (!h) + h = LIST_FIND_W(&unconfirmed, do_iter, + struct ip_conntrack_tuple_hash *, iter, data); + if (h) + atomic_inc(&tuplehash_to_ctrack(h)->ct_general.use); write_unlock_bh(&ip_conntrack_lock); - return NULL; -found: - atomic_inc(&ct->ct_general.use); - write_unlock_bh(&ip_conntrack_lock); - return ct; + return h; } void ip_ct_iterate_cleanup(int (*iter)(struct ip_conntrack *i, void *), void *data) { - struct ip_conntrack *ct; + struct ip_conntrack_tuple_hash *h; unsigned int bucket = 0; - while ((ct = get_next_corpse(iter, data, &bucket)) != NULL) { + while ((h = get_next_corpse(iter, data, &bucket)) != NULL) { + struct ip_conntrack *ct = tuplehash_to_ctrack(h); /* Time to push up daises... */ if (del_timer(&ct->timeout)) death_by_timeout((unsigned long)ct); diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/trunk/net/ipv4/netfilter/ip_conntrack_helper_pptp.c index fb0aee691721..b020a33e65e9 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_helper_pptp.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_helper_pptp.c @@ -20,11 +20,11 @@ * - We can only support one single call within each session * * TODO: - * - testing of incoming PPTP calls + * - testing of incoming PPTP calls * - * Changes: + * Changes: * 2002-02-05 - Version 1.3 - * - Call ip_conntrack_unexpect_related() from + * - Call ip_conntrack_unexpect_related() from * pptp_destroy_siblings() to destroy expectations in case * CALL_DISCONNECT_NOTIFY or tcp fin packet was seen * (Philip Craig ) @@ -80,7 +80,7 @@ int struct PptpControlHeader *ctlh, union pptp_ctrl_union *pptpReq); -void +int (*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *expect_orig, struct ip_conntrack_expect *expect_reply); @@ -141,7 +141,7 @@ static void pptp_expectfn(struct ip_conntrack *ct, invert_tuplepr(&inv_t, &exp->tuple); DEBUGP("trying to unexpect other dir: "); DUMP_TUPLE(&inv_t); - + exp_other = ip_conntrack_expect_find(&inv_t); if (exp_other) { /* delete other expectation. */ @@ -194,16 +194,15 @@ static void pptp_destroy_siblings(struct ip_conntrack *ct) { struct ip_conntrack_tuple t; - ip_ct_gre_keymap_destroy(ct); - /* Since ct->sibling_list has literally rusted away in 2.6.11, + /* Since ct->sibling_list has literally rusted away in 2.6.11, * we now need another way to find out about our sibling * contrack and expects... -HW */ /* try original (pns->pac) tuple */ memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t)); t.dst.protonum = IPPROTO_GRE; - t.src.u.gre.key = ct->help.ct_pptp_info.pns_call_id; - t.dst.u.gre.key = ct->help.ct_pptp_info.pac_call_id; + t.src.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id); + t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id); if (!destroy_sibling_or_exp(&t)) DEBUGP("failed to timeout original pns->pac ct/exp\n"); @@ -211,8 +210,8 @@ static void pptp_destroy_siblings(struct ip_conntrack *ct) /* try reply (pac->pns) tuple */ memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t)); t.dst.protonum = IPPROTO_GRE; - t.src.u.gre.key = ct->help.ct_pptp_info.pac_call_id; - t.dst.u.gre.key = ct->help.ct_pptp_info.pns_call_id; + t.src.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id); + t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id); if (!destroy_sibling_or_exp(&t)) DEBUGP("failed to timeout reply pac->pns ct/exp\n"); @@ -220,63 +219,94 @@ static void pptp_destroy_siblings(struct ip_conntrack *ct) /* expect GRE connections (PNS->PAC and PAC->PNS direction) */ static inline int -exp_gre(struct ip_conntrack *ct, +exp_gre(struct ip_conntrack *master, + u_int32_t seq, __be16 callid, __be16 peer_callid) { + struct ip_conntrack_tuple inv_tuple; + struct ip_conntrack_tuple exp_tuples[] = { + /* tuple in original direction, PNS->PAC */ + { .src = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip, + .u = { .gre = { .key = peer_callid } } + }, + .dst = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip, + .u = { .gre = { .key = callid } }, + .protonum = IPPROTO_GRE + }, + }, + /* tuple in reply direction, PAC->PNS */ + { .src = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip, + .u = { .gre = { .key = callid } } + }, + .dst = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip, + .u = { .gre = { .key = peer_callid } }, + .protonum = IPPROTO_GRE + }, + } + }; struct ip_conntrack_expect *exp_orig, *exp_reply; int ret = 1; - exp_orig = ip_conntrack_expect_alloc(ct); + exp_orig = ip_conntrack_expect_alloc(master); if (exp_orig == NULL) goto out; - exp_reply = ip_conntrack_expect_alloc(ct); + exp_reply = ip_conntrack_expect_alloc(master); if (exp_reply == NULL) goto out_put_orig; - /* original direction, PNS->PAC */ - exp_orig->tuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; - exp_orig->tuple.src.u.gre.key = peer_callid; - exp_orig->tuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; - exp_orig->tuple.dst.u.gre.key = callid; - exp_orig->tuple.dst.protonum = IPPROTO_GRE; + memcpy(&exp_orig->tuple, &exp_tuples[0], sizeof(exp_orig->tuple)); exp_orig->mask.src.ip = 0xffffffff; exp_orig->mask.src.u.all = 0; + exp_orig->mask.dst.u.all = 0; exp_orig->mask.dst.u.gre.key = htons(0xffff); exp_orig->mask.dst.ip = 0xffffffff; exp_orig->mask.dst.protonum = 0xff; - - exp_orig->master = ct; + + exp_orig->master = master; exp_orig->expectfn = pptp_expectfn; exp_orig->flags = 0; /* both expectations are identical apart from tuple */ memcpy(exp_reply, exp_orig, sizeof(*exp_reply)); - - /* reply direction, PAC->PNS */ - exp_reply->tuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; - exp_reply->tuple.src.u.gre.key = callid; - exp_reply->tuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; - exp_reply->tuple.dst.u.gre.key = peer_callid; - exp_reply->tuple.dst.protonum = IPPROTO_GRE; + memcpy(&exp_reply->tuple, &exp_tuples[1], sizeof(exp_reply->tuple)); if (ip_nat_pptp_hook_exp_gre) - ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply); - if (ip_conntrack_expect_related(exp_orig) != 0) - goto out_put_both; - if (ip_conntrack_expect_related(exp_reply) != 0) - goto out_unexpect_orig; - - /* Add GRE keymap entries */ - if (ip_ct_gre_keymap_add(ct, &exp_orig->tuple, 0) != 0) - goto out_unexpect_both; - if (ip_ct_gre_keymap_add(ct, &exp_reply->tuple, 1) != 0) { - ip_ct_gre_keymap_destroy(ct); - goto out_unexpect_both; + ret = ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply); + else { + + DEBUGP("calling expect_related PNS->PAC"); + DUMP_TUPLE(&exp_orig->tuple); + + if (ip_conntrack_expect_related(exp_orig) != 0) { + DEBUGP("cannot expect_related()\n"); + goto out_put_both; + } + + DEBUGP("calling expect_related PAC->PNS"); + DUMP_TUPLE(&exp_reply->tuple); + + if (ip_conntrack_expect_related(exp_reply) != 0) { + DEBUGP("cannot expect_related()\n"); + goto out_unexpect_orig; + } + + /* Add GRE keymap entries */ + if (ip_ct_gre_keymap_add(master, &exp_reply->tuple, 0) != 0) { + DEBUGP("cannot keymap_add() exp\n"); + goto out_unexpect_both; + } + + invert_tuplepr(&inv_tuple, &exp_reply->tuple); + if (ip_ct_gre_keymap_add(master, &inv_tuple, 1) != 0) { + ip_ct_gre_keymap_destroy(master); + DEBUGP("cannot keymap_add() exp_inv\n"); + goto out_unexpect_both; + } + ret = 0; } - ret = 0; out_put_both: ip_conntrack_expect_put(exp_reply); @@ -292,36 +322,73 @@ exp_gre(struct ip_conntrack *ct, goto out_put_both; } -static inline int +static inline int pptp_inbound_pkt(struct sk_buff **pskb, - struct PptpControlHeader *ctlh, - union pptp_ctrl_union *pptpReq, - unsigned int reqlen, + struct tcphdr *tcph, + unsigned int nexthdr_off, + unsigned int datalen, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) { + struct PptpControlHeader _ctlh, *ctlh; + unsigned int reqlen; + union pptp_ctrl_union _pptpReq, *pptpReq; struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; u_int16_t msg; - __be16 cid = 0, pcid = 0; + __be16 *cid, *pcid; + u_int32_t seq; + + ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh); + if (!ctlh) { + DEBUGP("error during skb_header_pointer\n"); + return NF_ACCEPT; + } + nexthdr_off += sizeof(_ctlh); + datalen -= sizeof(_ctlh); + + reqlen = datalen; + if (reqlen > sizeof(*pptpReq)) + reqlen = sizeof(*pptpReq); + pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq); + if (!pptpReq) { + DEBUGP("error during skb_header_pointer\n"); + return NF_ACCEPT; + } msg = ntohs(ctlh->messageType); DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); switch (msg) { case PPTP_START_SESSION_REPLY: + if (reqlen < sizeof(_pptpReq.srep)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } + /* server confirms new control session */ - if (info->sstate < PPTP_SESSION_REQUESTED) - goto invalid; + if (info->sstate < PPTP_SESSION_REQUESTED) { + DEBUGP("%s without START_SESS_REQUEST\n", + pptp_msg_name[msg]); + break; + } if (pptpReq->srep.resultCode == PPTP_START_OK) info->sstate = PPTP_SESSION_CONFIRMED; - else + else info->sstate = PPTP_SESSION_ERROR; break; case PPTP_STOP_SESSION_REPLY: + if (reqlen < sizeof(_pptpReq.strep)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } + /* server confirms end of control session */ - if (info->sstate > PPTP_SESSION_STOPREQ) - goto invalid; + if (info->sstate > PPTP_SESSION_STOPREQ) { + DEBUGP("%s without STOP_SESS_REQUEST\n", + pptp_msg_name[msg]); + break; + } if (pptpReq->strep.resultCode == PPTP_STOP_OK) info->sstate = PPTP_SESSION_NONE; else @@ -329,64 +396,116 @@ pptp_inbound_pkt(struct sk_buff **pskb, break; case PPTP_OUT_CALL_REPLY: + if (reqlen < sizeof(_pptpReq.ocack)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } + /* server accepted call, we now expect GRE frames */ - if (info->sstate != PPTP_SESSION_CONFIRMED) - goto invalid; + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("%s but no session\n", pptp_msg_name[msg]); + break; + } if (info->cstate != PPTP_CALL_OUT_REQ && - info->cstate != PPTP_CALL_OUT_CONF) - goto invalid; - - cid = pptpReq->ocack.callID; - pcid = pptpReq->ocack.peersCallID; - if (info->pns_call_id != pcid) - goto invalid; - DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], - ntohs(cid), ntohs(pcid)); - - if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) { - info->cstate = PPTP_CALL_OUT_CONF; - info->pac_call_id = cid; - exp_gre(ct, cid, pcid); - } else + info->cstate != PPTP_CALL_OUT_CONF) { + DEBUGP("%s without OUTCALL_REQ\n", pptp_msg_name[msg]); + break; + } + if (pptpReq->ocack.resultCode != PPTP_OUTCALL_CONNECT) { info->cstate = PPTP_CALL_NONE; + break; + } + + cid = &pptpReq->ocack.callID; + pcid = &pptpReq->ocack.peersCallID; + + info->pac_call_id = ntohs(*cid); + + if (htons(info->pns_call_id) != *pcid) { + DEBUGP("%s for unknown callid %u\n", + pptp_msg_name[msg], ntohs(*pcid)); + break; + } + + DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], + ntohs(*cid), ntohs(*pcid)); + + info->cstate = PPTP_CALL_OUT_CONF; + + seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr) + + sizeof(struct PptpControlHeader) + + ((void *)pcid - (void *)pptpReq); + + if (exp_gre(ct, seq, *cid, *pcid) != 0) + printk("ip_conntrack_pptp: error during exp_gre\n"); break; case PPTP_IN_CALL_REQUEST: - /* server tells us about incoming call request */ - if (info->sstate != PPTP_SESSION_CONFIRMED) - goto invalid; + if (reqlen < sizeof(_pptpReq.icack)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } - cid = pptpReq->icreq.callID; - DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); + /* server tells us about incoming call request */ + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("%s but no session\n", pptp_msg_name[msg]); + break; + } + pcid = &pptpReq->icack.peersCallID; + DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid)); info->cstate = PPTP_CALL_IN_REQ; - info->pac_call_id = cid; + info->pac_call_id = ntohs(*pcid); break; case PPTP_IN_CALL_CONNECT: + if (reqlen < sizeof(_pptpReq.iccon)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } + /* server tells us about incoming call established */ - if (info->sstate != PPTP_SESSION_CONFIRMED) - goto invalid; - if (info->cstate != PPTP_CALL_IN_REP && - info->cstate != PPTP_CALL_IN_CONF) - goto invalid; + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("%s but no session\n", pptp_msg_name[msg]); + break; + } + if (info->cstate != PPTP_CALL_IN_REP + && info->cstate != PPTP_CALL_IN_CONF) { + DEBUGP("%s but never sent IN_CALL_REPLY\n", + pptp_msg_name[msg]); + break; + } - pcid = pptpReq->iccon.peersCallID; - cid = info->pac_call_id; + pcid = &pptpReq->iccon.peersCallID; + cid = &info->pac_call_id; - if (info->pns_call_id != pcid) - goto invalid; + if (info->pns_call_id != ntohs(*pcid)) { + DEBUGP("%s for unknown CallID %u\n", + pptp_msg_name[msg], ntohs(*pcid)); + break; + } - DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(pcid)); + DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid)); info->cstate = PPTP_CALL_IN_CONF; /* we expect a GRE connection from PAC to PNS */ - exp_gre(ct, cid, pcid); + seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr) + + sizeof(struct PptpControlHeader) + + ((void *)pcid - (void *)pptpReq); + + if (exp_gre(ct, seq, *cid, *pcid) != 0) + printk("ip_conntrack_pptp: error during exp_gre\n"); + break; case PPTP_CALL_DISCONNECT_NOTIFY: + if (reqlen < sizeof(_pptpReq.disc)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } + /* server confirms disconnect */ - cid = pptpReq->disc.callID; - DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); + cid = &pptpReq->disc.callID; + DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid)); info->cstate = PPTP_CALL_NONE; /* untrack this call id, unexpect GRE packets */ @@ -394,39 +513,54 @@ pptp_inbound_pkt(struct sk_buff **pskb, break; case PPTP_WAN_ERROR_NOTIFY: + break; + case PPTP_ECHO_REQUEST: case PPTP_ECHO_REPLY: /* I don't have to explain these ;) */ break; default: - goto invalid; + DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX) + ? pptp_msg_name[msg]:pptp_msg_name[0], msg); + break; } + if (ip_nat_pptp_hook_inbound) return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh, pptpReq); - return NF_ACCEPT; -invalid: - DEBUGP("invalid %s: type=%d cid=%u pcid=%u " - "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", - msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], - msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, - ntohs(info->pns_call_id), ntohs(info->pac_call_id)); return NF_ACCEPT; + } static inline int pptp_outbound_pkt(struct sk_buff **pskb, - struct PptpControlHeader *ctlh, - union pptp_ctrl_union *pptpReq, - unsigned int reqlen, + struct tcphdr *tcph, + unsigned int nexthdr_off, + unsigned int datalen, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) { + struct PptpControlHeader _ctlh, *ctlh; + unsigned int reqlen; + union pptp_ctrl_union _pptpReq, *pptpReq; struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; u_int16_t msg; - __be16 cid = 0, pcid = 0; + __be16 *cid, *pcid; + + ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh); + if (!ctlh) + return NF_ACCEPT; + nexthdr_off += sizeof(_ctlh); + datalen -= sizeof(_ctlh); + + reqlen = datalen; + if (reqlen > sizeof(*pptpReq)) + reqlen = sizeof(*pptpReq); + pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq); + if (!pptpReq) + return NF_ACCEPT; msg = ntohs(ctlh->messageType); DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); @@ -434,8 +568,10 @@ pptp_outbound_pkt(struct sk_buff **pskb, switch (msg) { case PPTP_START_SESSION_REQUEST: /* client requests for new control session */ - if (info->sstate != PPTP_SESSION_NONE) - goto invalid; + if (info->sstate != PPTP_SESSION_NONE) { + DEBUGP("%s but we already have one", + pptp_msg_name[msg]); + } info->sstate = PPTP_SESSION_REQUESTED; break; case PPTP_STOP_SESSION_REQUEST: @@ -444,115 +580,123 @@ pptp_outbound_pkt(struct sk_buff **pskb, break; case PPTP_OUT_CALL_REQUEST: + if (reqlen < sizeof(_pptpReq.ocreq)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + /* FIXME: break; */ + } + /* client initiating connection to server */ - if (info->sstate != PPTP_SESSION_CONFIRMED) - goto invalid; + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("%s but no session\n", + pptp_msg_name[msg]); + break; + } info->cstate = PPTP_CALL_OUT_REQ; /* track PNS call id */ - cid = pptpReq->ocreq.callID; - DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(cid)); - info->pns_call_id = cid; + cid = &pptpReq->ocreq.callID; + DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid)); + info->pns_call_id = ntohs(*cid); break; case PPTP_IN_CALL_REPLY: + if (reqlen < sizeof(_pptpReq.icack)) { + DEBUGP("%s: short packet\n", pptp_msg_name[msg]); + break; + } + /* client answers incoming call */ - if (info->cstate != PPTP_CALL_IN_REQ && - info->cstate != PPTP_CALL_IN_REP) - goto invalid; - - cid = pptpReq->icack.callID; - pcid = pptpReq->icack.peersCallID; - if (info->pac_call_id != pcid) - goto invalid; - DEBUGP("%s, CID=%X PCID=%X\n", pptp_msg_name[msg], - ntohs(cid), ntohs(pcid)); - - if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) { - /* part two of the three-way handshake */ - info->cstate = PPTP_CALL_IN_REP; - info->pns_call_id = cid; - } else + if (info->cstate != PPTP_CALL_IN_REQ + && info->cstate != PPTP_CALL_IN_REP) { + DEBUGP("%s without incall_req\n", + pptp_msg_name[msg]); + break; + } + if (pptpReq->icack.resultCode != PPTP_INCALL_ACCEPT) { info->cstate = PPTP_CALL_NONE; + break; + } + pcid = &pptpReq->icack.peersCallID; + if (info->pac_call_id != ntohs(*pcid)) { + DEBUGP("%s for unknown call %u\n", + pptp_msg_name[msg], ntohs(*pcid)); + break; + } + DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*pcid)); + /* part two of the three-way handshake */ + info->cstate = PPTP_CALL_IN_REP; + info->pns_call_id = ntohs(pptpReq->icack.callID); break; case PPTP_CALL_CLEAR_REQUEST: /* client requests hangup of call */ - if (info->sstate != PPTP_SESSION_CONFIRMED) - goto invalid; + if (info->sstate != PPTP_SESSION_CONFIRMED) { + DEBUGP("CLEAR_CALL but no session\n"); + break; + } /* FUTURE: iterate over all calls and check if * call ID is valid. We don't do this without newnat, * because we only know about last call */ info->cstate = PPTP_CALL_CLEAR_REQ; break; case PPTP_SET_LINK_INFO: + break; case PPTP_ECHO_REQUEST: case PPTP_ECHO_REPLY: /* I don't have to explain these ;) */ break; default: - goto invalid; + DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)? + pptp_msg_name[msg]:pptp_msg_name[0], msg); + /* unknown: no need to create GRE masq table entry */ + break; } - + if (ip_nat_pptp_hook_outbound) return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh, pptpReq); - return NF_ACCEPT; -invalid: - DEBUGP("invalid %s: type=%d cid=%u pcid=%u " - "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n", - msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0], - msg, ntohs(cid), ntohs(pcid), info->cstate, info->sstate, - ntohs(info->pns_call_id), ntohs(info->pac_call_id)); return NF_ACCEPT; } -static const unsigned int pptp_msg_size[] = { - [PPTP_START_SESSION_REQUEST] = sizeof(struct PptpStartSessionRequest), - [PPTP_START_SESSION_REPLY] = sizeof(struct PptpStartSessionReply), - [PPTP_STOP_SESSION_REQUEST] = sizeof(struct PptpStopSessionRequest), - [PPTP_STOP_SESSION_REPLY] = sizeof(struct PptpStopSessionReply), - [PPTP_OUT_CALL_REQUEST] = sizeof(struct PptpOutCallRequest), - [PPTP_OUT_CALL_REPLY] = sizeof(struct PptpOutCallReply), - [PPTP_IN_CALL_REQUEST] = sizeof(struct PptpInCallRequest), - [PPTP_IN_CALL_REPLY] = sizeof(struct PptpInCallReply), - [PPTP_IN_CALL_CONNECT] = sizeof(struct PptpInCallConnected), - [PPTP_CALL_CLEAR_REQUEST] = sizeof(struct PptpClearCallRequest), - [PPTP_CALL_DISCONNECT_NOTIFY] = sizeof(struct PptpCallDisconnectNotify), - [PPTP_WAN_ERROR_NOTIFY] = sizeof(struct PptpWanErrorNotify), - [PPTP_SET_LINK_INFO] = sizeof(struct PptpSetLinkInfo), -}; /* track caller id inside control connection, call expect_related */ -static int +static int conntrack_pptp_help(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) { + struct pptp_pkt_hdr _pptph, *pptph; + struct tcphdr _tcph, *tcph; + u_int32_t tcplen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4; + u_int32_t datalen; int dir = CTINFO2DIR(ctinfo); struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; - struct tcphdr _tcph, *tcph; - struct pptp_pkt_hdr _pptph, *pptph; - struct PptpControlHeader _ctlh, *ctlh; - union pptp_ctrl_union _pptpReq, *pptpReq; - unsigned int tcplen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4; - unsigned int datalen, reqlen, nexthdr_off; + unsigned int nexthdr_off; + int oldsstate, oldcstate; int ret; - u_int16_t msg; /* don't do any tracking before tcp handshake complete */ - if (ctinfo != IP_CT_ESTABLISHED + if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) { DEBUGP("ctinfo = %u, skipping\n", ctinfo); return NF_ACCEPT; } - + nexthdr_off = (*pskb)->nh.iph->ihl*4; tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph); BUG_ON(!tcph); nexthdr_off += tcph->doff * 4; datalen = tcplen - tcph->doff * 4; + if (tcph->fin || tcph->rst) { + DEBUGP("RST/FIN received, timeouting GRE\n"); + /* can't do this after real newnat */ + info->cstate = PPTP_CALL_NONE; + + /* untrack this call id, unexpect GRE packets */ + pptp_destroy_siblings(ct); + } + pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph); if (!pptph) { DEBUGP("no full PPTP header, can't track\n"); @@ -568,23 +712,6 @@ conntrack_pptp_help(struct sk_buff **pskb, return NF_ACCEPT; } - ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh); - if (!ctlh) - return NF_ACCEPT; - nexthdr_off += sizeof(_ctlh); - datalen -= sizeof(_ctlh); - - reqlen = datalen; - msg = ntohs(ctlh->messageType); - if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg]) - return NF_ACCEPT; - if (reqlen > sizeof(*pptpReq)) - reqlen = sizeof(*pptpReq); - - pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq); - if (!pptpReq) - return NF_ACCEPT; - oldsstate = info->sstate; oldcstate = info->cstate; @@ -594,11 +721,11 @@ conntrack_pptp_help(struct sk_buff **pskb, * established from PNS->PAC. However, RFC makes no guarantee */ if (dir == IP_CT_DIR_ORIGINAL) /* client -> server (PNS -> PAC) */ - ret = pptp_outbound_pkt(pskb, ctlh, pptpReq, reqlen, ct, + ret = pptp_outbound_pkt(pskb, tcph, nexthdr_off, datalen, ct, ctinfo); else /* server -> client (PAC -> PNS) */ - ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct, + ret = pptp_inbound_pkt(pskb, tcph, nexthdr_off, datalen, ct, ctinfo); DEBUGP("sstate: %d->%d, cstate: %d->%d\n", oldsstate, info->sstate, oldcstate, info->cstate); @@ -608,31 +735,30 @@ conntrack_pptp_help(struct sk_buff **pskb, } /* control protocol helper */ -static struct ip_conntrack_helper pptp = { +static struct ip_conntrack_helper pptp = { .list = { NULL, NULL }, - .name = "pptp", + .name = "pptp", .me = THIS_MODULE, .max_expected = 2, .timeout = 5 * 60, - .tuple = { .src = { .ip = 0, - .u = { .tcp = { .port = - __constant_htons(PPTP_CONTROL_PORT) } } - }, - .dst = { .ip = 0, + .tuple = { .src = { .ip = 0, + .u = { .tcp = { .port = + __constant_htons(PPTP_CONTROL_PORT) } } + }, + .dst = { .ip = 0, .u = { .all = 0 }, .protonum = IPPROTO_TCP - } + } }, - .mask = { .src = { .ip = 0, - .u = { .tcp = { .port = __constant_htons(0xffff) } } - }, - .dst = { .ip = 0, + .mask = { .src = { .ip = 0, + .u = { .tcp = { .port = __constant_htons(0xffff) } } + }, + .dst = { .ip = 0, .u = { .all = 0 }, - .protonum = 0xff - } + .protonum = 0xff + } }, - .help = conntrack_pptp_help, - .destroy = pptp_destroy_siblings, + .help = conntrack_pptp_help }; extern void ip_ct_proto_gre_fini(void); @@ -642,7 +768,7 @@ extern int __init ip_ct_proto_gre_init(void); static int __init ip_conntrack_helper_pptp_init(void) { int retcode; - + retcode = ip_ct_proto_gre_init(); if (retcode < 0) return retcode; diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/trunk/net/ipv4/netfilter/ip_conntrack_netbios_ns.c index 3d0b438783db..a566a81325b2 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_netbios_ns.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_netbios_ns.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_netlink.c b/trunk/net/ipv4/netfilter/ip_conntrack_netlink.c index 52eddea27e93..33891bb1fde4 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -329,7 +329,11 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, /* dump everything */ events = ~0UL; group = NFNLGRP_CONNTRACK_NEW; - } else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) { + } else if (events & (IPCT_STATUS | + IPCT_PROTOINFO | + IPCT_HELPER | + IPCT_HELPINFO | + IPCT_NATINFO)) { type = IPCTNL_MSG_CT_NEW; group = NFNLGRP_CONNTRACK_UPDATE; } else @@ -381,10 +385,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0) goto nfattr_failure; - if (events & IPCT_MARK - && ctnetlink_dump_mark(skb, ct) < 0) - goto nfattr_failure; - nlh->nlmsg_len = skb->tail - b; nfnetlink_send(skb, 0, group, 0); return NOTIFY_DONE; @@ -415,18 +415,21 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) cb->args[0], *id); read_lock_bh(&ip_conntrack_lock); - last = (struct ip_conntrack *)cb->args[1]; for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) { restart: + last = (struct ip_conntrack *)cb->args[1]; list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) { h = (struct ip_conntrack_tuple_hash *) i; if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) continue; ct = tuplehash_to_ctrack(h); - if (cb->args[1]) { - if (ct != last) + if (last != NULL) { + if (ct == last) { + ip_conntrack_put(last); + cb->args[1] = 0; + last = NULL; + } else continue; - cb->args[1] = 0; } if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, @@ -436,25 +439,60 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) cb->args[1] = (unsigned long)ct; goto out; } -#ifdef CONFIG_NF_CT_ACCT - if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == - IPCTNL_MSG_CT_GET_CTRZERO) - memset(&ct->counters, 0, sizeof(ct->counters)); -#endif } - if (cb->args[1]) { + if (last != NULL) { + ip_conntrack_put(last); cb->args[1] = 0; goto restart; } } out: read_unlock_bh(&ip_conntrack_lock); - if (last) - ip_conntrack_put(last); DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); + + return skb->len; +} + +#ifdef CONFIG_IP_NF_CT_ACCT +static int +ctnetlink_dump_table_w(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct ip_conntrack *ct = NULL; + struct ip_conntrack_tuple_hash *h; + struct list_head *i; + u_int32_t *id = (u_int32_t *) &cb->args[1]; + + DEBUGP("entered %s, last bucket=%u id=%u\n", __FUNCTION__, + cb->args[0], *id); + + write_lock_bh(&ip_conntrack_lock); + for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++, *id = 0) { + list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) { + h = (struct ip_conntrack_tuple_hash *) i; + if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) + continue; + ct = tuplehash_to_ctrack(h); + if (ct->id <= *id) + continue; + if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, + IPCTNL_MSG_CT_NEW, + 1, ct) < 0) + goto out; + *id = ct->id; + + memset(&ct->counters, 0, sizeof(ct->counters)); + } + } +out: + write_unlock_bh(&ip_conntrack_lock); + + DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); + return skb->len; } +#endif static const size_t cta_min_ip[CTA_IP_MAX] = { [CTA_IP_V4_SRC-1] = sizeof(u_int32_t), @@ -740,14 +778,22 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, if (msg->nfgen_family != AF_INET) return -EAFNOSUPPORT; -#ifndef CONFIG_IP_NF_CT_ACCT - if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO) + if (NFNL_MSG_TYPE(nlh->nlmsg_type) == + IPCTNL_MSG_CT_GET_CTRZERO) { +#ifdef CONFIG_IP_NF_CT_ACCT + if ((*errp = netlink_dump_start(ctnl, skb, nlh, + ctnetlink_dump_table_w, + ctnetlink_done)) != 0) + return -EINVAL; +#else return -ENOTSUPP; #endif - if ((*errp = netlink_dump_start(ctnl, skb, nlh, - ctnetlink_dump_table, - ctnetlink_done)) != 0) + } else { + if ((*errp = netlink_dump_start(ctnl, skb, nlh, + ctnetlink_dump_table, + ctnetlink_done)) != 0) return -EINVAL; + } rlen = NLMSG_ALIGN(nlh->nlmsg_len); if (rlen > skb->len) @@ -1210,9 +1256,6 @@ static int ctnetlink_expect_event(struct notifier_block *this, } else return NOTIFY_DONE; - if (!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW)) - return NOTIFY_DONE; - skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); if (!skb) return NOTIFY_DONE; diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_proto_generic.c b/trunk/net/ipv4/netfilter/ip_conntrack_proto_generic.c index 36f2b5e5d80a..f891308b5e4c 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_proto_generic.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_proto_generic.c @@ -12,7 +12,7 @@ #include #include -unsigned int ip_ct_generic_timeout __read_mostly = 600*HZ; +unsigned int ip_ct_generic_timeout = 600*HZ; static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/trunk/net/ipv4/netfilter/ip_conntrack_proto_gre.c index 5fe026f467d3..4ee016c427b4 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_proto_gre.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_proto_gre.c @@ -1,15 +1,15 @@ /* - * ip_conntrack_proto_gre.c - Version 3.0 + * ip_conntrack_proto_gre.c - Version 3.0 * * Connection tracking protocol helper module for GRE. * * GRE is a generic encapsulation protocol, which is generally not very * suited for NAT, as it has no protocol-specific part as port numbers. * - * It has an optional key field, which may help us distinguishing two + * It has an optional key field, which may help us distinguishing two * connections between the same two hosts. * - * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 * * PPTP is built on top of a modified version of GRE, and has a mandatory * field called "CallID", which serves us for the same purpose as the key @@ -37,6 +37,7 @@ static DEFINE_RWLOCK(ip_ct_gre_lock); #define ASSERT_READ_LOCK(x) #define ASSERT_WRITE_LOCK(x) +#include #include #include #include @@ -61,7 +62,7 @@ MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE"); #define DEBUGP(x, args...) #define DUMP_TUPLE_GRE(x) #endif - + /* GRE KEYMAP HANDLING FUNCTIONS */ static LIST_HEAD(gre_keymap_list); @@ -81,14 +82,12 @@ static __be16 gre_keymap_lookup(struct ip_conntrack_tuple *t) __be16 key = 0; read_lock_bh(&ip_ct_gre_lock); - list_for_each_entry(km, &gre_keymap_list, list) { - if (gre_key_cmpfn(km, t)) { - key = km->tuple.src.u.gre.key; - break; - } - } + km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn, + struct ip_ct_gre_keymap *, t); + if (km) + key = km->tuple.src.u.gre.key; read_unlock_bh(&ip_ct_gre_lock); - + DEBUGP("lookup src key 0x%x up key for ", key); DUMP_TUPLE_GRE(t); @@ -100,25 +99,28 @@ int ip_ct_gre_keymap_add(struct ip_conntrack *ct, struct ip_conntrack_tuple *t, int reply) { - struct ip_ct_gre_keymap **exist_km, *km; + struct ip_ct_gre_keymap **exist_km, *km, *old; if (!ct->helper || strcmp(ct->helper->name, "pptp")) { DEBUGP("refusing to add GRE keymap to non-pptp session\n"); return -1; } - if (!reply) + if (!reply) exist_km = &ct->help.ct_pptp_info.keymap_orig; else exist_km = &ct->help.ct_pptp_info.keymap_reply; if (*exist_km) { /* check whether it's a retransmission */ - list_for_each_entry(km, &gre_keymap_list, list) { - if (gre_key_cmpfn(km, t) && km == *exist_km) - return 0; + old = LIST_FIND(&gre_keymap_list, gre_key_cmpfn, + struct ip_ct_gre_keymap *, t); + if (old == *exist_km) { + DEBUGP("retransmission\n"); + return 0; } - DEBUGP("trying to override keymap_%s for ct %p\n", + + DEBUGP("trying to override keymap_%s for ct %p\n", reply? "reply":"orig", ct); return -EEXIST; } @@ -134,7 +136,7 @@ ip_ct_gre_keymap_add(struct ip_conntrack *ct, DUMP_TUPLE_GRE(&km->tuple); write_lock_bh(&ip_ct_gre_lock); - list_add_tail(&km->list, &gre_keymap_list); + list_append(&gre_keymap_list, km); write_unlock_bh(&ip_ct_gre_lock); return 0; @@ -152,7 +154,7 @@ void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct) write_lock_bh(&ip_ct_gre_lock); if (ct->help.ct_pptp_info.keymap_orig) { - DEBUGP("removing %p from list\n", + DEBUGP("removing %p from list\n", ct->help.ct_pptp_info.keymap_orig); list_del(&ct->help.ct_pptp_info.keymap_orig->list); kfree(ct->help.ct_pptp_info.keymap_orig); @@ -220,7 +222,7 @@ static int gre_pkt_to_tuple(const struct sk_buff *skb, static int gre_print_tuple(struct seq_file *s, const struct ip_conntrack_tuple *tuple) { - return seq_printf(s, "srckey=0x%x dstkey=0x%x ", + return seq_printf(s, "srckey=0x%x dstkey=0x%x ", ntohs(tuple->src.u.gre.key), ntohs(tuple->dst.u.gre.key)); } @@ -250,14 +252,14 @@ static int gre_packet(struct ip_conntrack *ct, } else ip_ct_refresh_acct(ct, conntrackinfo, skb, ct->proto.gre.timeout); - + return NF_ACCEPT; } /* Called when a new connection for this protocol found. */ static int gre_new(struct ip_conntrack *ct, const struct sk_buff *skb) -{ +{ DEBUGP(": "); DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); @@ -283,9 +285,9 @@ static void gre_destroy(struct ip_conntrack *ct) } /* protocol helper struct */ -static struct ip_conntrack_protocol gre = { +static struct ip_conntrack_protocol gre = { .proto = IPPROTO_GRE, - .name = "gre", + .name = "gre", .pkt_to_tuple = gre_pkt_to_tuple, .invert_tuple = gre_invert_tuple, .print_tuple = gre_print_tuple, @@ -323,7 +325,7 @@ void ip_ct_proto_gre_fini(void) } write_unlock_bh(&ip_ct_gre_lock); - ip_conntrack_protocol_unregister(&gre); + ip_conntrack_protocol_unregister(&gre); } EXPORT_SYMBOL(ip_ct_gre_keymap_add); diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/trunk/net/ipv4/netfilter/ip_conntrack_proto_icmp.c index 09c40ebe3345..23f1c504586d 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_proto_icmp.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_proto_icmp.c @@ -21,7 +21,7 @@ #include #include -unsigned int ip_ct_icmp_timeout __read_mostly = 30*HZ; +unsigned int ip_ct_icmp_timeout = 30*HZ; #if 0 #define DEBUGP printk diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c index b908a4842e18..2d3612cd5f18 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c @@ -58,13 +58,13 @@ static const char *sctp_conntrack_names[] = { #define HOURS * 60 MINS #define DAYS * 24 HOURS -static unsigned int ip_ct_sctp_timeout_closed __read_mostly = 10 SECS; -static unsigned int ip_ct_sctp_timeout_cookie_wait __read_mostly = 3 SECS; -static unsigned int ip_ct_sctp_timeout_cookie_echoed __read_mostly = 3 SECS; -static unsigned int ip_ct_sctp_timeout_established __read_mostly = 5 DAYS; -static unsigned int ip_ct_sctp_timeout_shutdown_sent __read_mostly = 300 SECS / 1000; -static unsigned int ip_ct_sctp_timeout_shutdown_recd __read_mostly = 300 SECS / 1000; -static unsigned int ip_ct_sctp_timeout_shutdown_ack_sent __read_mostly = 3 SECS; +static unsigned int ip_ct_sctp_timeout_closed = 10 SECS; +static unsigned int ip_ct_sctp_timeout_cookie_wait = 3 SECS; +static unsigned int ip_ct_sctp_timeout_cookie_echoed = 3 SECS; +static unsigned int ip_ct_sctp_timeout_established = 5 DAYS; +static unsigned int ip_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000; +static unsigned int ip_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000; +static unsigned int ip_ct_sctp_timeout_shutdown_ack_sent = 3 SECS; static const unsigned int * sctp_timeouts[] = { NULL, /* SCTP_CONNTRACK_NONE */ diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index 03ae9a04cb37..fb920e76ec10 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -48,19 +48,19 @@ static DEFINE_RWLOCK(tcp_lock); /* "Be conservative in what you do, be liberal in what you accept from others." If it's non-zero, we mark only out of window RST segments as INVALID. */ -int ip_ct_tcp_be_liberal __read_mostly = 0; +int ip_ct_tcp_be_liberal = 0; /* When connection is picked up from the middle, how many packets are required to pass in each direction when we assume we are in sync - if any side uses window scaling, we lost the game. If it is set to zero, we disable picking up already established connections. */ -int ip_ct_tcp_loose __read_mostly = 3; +int ip_ct_tcp_loose = 3; /* Max number of the retransmitted packets without receiving an (acceptable) ACK from the destination. If this number is reached, a shorter timer will be started. */ -int ip_ct_tcp_max_retrans __read_mostly = 3; +int ip_ct_tcp_max_retrans = 3; /* FIXME: Examine ipfilter's timeouts and conntrack transitions more closely. They're more complex. --RR */ @@ -83,19 +83,19 @@ static const char *tcp_conntrack_names[] = { #define HOURS * 60 MINS #define DAYS * 24 HOURS -unsigned int ip_ct_tcp_timeout_syn_sent __read_mostly = 2 MINS; -unsigned int ip_ct_tcp_timeout_syn_recv __read_mostly = 60 SECS; -unsigned int ip_ct_tcp_timeout_established __read_mostly = 5 DAYS; -unsigned int ip_ct_tcp_timeout_fin_wait __read_mostly = 2 MINS; -unsigned int ip_ct_tcp_timeout_close_wait __read_mostly = 60 SECS; -unsigned int ip_ct_tcp_timeout_last_ack __read_mostly = 30 SECS; -unsigned int ip_ct_tcp_timeout_time_wait __read_mostly = 2 MINS; -unsigned int ip_ct_tcp_timeout_close __read_mostly = 10 SECS; +unsigned int ip_ct_tcp_timeout_syn_sent = 2 MINS; +unsigned int ip_ct_tcp_timeout_syn_recv = 60 SECS; +unsigned int ip_ct_tcp_timeout_established = 5 DAYS; +unsigned int ip_ct_tcp_timeout_fin_wait = 2 MINS; +unsigned int ip_ct_tcp_timeout_close_wait = 60 SECS; +unsigned int ip_ct_tcp_timeout_last_ack = 30 SECS; +unsigned int ip_ct_tcp_timeout_time_wait = 2 MINS; +unsigned int ip_ct_tcp_timeout_close = 10 SECS; /* RFC1122 says the R2 limit should be at least 100 seconds. Linux uses 15 packets as limit, which corresponds to ~13-30min depending on RTO. */ -unsigned int ip_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS; +unsigned int ip_ct_tcp_timeout_max_retrans = 5 MINS; static const unsigned int * tcp_timeouts[] = { NULL, /* TCP_CONNTRACK_NONE */ @@ -731,15 +731,13 @@ static int tcp_in_window(struct ip_ct_tcp *state, if (state->last_dir == dir && state->last_seq == seq && state->last_ack == ack - && state->last_end == end - && state->last_win == win) + && state->last_end == end) state->retrans++; else { state->last_dir = dir; state->last_seq = seq; state->last_ack = ack; state->last_end = end; - state->last_win = win; state->retrans = 0; } } @@ -867,7 +865,8 @@ static int tcp_error(struct sk_buff *skb, /* Checksum invalid? Ignore. * We skip checking packets on the outgoing path - * because it is assumed to be correct. + * because the semantic of CHECKSUM_HW is different there + * and moreover root might send raw packets. */ /* FIXME: Source route IP option packets --RR */ if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING && diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/trunk/net/ipv4/netfilter/ip_conntrack_proto_udp.c index d0e8a16970ec..9b2c16b4d2ff 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_proto_udp.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_proto_udp.c @@ -18,8 +18,8 @@ #include #include -unsigned int ip_ct_udp_timeout __read_mostly = 30*HZ; -unsigned int ip_ct_udp_timeout_stream __read_mostly = 180*HZ; +unsigned int ip_ct_udp_timeout = 30*HZ; +unsigned int ip_ct_udp_timeout_stream = 180*HZ; static int udp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, @@ -117,7 +117,8 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, /* Checksum invalid? Ignore. * We skip checking packets on the outgoing path - * because the checksum is assumed to be correct. + * because the semantic of CHECKSUM_HW is different there + * and moreover root might send raw packets. * FIXME: Source route IP option packets --RR */ if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING && nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) { diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_sip.c b/trunk/net/ipv4/netfilter/ip_conntrack_sip.c index 2893e9c74850..fc87ce0da40d 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_sip.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_sip.c @@ -8,6 +8,7 @@ * published by the Free Software Foundation. */ +#include #include #include #include @@ -441,7 +442,7 @@ static int __init init(void) sip[i].tuple.src.u.udp.port = htons(ports[i]); sip[i].mask.src.u.udp.port = 0xFFFF; sip[i].mask.dst.protonum = 0xFF; - sip[i].max_expected = 2; + sip[i].max_expected = 1; sip[i].timeout = 3 * 60; /* 3 minutes */ sip[i].me = THIS_MODULE; sip[i].help = sip_help; diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c b/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c index 02135756562e..7a9fa04a467a 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -35,6 +35,7 @@ #include #include #include +#include #if 0 #define DEBUGP printk @@ -533,7 +534,7 @@ static struct nf_hook_ops ip_conntrack_ops[] = { /* Sysctl support */ -int ip_conntrack_checksum __read_mostly = 1; +int ip_conntrack_checksum = 1; #ifdef CONFIG_SYSCTL @@ -562,7 +563,7 @@ extern unsigned int ip_ct_udp_timeout_stream; /* From ip_conntrack_proto_icmp.c */ extern unsigned int ip_ct_icmp_timeout; -/* From ip_conntrack_proto_generic.c */ +/* From ip_conntrack_proto_icmp.c */ extern unsigned int ip_ct_generic_timeout; /* Log invalid packets of a given protocol */ diff --git a/trunk/net/ipv4/netfilter/ip_nat_core.c b/trunk/net/ipv4/netfilter/ip_nat_core.c index 71f3e09cbc84..1741d555ad0d 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_core.c +++ b/trunk/net/ipv4/netfilter/ip_nat_core.c @@ -22,6 +22,9 @@ #include #include +#define ASSERT_READ_LOCK(x) +#define ASSERT_WRITE_LOCK(x) + #include #include #include @@ -30,6 +33,7 @@ #include #include #include +#include #if 0 #define DEBUGP printk @@ -97,6 +101,18 @@ static void ip_nat_cleanup_conntrack(struct ip_conntrack *conn) write_unlock_bh(&ip_nat_lock); } +/* We do checksum mangling, so if they were wrong before they're still + * wrong. Also works for incomplete packets (eg. ICMP dest + * unreachables.) */ +u_int16_t +ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck) +{ + u_int32_t diffs[] = { oldvalinv, newval }; + return csum_fold(csum_partial((char *)diffs, sizeof(diffs), + oldcheck^0xFFFF)); +} +EXPORT_SYMBOL(ip_nat_cheat_check); + /* Is this tuple already taken? (not by us) */ int ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple, @@ -362,12 +378,12 @@ manip_pkt(u_int16_t proto, iph = (void *)(*pskb)->data + iphdroff; if (maniptype == IP_NAT_MANIP_SRC) { - iph->check = nf_csum_update(~iph->saddr, target->src.ip, - iph->check); + iph->check = ip_nat_cheat_check(~iph->saddr, target->src.ip, + iph->check); iph->saddr = target->src.ip; } else { - iph->check = nf_csum_update(~iph->daddr, target->dst.ip, - iph->check); + iph->check = ip_nat_cheat_check(~iph->daddr, target->dst.ip, + iph->check); iph->daddr = target->dst.ip; } return 1; @@ -407,10 +423,10 @@ unsigned int ip_nat_packet(struct ip_conntrack *ct, EXPORT_SYMBOL_GPL(ip_nat_packet); /* Dir is direction ICMP is coming from (opposite to packet it contains) */ -int ip_nat_icmp_reply_translation(struct ip_conntrack *ct, - enum ip_conntrack_info ctinfo, - unsigned int hooknum, - struct sk_buff **pskb) +int ip_nat_icmp_reply_translation(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_nat_manip_type manip, + enum ip_conntrack_dir dir) { struct { struct icmphdr icmp; @@ -418,9 +434,7 @@ int ip_nat_icmp_reply_translation(struct ip_conntrack *ct, } *inside; struct ip_conntrack_tuple inner, target; int hdrlen = (*pskb)->nh.iph->ihl * 4; - enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); unsigned long statusbit; - enum ip_nat_manip_type manip = HOOK2MANIP(hooknum); if (!skb_make_writable(pskb, hdrlen + sizeof(*inside))) return 0; @@ -429,8 +443,12 @@ int ip_nat_icmp_reply_translation(struct ip_conntrack *ct, /* We're actually going to mangle it beyond trivial checksum adjustment, so make sure the current checksum is correct. */ - if (nf_ip_checksum(*pskb, hooknum, hdrlen, 0)) - return 0; + if ((*pskb)->ip_summed != CHECKSUM_UNNECESSARY) { + hdrlen = (*pskb)->nh.iph->ihl * 4; + if ((u16)csum_fold(skb_checksum(*pskb, hdrlen, + (*pskb)->len - hdrlen, 0))) + return 0; + } /* Must be RELATED */ IP_NF_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED || @@ -469,14 +487,12 @@ int ip_nat_icmp_reply_translation(struct ip_conntrack *ct, !manip)) return 0; - if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { - /* Reloading "inside" here since manip_pkt inner. */ - inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4; - inside->icmp.checksum = 0; - inside->icmp.checksum = csum_fold(skb_checksum(*pskb, hdrlen, - (*pskb)->len - hdrlen, - 0)); - } + /* Reloading "inside" here since manip_pkt inner. */ + inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4; + inside->icmp.checksum = 0; + inside->icmp.checksum = csum_fold(skb_checksum(*pskb, hdrlen, + (*pskb)->len - hdrlen, + 0)); /* Change outer to look the reply to an incoming packet * (proto 0 means don't invert per-proto part). */ diff --git a/trunk/net/ipv4/netfilter/ip_nat_helper.c b/trunk/net/ipv4/netfilter/ip_nat_helper.c index 7f6a75984f6c..cbcaa45370ae 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_helper.c +++ b/trunk/net/ipv4/netfilter/ip_nat_helper.c @@ -27,12 +27,16 @@ #include #include +#define ASSERT_READ_LOCK(x) +#define ASSERT_WRITE_LOCK(x) + #include #include #include #include #include #include +#include #if 0 #define DEBUGP printk @@ -161,7 +165,7 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb, { struct iphdr *iph; struct tcphdr *tcph; - int oldlen, datalen; + int datalen; if (!skb_make_writable(pskb, (*pskb)->len)) return 0; @@ -176,22 +180,13 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb, iph = (*pskb)->nh.iph; tcph = (void *)iph + iph->ihl*4; - oldlen = (*pskb)->len - iph->ihl*4; mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4, match_offset, match_len, rep_buffer, rep_len); datalen = (*pskb)->len - iph->ihl*4; - if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { - tcph->check = 0; - tcph->check = tcp_v4_check(tcph, datalen, - iph->saddr, iph->daddr, - csum_partial((char *)tcph, - datalen, 0)); - } else - tcph->check = nf_proto_csum_update(*pskb, - htons(oldlen) ^ 0xFFFF, - htons(datalen), - tcph->check, 1); + tcph->check = 0; + tcph->check = tcp_v4_check(tcph, datalen, iph->saddr, iph->daddr, + csum_partial((char *)tcph, datalen, 0)); if (rep_len != match_len) { set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); @@ -226,7 +221,6 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb, { struct iphdr *iph; struct udphdr *udph; - int datalen, oldlen; /* UDP helpers might accidentally mangle the wrong packet */ iph = (*pskb)->nh.iph; @@ -244,32 +238,22 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb, iph = (*pskb)->nh.iph; udph = (void *)iph + iph->ihl*4; - - oldlen = (*pskb)->len - iph->ihl*4; mangle_contents(*pskb, iph->ihl*4 + sizeof(*udph), match_offset, match_len, rep_buffer, rep_len); /* update the length of the UDP packet */ - datalen = (*pskb)->len - iph->ihl*4; - udph->len = htons(datalen); + udph->len = htons((*pskb)->len - iph->ihl*4); /* fix udp checksum if udp checksum was previously calculated */ - if (!udph->check && (*pskb)->ip_summed != CHECKSUM_PARTIAL) - return 1; - - if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) { + if (udph->check) { + int datalen = (*pskb)->len - iph->ihl * 4; udph->check = 0; udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, IPPROTO_UDP, csum_partial((char *)udph, datalen, 0)); - if (!udph->check) - udph->check = -1; - } else - udph->check = nf_proto_csum_update(*pskb, - htons(oldlen) ^ 0xFFFF, - htons(datalen), - udph->check, 1); + } + return 1; } EXPORT_SYMBOL(ip_nat_mangle_udp_packet); @@ -309,14 +293,11 @@ sack_adjust(struct sk_buff *skb, ntohl(sack->start_seq), new_start_seq, ntohl(sack->end_seq), new_end_seq); - tcph->check = nf_proto_csum_update(skb, - ~sack->start_seq, - new_start_seq, - tcph->check, 0); - tcph->check = nf_proto_csum_update(skb, - ~sack->end_seq, - new_end_seq, - tcph->check, 0); + tcph->check = + ip_nat_cheat_check(~sack->start_seq, new_start_seq, + ip_nat_cheat_check(~sack->end_seq, + new_end_seq, + tcph->check)); sack->start_seq = new_start_seq; sack->end_seq = new_end_seq; sackoff += sizeof(*sack); @@ -400,10 +381,10 @@ ip_nat_seq_adjust(struct sk_buff **pskb, newack = ntohl(tcph->ack_seq) - other_way->offset_before; newack = htonl(newack); - tcph->check = nf_proto_csum_update(*pskb, ~tcph->seq, newseq, - tcph->check, 0); - tcph->check = nf_proto_csum_update(*pskb, ~tcph->ack_seq, newack, - tcph->check, 0); + tcph->check = ip_nat_cheat_check(~tcph->seq, newseq, + ip_nat_cheat_check(~tcph->ack_seq, + newack, + tcph->check)); DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n", ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), diff --git a/trunk/net/ipv4/netfilter/ip_nat_helper_pptp.c b/trunk/net/ipv4/netfilter/ip_nat_helper_pptp.c index 2ff578807123..1d149964dc38 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_helper_pptp.c +++ b/trunk/net/ipv4/netfilter/ip_nat_helper_pptp.c @@ -32,7 +32,7 @@ * 2005-06-10 - Version 3.0 * - kernel >= 2.6.11 version, * funded by Oxcoda NetBox Blue (http://www.netboxblue.com/) - * + * */ #include @@ -85,17 +85,19 @@ static void pptp_nat_expected(struct ip_conntrack *ct, DEBUGP("we are PNS->PAC\n"); /* therefore, build tuple for PAC->PNS */ t.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; - t.src.u.gre.key = master->help.ct_pptp_info.pac_call_id; + t.src.u.gre.key = htons(master->help.ct_pptp_info.pac_call_id); t.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; - t.dst.u.gre.key = master->help.ct_pptp_info.pns_call_id; + t.dst.u.gre.key = htons(master->help.ct_pptp_info.pns_call_id); t.dst.protonum = IPPROTO_GRE; } else { DEBUGP("we are PAC->PNS\n"); /* build tuple for PNS->PAC */ t.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; - t.src.u.gre.key = master->nat.help.nat_pptp_info.pns_call_id; + t.src.u.gre.key = + htons(master->nat.help.nat_pptp_info.pns_call_id); t.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; - t.dst.u.gre.key = master->nat.help.nat_pptp_info.pac_call_id; + t.dst.u.gre.key = + htons(master->nat.help.nat_pptp_info.pac_call_id); t.dst.protonum = IPPROTO_GRE; } @@ -147,52 +149,51 @@ pptp_outbound_pkt(struct sk_buff **pskb, { struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info; struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; - u_int16_t msg; - __be16 new_callid; + u_int16_t msg, new_callid; unsigned int cid_off; - new_callid = ct_pptp_info->pns_call_id; - + new_callid = htons(ct_pptp_info->pns_call_id); + switch (msg = ntohs(ctlh->messageType)) { - case PPTP_OUT_CALL_REQUEST: - cid_off = offsetof(union pptp_ctrl_union, ocreq.callID); - /* FIXME: ideally we would want to reserve a call ID - * here. current netfilter NAT core is not able to do - * this :( For now we use TCP source port. This breaks - * multiple calls within one control session */ - - /* save original call ID in nat_info */ - nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id; - - /* don't use tcph->source since we are at a DSTmanip - * hook (e.g. PREROUTING) and pkt is not mangled yet */ - new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port; - - /* save new call ID in ct info */ - ct_pptp_info->pns_call_id = new_callid; - break; - case PPTP_IN_CALL_REPLY: - cid_off = offsetof(union pptp_ctrl_union, icack.callID); - break; - case PPTP_CALL_CLEAR_REQUEST: - cid_off = offsetof(union pptp_ctrl_union, clrreq.callID); - break; - default: - DEBUGP("unknown outbound packet 0x%04x:%s\n", msg, - (msg <= PPTP_MSG_MAX)? - pptp_msg_name[msg]:pptp_msg_name[0]); - /* fall through */ - - case PPTP_SET_LINK_INFO: - /* only need to NAT in case PAC is behind NAT box */ - case PPTP_START_SESSION_REQUEST: - case PPTP_START_SESSION_REPLY: - case PPTP_STOP_SESSION_REQUEST: - case PPTP_STOP_SESSION_REPLY: - case PPTP_ECHO_REQUEST: - case PPTP_ECHO_REPLY: - /* no need to alter packet */ - return NF_ACCEPT; + case PPTP_OUT_CALL_REQUEST: + cid_off = offsetof(union pptp_ctrl_union, ocreq.callID); + /* FIXME: ideally we would want to reserve a call ID + * here. current netfilter NAT core is not able to do + * this :( For now we use TCP source port. This breaks + * multiple calls within one control session */ + + /* save original call ID in nat_info */ + nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id; + + /* don't use tcph->source since we are at a DSTmanip + * hook (e.g. PREROUTING) and pkt is not mangled yet */ + new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port; + + /* save new call ID in ct info */ + ct_pptp_info->pns_call_id = ntohs(new_callid); + break; + case PPTP_IN_CALL_REPLY: + cid_off = offsetof(union pptp_ctrl_union, icreq.callID); + break; + case PPTP_CALL_CLEAR_REQUEST: + cid_off = offsetof(union pptp_ctrl_union, clrreq.callID); + break; + default: + DEBUGP("unknown outbound packet 0x%04x:%s\n", msg, + (msg <= PPTP_MSG_MAX)? + pptp_msg_name[msg]:pptp_msg_name[0]); + /* fall through */ + + case PPTP_SET_LINK_INFO: + /* only need to NAT in case PAC is behind NAT box */ + case PPTP_START_SESSION_REQUEST: + case PPTP_START_SESSION_REPLY: + case PPTP_STOP_SESSION_REQUEST: + case PPTP_STOP_SESSION_REPLY: + case PPTP_ECHO_REQUEST: + case PPTP_ECHO_REPLY: + /* no need to alter packet */ + return NF_ACCEPT; } /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass @@ -211,28 +212,80 @@ pptp_outbound_pkt(struct sk_buff **pskb, return NF_ACCEPT; } -static void +static int pptp_exp_gre(struct ip_conntrack_expect *expect_orig, struct ip_conntrack_expect *expect_reply) { + struct ip_ct_pptp_master *ct_pptp_info = + &expect_orig->master->help.ct_pptp_info; + struct ip_nat_pptp *nat_pptp_info = + &expect_orig->master->nat.help.nat_pptp_info; + struct ip_conntrack *ct = expect_orig->master; - struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info; - struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; + + struct ip_conntrack_tuple inv_t; + struct ip_conntrack_tuple *orig_t, *reply_t; /* save original PAC call ID in nat_info */ nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id; + /* alter expectation */ + orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; + reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; + /* alter expectation for PNS->PAC direction */ - expect_orig->saved_proto.gre.key = ct_pptp_info->pns_call_id; - expect_orig->tuple.src.u.gre.key = nat_pptp_info->pns_call_id; - expect_orig->tuple.dst.u.gre.key = ct_pptp_info->pac_call_id; + invert_tuplepr(&inv_t, &expect_orig->tuple); + expect_orig->saved_proto.gre.key = htons(ct_pptp_info->pns_call_id); + expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id); + expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); expect_orig->dir = IP_CT_DIR_ORIGINAL; + inv_t.src.ip = reply_t->src.ip; + inv_t.dst.ip = reply_t->dst.ip; + inv_t.src.u.gre.key = htons(nat_pptp_info->pac_call_id); + inv_t.dst.u.gre.key = htons(ct_pptp_info->pns_call_id); + + if (!ip_conntrack_expect_related(expect_orig)) { + DEBUGP("successfully registered expect\n"); + } else { + DEBUGP("can't expect_related(expect_orig)\n"); + return 1; + } /* alter expectation for PAC->PNS direction */ - expect_reply->saved_proto.gre.key = nat_pptp_info->pns_call_id; - expect_reply->tuple.src.u.gre.key = nat_pptp_info->pac_call_id; - expect_reply->tuple.dst.u.gre.key = ct_pptp_info->pns_call_id; + invert_tuplepr(&inv_t, &expect_reply->tuple); + expect_reply->saved_proto.gre.key = htons(nat_pptp_info->pns_call_id); + expect_reply->tuple.src.u.gre.key = htons(nat_pptp_info->pac_call_id); + expect_reply->tuple.dst.u.gre.key = htons(ct_pptp_info->pns_call_id); expect_reply->dir = IP_CT_DIR_REPLY; + inv_t.src.ip = orig_t->src.ip; + inv_t.dst.ip = orig_t->dst.ip; + inv_t.src.u.gre.key = htons(nat_pptp_info->pns_call_id); + inv_t.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); + + if (!ip_conntrack_expect_related(expect_reply)) { + DEBUGP("successfully registered expect\n"); + } else { + DEBUGP("can't expect_related(expect_reply)\n"); + ip_conntrack_unexpect_related(expect_orig); + return 1; + } + + if (ip_ct_gre_keymap_add(ct, &expect_reply->tuple, 0) < 0) { + DEBUGP("can't register original keymap\n"); + ip_conntrack_unexpect_related(expect_orig); + ip_conntrack_unexpect_related(expect_reply); + return 1; + } + + if (ip_ct_gre_keymap_add(ct, &inv_t, 1) < 0) { + DEBUGP("can't register reply keymap\n"); + ip_conntrack_unexpect_related(expect_orig); + ip_conntrack_unexpect_related(expect_reply); + ip_ct_gre_keymap_destroy(ct); + return 1; + } + + return 0; } /* inbound packets == from PAC to PNS */ @@ -244,15 +297,15 @@ pptp_inbound_pkt(struct sk_buff **pskb, union pptp_ctrl_union *pptpReq) { struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; - u_int16_t msg; - __be16 new_pcid; - unsigned int pcid_off; + u_int16_t msg, new_cid = 0, new_pcid; + unsigned int pcid_off, cid_off = 0; - new_pcid = nat_pptp_info->pns_call_id; + new_pcid = htons(nat_pptp_info->pns_call_id); switch (msg = ntohs(ctlh->messageType)) { case PPTP_OUT_CALL_REPLY: pcid_off = offsetof(union pptp_ctrl_union, ocack.peersCallID); + cid_off = offsetof(union pptp_ctrl_union, ocack.callID); break; case PPTP_IN_CALL_CONNECT: pcid_off = offsetof(union pptp_ctrl_union, iccon.peersCallID); @@ -271,7 +324,7 @@ pptp_inbound_pkt(struct sk_buff **pskb, break; default: - DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)? + DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)? pptp_msg_name[msg]:pptp_msg_name[0]); /* fall through */ @@ -298,6 +351,17 @@ pptp_inbound_pkt(struct sk_buff **pskb, sizeof(new_pcid), (char *)&new_pcid, sizeof(new_pcid)) == 0) return NF_DROP; + + if (new_cid) { + DEBUGP("altering call id from 0x%04x to 0x%04x\n", + ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_cid)); + if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, + cid_off + sizeof(struct pptp_pkt_hdr) + + sizeof(struct PptpControlHeader), + sizeof(new_cid), (char *)&new_cid, + sizeof(new_cid)) == 0) + return NF_DROP; + } return NF_ACCEPT; } diff --git a/trunk/net/ipv4/netfilter/ip_nat_proto_gre.c b/trunk/net/ipv4/netfilter/ip_nat_proto_gre.c index bf91f9312b3c..38acfdf540eb 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_proto_gre.c +++ b/trunk/net/ipv4/netfilter/ip_nat_proto_gre.c @@ -6,10 +6,10 @@ * GRE is a generic encapsulation protocol, which is generally not very * suited for NAT, as it has no protocol-specific part as port numbers. * - * It has an optional key field, which may help us distinguishing two + * It has an optional key field, which may help us distinguishing two * connections between the same two hosts. * - * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 * * PPTP is built on top of a modified version of GRE, and has a mandatory * field called "CallID", which serves us for the same purpose as the key @@ -60,14 +60,14 @@ gre_in_range(const struct ip_conntrack_tuple *tuple, } /* generate unique tuple ... */ -static int +static int gre_unique_tuple(struct ip_conntrack_tuple *tuple, const struct ip_nat_range *range, enum ip_nat_manip_type maniptype, const struct ip_conntrack *conntrack) { static u_int16_t key; - __be16 *keyptr; + u_int16_t *keyptr; unsigned int min, i, range_size; if (maniptype == IP_NAT_MANIP_SRC) @@ -84,7 +84,7 @@ gre_unique_tuple(struct ip_conntrack_tuple *tuple, range_size = ntohs(range->max.gre.key) - min + 1; } - DEBUGP("min = %u, range_size = %u\n", min, range_size); + DEBUGP("min = %u, range_size = %u\n", min, range_size); for (i = 0; i < range_size; i++, key++) { *keyptr = htons(min + key % range_size); @@ -117,7 +117,7 @@ gre_manip_pkt(struct sk_buff **pskb, greh = (void *)(*pskb)->data + hdroff; pgreh = (struct gre_hdr_pptp *) greh; - /* we only have destination manip of a packet, since 'source key' + /* we only have destination manip of a packet, since 'source key' * is not present in the packet itself */ if (maniptype == IP_NAT_MANIP_DST) { /* key manipulation is always dest */ @@ -129,16 +129,15 @@ gre_manip_pkt(struct sk_buff **pskb, } if (greh->csum) { /* FIXME: Never tested this code... */ - *(gre_csum(greh)) = - nf_proto_csum_update(*pskb, - ~*(gre_key(greh)), + *(gre_csum(greh)) = + ip_nat_cheat_check(~*(gre_key(greh)), tuple->dst.u.gre.key, - *(gre_csum(greh)), 0); + *(gre_csum(greh))); } *(gre_key(greh)) = tuple->dst.u.gre.key; break; case GRE_VERSION_PPTP: - DEBUGP("call_id -> 0x%04x\n", + DEBUGP("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key)); pgreh->call_id = tuple->dst.u.gre.key; break; @@ -152,8 +151,8 @@ gre_manip_pkt(struct sk_buff **pskb, } /* nat helper struct */ -static struct ip_nat_protocol gre = { - .name = "GRE", +static struct ip_nat_protocol gre = { + .name = "GRE", .protonum = IPPROTO_GRE, .manip_pkt = gre_manip_pkt, .in_range = gre_in_range, @@ -164,7 +163,7 @@ static struct ip_nat_protocol gre = { .nfattr_to_range = ip_nat_port_nfattr_to_range, #endif }; - + int __init ip_nat_proto_gre_init(void) { return ip_nat_protocol_register(&gre); diff --git a/trunk/net/ipv4/netfilter/ip_nat_proto_icmp.c b/trunk/net/ipv4/netfilter/ip_nat_proto_icmp.c index ec50cc295317..31a3f4ccb99c 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_proto_icmp.c +++ b/trunk/net/ipv4/netfilter/ip_nat_proto_icmp.c @@ -66,10 +66,10 @@ icmp_manip_pkt(struct sk_buff **pskb, return 0; hdr = (struct icmphdr *)((*pskb)->data + hdroff); - hdr->checksum = nf_proto_csum_update(*pskb, - hdr->un.echo.id ^ 0xFFFF, - tuple->src.u.icmp.id, - hdr->checksum, 0); + + hdr->checksum = ip_nat_cheat_check(hdr->un.echo.id ^ 0xFFFF, + tuple->src.u.icmp.id, + hdr->checksum); hdr->un.echo.id = tuple->src.u.icmp.id; return 1; } diff --git a/trunk/net/ipv4/netfilter/ip_nat_proto_tcp.c b/trunk/net/ipv4/netfilter/ip_nat_proto_tcp.c index 72a6307bd2db..a3d14079eba6 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_proto_tcp.c +++ b/trunk/net/ipv4/netfilter/ip_nat_proto_tcp.c @@ -129,9 +129,10 @@ tcp_manip_pkt(struct sk_buff **pskb, if (hdrsize < sizeof(*hdr)) return 1; - hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, hdr->check, 1); - hdr->check = nf_proto_csum_update(*pskb, oldport ^ 0xFFFF, newport, - hdr->check, 0); + hdr->check = ip_nat_cheat_check(~oldip, newip, + ip_nat_cheat_check(oldport ^ 0xFFFF, + newport, + hdr->check)); return 1; } diff --git a/trunk/net/ipv4/netfilter/ip_nat_proto_udp.c b/trunk/net/ipv4/netfilter/ip_nat_proto_udp.c index 5da196ae758c..ec6053fdc867 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_proto_udp.c +++ b/trunk/net/ipv4/netfilter/ip_nat_proto_udp.c @@ -113,16 +113,11 @@ udp_manip_pkt(struct sk_buff **pskb, newport = tuple->dst.u.udp.port; portptr = &hdr->dest; } - - if (hdr->check || (*pskb)->ip_summed == CHECKSUM_PARTIAL) { - hdr->check = nf_proto_csum_update(*pskb, ~oldip, newip, - hdr->check, 1); - hdr->check = nf_proto_csum_update(*pskb, - *portptr ^ 0xFFFF, newport, - hdr->check, 0); - if (!hdr->check) - hdr->check = -1; - } + if (hdr->check) /* 0 is a special case meaning no checksum */ + hdr->check = ip_nat_cheat_check(~oldip, newip, + ip_nat_cheat_check(*portptr ^ 0xFFFF, + newport, + hdr->check)); *portptr = newport; return 1; } diff --git a/trunk/net/ipv4/netfilter/ip_nat_rule.c b/trunk/net/ipv4/netfilter/ip_nat_rule.c index 7b703839aa58..1aba926c1cb0 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_rule.c +++ b/trunk/net/ipv4/netfilter/ip_nat_rule.c @@ -19,10 +19,14 @@ #include #include +#define ASSERT_READ_LOCK(x) +#define ASSERT_WRITE_LOCK(x) + #include #include #include #include +#include #if 0 #define DEBUGP printk @@ -100,7 +104,8 @@ static unsigned int ipt_snat_target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct ipt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; @@ -142,7 +147,8 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct ipt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; @@ -168,6 +174,7 @@ static int ipt_snat_checkentry(const char *tablename, const void *entry, const struct ipt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { struct ip_nat_multi_range_compat *mr = targinfo; @@ -184,6 +191,7 @@ static int ipt_dnat_checkentry(const char *tablename, const void *entry, const struct ipt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { struct ip_nat_multi_range_compat *mr = targinfo; @@ -247,7 +255,7 @@ int ip_nat_rule_find(struct sk_buff **pskb, { int ret; - ret = ipt_do_table(pskb, hooknum, in, out, &nat_table); + ret = ipt_do_table(pskb, hooknum, in, out, &nat_table, NULL); if (ret == NF_ACCEPT) { if (!ip_nat_initialized(ct, HOOK2MANIP(hooknum))) diff --git a/trunk/net/ipv4/netfilter/ip_nat_standalone.c b/trunk/net/ipv4/netfilter/ip_nat_standalone.c index 9c577db62047..17de077a7901 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_standalone.c +++ b/trunk/net/ipv4/netfilter/ip_nat_standalone.c @@ -30,6 +30,9 @@ #include #include +#define ASSERT_READ_LOCK(x) +#define ASSERT_WRITE_LOCK(x) + #include #include #include @@ -37,6 +40,7 @@ #include #include #include +#include #if 0 #define DEBUGP printk @@ -106,6 +110,11 @@ ip_nat_fn(unsigned int hooknum, IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET))); + /* If we had a hardware checksum before, it's now invalid */ + if ((*pskb)->ip_summed == CHECKSUM_HW) + if (skb_checksum_help(*pskb, (out == NULL))) + return NF_DROP; + ct = ip_conntrack_get(*pskb, &ctinfo); /* Can't track? It's not due to stress, or conntrack would have dropped it. Hence it's the user's responsibilty to @@ -136,8 +145,8 @@ ip_nat_fn(unsigned int hooknum, case IP_CT_RELATED: case IP_CT_RELATED+IP_CT_IS_REPLY: if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) { - if (!ip_nat_icmp_reply_translation(ct, ctinfo, - hooknum, pskb)) + if (!ip_nat_icmp_reply_translation(pskb, ct, maniptype, + CTINFO2DIR(ctinfo))) return NF_DROP; else return NF_ACCEPT; diff --git a/trunk/net/ipv4/netfilter/ip_queue.c b/trunk/net/ipv4/netfilter/ip_queue.c index 7edad790478a..198ac36db861 100644 --- a/trunk/net/ipv4/netfilter/ip_queue.c +++ b/trunk/net/ipv4/netfilter/ip_queue.c @@ -52,15 +52,15 @@ struct ipq_queue_entry { typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long); -static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE; -static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT; +static unsigned char copy_mode = IPQ_COPY_NONE; +static unsigned int queue_maxlen = IPQ_QMAX_DEFAULT; static DEFINE_RWLOCK(queue_lock); -static int peer_pid __read_mostly; -static unsigned int copy_range __read_mostly; +static int peer_pid; +static unsigned int copy_range; static unsigned int queue_total; static unsigned int queue_dropped = 0; static unsigned int queue_user_dropped = 0; -static struct sock *ipqnl __read_mostly; +static struct sock *ipqnl; static LIST_HEAD(queue_list); static DEFINE_MUTEX(ipqnl_mutex); @@ -208,9 +208,9 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) break; case IPQ_COPY_PACKET: - if ((entry->skb->ip_summed == CHECKSUM_PARTIAL || - entry->skb->ip_summed == CHECKSUM_COMPLETE) && - (*errp = skb_checksum_help(entry->skb))) { + if (entry->skb->ip_summed == CHECKSUM_HW && + (*errp = skb_checksum_help(entry->skb, + entry->info->outdev == NULL))) { read_unlock_bh(&queue_lock); return NULL; } diff --git a/trunk/net/ipv4/netfilter/ip_tables.c b/trunk/net/ipv4/netfilter/ip_tables.c index 800067d69a9a..fc5bdd5eb7d3 100644 --- a/trunk/net/ipv4/netfilter/ip_tables.c +++ b/trunk/net/ipv4/netfilter/ip_tables.c @@ -180,7 +180,8 @@ ipt_error(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { if (net_ratelimit()) printk("ip_tables: error: `%s'\n", (char *)targinfo); @@ -216,7 +217,8 @@ ipt_do_table(struct sk_buff **pskb, unsigned int hook, const struct net_device *in, const struct net_device *out, - struct ipt_table *table) + struct ipt_table *table, + void *userdata) { static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); u_int16_t offset; @@ -228,7 +230,7 @@ ipt_do_table(struct sk_buff **pskb, const char *indev, *outdev; void *table_base; struct ipt_entry *e, *back; - struct xt_table_info *private; + struct xt_table_info *private = table->private; /* Initialization */ ip = (*pskb)->nh.iph; @@ -245,7 +247,6 @@ ipt_do_table(struct sk_buff **pskb, read_lock_bh(&table->lock); IP_NF_ASSERT(table->valid_hooks & (1 << hook)); - private = table->private; table_base = (void *)private->entries[smp_processor_id()]; e = get_entry(table_base, private->hook_entry[hook]); @@ -306,7 +307,8 @@ ipt_do_table(struct sk_buff **pskb, in, out, hook, t->u.kernel.target, - t->data); + t->data, + userdata); #ifdef CONFIG_NETFILTER_DEBUG if (((struct ipt_entry *)table_base)->comefrom @@ -464,7 +466,8 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i) return 1; if (m->u.kernel.match->destroy) - m->u.kernel.match->destroy(m->u.kernel.match, m->data); + m->u.kernel.match->destroy(m->u.kernel.match, m->data, + m->u.match_size - sizeof(*m)); module_put(m->u.kernel.match->me); return 0; } @@ -517,6 +520,7 @@ check_match(struct ipt_entry_match *m, if (m->u.kernel.match->checkentry && !m->u.kernel.match->checkentry(name, ip, match, m->data, + m->u.match_size - sizeof(*m), hookmask)) { duprintf("ip_tables: check failed for `%s'.\n", m->u.kernel.match->name); @@ -573,10 +577,12 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, if (t->u.kernel.target == &ipt_standard_target) { if (!standard_check(t, size)) { ret = -EINVAL; - goto err; + goto cleanup_matches; } } else if (t->u.kernel.target->checkentry && !t->u.kernel.target->checkentry(name, e, target, t->data, + t->u.target_size + - sizeof(*t), e->comefrom)) { duprintf("ip_tables: check failed for `%s'.\n", t->u.kernel.target->name); @@ -648,7 +654,8 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i) IPT_MATCH_ITERATE(e, cleanup_match, NULL); t = ipt_get_target(e); if (t->u.kernel.target->destroy) - t->u.kernel.target->destroy(t->u.kernel.target, t->data); + t->u.kernel.target->destroy(t->u.kernel.target, t->data, + t->u.target_size - sizeof(*t)); module_put(t->u.kernel.target->me); return 0; } @@ -942,28 +949,73 @@ static short compat_calc_jump(u_int16_t offset) return delta; } -static void compat_standard_from_user(void *dst, void *src) +struct compat_ipt_standard_target { - int v = *(compat_int_t *)src; + struct compat_xt_entry_target target; + compat_int_t verdict; +}; - if (v > 0) - v += compat_calc_jump(v); - memcpy(dst, &v, sizeof(v)); -} +struct compat_ipt_standard +{ + struct compat_ipt_entry entry; + struct compat_ipt_standard_target target; +}; -static int compat_standard_to_user(void __user *dst, void *src) +#define IPT_ST_LEN XT_ALIGN(sizeof(struct ipt_standard_target)) +#define IPT_ST_COMPAT_LEN COMPAT_XT_ALIGN(sizeof(struct compat_ipt_standard_target)) +#define IPT_ST_OFFSET (IPT_ST_LEN - IPT_ST_COMPAT_LEN) + +static int compat_ipt_standard_fn(void *target, + void **dstptr, int *size, int convert) { - compat_int_t cv = *(int *)src; + struct compat_ipt_standard_target compat_st, *pcompat_st; + struct ipt_standard_target st, *pst; + int ret; - if (cv > 0) - cv -= compat_calc_jump(cv); - return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; + ret = 0; + switch (convert) { + case COMPAT_TO_USER: + pst = target; + memcpy(&compat_st.target, &pst->target, + sizeof(compat_st.target)); + compat_st.verdict = pst->verdict; + if (compat_st.verdict > 0) + compat_st.verdict -= + compat_calc_jump(compat_st.verdict); + compat_st.target.u.user.target_size = IPT_ST_COMPAT_LEN; + if (copy_to_user(*dstptr, &compat_st, IPT_ST_COMPAT_LEN)) + ret = -EFAULT; + *size -= IPT_ST_OFFSET; + *dstptr += IPT_ST_COMPAT_LEN; + break; + case COMPAT_FROM_USER: + pcompat_st = target; + memcpy(&st.target, &pcompat_st->target, IPT_ST_COMPAT_LEN); + st.verdict = pcompat_st->verdict; + if (st.verdict > 0) + st.verdict += compat_calc_jump(st.verdict); + st.target.u.user.target_size = IPT_ST_LEN; + memcpy(*dstptr, &st, IPT_ST_LEN); + *size += IPT_ST_OFFSET; + *dstptr += IPT_ST_LEN; + break; + case COMPAT_CALC_SIZE: + *size += IPT_ST_OFFSET; + break; + default: + ret = -ENOPROTOOPT; + break; + } + return ret; } static inline int compat_calc_match(struct ipt_entry_match *m, int * size) { - *size += xt_compat_match_offset(m->u.kernel.match); + if (m->u.kernel.match->compat) + m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE); + else + xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE); return 0; } @@ -978,7 +1030,10 @@ static int compat_calc_entry(struct ipt_entry *e, struct xt_table_info *info, entry_offset = (void *)e - base; IPT_MATCH_ITERATE(e, compat_calc_match, &off); t = ipt_get_target(e); - off += xt_compat_target_offset(t->u.kernel.target); + if (t->u.kernel.target->compat) + t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE); + else + xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE); newinfo->size -= off; ret = compat_add_offset(entry_offset, off); if (ret) @@ -1364,13 +1419,17 @@ struct compat_ipt_replace { }; static inline int compat_copy_match_to_user(struct ipt_entry_match *m, - void * __user *dstptr, compat_uint_t *size) + void __user **dstptr, compat_uint_t *size) { - return xt_compat_match_to_user(m, dstptr, size); + if (m->u.kernel.match->compat) + return m->u.kernel.match->compat(m, dstptr, size, + COMPAT_TO_USER); + else + return xt_compat_match(m, dstptr, size, COMPAT_TO_USER); } static int compat_copy_entry_to_user(struct ipt_entry *e, - void * __user *dstptr, compat_uint_t *size) + void __user **dstptr, compat_uint_t *size) { struct ipt_entry_target __user *t; struct compat_ipt_entry __user *ce; @@ -1390,7 +1449,11 @@ static int compat_copy_entry_to_user(struct ipt_entry *e, if (ret) goto out; t = ipt_get_target(e); - ret = xt_compat_target_to_user(t, dstptr, size); + if (t->u.kernel.target->compat) + ret = t->u.kernel.target->compat(t, dstptr, size, + COMPAT_TO_USER); + else + ret = xt_compat_target(t, dstptr, size, COMPAT_TO_USER); if (ret) goto out; ret = -EFAULT; @@ -1422,7 +1485,11 @@ compat_check_calc_match(struct ipt_entry_match *m, return match ? PTR_ERR(match) : -ENOENT; } m->u.kernel.match = match; - *size += xt_compat_match_offset(match); + + if (m->u.kernel.match->compat) + m->u.kernel.match->compat(m, NULL, size, COMPAT_CALC_SIZE); + else + xt_compat_match(m, NULL, size, COMPAT_CALC_SIZE); (*i)++; return 0; @@ -1469,7 +1536,7 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e, ret = IPT_MATCH_ITERATE(e, compat_check_calc_match, name, &e->ip, e->comefrom, &off, &j); if (ret != 0) - goto cleanup_matches; + goto out; t = ipt_get_target(e); target = try_then_request_module(xt_find_target(AF_INET, @@ -1479,11 +1546,14 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e, if (IS_ERR(target) || !target) { duprintf("check_entry: `%s' not found\n", t->u.user.name); ret = target ? PTR_ERR(target) : -ENOENT; - goto cleanup_matches; + goto out; } t->u.kernel.target = target; - off += xt_compat_target_offset(target); + if (t->u.kernel.target->compat) + t->u.kernel.target->compat(t, NULL, &off, COMPAT_CALC_SIZE); + else + xt_compat_target(t, NULL, &off, COMPAT_CALC_SIZE); *size += off; ret = compat_add_offset(entry_offset, off); if (ret) @@ -1503,17 +1573,14 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e, (*i)++; return 0; - out: - module_put(t->u.kernel.target->me); -cleanup_matches: IPT_MATCH_ITERATE(e, cleanup_match, &j); return ret; } static inline int compat_copy_match_from_user(struct ipt_entry_match *m, void **dstptr, compat_uint_t *size, const char *name, - const struct ipt_ip *ip, unsigned int hookmask, int *i) + const struct ipt_ip *ip, unsigned int hookmask) { struct ipt_entry_match *dm; struct ipt_match *match; @@ -1521,28 +1588,26 @@ static inline int compat_copy_match_from_user(struct ipt_entry_match *m, dm = (struct ipt_entry_match *)*dstptr; match = m->u.kernel.match; - xt_compat_match_from_user(m, dstptr, size); + if (match->compat) + match->compat(m, dstptr, size, COMPAT_FROM_USER); + else + xt_compat_match(m, dstptr, size, COMPAT_FROM_USER); ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm), name, hookmask, ip->proto, ip->invflags & IPT_INV_PROTO); if (ret) - goto err; + return ret; if (m->u.kernel.match->checkentry && !m->u.kernel.match->checkentry(name, ip, match, dm->data, + dm->u.match_size - sizeof(*dm), hookmask)) { duprintf("ip_tables: check failed for `%s'.\n", m->u.kernel.match->name); - ret = -EINVAL; - goto err; + return -EINVAL; } - (*i)++; return 0; - -err: - module_put(m->u.kernel.match->me); - return ret; } static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, @@ -1553,23 +1618,25 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, struct ipt_target *target; struct ipt_entry *de; unsigned int origsize; - int ret, h, j; + int ret, h; ret = 0; origsize = *size; de = (struct ipt_entry *)*dstptr; memcpy(de, e, sizeof(struct ipt_entry)); - j = 0; *dstptr += sizeof(struct compat_ipt_entry); ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size, - name, &de->ip, de->comefrom, &j); + name, &de->ip, de->comefrom); if (ret) - goto cleanup_matches; + goto out; de->target_offset = e->target_offset - (origsize - *size); t = ipt_get_target(e); target = t->u.kernel.target; - xt_compat_target_from_user(t, dstptr, size); + if (target->compat) + target->compat(t, dstptr, size, COMPAT_FROM_USER); + else + xt_compat_target(t, dstptr, size, COMPAT_FROM_USER); de->next_offset = e->next_offset - (origsize - *size); for (h = 0; h < NF_IP_NUMHOOKS; h++) { @@ -1585,26 +1652,22 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, name, e->comefrom, e->ip.proto, e->ip.invflags & IPT_INV_PROTO); if (ret) - goto err; + goto out; ret = -EINVAL; if (t->u.kernel.target == &ipt_standard_target) { if (!standard_check(t, *size)) - goto err; + goto out; } else if (t->u.kernel.target->checkentry && !t->u.kernel.target->checkentry(name, de, target, - t->data, de->comefrom)) { + t->data, t->u.target_size - sizeof(*t), + de->comefrom)) { duprintf("ip_tables: compat: check failed for `%s'.\n", t->u.kernel.target->name); - goto err; + goto out; } ret = 0; - return ret; - -err: - module_put(t->u.kernel.target->me); -cleanup_matches: - IPT_MATCH_ITERATE(e, cleanup_match, &j); +out: return ret; } @@ -1925,8 +1988,6 @@ compat_get_entries(struct compat_ipt_get_entries __user *uptr, int *len) return ret; } -static int do_ipt_get_ctl(struct sock *, int, void __user *, int *); - static int compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) { @@ -1940,7 +2001,8 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) ret = compat_get_entries(user, len); break; default: - ret = do_ipt_get_ctl(sk, cmd, user, len); + duprintf("compat_do_ipt_get_ctl: unknown request %i\n", cmd); + ret = -EINVAL; } return ret; } @@ -2122,6 +2184,7 @@ icmp_checkentry(const char *tablename, const void *info, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct ipt_icmp *icmpinfo = matchinfo; @@ -2136,9 +2199,7 @@ static struct ipt_target ipt_standard_target = { .targetsize = sizeof(int), .family = AF_INET, #ifdef CONFIG_COMPAT - .compatsize = sizeof(compat_int_t), - .compat_from_user = compat_standard_from_user, - .compat_to_user = compat_standard_to_user, + .compat = &compat_ipt_standard_fn, #endif }; @@ -2178,39 +2239,22 @@ static int __init ip_tables_init(void) { int ret; - ret = xt_proto_init(AF_INET); - if (ret < 0) - goto err1; + xt_proto_init(AF_INET); /* Noone else will be downing sem now, so we won't sleep */ - ret = xt_register_target(&ipt_standard_target); - if (ret < 0) - goto err2; - ret = xt_register_target(&ipt_error_target); - if (ret < 0) - goto err3; - ret = xt_register_match(&icmp_matchstruct); - if (ret < 0) - goto err4; + xt_register_target(&ipt_standard_target); + xt_register_target(&ipt_error_target); + xt_register_match(&icmp_matchstruct); /* Register setsockopt */ ret = nf_register_sockopt(&ipt_sockopts); - if (ret < 0) - goto err5; + if (ret < 0) { + duprintf("Unable to register sockopts.\n"); + return ret; + } printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n"); return 0; - -err5: - xt_unregister_match(&icmp_matchstruct); -err4: - xt_unregister_target(&ipt_error_target); -err3: - xt_unregister_target(&ipt_standard_target); -err2: - xt_proto_fini(AF_INET); -err1: - return ret; } static void __exit ip_tables_fini(void) diff --git a/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c b/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c index 41589665fc5d..d994c5f5744c 100644 --- a/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -302,7 +302,8 @@ target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { const struct ipt_clusterip_tgt_info *cipinfo = targinfo; enum ip_conntrack_info ctinfo; @@ -372,6 +373,7 @@ checkentry(const char *tablename, const void *e_void, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { struct ipt_clusterip_tgt_info *cipinfo = targinfo; @@ -448,7 +450,8 @@ checkentry(const char *tablename, } /* drop reference count of cluster config when rule is deleted */ -static void destroy(const struct xt_target *target, void *targinfo) +static void destroy(const struct xt_target *target, void *targinfo, + unsigned int targinfosize) { struct ipt_clusterip_tgt_info *cipinfo = targinfo; diff --git a/trunk/net/ipv4/netfilter/ipt_DSCP.c b/trunk/net/ipv4/netfilter/ipt_DSCP.c new file mode 100644 index 000000000000..c8e971288dfe --- /dev/null +++ b/trunk/net/ipv4/netfilter/ipt_DSCP.c @@ -0,0 +1,96 @@ +/* iptables module for setting the IPv4 DSCP field, Version 1.8 + * + * (C) 2002 by Harald Welte + * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * See RFC2474 for a description of the DSCP field within the IP Header. + * + * ipt_DSCP.c,v 1.8 2002/08/06 18:41:57 laforge Exp +*/ + +#include +#include +#include +#include + +#include +#include + +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("iptables DSCP modification module"); +MODULE_LICENSE("GPL"); + +static unsigned int +target(struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, + const struct xt_target *target, + const void *targinfo, + void *userinfo) +{ + const struct ipt_DSCP_info *dinfo = targinfo; + u_int8_t sh_dscp = ((dinfo->dscp << IPT_DSCP_SHIFT) & IPT_DSCP_MASK); + + + if (((*pskb)->nh.iph->tos & IPT_DSCP_MASK) != sh_dscp) { + u_int16_t diffs[2]; + + if (!skb_make_writable(pskb, sizeof(struct iphdr))) + return NF_DROP; + + diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF; + (*pskb)->nh.iph->tos = ((*pskb)->nh.iph->tos & ~IPT_DSCP_MASK) + | sh_dscp; + diffs[1] = htons((*pskb)->nh.iph->tos); + (*pskb)->nh.iph->check + = csum_fold(csum_partial((char *)diffs, + sizeof(diffs), + (*pskb)->nh.iph->check + ^ 0xFFFF)); + } + return IPT_CONTINUE; +} + +static int +checkentry(const char *tablename, + const void *e_void, + const struct xt_target *target, + void *targinfo, + unsigned int targinfosize, + unsigned int hook_mask) +{ + const u_int8_t dscp = ((struct ipt_DSCP_info *)targinfo)->dscp; + + if ((dscp > IPT_DSCP_MAX)) { + printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp); + return 0; + } + return 1; +} + +static struct ipt_target ipt_dscp_reg = { + .name = "DSCP", + .target = target, + .targetsize = sizeof(struct ipt_DSCP_info), + .table = "mangle", + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static int __init ipt_dscp_init(void) +{ + return ipt_register_target(&ipt_dscp_reg); +} + +static void __exit ipt_dscp_fini(void) +{ + ipt_unregister_target(&ipt_dscp_reg); +} + +module_init(ipt_dscp_init); +module_exit(ipt_dscp_fini); diff --git a/trunk/net/ipv4/netfilter/ipt_ECN.c b/trunk/net/ipv4/netfilter/ipt_ECN.c index 23f9c7ebe7eb..4adf5c9d34f5 100644 --- a/trunk/net/ipv4/netfilter/ipt_ECN.c +++ b/trunk/net/ipv4/netfilter/ipt_ECN.c @@ -27,28 +27,32 @@ MODULE_DESCRIPTION("iptables ECN modification module"); static inline int set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) { - struct iphdr *iph = (*pskb)->nh.iph; - u_int16_t oldtos; + if (((*pskb)->nh.iph->tos & IPT_ECN_IP_MASK) + != (einfo->ip_ect & IPT_ECN_IP_MASK)) { + u_int16_t diffs[2]; - if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { if (!skb_make_writable(pskb, sizeof(struct iphdr))) return 0; - iph = (*pskb)->nh.iph; - oldtos = iph->tos; - iph->tos &= ~IPT_ECN_IP_MASK; - iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); - iph->check = nf_csum_update(oldtos ^ 0xFFFF, iph->tos, - iph->check); + + diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF; + (*pskb)->nh.iph->tos &= ~IPT_ECN_IP_MASK; + (*pskb)->nh.iph->tos |= (einfo->ip_ect & IPT_ECN_IP_MASK); + diffs[1] = htons((*pskb)->nh.iph->tos); + (*pskb)->nh.iph->check + = csum_fold(csum_partial((char *)diffs, + sizeof(diffs), + (*pskb)->nh.iph->check + ^0xFFFF)); } return 1; } /* Return 0 if there was an error. */ static inline int -set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) +set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward) { struct tcphdr _tcph, *tcph; - u_int16_t oldval; + u_int16_t diffs[2]; /* Not enought header? */ tcph = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4, @@ -66,16 +70,22 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo) return 0; tcph = (void *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl*4; - oldval = ((u_int16_t *)tcph)[6]; + if ((*pskb)->ip_summed == CHECKSUM_HW && + skb_checksum_help(*pskb, inward)) + return 0; + + diffs[0] = ((u_int16_t *)tcph)[6]; if (einfo->operation & IPT_ECN_OP_SET_ECE) tcph->ece = einfo->proto.tcp.ece; if (einfo->operation & IPT_ECN_OP_SET_CWR) tcph->cwr = einfo->proto.tcp.cwr; + diffs[1] = ((u_int16_t *)tcph)[6]; + diffs[0] = diffs[0] ^ 0xFFFF; - tcph->check = nf_proto_csum_update((*pskb), - oldval ^ 0xFFFF, - ((u_int16_t *)tcph)[6], - tcph->check, 0); + if ((*pskb)->ip_summed != CHECKSUM_UNNECESSARY) + tcph->check = csum_fold(csum_partial((char *)diffs, + sizeof(diffs), + tcph->check^0xFFFF)); return 1; } @@ -85,7 +95,8 @@ target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { const struct ipt_ECN_info *einfo = targinfo; @@ -95,7 +106,7 @@ target(struct sk_buff **pskb, if (einfo->operation & (IPT_ECN_OP_SET_ECE | IPT_ECN_OP_SET_CWR) && (*pskb)->nh.iph->protocol == IPPROTO_TCP) - if (!set_ect_tcp(pskb, einfo)) + if (!set_ect_tcp(pskb, einfo, (out == NULL))) return NF_DROP; return IPT_CONTINUE; @@ -106,6 +117,7 @@ checkentry(const char *tablename, const void *e_void, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; diff --git a/trunk/net/ipv4/netfilter/ipt_LOG.c b/trunk/net/ipv4/netfilter/ipt_LOG.c index 7dc820df8bc5..b98f7b08b084 100644 --- a/trunk/net/ipv4/netfilter/ipt_LOG.c +++ b/trunk/net/ipv4/netfilter/ipt_LOG.c @@ -416,7 +416,8 @@ ipt_log_target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { const struct ipt_log_info *loginfo = targinfo; struct nf_loginfo li; @@ -439,6 +440,7 @@ static int ipt_log_checkentry(const char *tablename, const void *e, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_log_info *loginfo = targinfo; diff --git a/trunk/net/ipv4/netfilter/ipt_MASQUERADE.c b/trunk/net/ipv4/netfilter/ipt_MASQUERADE.c index bc65168a3437..ebd94f2abf0d 100644 --- a/trunk/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/trunk/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -42,6 +42,7 @@ masquerade_check(const char *tablename, const void *e, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { const struct ip_nat_multi_range_compat *mr = targinfo; @@ -63,7 +64,8 @@ masquerade_target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; diff --git a/trunk/net/ipv4/netfilter/ipt_NETMAP.c b/trunk/net/ipv4/netfilter/ipt_NETMAP.c index beb2914225ff..736c4b5a86a7 100644 --- a/trunk/net/ipv4/netfilter/ipt_NETMAP.c +++ b/trunk/net/ipv4/netfilter/ipt_NETMAP.c @@ -33,6 +33,7 @@ check(const char *tablename, const void *e, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { const struct ip_nat_multi_range_compat *mr = targinfo; @@ -54,7 +55,8 @@ target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; diff --git a/trunk/net/ipv4/netfilter/ipt_REDIRECT.c b/trunk/net/ipv4/netfilter/ipt_REDIRECT.c index f03d43671c6d..f290463232de 100644 --- a/trunk/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/trunk/net/ipv4/netfilter/ipt_REDIRECT.c @@ -36,6 +36,7 @@ redirect_check(const char *tablename, const void *e, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { const struct ip_nat_multi_range_compat *mr = targinfo; @@ -57,7 +58,8 @@ redirect_target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; diff --git a/trunk/net/ipv4/netfilter/ipt_REJECT.c b/trunk/net/ipv4/netfilter/ipt_REJECT.c index b81821edd893..269bc2067cb8 100644 --- a/trunk/net/ipv4/netfilter/ipt_REJECT.c +++ b/trunk/net/ipv4/netfilter/ipt_REJECT.c @@ -90,7 +90,6 @@ static inline struct rtable *route_reverse(struct sk_buff *skb, fl.proto = IPPROTO_TCP; fl.fl_ip_sport = tcph->dest; fl.fl_ip_dport = tcph->source; - security_skb_classify_flow(skb, &fl); xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0); @@ -185,7 +184,6 @@ static void send_reset(struct sk_buff *oldskb, int hook) tcph->urg_ptr = 0; /* Adjust TCP checksum */ - nskb->ip_summed = CHECKSUM_NONE; tcph->check = 0; tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr), nskb->nh.iph->saddr, @@ -228,7 +226,8 @@ static unsigned int reject(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { const struct ipt_reject_info *reject = targinfo; @@ -276,6 +275,7 @@ static int check(const char *tablename, const void *e_void, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_reject_info *rejinfo = targinfo; diff --git a/trunk/net/ipv4/netfilter/ipt_SAME.c b/trunk/net/ipv4/netfilter/ipt_SAME.c index efbcb1198832..7169b09b5a67 100644 --- a/trunk/net/ipv4/netfilter/ipt_SAME.c +++ b/trunk/net/ipv4/netfilter/ipt_SAME.c @@ -52,6 +52,7 @@ same_check(const char *tablename, const void *e, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { unsigned int count, countess, rangeip, index = 0; @@ -115,7 +116,8 @@ same_check(const char *tablename, } static void -same_destroy(const struct xt_target *target, void *targinfo) +same_destroy(const struct xt_target *target, void *targinfo, + unsigned int targinfosize) { struct ipt_same_info *mr = targinfo; @@ -131,7 +133,8 @@ same_target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; diff --git a/trunk/net/ipv4/netfilter/ipt_TCPMSS.c b/trunk/net/ipv4/netfilter/ipt_TCPMSS.c index 4246c4321e5b..ef2fe5b3f0d8 100644 --- a/trunk/net/ipv4/netfilter/ipt_TCPMSS.c +++ b/trunk/net/ipv4/netfilter/ipt_TCPMSS.c @@ -21,14 +21,26 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher "); MODULE_DESCRIPTION("iptables TCP MSS modification module"); +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +static u_int16_t +cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck) +{ + u_int32_t diffs[] = { oldvalinv, newval }; + return csum_fold(csum_partial((char *)diffs, sizeof(diffs), + oldcheck^0xFFFF)); +} + static inline unsigned int optlen(const u_int8_t *opt, unsigned int offset) { /* Beware zero-length options: make finite progress */ - if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0) - return 1; - else - return opt[offset+1]; + if (opt[offset] <= TCPOPT_NOP || opt[offset+1] == 0) return 1; + else return opt[offset+1]; } static unsigned int @@ -37,7 +49,8 @@ ipt_tcpmss_target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { const struct ipt_tcpmss_info *tcpmssinfo = targinfo; struct tcphdr *tcph; @@ -49,8 +62,13 @@ ipt_tcpmss_target(struct sk_buff **pskb, if (!skb_make_writable(pskb, (*pskb)->len)) return NF_DROP; + if ((*pskb)->ip_summed == CHECKSUM_HW && + skb_checksum_help(*pskb, out == NULL)) + return NF_DROP; + iph = (*pskb)->nh.iph; tcplen = (*pskb)->len - iph->ihl*4; + tcph = (void *)iph + iph->ihl*4; /* Since it passed flags test in tcp match, we know it is is @@ -66,41 +84,54 @@ ipt_tcpmss_target(struct sk_buff **pskb, return NF_DROP; } - if (tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) { - if (dst_mtu((*pskb)->dst) <= sizeof(struct iphdr) + - sizeof(struct tcphdr)) { + if(tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) { + if(!(*pskb)->dst) { if (net_ratelimit()) - printk(KERN_ERR "ipt_tcpmss_target: " - "unknown or invalid path-MTU (%d)\n", - dst_mtu((*pskb)->dst)); + printk(KERN_ERR + "ipt_tcpmss_target: no dst?! can't determine path-MTU\n"); return NF_DROP; /* or IPT_CONTINUE ?? */ } - newmss = dst_mtu((*pskb)->dst) - sizeof(struct iphdr) - - sizeof(struct tcphdr); + if(dst_mtu((*pskb)->dst) <= (sizeof(struct iphdr) + sizeof(struct tcphdr))) { + if (net_ratelimit()) + printk(KERN_ERR + "ipt_tcpmss_target: unknown or invalid path-MTU (%d)\n", dst_mtu((*pskb)->dst)); + return NF_DROP; /* or IPT_CONTINUE ?? */ + } + + newmss = dst_mtu((*pskb)->dst) - sizeof(struct iphdr) - sizeof(struct tcphdr); } else newmss = tcpmssinfo->mss; opt = (u_int8_t *)tcph; - for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)) { - if (opt[i] == TCPOPT_MSS && tcph->doff*4 - i >= TCPOLEN_MSS && - opt[i+1] == TCPOLEN_MSS) { + for (i = sizeof(struct tcphdr); i < tcph->doff*4; i += optlen(opt, i)){ + if ((opt[i] == TCPOPT_MSS) && + ((tcph->doff*4 - i) >= TCPOLEN_MSS) && + (opt[i+1] == TCPOLEN_MSS)) { u_int16_t oldmss; oldmss = (opt[i+2] << 8) | opt[i+3]; - if (tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU && - oldmss <= newmss) - return IPT_CONTINUE; + if((tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) && + (oldmss <= newmss)) + return IPT_CONTINUE; opt[i+2] = (newmss & 0xff00) >> 8; opt[i+3] = (newmss & 0x00ff); - tcph->check = nf_proto_csum_update(*pskb, - htons(oldmss)^0xFFFF, - htons(newmss), - tcph->check, 0); - return IPT_CONTINUE; + tcph->check = cheat_check(htons(oldmss)^0xFFFF, + htons(newmss), + tcph->check); + + DEBUGP(KERN_INFO "ipt_tcpmss_target: %u.%u.%u.%u:%hu" + "->%u.%u.%u.%u:%hu changed TCP MSS option" + " (from %u to %u)\n", + NIPQUAD((*pskb)->nh.iph->saddr), + ntohs(tcph->source), + NIPQUAD((*pskb)->nh.iph->daddr), + ntohs(tcph->dest), + oldmss, newmss); + goto retmodified; } } @@ -112,8 +143,13 @@ ipt_tcpmss_target(struct sk_buff **pskb, newskb = skb_copy_expand(*pskb, skb_headroom(*pskb), TCPOLEN_MSS, GFP_ATOMIC); - if (!newskb) + if (!newskb) { + if (net_ratelimit()) + printk(KERN_ERR "ipt_tcpmss_target:" + " unable to allocate larger skb\n"); return NF_DROP; + } + kfree_skb(*pskb); *pskb = newskb; iph = (*pskb)->nh.iph; @@ -125,29 +161,36 @@ ipt_tcpmss_target(struct sk_buff **pskb, opt = (u_int8_t *)tcph + sizeof(struct tcphdr); memmove(opt + TCPOLEN_MSS, opt, tcplen - sizeof(struct tcphdr)); - tcph->check = nf_proto_csum_update(*pskb, - htons(tcplen) ^ 0xFFFF, - htons(tcplen + TCPOLEN_MSS), - tcph->check, 1); + tcph->check = cheat_check(htons(tcplen) ^ 0xFFFF, + htons(tcplen + TCPOLEN_MSS), tcph->check); + tcplen += TCPOLEN_MSS; + opt[0] = TCPOPT_MSS; opt[1] = TCPOLEN_MSS; opt[2] = (newmss & 0xff00) >> 8; opt[3] = (newmss & 0x00ff); - tcph->check = nf_proto_csum_update(*pskb, ~0, *((u_int32_t *)opt), - tcph->check, 0); + tcph->check = cheat_check(~0, *((u_int32_t *)opt), tcph->check); oldval = ((u_int16_t *)tcph)[6]; tcph->doff += TCPOLEN_MSS/4; - tcph->check = nf_proto_csum_update(*pskb, - oldval ^ 0xFFFF, - ((u_int16_t *)tcph)[6], - tcph->check, 0); + tcph->check = cheat_check(oldval ^ 0xFFFF, + ((u_int16_t *)tcph)[6], tcph->check); newtotlen = htons(ntohs(iph->tot_len) + TCPOLEN_MSS); - iph->check = nf_csum_update(iph->tot_len ^ 0xFFFF, - newtotlen, iph->check); + iph->check = cheat_check(iph->tot_len ^ 0xFFFF, + newtotlen, iph->check); iph->tot_len = newtotlen; + + DEBUGP(KERN_INFO "ipt_tcpmss_target: %u.%u.%u.%u:%hu" + "->%u.%u.%u.%u:%hu added TCP MSS option (%u)\n", + NIPQUAD((*pskb)->nh.iph->saddr), + ntohs(tcph->source), + NIPQUAD((*pskb)->nh.iph->daddr), + ntohs(tcph->dest), + newmss); + + retmodified: return IPT_CONTINUE; } @@ -157,9 +200,9 @@ static inline int find_syn_match(const struct ipt_entry_match *m) { const struct ipt_tcp *tcpinfo = (const struct ipt_tcp *)m->data; - if (strcmp(m->u.kernel.match->name, "tcp") == 0 && - tcpinfo->flg_cmp & TH_SYN && - !(tcpinfo->invflags & IPT_TCP_INV_FLAGS)) + if (strcmp(m->u.kernel.match->name, "tcp") == 0 + && (tcpinfo->flg_cmp & TH_SYN) + && !(tcpinfo->invflags & IPT_TCP_INV_FLAGS)) return 1; return 0; @@ -171,17 +214,17 @@ ipt_tcpmss_checkentry(const char *tablename, const void *e_void, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { const struct ipt_tcpmss_info *tcpmssinfo = targinfo; const struct ipt_entry *e = e_void; - if (tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU && - (hook_mask & ~((1 << NF_IP_FORWARD) | - (1 << NF_IP_LOCAL_OUT) | - (1 << NF_IP_POST_ROUTING))) != 0) { - printk("TCPMSS: path-MTU clamping only supported in " - "FORWARD, OUTPUT and POSTROUTING hooks\n"); + if((tcpmssinfo->mss == IPT_TCPMSS_CLAMP_PMTU) && + ((hook_mask & ~((1 << NF_IP_FORWARD) + | (1 << NF_IP_LOCAL_OUT) + | (1 << NF_IP_POST_ROUTING))) != 0)) { + printk("TCPMSS: path-MTU clamping only supported in FORWARD, OUTPUT and POSTROUTING hooks\n"); return 0; } diff --git a/trunk/net/ipv4/netfilter/ipt_TOS.c b/trunk/net/ipv4/netfilter/ipt_TOS.c index 471a4c438b0a..1c7a5ca399b3 100644 --- a/trunk/net/ipv4/netfilter/ipt_TOS.c +++ b/trunk/net/ipv4/netfilter/ipt_TOS.c @@ -26,20 +26,27 @@ target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { const struct ipt_tos_target_info *tosinfo = targinfo; - struct iphdr *iph = (*pskb)->nh.iph; - u_int16_t oldtos; - if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { + if (((*pskb)->nh.iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { + u_int16_t diffs[2]; + if (!skb_make_writable(pskb, sizeof(struct iphdr))) return NF_DROP; - iph = (*pskb)->nh.iph; - oldtos = iph->tos; - iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos; - iph->check = nf_csum_update(oldtos ^ 0xFFFF, iph->tos, - iph->check); + + diffs[0] = htons((*pskb)->nh.iph->tos) ^ 0xFFFF; + (*pskb)->nh.iph->tos + = ((*pskb)->nh.iph->tos & IPTOS_PREC_MASK) + | tosinfo->tos; + diffs[1] = htons((*pskb)->nh.iph->tos); + (*pskb)->nh.iph->check + = csum_fold(csum_partial((char *)diffs, + sizeof(diffs), + (*pskb)->nh.iph->check + ^0xFFFF)); } return IPT_CONTINUE; } @@ -49,6 +56,7 @@ checkentry(const char *tablename, const void *e_void, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { const u_int8_t tos = ((struct ipt_tos_target_info *)targinfo)->tos; diff --git a/trunk/net/ipv4/netfilter/ipt_TTL.c b/trunk/net/ipv4/netfilter/ipt_TTL.c index 96e79cc6d0f2..f48892ae0be5 100644 --- a/trunk/net/ipv4/netfilter/ipt_TTL.c +++ b/trunk/net/ipv4/netfilter/ipt_TTL.c @@ -23,10 +23,11 @@ static unsigned int ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, void *userinfo) { struct iphdr *iph; const struct ipt_TTL_info *info = targinfo; + u_int16_t diffs[2]; int new_ttl; if (!skb_make_writable(pskb, (*pskb)->len)) @@ -54,10 +55,12 @@ ipt_ttl_target(struct sk_buff **pskb, } if (new_ttl != iph->ttl) { - iph->check = nf_csum_update(ntohs((iph->ttl << 8)) ^ 0xFFFF, - ntohs(new_ttl << 8), - iph->check); + diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF; iph->ttl = new_ttl; + diffs[1] = htons(((unsigned)iph->ttl) << 8); + iph->check = csum_fold(csum_partial((char *)diffs, + sizeof(diffs), + iph->check^0xFFFF)); } return IPT_CONTINUE; @@ -67,6 +70,7 @@ static int ipt_ttl_checkentry(const char *tablename, const void *e, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { struct ipt_TTL_info *info = targinfo; diff --git a/trunk/net/ipv4/netfilter/ipt_ULOG.c b/trunk/net/ipv4/netfilter/ipt_ULOG.c index 2b104ea54f48..d7dd7fe7051c 100644 --- a/trunk/net/ipv4/netfilter/ipt_ULOG.c +++ b/trunk/net/ipv4/netfilter/ipt_ULOG.c @@ -115,11 +115,6 @@ static void ulog_send(unsigned int nlgroupnum) del_timer(&ub->timer); } - if (!ub->skb) { - DEBUGP("ipt_ULOG: ulog_send: nothing to send\n"); - return; - } - /* last nlmsg needs NLMSG_DONE */ if (ub->qlen > 1) ub->lastnlh->nlmsg_type = NLMSG_DONE; @@ -308,7 +303,7 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, void *userinfo) { struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo; @@ -346,6 +341,7 @@ static int ipt_ulog_checkentry(const char *tablename, const void *e, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hookmask) { struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo; diff --git a/trunk/net/ipv4/netfilter/ipt_ah.c b/trunk/net/ipv4/netfilter/ipt_ah.c index 1798f86bc534..2927135873d7 100644 --- a/trunk/net/ipv4/netfilter/ipt_ah.c +++ b/trunk/net/ipv4/netfilter/ipt_ah.c @@ -74,6 +74,7 @@ checkentry(const char *tablename, const void *ip_void, const struct xt_match *match, void *matchinfo, + unsigned int matchinfosize, unsigned int hook_mask) { const struct ipt_ah *ahinfo = matchinfo; diff --git a/trunk/net/ipv4/netfilter/ipt_dscp.c b/trunk/net/ipv4/netfilter/ipt_dscp.c new file mode 100644 index 000000000000..47177591aeb6 --- /dev/null +++ b/trunk/net/ipv4/netfilter/ipt_dscp.c @@ -0,0 +1,54 @@ +/* IP tables module for matching the value of the IPv4 DSCP field + * + * ipt_dscp.c,v 1.3 2002/08/05 19:00:21 laforge Exp + * + * (C) 2002 by Harald Welte + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +#include +#include + +MODULE_AUTHOR("Harald Welte "); +MODULE_DESCRIPTION("iptables DSCP matching module"); +MODULE_LICENSE("GPL"); + +static int match(const struct sk_buff *skb, + const struct net_device *in, const struct net_device *out, + const struct xt_match *match, const void *matchinfo, + int offset, unsigned int protoff, int *hotdrop) +{ + const struct ipt_dscp_info *info = matchinfo; + const struct iphdr *iph = skb->nh.iph; + + u_int8_t sh_dscp = ((info->dscp << IPT_DSCP_SHIFT) & IPT_DSCP_MASK); + + return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert; +} + +static struct ipt_match dscp_match = { + .name = "dscp", + .match = match, + .matchsize = sizeof(struct ipt_dscp_info), + .me = THIS_MODULE, +}; + +static int __init ipt_dscp_init(void) +{ + return ipt_register_match(&dscp_match); +} + +static void __exit ipt_dscp_fini(void) +{ + ipt_unregister_match(&dscp_match); + +} + +module_init(ipt_dscp_init); +module_exit(ipt_dscp_fini); diff --git a/trunk/net/ipv4/netfilter/ipt_ecn.c b/trunk/net/ipv4/netfilter/ipt_ecn.c index dafbdec0efc0..b28250414933 100644 --- a/trunk/net/ipv4/netfilter/ipt_ecn.c +++ b/trunk/net/ipv4/netfilter/ipt_ecn.c @@ -88,7 +88,8 @@ static int match(const struct sk_buff *skb, static int checkentry(const char *tablename, const void *ip_void, const struct xt_match *match, - void *matchinfo, unsigned int hook_mask) + void *matchinfo, unsigned int matchsize, + unsigned int hook_mask) { const struct ipt_ecn_info *info = matchinfo; const struct ipt_ip *ip = ip_void; diff --git a/trunk/net/ipv4/netfilter/ipt_hashlimit.c b/trunk/net/ipv4/netfilter/ipt_hashlimit.c index 4f73a61aa3dd..92980ab8ce48 100644 --- a/trunk/net/ipv4/netfilter/ipt_hashlimit.c +++ b/trunk/net/ipv4/netfilter/ipt_hashlimit.c @@ -454,12 +454,15 @@ hashlimit_match(const struct sk_buff *skb, dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * hinfo->cfg.burst); dh->rateinfo.cost = user2credits(hinfo->cfg.avg); - } else { - /* update expiration timeout */ - dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); - rateinfo_recalc(dh, now); + + spin_unlock_bh(&hinfo->lock); + return 1; } + /* update expiration timeout */ + dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); + + rateinfo_recalc(dh, now); if (dh->rateinfo.credit >= dh->rateinfo.cost) { /* We're underlimit. */ dh->rateinfo.credit -= dh->rateinfo.cost; @@ -478,6 +481,7 @@ hashlimit_checkentry(const char *tablename, const void *inf, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { struct ipt_hashlimit_info *r = matchinfo; @@ -504,9 +508,6 @@ hashlimit_checkentry(const char *tablename, if (!r->cfg.expire) return 0; - if (r->name[sizeof(r->name) - 1] != '\0') - return 0; - /* This is the best we've got: We cannot release and re-grab lock, * since checkentry() is called before ip_tables.c grabs ipt_mutex. * We also cannot grab the hashtable spinlock, since htable_create will @@ -528,46 +529,18 @@ hashlimit_checkentry(const char *tablename, } static void -hashlimit_destroy(const struct xt_match *match, void *matchinfo) +hashlimit_destroy(const struct xt_match *match, void *matchinfo, + unsigned int matchsize) { struct ipt_hashlimit_info *r = matchinfo; htable_put(r->hinfo); } -#ifdef CONFIG_COMPAT -struct compat_ipt_hashlimit_info { - char name[IFNAMSIZ]; - struct hashlimit_cfg cfg; - compat_uptr_t hinfo; - compat_uptr_t master; -}; - -static void compat_from_user(void *dst, void *src) -{ - int off = offsetof(struct compat_ipt_hashlimit_info, hinfo); - - memcpy(dst, src, off); - memset(dst + off, 0, sizeof(struct compat_ipt_hashlimit_info) - off); -} - -static int compat_to_user(void __user *dst, void *src) -{ - int off = offsetof(struct compat_ipt_hashlimit_info, hinfo); - - return copy_to_user(dst, src, off) ? -EFAULT : 0; -} -#endif - static struct ipt_match ipt_hashlimit = { .name = "hashlimit", .match = hashlimit_match, .matchsize = sizeof(struct ipt_hashlimit_info), -#ifdef CONFIG_COMPAT - .compatsize = sizeof(struct compat_ipt_hashlimit_info), - .compat_from_user = compat_from_user, - .compat_to_user = compat_to_user, -#endif .checkentry = hashlimit_checkentry, .destroy = hashlimit_destroy, .me = THIS_MODULE diff --git a/trunk/net/ipv4/netfilter/ipt_owner.c b/trunk/net/ipv4/netfilter/ipt_owner.c index 78c336f12a9e..5ac6ac023b5e 100644 --- a/trunk/net/ipv4/netfilter/ipt_owner.c +++ b/trunk/net/ipv4/netfilter/ipt_owner.c @@ -56,6 +56,7 @@ checkentry(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct ipt_owner_info *info = matchinfo; diff --git a/trunk/net/ipv4/netfilter/ipt_recent.c b/trunk/net/ipv4/netfilter/ipt_recent.c index 32ae8d7ac506..61a2139f9cfd 100644 --- a/trunk/net/ipv4/netfilter/ipt_recent.c +++ b/trunk/net/ipv4/netfilter/ipt_recent.c @@ -35,20 +35,14 @@ static unsigned int ip_list_tot = 100; static unsigned int ip_pkt_list_tot = 20; static unsigned int ip_list_hash_size = 0; static unsigned int ip_list_perms = 0644; -static unsigned int ip_list_uid = 0; -static unsigned int ip_list_gid = 0; module_param(ip_list_tot, uint, 0400); module_param(ip_pkt_list_tot, uint, 0400); module_param(ip_list_hash_size, uint, 0400); module_param(ip_list_perms, uint, 0400); -module_param(ip_list_uid, uint, 0400); -module_param(ip_list_gid, uint, 0400); MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list"); MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP to remember (max. 255)"); MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs"); MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/ipt_recent/* files"); -MODULE_PARM_DESC(ip_list_uid,"owner of /proc/net/ipt_recent/* files"); -MODULE_PARM_DESC(ip_list_gid,"owning group of /proc/net/ipt_recent/* files"); struct recent_entry { @@ -238,7 +232,7 @@ ipt_recent_match(const struct sk_buff *skb, static int ipt_recent_checkentry(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, - unsigned int hook_mask) + unsigned int matchsize, unsigned int hook_mask) { const struct ipt_recent_info *info = matchinfo; struct recent_table *t; @@ -280,8 +274,6 @@ ipt_recent_checkentry(const char *tablename, const void *ip, goto out; } t->proc->proc_fops = &recent_fops; - t->proc->uid = ip_list_uid; - t->proc->gid = ip_list_gid; t->proc->data = t; #endif spin_lock_bh(&recent_lock); @@ -294,7 +286,8 @@ ipt_recent_checkentry(const char *tablename, const void *ip, } static void -ipt_recent_destroy(const struct xt_match *match, void *matchinfo) +ipt_recent_destroy(const struct xt_match *match, void *matchinfo, + unsigned int matchsize) { const struct ipt_recent_info *info = matchinfo; struct recent_table *t; diff --git a/trunk/net/ipv4/netfilter/iptable_filter.c b/trunk/net/ipv4/netfilter/iptable_filter.c index e2e7dd8d7903..7f417484bfbf 100644 --- a/trunk/net/ipv4/netfilter/iptable_filter.c +++ b/trunk/net/ipv4/netfilter/iptable_filter.c @@ -90,7 +90,7 @@ ipt_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return ipt_do_table(pskb, hook, in, out, &packet_filter); + return ipt_do_table(pskb, hook, in, out, &packet_filter, NULL); } static unsigned int @@ -108,7 +108,7 @@ ipt_local_out_hook(unsigned int hook, return NF_ACCEPT; } - return ipt_do_table(pskb, hook, in, out, &packet_filter); + return ipt_do_table(pskb, hook, in, out, &packet_filter, NULL); } static struct nf_hook_ops ipt_ops[] = { diff --git a/trunk/net/ipv4/netfilter/iptable_mangle.c b/trunk/net/ipv4/netfilter/iptable_mangle.c index 79336cb42527..4e7998beda63 100644 --- a/trunk/net/ipv4/netfilter/iptable_mangle.c +++ b/trunk/net/ipv4/netfilter/iptable_mangle.c @@ -119,7 +119,7 @@ ipt_route_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return ipt_do_table(pskb, hook, in, out, &packet_mangler); + return ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL); } static unsigned int @@ -148,7 +148,7 @@ ipt_local_hook(unsigned int hook, daddr = (*pskb)->nh.iph->daddr; tos = (*pskb)->nh.iph->tos; - ret = ipt_do_table(pskb, hook, in, out, &packet_mangler); + ret = ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL); /* Reroute for ANY change. */ if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE && ((*pskb)->nh.iph->saddr != saddr diff --git a/trunk/net/ipv4/netfilter/iptable_raw.c b/trunk/net/ipv4/netfilter/iptable_raw.c index bcbeb4aeacd9..7912cce1e1b8 100644 --- a/trunk/net/ipv4/netfilter/iptable_raw.c +++ b/trunk/net/ipv4/netfilter/iptable_raw.c @@ -95,7 +95,7 @@ ipt_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return ipt_do_table(pskb, hook, in, out, &packet_raw); + return ipt_do_table(pskb, hook, in, out, &packet_raw, NULL); } /* 'raw' is the very first table. */ diff --git a/trunk/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/trunk/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index 790f00d500c3..663a73ee3f2f 100644 --- a/trunk/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/trunk/net/ipv4/netfilter/nf_conntrack_proto_icmp.c @@ -25,7 +25,7 @@ #include #include -unsigned long nf_ct_icmp_timeout __read_mostly = 30*HZ; +unsigned long nf_ct_icmp_timeout = 30*HZ; #if 0 #define DEBUGP printk diff --git a/trunk/net/ipv4/proc.c b/trunk/net/ipv4/proc.c index 9c6cbe3d9fb8..d61e2a9d394d 100644 --- a/trunk/net/ipv4/proc.c +++ b/trunk/net/ipv4/proc.c @@ -173,8 +173,6 @@ static const struct snmp_mib snmp4_udp_list[] = { SNMP_MIB_ITEM("NoPorts", UDP_MIB_NOPORTS), SNMP_MIB_ITEM("InErrors", UDP_MIB_INERRORS), SNMP_MIB_ITEM("OutDatagrams", UDP_MIB_OUTDATAGRAMS), - SNMP_MIB_ITEM("RcvbufErrors", UDP_MIB_RCVBUFERRORS), - SNMP_MIB_ITEM("SndbufErrors", UDP_MIB_SNDBUFERRORS), SNMP_MIB_SENTINEL }; diff --git a/trunk/net/ipv4/raw.c b/trunk/net/ipv4/raw.c index 0e935b4c8741..62b2762a2420 100644 --- a/trunk/net/ipv4/raw.c +++ b/trunk/net/ipv4/raw.c @@ -38,7 +38,8 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ - + +#include #include #include #include @@ -483,7 +484,6 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (!inet->hdrincl) raw_probe_proto_opt(&fl, msg); - security_sk_classify_flow(sk, &fl); err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); } if (err) diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index 20ffe8e88c0f..2dc6dbb28467 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -104,7 +104,6 @@ #include #include #include -#include #ifdef CONFIG_SYSCTL #include #endif @@ -1126,7 +1125,6 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw, struct rtable *rth, **rthp; u32 skeys[2] = { saddr, 0 }; int ikeys[2] = { dev->ifindex, 0 }; - struct netevent_redirect netevent; if (!in_dev) return; @@ -1218,11 +1216,6 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw, rt_drop(rt); goto do_next; } - - netevent.old = &rth->u.dst; - netevent.new = &rt->u.dst; - call_netevent_notifiers(NETEVENT_REDIRECT, - &netevent); rt_del(hash, rth); if (!rt_intern_hash(hash, rt, &rt)) @@ -1459,7 +1452,6 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) } dst->metrics[RTAX_MTU-1] = mtu; dst_set_expires(dst, ip_rt_mtu_expires); - call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); } } @@ -2639,54 +2631,51 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, { struct rtable *rt = (struct rtable*)skb->dst; struct rtmsg *r; - struct nlmsghdr *nlh; + struct nlmsghdr *nlh; + unsigned char *b = skb->tail; struct rta_cacheinfo ci; - - nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags); - if (nlh == NULL) - return -ENOBUFS; - - r = nlmsg_data(nlh); +#ifdef CONFIG_IP_MROUTE + struct rtattr *eptr; +#endif + nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags); + r = NLMSG_DATA(nlh); r->rtm_family = AF_INET; r->rtm_dst_len = 32; r->rtm_src_len = 0; r->rtm_tos = rt->fl.fl4_tos; r->rtm_table = RT_TABLE_MAIN; - NLA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN); r->rtm_type = rt->rt_type; r->rtm_scope = RT_SCOPE_UNIVERSE; r->rtm_protocol = RTPROT_UNSPEC; r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED; if (rt->rt_flags & RTCF_NOTIFY) r->rtm_flags |= RTM_F_NOTIFY; - - NLA_PUT_U32(skb, RTA_DST, rt->rt_dst); - + RTA_PUT(skb, RTA_DST, 4, &rt->rt_dst); if (rt->fl.fl4_src) { r->rtm_src_len = 32; - NLA_PUT_U32(skb, RTA_SRC, rt->fl.fl4_src); + RTA_PUT(skb, RTA_SRC, 4, &rt->fl.fl4_src); } if (rt->u.dst.dev) - NLA_PUT_U32(skb, RTA_OIF, rt->u.dst.dev->ifindex); + RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->u.dst.dev->ifindex); #ifdef CONFIG_NET_CLS_ROUTE if (rt->u.dst.tclassid) - NLA_PUT_U32(skb, RTA_FLOW, rt->u.dst.tclassid); + RTA_PUT(skb, RTA_FLOW, 4, &rt->u.dst.tclassid); #endif #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED - if (rt->rt_multipath_alg != IP_MP_ALG_NONE) - NLA_PUT_U32(skb, RTA_MP_ALGO, rt->rt_multipath_alg); + if (rt->rt_multipath_alg != IP_MP_ALG_NONE) { + __u32 alg = rt->rt_multipath_alg; + + RTA_PUT(skb, RTA_MP_ALGO, 4, &alg); + } #endif if (rt->fl.iif) - NLA_PUT_U32(skb, RTA_PREFSRC, rt->rt_spec_dst); + RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_spec_dst); else if (rt->rt_src != rt->fl.fl4_src) - NLA_PUT_U32(skb, RTA_PREFSRC, rt->rt_src); - + RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_src); if (rt->rt_dst != rt->rt_gateway) - NLA_PUT_U32(skb, RTA_GATEWAY, rt->rt_gateway); - + RTA_PUT(skb, RTA_GATEWAY, 4, &rt->rt_gateway); if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) - goto nla_put_failure; - + goto rtattr_failure; ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse); ci.rta_used = rt->u.dst.__use; ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt); @@ -2703,7 +2692,10 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, ci.rta_tsage = xtime.tv_sec - rt->peer->tcp_ts_stamp; } } - +#ifdef CONFIG_IP_MROUTE + eptr = (struct rtattr*)skb->tail; +#endif + RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); if (rt->fl.iif) { #ifdef CONFIG_IP_MROUTE u32 dst = rt->rt_dst; @@ -2715,46 +2707,41 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, if (!nowait) { if (err == 0) return 0; - goto nla_put_failure; + goto nlmsg_failure; } else { if (err == -EMSGSIZE) - goto nla_put_failure; - ci.rta_error = err; + goto nlmsg_failure; + ((struct rta_cacheinfo*)RTA_DATA(eptr))->rta_error = err; } } } else #endif - NLA_PUT_U32(skb, RTA_IIF, rt->fl.iif); + RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif); } - NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); - - return nlmsg_end(skb, nlh); + nlh->nlmsg_len = skb->tail - b; + return skb->len; -nla_put_failure: - return nlmsg_cancel(skb, nlh); +nlmsg_failure: +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; } int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) { - struct rtmsg *rtm; - struct nlattr *tb[RTA_MAX+1]; + struct rtattr **rta = arg; + struct rtmsg *rtm = NLMSG_DATA(nlh); struct rtable *rt = NULL; - u32 dst, src, iif; - int err; + u32 dst = 0; + u32 src = 0; + int iif = 0; + int err = -ENOBUFS; struct sk_buff *skb; - err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv4_policy); - if (err < 0) - goto errout; - - rtm = nlmsg_data(nlh); - skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); - if (skb == NULL) { - err = -ENOBUFS; - goto errout; - } + if (!skb) + goto out; /* Reserve room for dummy headers, this skb can pass through good chunk of routing engine. @@ -2765,61 +2752,62 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) skb->nh.iph->protocol = IPPROTO_ICMP; skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr)); - src = tb[RTA_SRC] ? nla_get_u32(tb[RTA_SRC]) : 0; - dst = tb[RTA_DST] ? nla_get_u32(tb[RTA_DST]) : 0; - iif = tb[RTA_IIF] ? nla_get_u32(tb[RTA_IIF]) : 0; + if (rta[RTA_SRC - 1]) + memcpy(&src, RTA_DATA(rta[RTA_SRC - 1]), 4); + if (rta[RTA_DST - 1]) + memcpy(&dst, RTA_DATA(rta[RTA_DST - 1]), 4); + if (rta[RTA_IIF - 1]) + memcpy(&iif, RTA_DATA(rta[RTA_IIF - 1]), sizeof(int)); if (iif) { - struct net_device *dev; - - dev = __dev_get_by_index(iif); - if (dev == NULL) { - err = -ENODEV; - goto errout_free; - } - + struct net_device *dev = __dev_get_by_index(iif); + err = -ENODEV; + if (!dev) + goto out_free; skb->protocol = htons(ETH_P_IP); skb->dev = dev; local_bh_disable(); err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev); local_bh_enable(); - - rt = (struct rtable*) skb->dst; - if (err == 0 && rt->u.dst.error) + rt = (struct rtable*)skb->dst; + if (!err && rt->u.dst.error) err = -rt->u.dst.error; } else { - struct flowi fl = { - .nl_u = { - .ip4_u = { - .daddr = dst, - .saddr = src, - .tos = rtm->rtm_tos, - }, - }, - .oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0, - }; + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dst, + .saddr = src, + .tos = rtm->rtm_tos } } }; + int oif = 0; + if (rta[RTA_OIF - 1]) + memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int)); + fl.oif = oif; err = ip_route_output_key(&rt, &fl); } - if (err) - goto errout_free; + goto out_free; skb->dst = &rt->u.dst; if (rtm->rtm_flags & RTM_F_NOTIFY) rt->rt_flags |= RTCF_NOTIFY; + NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; + err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0, 0); - if (err <= 0) - goto errout_free; + if (!err) + goto out_free; + if (err < 0) { + err = -EMSGSIZE; + goto out_free; + } - err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid); -errout: - return err; + err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); + if (err > 0) + err = 0; +out: return err; -errout_free: +out_free: kfree_skb(skb); - goto errout; + goto out; } int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) @@ -3147,9 +3135,13 @@ int __init ip_rt_init(void) } #endif - ipv4_dst_ops.kmem_cachep = - kmem_cache_create("ip_dst_cache", sizeof(struct rtable), 0, - SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); + ipv4_dst_ops.kmem_cachep = kmem_cache_create("ip_dst_cache", + sizeof(struct rtable), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + + if (!ipv4_dst_ops.kmem_cachep) + panic("IP: failed to allocate ip_dst_cache\n"); rt_hash_table = (struct rt_hash_bucket *) alloc_large_system_hash("IP route cache", @@ -3157,7 +3149,7 @@ int __init ip_rt_init(void) rhash_entries, (num_physpages >= 128 * 1024) ? 15 : 17, - 0, + HASH_HIGHMEM, &rt_hash_log, &rt_hash_mask, 0); diff --git a/trunk/net/ipv4/syncookies.c b/trunk/net/ipv4/syncookies.c index 661e0a4bca72..e20be3331f67 100644 --- a/trunk/net/ipv4/syncookies.c +++ b/trunk/net/ipv4/syncookies.c @@ -214,10 +214,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, if (!req) goto out; - if (security_inet_conn_request(sk, skb, req)) { - reqsk_free(req); - goto out; - } ireq = inet_rsk(req); treq = tcp_rsk(req); treq->rcv_isn = htonl(skb->h.th->seq) - 1; @@ -263,7 +259,6 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, .uli_u = { .ports = { .sport = skb->h.th->dest, .dport = skb->h.th->source } } }; - security_req_classify_flow(req, &fl); if (ip_route_output_key(&rt, &fl)) { reqsk_free(req); goto out; diff --git a/trunk/net/ipv4/sysctl_net_ipv4.c b/trunk/net/ipv4/sysctl_net_ipv4.c index 19b2071ff319..70cea9d08a38 100644 --- a/trunk/net/ipv4/sysctl_net_ipv4.c +++ b/trunk/net/ipv4/sysctl_net_ipv4.c @@ -17,7 +17,6 @@ #include #include #include -#include /* From af_inet.c */ extern int sysctl_ip_nonlocal_bind; @@ -698,40 +697,6 @@ ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = &proc_dointvec }, -#ifdef CONFIG_NETLABEL - { - .ctl_name = NET_CIPSOV4_CACHE_ENABLE, - .procname = "cipso_cache_enable", - .data = &cipso_v4_cache_enabled, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, - { - .ctl_name = NET_CIPSOV4_CACHE_BUCKET_SIZE, - .procname = "cipso_cache_bucket_size", - .data = &cipso_v4_cache_bucketsize, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, - { - .ctl_name = NET_CIPSOV4_RBM_OPTFMT, - .procname = "cipso_rbm_optfmt", - .data = &cipso_v4_rbm_optfmt, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, - { - .ctl_name = NET_CIPSOV4_RBM_STRICTVALID, - .procname = "cipso_rbm_strictvalid", - .data = &cipso_v4_rbm_strictvalid, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, -#endif /* CONFIG_NETLABEL */ { .ctl_name = 0 } }; diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index 66e9a729f6df..f6a2d9223d07 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -268,7 +268,7 @@ #include #include -int sysctl_tcp_fin_timeout __read_mostly = TCP_FIN_TIMEOUT; +int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT; DEFINE_SNMP_STAT(struct tcp_mib, tcp_statistics) __read_mostly; @@ -568,7 +568,7 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse skb->truesize += copy; sk->sk_wmem_queued += copy; sk->sk_forward_alloc -= copy; - skb->ip_summed = CHECKSUM_PARTIAL; + skb->ip_summed = CHECKSUM_HW; tp->write_seq += copy; TCP_SKB_CB(skb)->end_seq += copy; skb_shinfo(skb)->gso_segs = 0; @@ -723,7 +723,7 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, * Check whether we can use HW checksum. */ if (sk->sk_route_caps & NETIF_F_ALL_CSUM) - skb->ip_summed = CHECKSUM_PARTIAL; + skb->ip_summed = CHECKSUM_HW; skb_entail(sk, tp, skb); copy = size_goal; @@ -955,11 +955,8 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied) * receive buffer and there was a small segment * in queue. */ - (copied > 0 && - ((icsk->icsk_ack.pending & ICSK_ACK_PUSHED2) || - ((icsk->icsk_ack.pending & ICSK_ACK_PUSHED) && - !icsk->icsk_ack.pingpong)) && - !atomic_read(&sk->sk_rmem_alloc))) + (copied > 0 && (icsk->icsk_ack.pending & ICSK_ACK_PUSHED) && + !icsk->icsk_ack.pingpong && !atomic_read(&sk->sk_rmem_alloc))) time_to_ack = 1; } @@ -1135,7 +1132,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, tp->ucopy.dma_chan = NULL; preempt_disable(); if ((len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) && - !sysctl_tcp_low_latency && __get_cpu_var(softnet_data).net_dma) { + !sysctl_tcp_low_latency && __get_cpu_var(softnet_data.net_dma)) { preempt_enable_no_resched(); tp->ucopy.pinned_list = dma_pin_iovec_pages(msg->msg_iov, len); } else @@ -1662,8 +1659,7 @@ void tcp_close(struct sock *sk, long timeout) const int tmo = tcp_fin_time(sk); if (tmo > TCP_TIMEWAIT_LEN) { - inet_csk_reset_keepalive_timer(sk, - tmo - TCP_TIMEWAIT_LEN); + inet_csk_reset_keepalive_timer(sk, tcp_fin_time(sk)); } else { tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); goto out; @@ -2208,7 +2204,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) th->fin = th->psh = 0; th->check = ~csum_fold(th->check + delta); - if (skb->ip_summed != CHECKSUM_PARTIAL) + if (skb->ip_summed != CHECKSUM_HW) th->check = csum_fold(csum_partial(skb->h.raw, thlen, skb->csum)); @@ -2222,7 +2218,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len); th->check = ~csum_fold(th->check + delta); - if (skb->ip_summed != CHECKSUM_PARTIAL) + if (skb->ip_summed != CHECKSUM_HW) th->check = csum_fold(csum_partial(skb->h.raw, thlen, skb->csum)); @@ -2257,7 +2253,9 @@ void __init tcp_init(void) tcp_hashinfo.bind_bucket_cachep = kmem_cache_create("tcp_bind_bucket", sizeof(struct inet_bind_bucket), 0, - SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); + SLAB_HWCACHE_ALIGN, NULL, NULL); + if (!tcp_hashinfo.bind_bucket_cachep) + panic("tcp_init: Cannot alloc tcp_bind_bucket cache."); /* Size and allocate the main established and bind bucket * hash tables. diff --git a/trunk/net/ipv4/tcp_bic.c b/trunk/net/ipv4/tcp_bic.c index 5730333cd0ac..b0134ab08379 100644 --- a/trunk/net/ipv4/tcp_bic.c +++ b/trunk/net/ipv4/tcp_bic.c @@ -231,7 +231,7 @@ static struct tcp_congestion_ops bictcp = { static int __init bictcp_register(void) { - BUILD_BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE); + BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE); return tcp_register_congestion_control(&bictcp); } diff --git a/trunk/net/ipv4/tcp_cong.c b/trunk/net/ipv4/tcp_cong.c index 7ff2e4273a7c..5765f9d03174 100644 --- a/trunk/net/ipv4/tcp_cong.c +++ b/trunk/net/ipv4/tcp_cong.c @@ -189,7 +189,7 @@ void tcp_slow_start(struct tcp_sock *tp) return; /* We MAY increase by 2 if discovered delayed ack */ - if (sysctl_tcp_abc > 1 && tp->bytes_acked >= 2*tp->mss_cache) { + if (sysctl_tcp_abc > 1 && tp->bytes_acked > 2*tp->mss_cache) { if (tp->snd_cwnd < tp->snd_cwnd_clamp) tp->snd_cwnd++; } diff --git a/trunk/net/ipv4/tcp_cubic.c b/trunk/net/ipv4/tcp_cubic.c index a60ef38d75c6..2be27980ca78 100644 --- a/trunk/net/ipv4/tcp_cubic.c +++ b/trunk/net/ipv4/tcp_cubic.c @@ -358,7 +358,7 @@ static struct tcp_congestion_ops cubictcp = { static int __init cubictcp_register(void) { - BUILD_BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE); + BUG_ON(sizeof(struct bictcp) > ICSK_CA_PRIV_SIZE); /* Precompute a bunch of the scaling factors that are used per-packet * based on SRTT of 100ms diff --git a/trunk/net/ipv4/tcp_highspeed.c b/trunk/net/ipv4/tcp_highspeed.c index c4fc811bf377..fa3e1aad660c 100644 --- a/trunk/net/ipv4/tcp_highspeed.c +++ b/trunk/net/ipv4/tcp_highspeed.c @@ -189,7 +189,7 @@ static struct tcp_congestion_ops tcp_highspeed = { static int __init hstcp_register(void) { - BUILD_BUG_ON(sizeof(struct hstcp) > ICSK_CA_PRIV_SIZE); + BUG_ON(sizeof(struct hstcp) > ICSK_CA_PRIV_SIZE); return tcp_register_congestion_control(&tcp_highspeed); } diff --git a/trunk/net/ipv4/tcp_htcp.c b/trunk/net/ipv4/tcp_htcp.c index 682e7d5b6f2f..6edfe5e4510e 100644 --- a/trunk/net/ipv4/tcp_htcp.c +++ b/trunk/net/ipv4/tcp_htcp.c @@ -286,7 +286,7 @@ static struct tcp_congestion_ops htcp = { static int __init htcp_register(void) { - BUILD_BUG_ON(sizeof(struct htcp) > ICSK_CA_PRIV_SIZE); + BUG_ON(sizeof(struct htcp) > ICSK_CA_PRIV_SIZE); BUILD_BUG_ON(BETA_MIN >= BETA_MAX); return tcp_register_congestion_control(&htcp); } diff --git a/trunk/net/ipv4/tcp_hybla.c b/trunk/net/ipv4/tcp_hybla.c index 59e691d26f64..7406e0c5fb8e 100644 --- a/trunk/net/ipv4/tcp_hybla.c +++ b/trunk/net/ipv4/tcp_hybla.c @@ -170,7 +170,7 @@ static struct tcp_congestion_ops tcp_hybla = { static int __init hybla_register(void) { - BUILD_BUG_ON(sizeof(struct hybla) > ICSK_CA_PRIV_SIZE); + BUG_ON(sizeof(struct hybla) > ICSK_CA_PRIV_SIZE); return tcp_register_congestion_control(&tcp_hybla); } diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index b3def0df14fb..738dad9f7d49 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -72,24 +72,24 @@ #include #include -int sysctl_tcp_timestamps __read_mostly = 1; -int sysctl_tcp_window_scaling __read_mostly = 1; -int sysctl_tcp_sack __read_mostly = 1; -int sysctl_tcp_fack __read_mostly = 1; -int sysctl_tcp_reordering __read_mostly = TCP_FASTRETRANS_THRESH; -int sysctl_tcp_ecn __read_mostly; -int sysctl_tcp_dsack __read_mostly = 1; -int sysctl_tcp_app_win __read_mostly = 31; -int sysctl_tcp_adv_win_scale __read_mostly = 2; - -int sysctl_tcp_stdurg __read_mostly; -int sysctl_tcp_rfc1337 __read_mostly; -int sysctl_tcp_max_orphans __read_mostly = NR_FILE; -int sysctl_tcp_frto __read_mostly; -int sysctl_tcp_nometrics_save __read_mostly; - -int sysctl_tcp_moderate_rcvbuf __read_mostly = 1; -int sysctl_tcp_abc __read_mostly; +int sysctl_tcp_timestamps = 1; +int sysctl_tcp_window_scaling = 1; +int sysctl_tcp_sack = 1; +int sysctl_tcp_fack = 1; +int sysctl_tcp_reordering = TCP_FASTRETRANS_THRESH; +int sysctl_tcp_ecn; +int sysctl_tcp_dsack = 1; +int sysctl_tcp_app_win = 31; +int sysctl_tcp_adv_win_scale = 2; + +int sysctl_tcp_stdurg; +int sysctl_tcp_rfc1337; +int sysctl_tcp_max_orphans = NR_FILE; +int sysctl_tcp_frto; +int sysctl_tcp_nometrics_save; + +int sysctl_tcp_moderate_rcvbuf = 1; +int sysctl_tcp_abc = 1; #define FLAG_DATA 0x01 /* Incoming frame contained data. */ #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */ @@ -127,7 +127,7 @@ static void tcp_measure_rcv_mss(struct sock *sk, /* skb->len may jitter because of SACKs, even if peer * sends good full-sized frames. */ - len = skb_shinfo(skb)->gso_size ?: skb->len; + len = skb->len; if (len >= icsk->icsk_ack.rcv_mss) { icsk->icsk_ack.rcv_mss = len; } else { @@ -156,8 +156,6 @@ static void tcp_measure_rcv_mss(struct sock *sk, return; } } - if (icsk->icsk_ack.pending & ICSK_ACK_PUSHED) - icsk->icsk_ack.pending |= ICSK_ACK_PUSHED2; icsk->icsk_ack.pending |= ICSK_ACK_PUSHED; } } @@ -2507,13 +2505,8 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag) if (before(ack, prior_snd_una)) goto old_ack; - if (sysctl_tcp_abc) { - if (icsk->icsk_ca_state < TCP_CA_CWR) - tp->bytes_acked += ack - prior_snd_una; - else if (icsk->icsk_ca_state == TCP_CA_Loss) - /* we assume just one segment left network */ - tp->bytes_acked += min(ack - prior_snd_una, tp->mss_cache); - } + if (sysctl_tcp_abc && icsk->icsk_ca_state < TCP_CA_CWR) + tp->bytes_acked += ack - prior_snd_una; if (!(flag&FLAG_SLOWPATH) && after(ack, prior_snd_una)) { /* Window is constant, pure forward advance. @@ -3548,8 +3541,7 @@ void tcp_cwnd_application_limited(struct sock *sk) if (inet_csk(sk)->icsk_ca_state == TCP_CA_Open && sk->sk_socket && !test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { /* Limited by application or receiver window. */ - u32 init_win = tcp_init_cwnd(tp, __sk_dst_get(sk)); - u32 win_used = max(tp->snd_cwnd_used, init_win); + u32 win_used = max(tp->snd_cwnd_used, 2U); if (win_used < tp->snd_cwnd) { tp->snd_ssthresh = tcp_current_ssthresh(sk); tp->snd_cwnd = (tp->snd_cwnd + win_used) >> 1; diff --git a/trunk/net/ipv4/tcp_ipv4.c b/trunk/net/ipv4/tcp_ipv4.c index 39b179856082..f6f39e814291 100644 --- a/trunk/net/ipv4/tcp_ipv4.c +++ b/trunk/net/ipv4/tcp_ipv4.c @@ -78,8 +78,8 @@ #include #include -int sysctl_tcp_tw_reuse __read_mostly; -int sysctl_tcp_low_latency __read_mostly; +int sysctl_tcp_tw_reuse; +int sysctl_tcp_low_latency; /* Check TCP sequence numbers in ICMP packets. */ #define ICMP_MIN_LENGTH 8 @@ -438,6 +438,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info) It can f.e. if SYNs crossed. */ if (!sock_owned_by_user(sk)) { + TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); sk->sk_err = err; sk->sk_error_report(sk); @@ -484,7 +485,7 @@ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) struct inet_sock *inet = inet_sk(sk); struct tcphdr *th = skb->h.th; - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { th->check = ~tcp_v4_check(th, len, inet->saddr, inet->daddr, 0); skb->csum = offsetof(struct tcphdr, check); } else { @@ -509,7 +510,7 @@ int tcp_v4_gso_send_check(struct sk_buff *skb) th->check = 0; th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0); skb->csum = offsetof(struct tcphdr, check); - skb->ip_summed = CHECKSUM_PARTIAL; + skb->ip_summed = CHECKSUM_HW; return 0; } @@ -798,9 +799,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) tcp_openreq_init(req, &tmp_opt, skb); - if (security_inet_conn_request(sk, skb, req)) - goto drop_and_free; - ireq = inet_rsk(req); ireq->loc_addr = daddr; ireq->rmt_addr = saddr; @@ -876,6 +874,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) drop_and_free: reqsk_free(req); drop: + TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); return 0; } @@ -951,9 +950,9 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) if (req) return tcp_check_req(sk, skb, req, prev); - nsk = inet_lookup_established(&tcp_hashinfo, skb->nh.iph->saddr, - th->source, skb->nh.iph->daddr, - th->dest, inet_iif(skb)); + nsk = __inet_lookup_established(&tcp_hashinfo, skb->nh.iph->saddr, + th->source, skb->nh.iph->daddr, + ntohs(th->dest), inet_iif(skb)); if (nsk) { if (nsk->sk_state != TCP_TIME_WAIT) { @@ -973,7 +972,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) static int tcp_v4_checksum_init(struct sk_buff *skb) { - if (skb->ip_summed == CHECKSUM_COMPLETE) { + if (skb->ip_summed == CHECKSUM_HW) { if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr, skb->nh.iph->daddr, skb->csum)) { skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -1090,7 +1089,7 @@ int tcp_v4_rcv(struct sk_buff *skb) TCP_SKB_CB(skb)->sacked = 0; sk = __inet_lookup(&tcp_hashinfo, skb->nh.iph->saddr, th->source, - skb->nh.iph->daddr, th->dest, + skb->nh.iph->daddr, ntohs(th->dest), inet_iif(skb)); if (!sk) @@ -1104,7 +1103,7 @@ int tcp_v4_rcv(struct sk_buff *skb) goto discard_and_relse; nf_reset(skb); - if (sk_filter(sk, skb)) + if (sk_filter(sk, skb, 0)) goto discard_and_relse; skb->dev = NULL; @@ -1168,7 +1167,7 @@ int tcp_v4_rcv(struct sk_buff *skb) case TCP_TW_SYN: { struct sock *sk2 = inet_lookup_listener(&tcp_hashinfo, skb->nh.iph->daddr, - th->dest, + ntohs(th->dest), inet_iif(skb)); if (sk2) { inet_twsk_deschedule((struct inet_timewait_sock *)sk, diff --git a/trunk/net/ipv4/tcp_lp.c b/trunk/net/ipv4/tcp_lp.c index 308fb7e071c5..1f977b6ee9a1 100644 --- a/trunk/net/ipv4/tcp_lp.c +++ b/trunk/net/ipv4/tcp_lp.c @@ -3,8 +3,13 @@ * * TCP Low Priority is a distributed algorithm whose goal is to utilize only * the excess network bandwidth as compared to the ``fair share`` of - * bandwidth as targeted by TCP. + * bandwidth as targeted by TCP. Available from: + * http://www.ece.rice.edu/~akuzma/Doc/akuzma/TCP-LP.pdf * + * Original Author: + * Aleksandar Kuzmanovic + * + * See http://www-ece.rice.edu/networks/TCP-LP/ for their implementation. * As of 2.6.13, Linux supports pluggable congestion control algorithms. * Due to the limitation of the API, we take the following changes from * the original TCP-LP implementation: @@ -19,22 +24,14 @@ * o OWD is handled in relative format, where local time stamp will in * tcp_time_stamp format. * - * Original Author: - * Aleksandar Kuzmanovic - * Available from: - * http://www.ece.rice.edu/~akuzma/Doc/akuzma/TCP-LP.pdf - * Original implementation for 2.4.19: - * http://www-ece.rice.edu/networks/TCP-LP/ + * Port from 2.4.19 to 2.6.16 as module by: + * Wong Hoi Sing Edison + * Hung Hing Lun * - * 2.6.x module Authors: - * Wong Hoi Sing, Edison - * Hung Hing Lun, Mike - * SourceForge project page: - * http://tcp-lp-mod.sourceforge.net/ - * - * Version: $Id: tcp_lp.c,v 1.24 2006/09/05 20:22:53 hswong3i Exp $ + * Version: $Id: tcp_lp.c,v 1.22 2006-05-02 18:18:19 hswong3i Exp $ */ +#include #include #include @@ -156,19 +153,16 @@ static u32 tcp_lp_remote_hz_estimator(struct sock *sk) if (m < 0) m = -m; - if (rhz > 0) { + if (rhz != 0) { m -= rhz >> 6; /* m is now error in remote HZ est */ rhz += m; /* 63/64 old + 1/64 new */ } else rhz = m << 6; - out: /* record time for successful remote HZ calc */ - if (rhz > 0) - lp->flag |= LP_VALID_RHZ; - else - lp->flag &= ~LP_VALID_RHZ; + lp->flag |= LP_VALID_RHZ; + out: /* record reference time stamp */ lp->remote_ref_time = tp->rx_opt.rcv_tsval; lp->local_ref_time = tp->rx_opt.rcv_tsecr; @@ -327,7 +321,7 @@ static struct tcp_congestion_ops tcp_lp = { static int __init tcp_lp_register(void) { - BUILD_BUG_ON(sizeof(struct lp) > ICSK_CA_PRIV_SIZE); + BUG_ON(sizeof(struct lp) > ICSK_CA_PRIV_SIZE); return tcp_register_congestion_control(&tcp_lp); } @@ -339,6 +333,6 @@ static void __exit tcp_lp_unregister(void) module_init(tcp_lp_register); module_exit(tcp_lp_unregister); -MODULE_AUTHOR("Wong Hoi Sing Edison, Hung Hing Lun Mike"); +MODULE_AUTHOR("Wong Hoi Sing Edison, Hung Hing Lun"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("TCP Low Priority"); diff --git a/trunk/net/ipv4/tcp_minisocks.c b/trunk/net/ipv4/tcp_minisocks.c index 0163d9826907..0ccb7cb22b15 100644 --- a/trunk/net/ipv4/tcp_minisocks.c +++ b/trunk/net/ipv4/tcp_minisocks.c @@ -34,8 +34,8 @@ #define SYNC_INIT 1 #endif -int sysctl_tcp_syncookies __read_mostly = SYNC_INIT; -int sysctl_tcp_abort_on_overflow __read_mostly; +int sysctl_tcp_syncookies = SYNC_INIT; +int sysctl_tcp_abort_on_overflow; struct inet_timewait_death_row tcp_death_row = { .sysctl_max_tw_buckets = NR_FILE * 2, @@ -589,10 +589,8 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, /* RFC793: "second check the RST bit" and * "fourth, check the SYN bit" */ - if (flg & (TCP_FLAG_RST|TCP_FLAG_SYN)) { - TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); + if (flg & (TCP_FLAG_RST|TCP_FLAG_SYN)) goto embryonic_reset; - } /* ACK sequence verified above, just make sure ACK is * set. If ACK not set, just silently drop the packet. diff --git a/trunk/net/ipv4/tcp_output.c b/trunk/net/ipv4/tcp_output.c index 061edfae0c29..5c08ea20a18d 100644 --- a/trunk/net/ipv4/tcp_output.c +++ b/trunk/net/ipv4/tcp_output.c @@ -43,24 +43,24 @@ #include /* People can turn this off for buggy TCP's found in printers etc. */ -int sysctl_tcp_retrans_collapse __read_mostly = 1; +int sysctl_tcp_retrans_collapse = 1; /* People can turn this on to work with those rare, broken TCPs that * interpret the window field as a signed quantity. */ -int sysctl_tcp_workaround_signed_windows __read_mostly = 0; +int sysctl_tcp_workaround_signed_windows = 0; /* This limits the percentage of the congestion window which we * will allow a single TSO frame to consume. Building TSO frames * which are too large can cause TCP streams to be bursty. */ -int sysctl_tcp_tso_win_divisor __read_mostly = 3; +int sysctl_tcp_tso_win_divisor = 3; -int sysctl_tcp_mtu_probing __read_mostly = 0; -int sysctl_tcp_base_mss __read_mostly = 512; +int sysctl_tcp_mtu_probing = 0; +int sysctl_tcp_base_mss = 512; /* By default, RFC2861 behavior. */ -int sysctl_tcp_slow_start_after_idle __read_mostly = 1; +int sysctl_tcp_slow_start_after_idle = 1; static void update_send_head(struct sock *sk, struct tcp_sock *tp, struct sk_buff *skb) @@ -201,7 +201,6 @@ void tcp_select_initial_window(int __space, __u32 mss, * See RFC1323 for an explanation of the limit to 14 */ space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max); - space = min_t(u32, space, *window_clamp); while (space > 65535 && (*rcv_wscale) < 14) { space >>= 1; (*rcv_wscale)++; @@ -467,8 +466,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, if (skb->len != tcp_header_size) tcp_event_data_sent(tp, skb, sk); - if (after(tcb->end_seq, tp->snd_nxt) || tcb->seq == tcb->end_seq) - TCP_INC_STATS(TCP_MIB_OUTSEGS); + TCP_INC_STATS(TCP_MIB_OUTSEGS); err = icsk->icsk_af_ops->queue_xmit(skb, 0); if (likely(err <= 0)) @@ -577,7 +575,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked; TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL; - if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_PARTIAL) { + if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) { /* Copy and checksum data tail into the new buffer. */ buff->csum = csum_partial_copy_nocheck(skb->data + len, skb_put(buff, nsize), nsize, 0); @@ -586,7 +584,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss skb->csum = csum_block_sub(skb->csum, buff->csum, len); } else { - skb->ip_summed = CHECKSUM_PARTIAL; + skb->ip_summed = CHECKSUM_HW; skb_split(skb, buff, len); } @@ -689,7 +687,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) __pskb_trim_head(skb, len - skb_headlen(skb)); TCP_SKB_CB(skb)->seq += len; - skb->ip_summed = CHECKSUM_PARTIAL; + skb->ip_summed = CHECKSUM_HW; skb->truesize -= len; sk->sk_wmem_queued -= len; @@ -1062,7 +1060,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len, /* This packet was never sent out yet, so no SACK bits. */ TCP_SKB_CB(buff)->sacked = 0; - buff->ip_summed = skb->ip_summed = CHECKSUM_PARTIAL; + buff->ip_summed = skb->ip_summed = CHECKSUM_HW; skb_split(skb, buff, len); /* Fix up tso_factor for both original and new SKB. */ @@ -1206,7 +1204,8 @@ static int tcp_mtu_probe(struct sock *sk) TCP_SKB_CB(nskb)->flags = TCPCB_FLAG_ACK; TCP_SKB_CB(nskb)->sacked = 0; nskb->csum = 0; - nskb->ip_summed = skb->ip_summed; + if (skb->ip_summed == CHECKSUM_HW) + nskb->ip_summed = CHECKSUM_HW; len = 0; while (len < probe_size) { @@ -1230,7 +1229,7 @@ static int tcp_mtu_probe(struct sock *sk) ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH); if (!skb_shinfo(skb)->nr_frags) { skb_pull(skb, copy); - if (skb->ip_summed != CHECKSUM_PARTIAL) + if (skb->ip_summed != CHECKSUM_HW) skb->csum = csum_partial(skb->data, skb->len, 0); } else { __pskb_trim_head(skb, copy); @@ -1571,9 +1570,10 @@ static void tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb, int m memcpy(skb_put(skb, next_skb_size), next_skb->data, next_skb_size); - skb->ip_summed = next_skb->ip_summed; + if (next_skb->ip_summed == CHECKSUM_HW) + skb->ip_summed = CHECKSUM_HW; - if (skb->ip_summed != CHECKSUM_PARTIAL) + if (skb->ip_summed != CHECKSUM_HW) skb->csum = csum_block_add(skb->csum, next_skb->csum, skb_size); /* Update sequence range on original skb. */ @@ -2157,9 +2157,10 @@ int tcp_connect(struct sock *sk) skb_shinfo(buff)->gso_size = 0; skb_shinfo(buff)->gso_type = 0; buff->csum = 0; - tp->snd_nxt = tp->write_seq; TCP_SKB_CB(buff)->seq = tp->write_seq++; TCP_SKB_CB(buff)->end_seq = tp->write_seq; + tp->snd_nxt = tp->write_seq; + tp->pushed_seq = tp->write_seq; /* Send it off. */ TCP_SKB_CB(buff)->when = tcp_time_stamp; @@ -2169,12 +2170,6 @@ int tcp_connect(struct sock *sk) sk_charge_skb(sk, buff); tp->packets_out += tcp_skb_pcount(buff); tcp_transmit_skb(sk, buff, 1, GFP_KERNEL); - - /* We change tp->snd_nxt after the tcp_transmit_skb() call - * in order to make this packet get counted in tcpOutSegs. - */ - tp->snd_nxt = tp->write_seq; - tp->pushed_seq = tp->write_seq; TCP_INC_STATS(TCP_MIB_ACTIVEOPENS); /* Timer for repeating the SYN until an answer. */ diff --git a/trunk/net/ipv4/tcp_probe.c b/trunk/net/ipv4/tcp_probe.c index dab37d2f65fc..d7d517a3a238 100644 --- a/trunk/net/ipv4/tcp_probe.c +++ b/trunk/net/ipv4/tcp_probe.c @@ -114,7 +114,7 @@ static int tcpprobe_open(struct inode * inode, struct file * file) static ssize_t tcpprobe_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) { - int error = 0, cnt = 0; + int error = 0, cnt; unsigned char *tbuf; if (!buf || len < 0) @@ -130,12 +130,11 @@ static ssize_t tcpprobe_read(struct file *file, char __user *buf, error = wait_event_interruptible(tcpw.wait, __kfifo_len(tcpw.fifo) != 0); if (error) - goto out_free; + return error; cnt = kfifo_get(tcpw.fifo, tbuf, len); error = copy_to_user(buf, tbuf, cnt); -out_free: vfree(tbuf); return error ? error : cnt; diff --git a/trunk/net/ipv4/tcp_timer.c b/trunk/net/ipv4/tcp_timer.c index fb09ade5897b..7c1bde3cd6cb 100644 --- a/trunk/net/ipv4/tcp_timer.c +++ b/trunk/net/ipv4/tcp_timer.c @@ -23,14 +23,14 @@ #include #include -int sysctl_tcp_syn_retries __read_mostly = TCP_SYN_RETRIES; -int sysctl_tcp_synack_retries __read_mostly = TCP_SYNACK_RETRIES; -int sysctl_tcp_keepalive_time __read_mostly = TCP_KEEPALIVE_TIME; -int sysctl_tcp_keepalive_probes __read_mostly = TCP_KEEPALIVE_PROBES; -int sysctl_tcp_keepalive_intvl __read_mostly = TCP_KEEPALIVE_INTVL; -int sysctl_tcp_retries1 __read_mostly = TCP_RETR1; -int sysctl_tcp_retries2 __read_mostly = TCP_RETR2; -int sysctl_tcp_orphan_retries __read_mostly; +int sysctl_tcp_syn_retries = TCP_SYN_RETRIES; +int sysctl_tcp_synack_retries = TCP_SYNACK_RETRIES; +int sysctl_tcp_keepalive_time = TCP_KEEPALIVE_TIME; +int sysctl_tcp_keepalive_probes = TCP_KEEPALIVE_PROBES; +int sysctl_tcp_keepalive_intvl = TCP_KEEPALIVE_INTVL; +int sysctl_tcp_retries1 = TCP_RETR1; +int sysctl_tcp_retries2 = TCP_RETR2; +int sysctl_tcp_orphan_retries; static void tcp_write_timer(unsigned long); static void tcp_delack_timer(unsigned long); diff --git a/trunk/net/ipv4/tcp_vegas.c b/trunk/net/ipv4/tcp_vegas.c index a3b7aa015a2f..490360b5b4bf 100644 --- a/trunk/net/ipv4/tcp_vegas.c +++ b/trunk/net/ipv4/tcp_vegas.c @@ -370,7 +370,7 @@ static struct tcp_congestion_ops tcp_vegas = { static int __init tcp_vegas_register(void) { - BUILD_BUG_ON(sizeof(struct vegas) > ICSK_CA_PRIV_SIZE); + BUG_ON(sizeof(struct vegas) > ICSK_CA_PRIV_SIZE); tcp_register_congestion_control(&tcp_vegas); return 0; } diff --git a/trunk/net/ipv4/tcp_veno.c b/trunk/net/ipv4/tcp_veno.c index ce57bf302f6c..11b42a7135c1 100644 --- a/trunk/net/ipv4/tcp_veno.c +++ b/trunk/net/ipv4/tcp_veno.c @@ -9,6 +9,7 @@ * See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf */ +#include #include #include #include @@ -212,7 +213,7 @@ static struct tcp_congestion_ops tcp_veno = { static int __init tcp_veno_register(void) { - BUILD_BUG_ON(sizeof(struct veno) > ICSK_CA_PRIV_SIZE); + BUG_ON(sizeof(struct veno) > ICSK_CA_PRIV_SIZE); tcp_register_congestion_control(&tcp_veno); return 0; } diff --git a/trunk/net/ipv4/tcp_westwood.c b/trunk/net/ipv4/tcp_westwood.c index 4f42a86c77f3..5446312ffd2a 100644 --- a/trunk/net/ipv4/tcp_westwood.c +++ b/trunk/net/ipv4/tcp_westwood.c @@ -289,7 +289,7 @@ static struct tcp_congestion_ops tcp_westwood = { static int __init tcp_westwood_register(void) { - BUILD_BUG_ON(sizeof(struct westwood) > ICSK_CA_PRIV_SIZE); + BUG_ON(sizeof(struct westwood) > ICSK_CA_PRIV_SIZE); return tcp_register_congestion_control(&tcp_westwood); } diff --git a/trunk/net/ipv4/udp.c b/trunk/net/ipv4/udp.c index 77e265d7bb8f..f136cec96d95 100644 --- a/trunk/net/ipv4/udp.c +++ b/trunk/net/ipv4/udp.c @@ -118,33 +118,14 @@ DEFINE_SNMP_STAT(struct udp_mib, udp_statistics) __read_mostly; struct hlist_head udp_hash[UDP_HTABLE_SIZE]; DEFINE_RWLOCK(udp_hash_lock); -static int udp_port_rover; +/* Shared by v4/v6 udp. */ +int udp_port_rover; -static inline int udp_lport_inuse(u16 num) -{ - struct sock *sk; - struct hlist_node *node; - - sk_for_each(sk, node, &udp_hash[num & (UDP_HTABLE_SIZE - 1)]) - if (inet_sk(sk)->num == num) - return 1; - return 0; -} - -/** - * udp_get_port - common port lookup for IPv4 and IPv6 - * - * @sk: socket struct in question - * @snum: port number to look up - * @saddr_comp: AF-dependent comparison of bound local IP addresses - */ -int udp_get_port(struct sock *sk, unsigned short snum, - int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2)) +static int udp_v4_get_port(struct sock *sk, unsigned short snum) { struct hlist_node *node; - struct hlist_head *head; struct sock *sk2; - int error = 1; + struct inet_sock *inet = inet_sk(sk); write_lock_bh(&udp_hash_lock); if (snum == 0) { @@ -156,10 +137,11 @@ int udp_get_port(struct sock *sk, unsigned short snum, best_size_so_far = 32767; best = result = udp_port_rover; for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) { + struct hlist_head *list; int size; - head = &udp_hash[result & (UDP_HTABLE_SIZE - 1)]; - if (hlist_empty(head)) { + list = &udp_hash[result & (UDP_HTABLE_SIZE - 1)]; + if (hlist_empty(list)) { if (result > sysctl_local_port_range[1]) result = sysctl_local_port_range[0] + ((result - sysctl_local_port_range[0]) & @@ -167,11 +149,12 @@ int udp_get_port(struct sock *sk, unsigned short snum, goto gotit; } size = 0; - sk_for_each(sk2, node, head) - if (++size < best_size_so_far) { - best_size_so_far = size; - best = result; - } + sk_for_each(sk2, node, list) + if (++size >= best_size_so_far) + goto next; + best_size_so_far = size; + best = result; + next:; } result = best; for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) { @@ -187,44 +170,38 @@ int udp_get_port(struct sock *sk, unsigned short snum, gotit: udp_port_rover = snum = result; } else { - head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; - - sk_for_each(sk2, node, head) - if (inet_sk(sk2)->num == snum && - sk2 != sk && - (!sk2->sk_reuse || !sk->sk_reuse) && - (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if - || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && - (*saddr_cmp)(sk, sk2) ) + sk_for_each(sk2, node, + &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]) { + struct inet_sock *inet2 = inet_sk(sk2); + + if (inet2->num == snum && + sk2 != sk && + !ipv6_only_sock(sk2) && + (!sk2->sk_bound_dev_if || + !sk->sk_bound_dev_if || + sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && + (!inet2->rcv_saddr || + !inet->rcv_saddr || + inet2->rcv_saddr == inet->rcv_saddr) && + (!sk2->sk_reuse || !sk->sk_reuse)) goto fail; + } } - inet_sk(sk)->num = snum; + inet->num = snum; if (sk_unhashed(sk)) { - head = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; - sk_add_node(sk, head); + struct hlist_head *h = &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]; + + sk_add_node(sk, h); sock_prot_inc_use(sk->sk_prot); } - error = 0; -fail: write_unlock_bh(&udp_hash_lock); - return error; -} - -static inline int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) -{ - struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2); - - return ( !ipv6_only_sock(sk2) && - (!inet1->rcv_saddr || !inet2->rcv_saddr || - inet1->rcv_saddr == inet2->rcv_saddr )); -} + return 0; -static inline int udp_v4_get_port(struct sock *sk, unsigned short snum) -{ - return udp_get_port(sk, snum, ipv4_rcv_saddr_equal); +fail: + write_unlock_bh(&udp_hash_lock); + return 1; } - static void udp_v4_hash(struct sock *sk) { BUG(); @@ -452,7 +429,7 @@ static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) /* * Only one fragment on the socket. */ - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { skb->csum = offsetof(struct udphdr, check); uh->check = ~csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, up->len, IPPROTO_UDP, 0); @@ -471,7 +448,7 @@ static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) * fragments on the socket so that all csums of sk_buffs * should be together. */ - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { int offset = (unsigned char *)uh - skb->data; skb->csum = skb_checksum(skb, offset, skb->len - offset, 0); @@ -626,7 +603,6 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, .uli_u = { .ports = { .sport = inet->sport, .dport = dport } } }; - security_sk_classify_flow(sk, &fl); err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); if (err) goto out; @@ -685,16 +661,6 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, UDP_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS); return len; } - /* - * ENOBUFS = no kernel mem, SOCK_NOSPACE = no sndbuf space. Reporting - * ENOBUFS might not be good (it's not tunable per se), but otherwise - * we don't have a good statistic (IpOutDiscards but it can be too many - * things). We could add another new stat but at least for now that - * seems like overkill. - */ - if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { - UDP_INC_STATS_USER(UDP_MIB_SNDBUFERRORS); - } return err; do_confirm: @@ -1014,7 +980,6 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) { struct udp_sock *up = udp_sk(sk); - int rc; /* * Charge it to the socket, dropping if the queue is full. @@ -1061,10 +1026,7 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) skb->ip_summed = CHECKSUM_UNNECESSARY; } - if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { - /* Note that an ENOMEM error is charged twice */ - if (rc == -ENOMEM) - UDP_INC_STATS_BH(UDP_MIB_RCVBUFERRORS); + if (sock_queue_rcv_skb(sk,skb)<0) { UDP_INC_STATS_BH(UDP_MIB_INERRORS); kfree_skb(skb); return -1; @@ -1125,7 +1087,7 @@ static void udp_checksum_init(struct sk_buff *skb, struct udphdr *uh, { if (uh->check == 0) { skb->ip_summed = CHECKSUM_UNNECESSARY; - } else if (skb->ip_summed == CHECKSUM_COMPLETE) { + } else if (skb->ip_summed == CHECKSUM_HW) { if (!udp_check(uh, ulen, saddr, daddr, skb->csum)) skb->ip_summed = CHECKSUM_UNNECESSARY; } @@ -1619,7 +1581,7 @@ EXPORT_SYMBOL(udp_disconnect); EXPORT_SYMBOL(udp_hash); EXPORT_SYMBOL(udp_hash_lock); EXPORT_SYMBOL(udp_ioctl); -EXPORT_SYMBOL(udp_get_port); +EXPORT_SYMBOL(udp_port_rover); EXPORT_SYMBOL(udp_prot); EXPORT_SYMBOL(udp_sendmsg); EXPORT_SYMBOL(udp_poll); diff --git a/trunk/net/ipv4/xfrm4_input.c b/trunk/net/ipv4/xfrm4_input.c index 040e8475f295..817ed84511a6 100644 --- a/trunk/net/ipv4/xfrm4_input.c +++ b/trunk/net/ipv4/xfrm4_input.c @@ -106,7 +106,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) if (x->mode->input(x, skb)) goto drop; - if (x->props.mode == XFRM_MODE_TUNNEL) { + if (x->props.mode) { decaps = 1; break; } diff --git a/trunk/net/ipv4/xfrm4_mode_transport.c b/trunk/net/ipv4/xfrm4_mode_transport.c index 92676b7e4034..a9e6b3dd19c9 100644 --- a/trunk/net/ipv4/xfrm4_mode_transport.c +++ b/trunk/net/ipv4/xfrm4_mode_transport.c @@ -21,8 +21,9 @@ * On exit, skb->h will be set to the start of the payload to be processed * by x->type->output and skb->nh will be set to the top IP header. */ -static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb) +static int xfrm4_transport_output(struct sk_buff *skb) { + struct xfrm_state *x; struct iphdr *iph; int ihl; @@ -32,6 +33,7 @@ static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb) ihl = iph->ihl * 4; skb->h.raw += ihl; + x = skb->dst->xfrm; skb->nh.raw = memmove(skb_push(skb, x->props.header_len), iph, ihl); return 0; } diff --git a/trunk/net/ipv4/xfrm4_mode_tunnel.c b/trunk/net/ipv4/xfrm4_mode_tunnel.c index e23c21d31a53..13cafbe56ce3 100644 --- a/trunk/net/ipv4/xfrm4_mode_tunnel.c +++ b/trunk/net/ipv4/xfrm4_mode_tunnel.c @@ -33,9 +33,10 @@ static inline void ipip_ecn_decapsulate(struct sk_buff *skb) * On exit, skb->h will be set to the start of the payload to be processed * by x->type->output and skb->nh will be set to the top IP header. */ -static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) +static int xfrm4_tunnel_output(struct sk_buff *skb) { struct dst_entry *dst = skb->dst; + struct xfrm_state *x = dst->xfrm; struct iphdr *iph, *top_iph; int flags; diff --git a/trunk/net/ipv4/xfrm4_output.c b/trunk/net/ipv4/xfrm4_output.c index 04403fb01a58..d16f863cf687 100644 --- a/trunk/net/ipv4/xfrm4_output.c +++ b/trunk/net/ipv4/xfrm4_output.c @@ -48,13 +48,13 @@ static int xfrm4_output_one(struct sk_buff *skb) struct xfrm_state *x = dst->xfrm; int err; - if (skb->ip_summed == CHECKSUM_PARTIAL) { - err = skb_checksum_help(skb); + if (skb->ip_summed == CHECKSUM_HW) { + err = skb_checksum_help(skb, 0); if (err) goto error_nolock; } - if (x->props.mode == XFRM_MODE_TUNNEL) { + if (x->props.mode) { err = xfrm4_tunnel_check_size(skb); if (err) goto error_nolock; @@ -66,7 +66,7 @@ static int xfrm4_output_one(struct sk_buff *skb) if (err) goto error; - err = x->mode->output(x, skb); + err = x->mode->output(skb); if (err) goto error; @@ -85,7 +85,7 @@ static int xfrm4_output_one(struct sk_buff *skb) } dst = skb->dst; x = dst->xfrm; - } while (x && (x->props.mode != XFRM_MODE_TUNNEL)); + } while (x && !x->props.mode); IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; err = 0; diff --git a/trunk/net/ipv4/xfrm4_policy.c b/trunk/net/ipv4/xfrm4_policy.c index eabcd27b1767..8f50eae47d03 100644 --- a/trunk/net/ipv4/xfrm4_policy.c +++ b/trunk/net/ipv4/xfrm4_policy.c @@ -21,25 +21,6 @@ static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) return __ip_route_output_key((struct rtable**)dst, fl); } -static int xfrm4_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr) -{ - struct rtable *rt; - struct flowi fl_tunnel = { - .nl_u = { - .ip4_u = { - .daddr = daddr->a4, - }, - }, - }; - - if (!xfrm4_dst_lookup((struct xfrm_dst **)&rt, &fl_tunnel)) { - saddr->a4 = rt->rt_src; - dst_release(&rt->u.dst); - return 0; - } - return -EHOSTUNREACH; -} - static struct dst_entry * __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy) { @@ -52,7 +33,7 @@ __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy) xdst->u.rt.fl.fl4_dst == fl->fl4_dst && xdst->u.rt.fl.fl4_src == fl->fl4_src && xdst->u.rt.fl.fl4_tos == fl->fl4_tos && - xfrm_bundle_ok(xdst, fl, AF_INET, 0)) { + xfrm_bundle_ok(xdst, fl, AF_INET)) { dst_clone(dst); break; } @@ -112,11 +93,10 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int xdst = (struct xfrm_dst *)dst1; xdst->route = &rt->u.dst; - xdst->genid = xfrm[i]->genid; dst1->next = dst_prev; dst_prev = dst1; - if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { + if (xfrm[i]->props.mode) { remote = xfrm[i]->id.daddr.a4; local = xfrm[i]->props.saddr.a4; tunnel = 1; @@ -155,7 +135,6 @@ __xfrm4_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int dst_prev->flags |= DST_HOST; dst_prev->lastuse = jiffies; dst_prev->header_len = header_len; - dst_prev->nfheader_len = 0; dst_prev->trailer_len = trailer_len; memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics)); @@ -317,7 +296,6 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { .family = AF_INET, .dst_ops = &xfrm4_dst_ops, .dst_lookup = xfrm4_dst_lookup, - .get_saddr = xfrm4_get_saddr, .find_bundle = __xfrm4_find_bundle, .bundle_create = __xfrm4_bundle_create, .decode_session = _decode_session4, diff --git a/trunk/net/ipv4/xfrm4_state.c b/trunk/net/ipv4/xfrm4_state.c index fe2034494d08..81e1751c966e 100644 --- a/trunk/net/ipv4/xfrm4_state.c +++ b/trunk/net/ipv4/xfrm4_state.c @@ -42,15 +42,99 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, x->props.saddr = tmpl->saddr; if (x->props.saddr.a4 == 0) x->props.saddr.a4 = saddr->a4; + if (tmpl->mode && x->props.saddr.a4 == 0) { + struct rtable *rt; + struct flowi fl_tunnel = { + .nl_u = { + .ip4_u = { + .daddr = x->id.daddr.a4, + } + } + }; + if (!xfrm_dst_lookup((struct xfrm_dst **)&rt, + &fl_tunnel, AF_INET)) { + x->props.saddr.a4 = rt->rt_src; + dst_release(&rt->u.dst); + } + } x->props.mode = tmpl->mode; x->props.reqid = tmpl->reqid; x->props.family = AF_INET; } +static struct xfrm_state * +__xfrm4_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto) +{ + unsigned h = __xfrm4_spi_hash(daddr, spi, proto); + struct xfrm_state *x; + + list_for_each_entry(x, xfrm4_state_afinfo.state_byspi+h, byspi) { + if (x->props.family == AF_INET && + spi == x->id.spi && + daddr->a4 == x->id.daddr.a4 && + proto == x->id.proto) { + xfrm_state_hold(x); + return x; + } + } + return NULL; +} + +static struct xfrm_state * +__xfrm4_find_acq(u8 mode, u32 reqid, u8 proto, + xfrm_address_t *daddr, xfrm_address_t *saddr, + int create) +{ + struct xfrm_state *x, *x0; + unsigned h = __xfrm4_dst_hash(daddr); + + x0 = NULL; + + list_for_each_entry(x, xfrm4_state_afinfo.state_bydst+h, bydst) { + if (x->props.family == AF_INET && + daddr->a4 == x->id.daddr.a4 && + mode == x->props.mode && + proto == x->id.proto && + saddr->a4 == x->props.saddr.a4 && + reqid == x->props.reqid && + x->km.state == XFRM_STATE_ACQ && + !x->id.spi) { + x0 = x; + break; + } + } + if (!x0 && create && (x0 = xfrm_state_alloc()) != NULL) { + x0->sel.daddr.a4 = daddr->a4; + x0->sel.saddr.a4 = saddr->a4; + x0->sel.prefixlen_d = 32; + x0->sel.prefixlen_s = 32; + x0->props.saddr.a4 = saddr->a4; + x0->km.state = XFRM_STATE_ACQ; + x0->id.daddr.a4 = daddr->a4; + x0->id.proto = proto; + x0->props.family = AF_INET; + x0->props.mode = mode; + x0->props.reqid = reqid; + x0->props.family = AF_INET; + x0->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES; + xfrm_state_hold(x0); + x0->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; + add_timer(&x0->timer); + xfrm_state_hold(x0); + list_add_tail(&x0->bydst, xfrm4_state_afinfo.state_bydst+h); + wake_up(&km_waitq); + } + if (x0) + xfrm_state_hold(x0); + return x0; +} + static struct xfrm_state_afinfo xfrm4_state_afinfo = { .family = AF_INET, .init_flags = xfrm4_init_flags, .init_tempsel = __xfrm4_init_tempsel, + .state_lookup = __xfrm4_state_lookup, + .find_acq = __xfrm4_find_acq, }; void __init xfrm4_state_init(void) diff --git a/trunk/net/ipv4/xfrm4_tunnel.c b/trunk/net/ipv4/xfrm4_tunnel.c index f110af5b1319..f8ceaa127c83 100644 --- a/trunk/net/ipv4/xfrm4_tunnel.c +++ b/trunk/net/ipv4/xfrm4_tunnel.c @@ -28,7 +28,7 @@ static int ipip_xfrm_rcv(struct xfrm_state *x, struct sk_buff *skb) static int ipip_init_state(struct xfrm_state *x) { - if (x->props.mode != XFRM_MODE_TUNNEL) + if (!x->props.mode) return -EINVAL; if (x->encap) diff --git a/trunk/net/ipv6/Kconfig b/trunk/net/ipv6/Kconfig index a2d211da2aba..e923d4dea418 100644 --- a/trunk/net/ipv6/Kconfig +++ b/trunk/net/ipv6/Kconfig @@ -77,7 +77,6 @@ config INET6_ESP select CRYPTO select CRYPTO_HMAC select CRYPTO_MD5 - select CRYPTO_CBC select CRYPTO_SHA1 select CRYPTO_DES ---help--- @@ -98,15 +97,6 @@ config INET6_IPCOMP If unsure, say Y. -config IPV6_MIP6 - bool "IPv6: Mobility (EXPERIMENTAL)" - depends on IPV6 && EXPERIMENTAL - select XFRM - ---help--- - Support for IPv6 Mobility described in RFC 3775. - - If unsure, say N. - config INET6_XFRM_TUNNEL tristate select INET6_TUNNEL @@ -136,13 +126,6 @@ config INET6_XFRM_MODE_TUNNEL If unsure, say Y. -config INET6_XFRM_MODE_ROUTEOPTIMIZATION - tristate "IPv6: MIPv6 route optimization mode (EXPERIMENTAL)" - depends on IPV6 && EXPERIMENTAL - select XFRM - ---help--- - Support for MIPv6 route optimization mode. - config IPV6_TUNNEL tristate "IPv6: IPv6-in-IPv6 tunnel" select INET6_TUNNEL @@ -152,31 +135,3 @@ config IPV6_TUNNEL If unsure, say N. -config IPV6_SUBTREES - bool "IPv6: source address based routing" - depends on IPV6 && EXPERIMENTAL - ---help--- - Enable routing by source address or prefix. - - The destination address is still the primary routing key, so mixing - normal and source prefix specific routes in the same routing table - may sometimes lead to unintended routing behavior. This can be - avoided by defining different routing tables for the normal and - source prefix specific routes. - - If unsure, say N. - -config IPV6_MULTIPLE_TABLES - bool "IPv6: Multiple Routing Tables" - depends on IPV6 && EXPERIMENTAL - select FIB_RULES - ---help--- - Support multiple routing tables. - -config IPV6_ROUTE_FWMARK - bool "IPv6: use netfilter MARK value as routing key" - depends on IPV6_MULTIPLE_TABLES && NETFILTER - ---help--- - If you say Y here, you will be able to specify different routes for - packets with different mark values (see iptables(8), MARK target). - diff --git a/trunk/net/ipv6/Makefile b/trunk/net/ipv6/Makefile index 0213c6612b58..386e0a626948 100644 --- a/trunk/net/ipv6/Makefile +++ b/trunk/net/ipv6/Makefile @@ -13,9 +13,6 @@ ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o sit.o \ ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ xfrm6_output.o ipv6-$(CONFIG_NETFILTER) += netfilter.o -ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o -ipv6-$(CONFIG_IPV6_MIP6) += mip6.o - ipv6-objs += $(ipv6-y) obj-$(CONFIG_INET6_AH) += ah6.o @@ -25,7 +22,6 @@ obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o -obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o diff --git a/trunk/net/ipv6/addrconf.c b/trunk/net/ipv6/addrconf.c index c18676352397..2316a4315a18 100644 --- a/trunk/net/ipv6/addrconf.c +++ b/trunk/net/ipv6/addrconf.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include #include @@ -73,7 +72,6 @@ #include #include #include -#include #include #include @@ -119,6 +117,9 @@ static int ipv6_count_addresses(struct inet6_dev *idev); static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE]; static DEFINE_RWLOCK(addrconf_hash_lock); +/* Protects inet6 devices */ +DEFINE_RWLOCK(addrconf_lock); + static void addrconf_verify(unsigned long); static DEFINE_TIMER(addr_chk_timer, addrconf_verify, 0, 0); @@ -143,7 +144,7 @@ static int ipv6_chk_same_addr(const struct in6_addr *addr, struct net_device *de static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); -struct ipv6_devconf ipv6_devconf __read_mostly = { +struct ipv6_devconf ipv6_devconf = { .forwarding = 0, .hop_limit = IPV6_DEFAULT_HOPLIMIT, .mtu6 = IPV6_MIN_MTU, @@ -172,10 +173,9 @@ struct ipv6_devconf ipv6_devconf __read_mostly = { .accept_ra_rt_info_max_plen = 0, #endif #endif - .proxy_ndp = 0, }; -static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { +static struct ipv6_devconf ipv6_devconf_dflt = { .forwarding = 0, .hop_limit = IPV6_DEFAULT_HOPLIMIT, .mtu6 = IPV6_MIN_MTU, @@ -203,7 +203,6 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { .accept_ra_rt_info_max_plen = 0, #endif #endif - .proxy_ndp = 0, }; /* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */ @@ -315,12 +314,6 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, /* Nobody refers to this device, we may destroy it. */ -static void in6_dev_finish_destroy_rcu(struct rcu_head *head) -{ - struct inet6_dev *idev = container_of(head, struct inet6_dev, rcu); - kfree(idev); -} - void in6_dev_finish_destroy(struct inet6_dev *idev) { struct net_device *dev = idev->dev; @@ -335,7 +328,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) return; } snmp6_free_dev(idev); - call_rcu(&idev->rcu, in6_dev_finish_destroy_rcu); + kfree(idev); } static struct inet6_dev * ipv6_add_dev(struct net_device *dev) @@ -411,8 +404,9 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) if (netif_carrier_ok(dev)) ndev->if_flags |= IF_READY; - /* protected by rtnl_lock */ - rcu_assign_pointer(dev->ip6_ptr, ndev); + write_lock_bh(&addrconf_lock); + dev->ip6_ptr = ndev; + write_unlock_bh(&addrconf_lock); ipv6_mc_init_dev(ndev); ndev->tstamp = jiffies; @@ -476,7 +470,7 @@ static void addrconf_forward_change(void) read_lock(&dev_base_lock); for (dev=dev_base; dev; dev=dev->next) { - rcu_read_lock(); + read_lock(&addrconf_lock); idev = __in6_dev_get(dev); if (idev) { int changed = (!idev->cnf.forwarding) ^ (!ipv6_devconf.forwarding); @@ -484,7 +478,7 @@ static void addrconf_forward_change(void) if (changed) dev_forward_change(idev); } - rcu_read_unlock(); + read_unlock(&addrconf_lock); } read_unlock(&dev_base_lock); } @@ -545,7 +539,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, int hash; int err = 0; - rcu_read_lock_bh(); + read_lock_bh(&addrconf_lock); if (idev->dead) { err = -ENODEV; /*XXX*/ goto out2; @@ -584,8 +578,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, ifa->flags = flags | IFA_F_TENTATIVE; ifa->cstamp = ifa->tstamp = jiffies; - ifa->rt = rt; - ifa->idev = idev; in6_dev_hold(idev); /* For caller */ @@ -611,10 +603,12 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, } #endif + ifa->rt = rt; + in6_ifa_hold(ifa); write_unlock(&idev->lock); out2: - rcu_read_unlock_bh(); + read_unlock_bh(&addrconf_lock); if (likely(err == 0)) atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa); @@ -740,7 +734,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { if (onlink == 0) { - ip6_del_rt(rt); + ip6_del_rt(rt, NULL, NULL, NULL); rt = NULL; } else if (!(rt->rt6i_flags & RTF_EXPIRES)) { rt->rt6i_expires = expires; @@ -917,7 +911,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, memset(&hiscore, 0, sizeof(hiscore)); read_lock(&dev_base_lock); - rcu_read_lock(); + read_lock(&addrconf_lock); for (dev = dev_base; dev; dev=dev->next) { struct inet6_dev *idev; @@ -1038,27 +1032,9 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, continue; } - /* Rule 4: Prefer home address */ -#ifdef CONFIG_IPV6_MIP6 - if (hiscore.rule < 4) { - if (ifa_result->flags & IFA_F_HOMEADDRESS) - hiscore.attrs |= IPV6_SADDR_SCORE_HOA; - hiscore.rule++; - } - if (ifa->flags & IFA_F_HOMEADDRESS) { - score.attrs |= IPV6_SADDR_SCORE_HOA; - if (!(ifa_result->flags & IFA_F_HOMEADDRESS)) { - score.rule = 4; - goto record_it; - } - } else { - if (hiscore.attrs & IPV6_SADDR_SCORE_HOA) - continue; - } -#else + /* Rule 4: Prefer home address -- not implemented yet */ if (hiscore.rule < 4) hiscore.rule++; -#endif /* Rule 5: Prefer outgoing interface */ if (hiscore.rule < 5) { @@ -1147,7 +1123,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, } read_unlock_bh(&idev->lock); } - rcu_read_unlock(); + read_unlock(&addrconf_lock); read_unlock(&dev_base_lock); if (!ifa_result) @@ -1171,7 +1147,7 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr) struct inet6_dev *idev; int err = -EADDRNOTAVAIL; - rcu_read_lock(); + read_lock(&addrconf_lock); if ((idev = __in6_dev_get(dev)) != NULL) { struct inet6_ifaddr *ifp; @@ -1185,7 +1161,7 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr) } read_unlock_bh(&idev->lock); } - rcu_read_unlock(); + read_unlock(&addrconf_lock); return err; } @@ -1486,7 +1462,7 @@ static void ipv6_regen_rndid(unsigned long data) struct inet6_dev *idev = (struct inet6_dev *) data; unsigned long expires; - rcu_read_lock_bh(); + read_lock_bh(&addrconf_lock); write_lock_bh(&idev->lock); if (idev->dead) @@ -1510,7 +1486,7 @@ static void ipv6_regen_rndid(unsigned long data) out: write_unlock_bh(&idev->lock); - rcu_read_unlock_bh(); + read_unlock_bh(&addrconf_lock); in6_dev_put(idev); } @@ -1531,56 +1507,59 @@ static void addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, unsigned long expires, u32 flags) { - struct fib6_config cfg = { - .fc_table = RT6_TABLE_PREFIX, - .fc_metric = IP6_RT_PRIO_ADDRCONF, - .fc_ifindex = dev->ifindex, - .fc_expires = expires, - .fc_dst_len = plen, - .fc_flags = RTF_UP | flags, - }; + struct in6_rtmsg rtmsg; - ipv6_addr_copy(&cfg.fc_dst, pfx); + memset(&rtmsg, 0, sizeof(rtmsg)); + ipv6_addr_copy(&rtmsg.rtmsg_dst, pfx); + rtmsg.rtmsg_dst_len = plen; + rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF; + rtmsg.rtmsg_ifindex = dev->ifindex; + rtmsg.rtmsg_info = expires; + rtmsg.rtmsg_flags = RTF_UP|flags; + rtmsg.rtmsg_type = RTMSG_NEWROUTE; /* Prevent useless cloning on PtP SIT. This thing is done here expecting that the whole class of non-broadcast devices need not cloning. */ - if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT)) - cfg.fc_flags |= RTF_NONEXTHOP; + if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT)) + rtmsg.rtmsg_flags |= RTF_NONEXTHOP; - ip6_route_add(&cfg); + ip6_route_add(&rtmsg, NULL, NULL, NULL); } /* Create "default" multicast route to the interface */ static void addrconf_add_mroute(struct net_device *dev) { - struct fib6_config cfg = { - .fc_table = RT6_TABLE_LOCAL, - .fc_metric = IP6_RT_PRIO_ADDRCONF, - .fc_ifindex = dev->ifindex, - .fc_dst_len = 8, - .fc_flags = RTF_UP, - }; - - ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0); + struct in6_rtmsg rtmsg; - ip6_route_add(&cfg); + memset(&rtmsg, 0, sizeof(rtmsg)); + ipv6_addr_set(&rtmsg.rtmsg_dst, + htonl(0xFF000000), 0, 0, 0); + rtmsg.rtmsg_dst_len = 8; + rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF; + rtmsg.rtmsg_ifindex = dev->ifindex; + rtmsg.rtmsg_flags = RTF_UP; + rtmsg.rtmsg_type = RTMSG_NEWROUTE; + ip6_route_add(&rtmsg, NULL, NULL, NULL); } static void sit_route_add(struct net_device *dev) { - struct fib6_config cfg = { - .fc_table = RT6_TABLE_MAIN, - .fc_metric = IP6_RT_PRIO_ADDRCONF, - .fc_ifindex = dev->ifindex, - .fc_dst_len = 96, - .fc_flags = RTF_UP | RTF_NONEXTHOP, - }; + struct in6_rtmsg rtmsg; + + memset(&rtmsg, 0, sizeof(rtmsg)); + + rtmsg.rtmsg_type = RTMSG_NEWROUTE; + rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF; /* prefix length - 96 bits "::d.d.d.d" */ - ip6_route_add(&cfg); + rtmsg.rtmsg_dst_len = 96; + rtmsg.rtmsg_flags = RTF_UP|RTF_NONEXTHOP; + rtmsg.rtmsg_ifindex = dev->ifindex; + + ip6_route_add(&rtmsg, NULL, NULL, NULL); } static void addrconf_add_lroute(struct net_device *dev) @@ -1681,7 +1660,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { if (rt->rt6i_flags&RTF_EXPIRES) { if (valid_lft == 0) { - ip6_del_rt(rt); + ip6_del_rt(rt, NULL, NULL, NULL); rt = NULL; } else { rt->rt6i_expires = jiffies + rt_expires; @@ -1890,8 +1869,7 @@ int addrconf_set_dstaddr(void __user *arg) /* * Manual configuration of address on an interface */ -static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, - __u8 ifa_flags, __u32 prefered_lft, __u32 valid_lft) +static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen) { struct inet6_ifaddr *ifp; struct inet6_dev *idev; @@ -1900,41 +1878,21 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, ASSERT_RTNL(); - /* check the lifetime */ - if (!valid_lft || prefered_lft > valid_lft) - return -EINVAL; - if ((dev = __dev_get_by_index(ifindex)) == NULL) return -ENODEV; + if (!(dev->flags&IFF_UP)) + return -ENETDOWN; + if ((idev = addrconf_add_dev(dev)) == NULL) return -ENOBUFS; scope = ipv6_addr_scope(pfx); - if (valid_lft == INFINITY_LIFE_TIME) - ifa_flags |= IFA_F_PERMANENT; - else if (valid_lft >= 0x7FFFFFFF/HZ) - valid_lft = 0x7FFFFFFF/HZ; - - if (prefered_lft == 0) - ifa_flags |= IFA_F_DEPRECATED; - else if ((prefered_lft >= 0x7FFFFFFF/HZ) && - (prefered_lft != INFINITY_LIFE_TIME)) - prefered_lft = 0x7FFFFFFF/HZ; - - ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags); - + ifp = ipv6_add_addr(idev, pfx, plen, scope, IFA_F_PERMANENT); if (!IS_ERR(ifp)) { - spin_lock_bh(&ifp->lock); - ifp->valid_lft = valid_lft; - ifp->prefered_lft = prefered_lft; - ifp->tstamp = jiffies; - spin_unlock_bh(&ifp->lock); - addrconf_dad_start(ifp, 0); in6_ifa_put(ifp); - addrconf_verify(0); return 0; } @@ -1987,8 +1945,7 @@ int addrconf_add_ifaddr(void __user *arg) return -EFAULT; rtnl_lock(); - err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen, - IFA_F_PERMANENT, INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); + err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen); rtnl_unlock(); return err; } @@ -2361,10 +2318,10 @@ static int addrconf_ifdown(struct net_device *dev, int how) Do not dev_put! */ if (how == 1) { + write_lock_bh(&addrconf_lock); + dev->ip6_ptr = NULL; idev->dead = 1; - - /* protected by rtnl_lock */ - rcu_assign_pointer(dev->ip6_ptr, NULL); + write_unlock_bh(&addrconf_lock); /* Step 1.5: remove snmp6 entry */ snmp6_unregister_dev(idev); @@ -2531,8 +2488,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) spin_lock_bh(&ifp->lock); if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || - !(ifp->flags&IFA_F_TENTATIVE) || - ifp->flags & IFA_F_NODAD) { + !(ifp->flags&IFA_F_TENTATIVE)) { ifp->flags &= ~IFA_F_TENTATIVE; spin_unlock_bh(&ifp->lock); read_unlock_bh(&idev->lock); @@ -2777,26 +2733,6 @@ void if6_proc_exit(void) } #endif /* CONFIG_PROC_FS */ -#ifdef CONFIG_IPV6_MIP6 -/* Check if address is a home address configured on any interface. */ -int ipv6_chk_home_addr(struct in6_addr *addr) -{ - int ret = 0; - struct inet6_ifaddr * ifp; - u8 hash = ipv6_addr_hash(addr); - read_lock_bh(&addrconf_hash_lock); - for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { - if (ipv6_addr_cmp(&ifp->addr, addr) == 0 && - (ifp->flags & IFA_F_HOMEADDRESS)) { - ret = 1; - break; - } - } - read_unlock_bh(&addrconf_hash_lock); - return ret; -} -#endif - /* * Periodic address status verification */ @@ -2835,16 +2771,12 @@ static void addrconf_verify(unsigned long foo) ifp->idev->nd_parms->retrans_time / HZ; #endif - if (ifp->valid_lft != INFINITY_LIFE_TIME && - age >= ifp->valid_lft) { + if (age >= ifp->valid_lft) { spin_unlock(&ifp->lock); in6_ifa_hold(ifp); read_unlock(&addrconf_hash_lock); ipv6_del_addr(ifp); goto restart; - } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) { - spin_unlock(&ifp->lock); - continue; } else if (age >= ifp->prefered_lft) { /* jiffies - ifp->tsamp > age >= ifp->prefered_lft */ int deprecate = 0; @@ -2907,267 +2839,178 @@ static void addrconf_verify(unsigned long foo) spin_unlock_bh(&addrconf_verify_lock); } -static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) -{ - struct in6_addr *pfx = NULL; - - if (addr) - pfx = nla_data(addr); - - if (local) { - if (pfx && nla_memcmp(local, pfx, sizeof(*pfx))) - pfx = NULL; - else - pfx = nla_data(local); - } - - return pfx; -} - -static struct nla_policy ifa_ipv6_policy[IFA_MAX+1] __read_mostly = { - [IFA_ADDRESS] = { .len = sizeof(struct in6_addr) }, - [IFA_LOCAL] = { .len = sizeof(struct in6_addr) }, - [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) }, -}; - static int inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { - struct ifaddrmsg *ifm; - struct nlattr *tb[IFA_MAX+1]; + struct rtattr **rta = arg; + struct ifaddrmsg *ifm = NLMSG_DATA(nlh); struct in6_addr *pfx; - int err; - - err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); - if (err < 0) - return err; - ifm = nlmsg_data(nlh); - pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]); + pfx = NULL; + if (rta[IFA_ADDRESS-1]) { + if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*pfx)) + return -EINVAL; + pfx = RTA_DATA(rta[IFA_ADDRESS-1]); + } + if (rta[IFA_LOCAL-1]) { + if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))) + return -EINVAL; + pfx = RTA_DATA(rta[IFA_LOCAL-1]); + } if (pfx == NULL) return -EINVAL; return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen); } -static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, - u32 prefered_lft, u32 valid_lft) -{ - if (!valid_lft || (prefered_lft > valid_lft)) - return -EINVAL; - - if (valid_lft == INFINITY_LIFE_TIME) - ifa_flags |= IFA_F_PERMANENT; - else if (valid_lft >= 0x7FFFFFFF/HZ) - valid_lft = 0x7FFFFFFF/HZ; - - if (prefered_lft == 0) - ifa_flags |= IFA_F_DEPRECATED; - else if ((prefered_lft >= 0x7FFFFFFF/HZ) && - (prefered_lft != INFINITY_LIFE_TIME)) - prefered_lft = 0x7FFFFFFF/HZ; - - spin_lock_bh(&ifp->lock); - ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags; - ifp->tstamp = jiffies; - ifp->valid_lft = valid_lft; - ifp->prefered_lft = prefered_lft; - - spin_unlock_bh(&ifp->lock); - if (!(ifp->flags&IFA_F_TENTATIVE)) - ipv6_ifa_notify(0, ifp); - - addrconf_verify(0); - - return 0; -} - static int inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { - struct ifaddrmsg *ifm; - struct nlattr *tb[IFA_MAX+1]; + struct rtattr **rta = arg; + struct ifaddrmsg *ifm = NLMSG_DATA(nlh); struct in6_addr *pfx; - struct inet6_ifaddr *ifa; - struct net_device *dev; - u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME; - u8 ifa_flags; - int err; - - err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); - if (err < 0) - return err; - - ifm = nlmsg_data(nlh); - pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]); - if (pfx == NULL) - return -EINVAL; - - if (tb[IFA_CACHEINFO]) { - struct ifa_cacheinfo *ci; - ci = nla_data(tb[IFA_CACHEINFO]); - valid_lft = ci->ifa_valid; - preferred_lft = ci->ifa_prefered; - } else { - preferred_lft = INFINITY_LIFE_TIME; - valid_lft = INFINITY_LIFE_TIME; + pfx = NULL; + if (rta[IFA_ADDRESS-1]) { + if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*pfx)) + return -EINVAL; + pfx = RTA_DATA(rta[IFA_ADDRESS-1]); } - - dev = __dev_get_by_index(ifm->ifa_index); - if (dev == NULL) - return -ENODEV; - - /* We ignore other flags so far. */ - ifa_flags = ifm->ifa_flags & (IFA_F_NODAD | IFA_F_HOMEADDRESS); - - ifa = ipv6_get_ifaddr(pfx, dev, 1); - if (ifa == NULL) { - /* - * It would be best to check for !NLM_F_CREATE here but - * userspace alreay relies on not having to provide this. - */ - return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen, - ifa_flags, preferred_lft, valid_lft); + if (rta[IFA_LOCAL-1]) { + if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))) + return -EINVAL; + pfx = RTA_DATA(rta[IFA_LOCAL-1]); } + if (pfx == NULL) + return -EINVAL; - if (nlh->nlmsg_flags & NLM_F_EXCL || - !(nlh->nlmsg_flags & NLM_F_REPLACE)) - err = -EEXIST; - else - err = inet6_addr_modify(ifa, ifa_flags, preferred_lft, valid_lft); - - in6_ifa_put(ifa); - - return err; -} - -static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u8 flags, - u8 scope, int ifindex) -{ - struct ifaddrmsg *ifm; - - ifm = nlmsg_data(nlh); - ifm->ifa_family = AF_INET6; - ifm->ifa_prefixlen = prefixlen; - ifm->ifa_flags = flags; - ifm->ifa_scope = scope; - ifm->ifa_index = ifindex; -} - -static int put_cacheinfo(struct sk_buff *skb, unsigned long cstamp, - unsigned long tstamp, u32 preferred, u32 valid) -{ - struct ifa_cacheinfo ci; - - ci.cstamp = (u32)(TIME_DELTA(cstamp, INITIAL_JIFFIES) / HZ * 100 - + TIME_DELTA(cstamp, INITIAL_JIFFIES) % HZ * 100 / HZ); - ci.tstamp = (u32)(TIME_DELTA(tstamp, INITIAL_JIFFIES) / HZ * 100 - + TIME_DELTA(tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ); - ci.ifa_prefered = preferred; - ci.ifa_valid = valid; - - return nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci); + return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen); } -static inline int rt_scope(int ifa_scope) -{ - if (ifa_scope & IFA_HOST) - return RT_SCOPE_HOST; - else if (ifa_scope & IFA_LINK) - return RT_SCOPE_LINK; - else if (ifa_scope & IFA_SITE) - return RT_SCOPE_SITE; - else - return RT_SCOPE_UNIVERSE; -} - -static inline int inet6_ifaddr_msgsize(void) -{ - return nlmsg_total_size(sizeof(struct ifaddrmsg) + - nla_total_size(16) + - nla_total_size(sizeof(struct ifa_cacheinfo)) + - 128); -} +/* Maximum length of ifa_cacheinfo attributes */ +#define INET6_IFADDR_RTA_SPACE \ + RTA_SPACE(16) /* IFA_ADDRESS */ + \ + RTA_SPACE(sizeof(struct ifa_cacheinfo)) /* CACHEINFO */ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, u32 pid, u32 seq, int event, unsigned int flags) { + struct ifaddrmsg *ifm; struct nlmsghdr *nlh; - u32 preferred, valid; - - nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); - if (nlh == NULL) - return -ENOBUFS; - - put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope), - ifa->idev->dev->ifindex); + struct ifa_cacheinfo ci; + unsigned char *b = skb->tail; + nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); + ifm = NLMSG_DATA(nlh); + ifm->ifa_family = AF_INET6; + ifm->ifa_prefixlen = ifa->prefix_len; + ifm->ifa_flags = ifa->flags; + ifm->ifa_scope = RT_SCOPE_UNIVERSE; + if (ifa->scope&IFA_HOST) + ifm->ifa_scope = RT_SCOPE_HOST; + else if (ifa->scope&IFA_LINK) + ifm->ifa_scope = RT_SCOPE_LINK; + else if (ifa->scope&IFA_SITE) + ifm->ifa_scope = RT_SCOPE_SITE; + ifm->ifa_index = ifa->idev->dev->ifindex; + RTA_PUT(skb, IFA_ADDRESS, 16, &ifa->addr); if (!(ifa->flags&IFA_F_PERMANENT)) { - preferred = ifa->prefered_lft; - valid = ifa->valid_lft; - if (preferred != INFINITY_LIFE_TIME) { + ci.ifa_prefered = ifa->prefered_lft; + ci.ifa_valid = ifa->valid_lft; + if (ci.ifa_prefered != INFINITY_LIFE_TIME) { long tval = (jiffies - ifa->tstamp)/HZ; - preferred -= tval; - if (valid != INFINITY_LIFE_TIME) - valid -= tval; + ci.ifa_prefered -= tval; + if (ci.ifa_valid != INFINITY_LIFE_TIME) + ci.ifa_valid -= tval; } } else { - preferred = INFINITY_LIFE_TIME; - valid = INFINITY_LIFE_TIME; - } - - if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 || - put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) - return nlmsg_cancel(skb, nlh); + ci.ifa_prefered = INFINITY_LIFE_TIME; + ci.ifa_valid = INFINITY_LIFE_TIME; + } + ci.cstamp = (__u32)(TIME_DELTA(ifa->cstamp, INITIAL_JIFFIES) / HZ * 100 + + TIME_DELTA(ifa->cstamp, INITIAL_JIFFIES) % HZ * 100 / HZ); + ci.tstamp = (__u32)(TIME_DELTA(ifa->tstamp, INITIAL_JIFFIES) / HZ * 100 + + TIME_DELTA(ifa->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ); + RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci); + nlh->nlmsg_len = skb->tail - b; + return skb->len; - return nlmsg_end(skb, nlh); +nlmsg_failure: +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; } static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca, u32 pid, u32 seq, int event, u16 flags) { + struct ifaddrmsg *ifm; struct nlmsghdr *nlh; - u8 scope = RT_SCOPE_UNIVERSE; - int ifindex = ifmca->idev->dev->ifindex; - - if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE) - scope = RT_SCOPE_SITE; - - nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); - if (nlh == NULL) - return -ENOBUFS; - - put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); - if (nla_put(skb, IFA_MULTICAST, 16, &ifmca->mca_addr) < 0 || - put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp, - INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) - return nlmsg_cancel(skb, nlh); + struct ifa_cacheinfo ci; + unsigned char *b = skb->tail; + + nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); + ifm = NLMSG_DATA(nlh); + ifm->ifa_family = AF_INET6; + ifm->ifa_prefixlen = 128; + ifm->ifa_flags = IFA_F_PERMANENT; + ifm->ifa_scope = RT_SCOPE_UNIVERSE; + if (ipv6_addr_scope(&ifmca->mca_addr)&IFA_SITE) + ifm->ifa_scope = RT_SCOPE_SITE; + ifm->ifa_index = ifmca->idev->dev->ifindex; + RTA_PUT(skb, IFA_MULTICAST, 16, &ifmca->mca_addr); + ci.cstamp = (__u32)(TIME_DELTA(ifmca->mca_cstamp, INITIAL_JIFFIES) / HZ + * 100 + TIME_DELTA(ifmca->mca_cstamp, INITIAL_JIFFIES) % HZ + * 100 / HZ); + ci.tstamp = (__u32)(TIME_DELTA(ifmca->mca_tstamp, INITIAL_JIFFIES) / HZ + * 100 + TIME_DELTA(ifmca->mca_tstamp, INITIAL_JIFFIES) % HZ + * 100 / HZ); + ci.ifa_prefered = INFINITY_LIFE_TIME; + ci.ifa_valid = INFINITY_LIFE_TIME; + RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci); + nlh->nlmsg_len = skb->tail - b; + return skb->len; - return nlmsg_end(skb, nlh); +nlmsg_failure: +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; } static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, u32 pid, u32 seq, int event, unsigned int flags) { + struct ifaddrmsg *ifm; struct nlmsghdr *nlh; - u8 scope = RT_SCOPE_UNIVERSE; - int ifindex = ifaca->aca_idev->dev->ifindex; - - if (ipv6_addr_scope(&ifaca->aca_addr) & IFA_SITE) - scope = RT_SCOPE_SITE; - - nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); - if (nlh == NULL) - return -ENOBUFS; - - put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); - if (nla_put(skb, IFA_ANYCAST, 16, &ifaca->aca_addr) < 0 || - put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp, - INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) - return nlmsg_cancel(skb, nlh); + struct ifa_cacheinfo ci; + unsigned char *b = skb->tail; + + nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); + ifm = NLMSG_DATA(nlh); + ifm->ifa_family = AF_INET6; + ifm->ifa_prefixlen = 128; + ifm->ifa_flags = IFA_F_PERMANENT; + ifm->ifa_scope = RT_SCOPE_UNIVERSE; + if (ipv6_addr_scope(&ifaca->aca_addr)&IFA_SITE) + ifm->ifa_scope = RT_SCOPE_SITE; + ifm->ifa_index = ifaca->aca_idev->dev->ifindex; + RTA_PUT(skb, IFA_ANYCAST, 16, &ifaca->aca_addr); + ci.cstamp = (__u32)(TIME_DELTA(ifaca->aca_cstamp, INITIAL_JIFFIES) / HZ + * 100 + TIME_DELTA(ifaca->aca_cstamp, INITIAL_JIFFIES) % HZ + * 100 / HZ); + ci.tstamp = (__u32)(TIME_DELTA(ifaca->aca_tstamp, INITIAL_JIFFIES) / HZ + * 100 + TIME_DELTA(ifaca->aca_tstamp, INITIAL_JIFFIES) % HZ + * 100 / HZ); + ci.ifa_prefered = INFINITY_LIFE_TIME; + ci.ifa_valid = INFINITY_LIFE_TIME; + RTA_PUT(skb, IFA_CACHEINFO, sizeof(ci), &ci); + nlh->nlmsg_len = skb->tail - b; + return skb->len; - return nlmsg_end(skb, nlh); +nlmsg_failure: +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; } enum addr_type_t @@ -3278,74 +3121,23 @@ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb) return inet6_dump_addr(skb, cb, type); } -static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, - void *arg) -{ - struct ifaddrmsg *ifm; - struct nlattr *tb[IFA_MAX+1]; - struct in6_addr *addr = NULL; - struct net_device *dev = NULL; - struct inet6_ifaddr *ifa; - struct sk_buff *skb; - int err; - - err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); - if (err < 0) - goto errout; - - addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]); - if (addr == NULL) { - err = -EINVAL; - goto errout; - } - - ifm = nlmsg_data(nlh); - if (ifm->ifa_index) - dev = __dev_get_by_index(ifm->ifa_index); - - if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) { - err = -EADDRNOTAVAIL; - goto errout; - } - - if ((skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL)) == NULL) { - err = -ENOBUFS; - goto errout_ifa; - } - - err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid, - nlh->nlmsg_seq, RTM_NEWADDR, 0); - if (err < 0) { - kfree_skb(skb); - goto errout_ifa; - } - - err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid); -errout_ifa: - in6_ifa_put(ifa); -errout: - return err; -} - static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) { struct sk_buff *skb; - int err = -ENOBUFS; + int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE); - skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_ATOMIC); - if (skb == NULL) - goto errout; - - err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0); - if (err < 0) { + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) { + netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFADDR, ENOBUFS); + return; + } + if (inet6_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) { kfree_skb(skb); - goto errout; + netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFADDR, EINVAL); + return; } - - err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); -errout: - if (err < 0) - rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err); + NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_IFADDR; + netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFADDR, GFP_ATOMIC); } static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, @@ -3380,7 +3172,6 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen; #endif #endif - array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; } /* Maximum length of ifinfomsg attributes */ @@ -3487,23 +3278,20 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) void inet6_ifinfo_notify(int event, struct inet6_dev *idev) { struct sk_buff *skb; - int payload = sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE; - int err = -ENOBUFS; + int size = NLMSG_SPACE(sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE); - skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC); - if (skb == NULL) - goto errout; - - err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0); - if (err < 0) { + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) { + netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFINFO, ENOBUFS); + return; + } + if (inet6_fill_ifinfo(skb, idev, current->pid, 0, event, 0) < 0) { kfree_skb(skb); - goto errout; + netlink_set_err(rtnl, 0, RTNLGRP_IPV6_IFINFO, EINVAL); + return; } - - err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); -errout: - if (err < 0) - rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err); + NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_IFINFO; + netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFINFO, GFP_ATOMIC); } /* Maximum length of prefix_cacheinfo attributes */ @@ -3555,40 +3343,33 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, struct prefix_info *pinfo) { struct sk_buff *skb; - int payload = sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE; - int err = -ENOBUFS; - - skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC); - if (skb == NULL) - goto errout; + int size = NLMSG_SPACE(sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE); - err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0); - if (err < 0) { + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) { + netlink_set_err(rtnl, 0, RTNLGRP_IPV6_PREFIX, ENOBUFS); + return; + } + if (inet6_fill_prefix(skb, idev, pinfo, current->pid, 0, event, 0) < 0) { kfree_skb(skb); - goto errout; + netlink_set_err(rtnl, 0, RTNLGRP_IPV6_PREFIX, EINVAL); + return; } - - err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); -errout: - if (err < 0) - rtnl_set_sk_err(RTNLGRP_IPV6_PREFIX, err); + NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_PREFIX; + netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_PREFIX, GFP_ATOMIC); } static struct rtnetlink_link inet6_rtnetlink_table[RTM_NR_MSGTYPES] = { [RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, }, [RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, }, [RTM_DELADDR - RTM_BASE] = { .doit = inet6_rtm_deladdr, }, - [RTM_GETADDR - RTM_BASE] = { .doit = inet6_rtm_getaddr, - .dumpit = inet6_dump_ifaddr, }, + [RTM_GETADDR - RTM_BASE] = { .dumpit = inet6_dump_ifaddr, }, [RTM_GETMULTICAST - RTM_BASE] = { .dumpit = inet6_dump_ifmcaddr, }, [RTM_GETANYCAST - RTM_BASE] = { .dumpit = inet6_dump_ifacaddr, }, [RTM_NEWROUTE - RTM_BASE] = { .doit = inet6_rtm_newroute, }, [RTM_DELROUTE - RTM_BASE] = { .doit = inet6_rtm_delroute, }, [RTM_GETROUTE - RTM_BASE] = { .doit = inet6_rtm_getroute, .dumpit = inet6_dump_fib, }, -#ifdef CONFIG_IPV6_MULTIPLE_TABLES - [RTM_GETRULE - RTM_BASE] = { .dumpit = fib6_rules_dump, }, -#endif }; static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) @@ -3597,7 +3378,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) switch (event) { case RTM_NEWADDR: - ip6_ins_rt(ifp->rt); + ip6_ins_rt(ifp->rt, NULL, NULL, NULL); if (ifp->idev->cnf.forwarding) addrconf_join_anycast(ifp); break; @@ -3606,7 +3387,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) addrconf_leave_anycast(ifp); addrconf_leave_solict(ifp->idev, &ifp->addr); dst_hold(&ifp->rt->u.dst); - if (ip6_del_rt(ifp->rt)) + if (ip6_del_rt(ifp->rt, NULL, NULL, NULL)) dst_free(&ifp->rt->u.dst); break; } @@ -3614,10 +3395,10 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) { - rcu_read_lock_bh(); + read_lock_bh(&addrconf_lock); if (likely(ifp->idev->dead == 0)) __ipv6_ifa_notify(event, ifp); - rcu_read_unlock_bh(); + read_unlock_bh(&addrconf_lock); } #ifdef CONFIG_SYSCTL @@ -3714,7 +3495,7 @@ static struct addrconf_sysctl_table ctl_table addrconf_conf_dir[2]; ctl_table addrconf_proto_dir[2]; ctl_table addrconf_root_dir[2]; -} addrconf_sysctl __read_mostly = { +} addrconf_sysctl = { .sysctl_header = NULL, .addrconf_vars = { { @@ -3903,14 +3684,6 @@ static struct addrconf_sysctl_table }, #endif #endif - { - .ctl_name = NET_IPV6_PROXY_NDP, - .procname = "proxy_ndp", - .data = &ipv6_devconf.proxy_ndp, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, { .ctl_name = 0, /* sentinel */ } diff --git a/trunk/net/ipv6/af_inet6.c b/trunk/net/ipv6/af_inet6.c index bf6e8aff19d4..5a0ba58b86cc 100644 --- a/trunk/net/ipv6/af_inet6.c +++ b/trunk/net/ipv6/af_inet6.c @@ -59,9 +59,6 @@ #ifdef CONFIG_IPV6_TUNNEL #include #endif -#ifdef CONFIG_IPV6_MIP6 -#include -#endif #include #include @@ -70,7 +67,7 @@ MODULE_AUTHOR("Cast of dozens"); MODULE_DESCRIPTION("IPv6 protocol stack for Linux"); MODULE_LICENSE("GPL"); -int sysctl_ipv6_bindv6only __read_mostly; +int sysctl_ipv6_bindv6only; /* The inetsw table contains everything that inet_create needs to * build a new socket. @@ -640,7 +637,6 @@ int inet6_sk_rebuild_header(struct sock *sk) fl.oif = sk->sk_bound_dev_if; fl.fl_ip_dport = inet->dport; fl.fl_ip_sport = inet->sport; - security_sk_classify_flow(sk, &fl); if (np->opt && np->opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; @@ -662,7 +658,7 @@ int inet6_sk_rebuild_header(struct sock *sk) return err; } - __ip6_dst_store(sk, dst, NULL, NULL); + ip6_dst_store(sk, dst, NULL); } return 0; @@ -761,8 +757,6 @@ static int __init inet6_init(void) struct list_head *r; int err; - BUILD_BUG_ON(sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)); - #ifdef MODULE #if 0 /* FIXME --RR */ if (!mod_member_present(&__this_module, can_unload)) @@ -772,6 +766,11 @@ static int __init inet6_init(void) #endif #endif + if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb)) { + printk(KERN_CRIT "inet6_proto_init: size fault\n"); + return -EINVAL; + } + err = proto_register(&tcpv6_prot, 1); if (err) goto out; @@ -857,9 +856,6 @@ static int __init inet6_init(void) ipv6_frag_init(); ipv6_nodata_init(); ipv6_destopt_init(); -#ifdef CONFIG_IPV6_MIP6 - mip6_init(); -#endif /* Init v6 transport protocols. */ udpv6_init(); @@ -922,9 +918,6 @@ static void __exit inet6_exit(void) udp6_proc_exit(); tcp6_proc_exit(); raw6_proc_exit(); -#endif -#ifdef CONFIG_IPV6_MIP6 - mip6_fini(); #endif /* Cleanup code parts. */ sit_cleanup(); diff --git a/trunk/net/ipv6/ah6.c b/trunk/net/ipv6/ah6.c index b0d83e8e4252..9d4831bd4335 100644 --- a/trunk/net/ipv6/ah6.c +++ b/trunk/net/ipv6/ah6.c @@ -74,66 +74,6 @@ static int zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr) return 0; } -#ifdef CONFIG_IPV6_MIP6 -/** - * ipv6_rearrange_destopt - rearrange IPv6 destination options header - * @iph: IPv6 header - * @destopt: destionation options header - */ -static void ipv6_rearrange_destopt(struct ipv6hdr *iph, struct ipv6_opt_hdr *destopt) -{ - u8 *opt = (u8 *)destopt; - int len = ipv6_optlen(destopt); - int off = 0; - int optlen = 0; - - off += 2; - len -= 2; - - while (len > 0) { - - switch (opt[off]) { - - case IPV6_TLV_PAD0: - optlen = 1; - break; - default: - if (len < 2) - goto bad; - optlen = opt[off+1]+2; - if (len < optlen) - goto bad; - - /* Rearrange the source address in @iph and the - * addresses in home address option for final source. - * See 11.3.2 of RFC 3775 for details. - */ - if (opt[off] == IPV6_TLV_HAO) { - struct in6_addr final_addr; - struct ipv6_destopt_hao *hao; - - hao = (struct ipv6_destopt_hao *)&opt[off]; - if (hao->length != sizeof(hao->addr)) { - if (net_ratelimit()) - printk(KERN_WARNING "destopt hao: invalid header length: %u\n", hao->length); - goto bad; - } - ipv6_addr_copy(&final_addr, &hao->addr); - ipv6_addr_copy(&hao->addr, &iph->saddr); - ipv6_addr_copy(&iph->saddr, &final_addr); - } - break; - } - - off += optlen; - len -= optlen; - } - /* Note: ok if len == 0 */ -bad: - return; -} -#endif - /** * ipv6_rearrange_rthdr - rearrange IPv6 routing header * @iph: IPv6 header @@ -173,7 +113,7 @@ static void ipv6_rearrange_rthdr(struct ipv6hdr *iph, struct ipv6_rt_hdr *rthdr) ipv6_addr_copy(&iph->daddr, &final_addr); } -static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir) +static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len) { union { struct ipv6hdr *iph; @@ -188,12 +128,8 @@ static int ipv6_clear_mutable_options(struct ipv6hdr *iph, int len, int dir) while (exthdr.raw < end) { switch (nexthdr) { - case NEXTHDR_DEST: -#ifdef CONFIG_IPV6_MIP6 - if (dir == XFRM_POLICY_OUT) - ipv6_rearrange_destopt(iph, exthdr.opth); -#endif case NEXTHDR_HOP: + case NEXTHDR_DEST: if (!zero_out_mutable_opts(exthdr.opth)) { LIMIT_NETDEBUG( KERN_WARNING "overrun %sopts\n", @@ -228,9 +164,6 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) u8 nexthdr; char tmp_base[8]; struct { -#ifdef CONFIG_IPV6_MIP6 - struct in6_addr saddr; -#endif struct in6_addr daddr; char hdrs[0]; } *tmp_ext; @@ -255,15 +188,10 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) err = -ENOMEM; goto error; } -#ifdef CONFIG_IPV6_MIP6 - memcpy(tmp_ext, &top_iph->saddr, extlen); -#else memcpy(tmp_ext, &top_iph->daddr, extlen); -#endif err = ipv6_clear_mutable_options(top_iph, extlen - sizeof(*tmp_ext) + - sizeof(*top_iph), - XFRM_POLICY_OUT); + sizeof(*top_iph)); if (err) goto error_free_iph; } @@ -285,20 +213,13 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) ah->spi = x->id.spi; ah->seq_no = htonl(++x->replay.oseq); xfrm_aevent_doreplay(x); - err = ah_mac_digest(ahp, skb, ah->auth_data); - if (err) - goto error_free_iph; - memcpy(ah->auth_data, ahp->work_icv, ahp->icv_trunc_len); + ahp->icv(ahp, skb, ah->auth_data); err = 0; memcpy(top_iph, tmp_base, sizeof(tmp_base)); if (tmp_ext) { -#ifdef CONFIG_IPV6_MIP6 - memcpy(&top_iph->saddr, tmp_ext, extlen); -#else memcpy(&top_iph->daddr, tmp_ext, extlen); -#endif error_free_iph: kfree(tmp_ext); } @@ -330,7 +251,6 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) u16 hdr_len; u16 ah_hlen; int nexthdr; - int err = -EINVAL; if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr))) goto out; @@ -358,7 +278,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) if (!tmp_hdr) goto out; memcpy(tmp_hdr, skb->nh.raw, hdr_len); - if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len, XFRM_POLICY_IN)) + if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len)) goto free_out; skb->nh.ipv6h->priority = 0; skb->nh.ipv6h->flow_lbl[0] = 0; @@ -372,11 +292,8 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); memset(ah->auth_data, 0, ahp->icv_trunc_len); skb_push(skb, hdr_len); - err = ah_mac_digest(ahp, skb, ah->auth_data); - if (err) - goto free_out; - err = -EINVAL; - if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) { + ahp->icv(ahp, skb, ah->auth_data); + if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n"); x->stats.integrity_failed++; goto free_out; @@ -393,7 +310,7 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) free_out: kfree(tmp_hdr); out: - return err; + return -EINVAL; } static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, @@ -421,7 +338,6 @@ static int ah6_init_state(struct xfrm_state *x) { struct ah_data *ahp = NULL; struct xfrm_algo_desc *aalg_desc; - struct crypto_hash *tfm; if (!x->aalg) goto error; @@ -439,27 +355,24 @@ static int ah6_init_state(struct xfrm_state *x) ahp->key = x->aalg->alg_key; ahp->key_len = (x->aalg->alg_key_len+7)/8; - tfm = crypto_alloc_hash(x->aalg->alg_name, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) - goto error; - - ahp->tfm = tfm; - if (crypto_hash_setkey(tfm, ahp->key, ahp->key_len)) + ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); + if (!ahp->tfm) goto error; + ahp->icv = ah_hmac_digest; /* * Lookup the algorithm description maintained by xfrm_algo, * verify crypto transform properties, and store information * we need for AH processing. This lookup cannot fail here - * after a successful crypto_alloc_hash(). + * after a successful crypto_alloc_tfm(). */ aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); BUG_ON(!aalg_desc); if (aalg_desc->uinfo.auth.icv_fullbits/8 != - crypto_hash_digestsize(tfm)) { + crypto_tfm_alg_digestsize(ahp->tfm)) { printk(KERN_INFO "AH: %s digestsize %u != %hu\n", - x->aalg->alg_name, crypto_hash_digestsize(tfm), + x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm), aalg_desc->uinfo.auth.icv_fullbits/8); goto error; } @@ -474,7 +387,7 @@ static int ah6_init_state(struct xfrm_state *x) goto error; x->props.header_len = XFRM_ALIGN8(sizeof(struct ipv6_auth_hdr) + ahp->icv_trunc_len); - if (x->props.mode == XFRM_MODE_TUNNEL) + if (x->props.mode) x->props.header_len += sizeof(struct ipv6hdr); x->data = ahp; @@ -483,7 +396,7 @@ static int ah6_init_state(struct xfrm_state *x) error: if (ahp) { kfree(ahp->work_icv); - crypto_free_hash(ahp->tfm); + crypto_free_tfm(ahp->tfm); kfree(ahp); } return -EINVAL; @@ -498,7 +411,7 @@ static void ah6_destroy(struct xfrm_state *x) kfree(ahp->work_icv); ahp->work_icv = NULL; - crypto_free_hash(ahp->tfm); + crypto_free_tfm(ahp->tfm); ahp->tfm = NULL; kfree(ahp); } @@ -511,8 +424,7 @@ static struct xfrm_type ah6_type = .init_state = ah6_init_state, .destructor = ah6_destroy, .input = ah6_input, - .output = ah6_output, - .hdr_offset = xfrm6_find_1stfragopt, + .output = ah6_output }; static struct inet6_protocol ah6_protocol = { diff --git a/trunk/net/ipv6/anycast.c b/trunk/net/ipv6/anycast.c index a9604764e015..f6881d7a0385 100644 --- a/trunk/net/ipv6/anycast.c +++ b/trunk/net/ipv6/anycast.c @@ -56,7 +56,7 @@ ip6_onlink(struct in6_addr *addr, struct net_device *dev) int onlink; onlink = 0; - rcu_read_lock(); + read_lock(&addrconf_lock); idev = __in6_dev_get(dev); if (idev) { read_lock_bh(&idev->lock); @@ -68,7 +68,7 @@ ip6_onlink(struct in6_addr *addr, struct net_device *dev) } read_unlock_bh(&idev->lock); } - rcu_read_unlock(); + read_unlock(&addrconf_lock); return onlink; } @@ -335,7 +335,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr) write_unlock_bh(&idev->lock); dst_hold(&rt->u.dst); - if (ip6_ins_rt(rt)) + if (ip6_ins_rt(rt, NULL, NULL, NULL)) dst_release(&rt->u.dst); addrconf_join_solict(dev, &aca->aca_addr); @@ -378,7 +378,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr) addrconf_leave_solict(idev, &aca->aca_addr); dst_hold(&aca->aca_rt->u.dst); - if (ip6_del_rt(aca->aca_rt)) + if (ip6_del_rt(aca->aca_rt, NULL, NULL, NULL)) dst_free(&aca->aca_rt->u.dst); else dst_release(&aca->aca_rt->u.dst); diff --git a/trunk/net/ipv6/datagram.c b/trunk/net/ipv6/datagram.c index 7206747022fc..99a6eb23378b 100644 --- a/trunk/net/ipv6/datagram.c +++ b/trunk/net/ipv6/datagram.c @@ -156,8 +156,6 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (!fl.oif && (addr_type&IPV6_ADDR_MULTICAST)) fl.oif = np->mcast_oif; - security_sk_classify_flow(sk, &fl); - if (flowlabel) { if (flowlabel->opt && flowlabel->opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *) flowlabel->opt->srcrt; @@ -193,12 +191,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ip6_dst_store(sk, dst, ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ? - &np->daddr : NULL, -#ifdef CONFIG_IPV6_SUBTREES - ipv6_addr_equal(&fl.fl6_src, &np->saddr) ? - &np->saddr : -#endif - NULL); + &np->daddr : NULL); sk->sk_state = TCP_ESTABLISHED; out: @@ -648,13 +641,10 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, rthdr = (struct ipv6_rt_hdr *)CMSG_DATA(cmsg); - switch (rthdr->type) { - case IPV6_SRCRT_TYPE_0: -#ifdef CONFIG_IPV6_MIP6 - case IPV6_SRCRT_TYPE_2: -#endif - break; - default: + /* + * TYPE 0 + */ + if (rthdr->type) { err = -EINVAL; goto exit_f; } @@ -706,7 +696,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, } tc = *(int *)CMSG_DATA(cmsg); - if (tc < -1 || tc > 0xff) + if (tc < 0 || tc > 0xff) goto exit_f; err = 0; diff --git a/trunk/net/ipv6/esp6.c b/trunk/net/ipv6/esp6.c index e78680a9985b..a278d5e862fe 100644 --- a/trunk/net/ipv6/esp6.c +++ b/trunk/net/ipv6/esp6.c @@ -24,7 +24,6 @@ * This file is derived from net/ipv4/esp.c */ -#include #include #include #include @@ -45,8 +44,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) int hdr_len; struct ipv6hdr *top_iph; struct ipv6_esp_hdr *esph; - struct crypto_blkcipher *tfm; - struct blkcipher_desc desc; + struct crypto_tfm *tfm; struct esp_data *esp; struct sk_buff *trailer; int blksize; @@ -69,9 +67,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) alen = esp->auth.icv_trunc_len; tfm = esp->conf.tfm; - desc.tfm = tfm; - desc.flags = 0; - blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); + blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4); clen = ALIGN(clen + 2, blksize); if (esp->conf.padlen) clen = ALIGN(clen, esp->conf.padlen); @@ -99,13 +95,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) esph->seq_no = htonl(++x->replay.oseq); xfrm_aevent_doreplay(x); - if (esp->conf.ivlen) { - if (unlikely(!esp->conf.ivinitted)) { - get_random_bytes(esp->conf.ivec, esp->conf.ivlen); - esp->conf.ivinitted = 1; - } - crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen); - } + if (esp->conf.ivlen) + crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); do { struct scatterlist *sg = &esp->sgbuf[0]; @@ -116,25 +107,24 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) goto error; } skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); - err = crypto_blkcipher_encrypt(&desc, sg, sg, clen); + crypto_cipher_encrypt(tfm, sg, sg, clen); if (unlikely(sg != &esp->sgbuf[0])) kfree(sg); } while (0); - if (unlikely(err)) - goto error; - if (esp->conf.ivlen) { - memcpy(esph->enc_data, esp->conf.ivec, esp->conf.ivlen); - crypto_blkcipher_get_iv(tfm, esp->conf.ivec, esp->conf.ivlen); + memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); + crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); } if (esp->auth.icv_full_len) { - err = esp_mac_digest(esp, skb, (u8 *)esph - skb->data, - sizeof(*esph) + esp->conf.ivlen + clen); - memcpy(pskb_put(skb, trailer, alen), esp->auth.work_icv, alen); + esp->auth.icv(esp, skb, (u8*)esph-skb->data, + sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen+clen, trailer->tail); + pskb_put(skb, trailer, alen); } + err = 0; + error: return err; } @@ -144,10 +134,8 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) struct ipv6hdr *iph; struct ipv6_esp_hdr *esph; struct esp_data *esp = x->data; - struct crypto_blkcipher *tfm = esp->conf.tfm; - struct blkcipher_desc desc = { .tfm = tfm }; struct sk_buff *trailer; - int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); + int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); int alen = esp->auth.icv_trunc_len; int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen; @@ -167,16 +155,15 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) /* If integrity check is required, do this. */ if (esp->auth.icv_full_len) { - u8 sum[alen]; + u8 sum[esp->auth.icv_full_len]; + u8 sum1[alen]; - ret = esp_mac_digest(esp, skb, 0, skb->len - alen); - if (ret) - goto out; + esp->auth.icv(esp, skb, 0, skb->len-alen, sum); - if (skb_copy_bits(skb, skb->len - alen, sum, alen)) + if (skb_copy_bits(skb, skb->len-alen, sum1, alen)) BUG(); - if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { + if (unlikely(memcmp(sum, sum1, alen))) { x->stats.integrity_failed++; ret = -EINVAL; goto out; @@ -195,7 +182,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) /* Get ivec. This can be wrong, check against another impls. */ if (esp->conf.ivlen) - crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen); + crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm)); { u8 nexthdr[2]; @@ -210,11 +197,9 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) } } skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen); - ret = crypto_blkcipher_decrypt(&desc, sg, sg, elen); + crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); if (unlikely(sg != &esp->sgbuf[0])) kfree(sg); - if (unlikely(ret)) - goto out; if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) BUG(); @@ -240,9 +225,9 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) { struct esp_data *esp = x->data; - u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); + u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); - if (x->props.mode == XFRM_MODE_TUNNEL) { + if (x->props.mode) { mtu = ALIGN(mtu + 2, blksize); } else { /* The worst case. */ @@ -281,11 +266,11 @@ static void esp6_destroy(struct xfrm_state *x) if (!esp) return; - crypto_free_blkcipher(esp->conf.tfm); + crypto_free_tfm(esp->conf.tfm); esp->conf.tfm = NULL; kfree(esp->conf.ivec); esp->conf.ivec = NULL; - crypto_free_hash(esp->auth.tfm); + crypto_free_tfm(esp->auth.tfm); esp->auth.tfm = NULL; kfree(esp->auth.work_icv); esp->auth.work_icv = NULL; @@ -295,7 +280,6 @@ static void esp6_destroy(struct xfrm_state *x) static int esp6_init_state(struct xfrm_state *x) { struct esp_data *esp = NULL; - struct crypto_blkcipher *tfm; /* null auth and encryption can have zero length keys */ if (x->aalg) { @@ -314,29 +298,24 @@ static int esp6_init_state(struct xfrm_state *x) if (x->aalg) { struct xfrm_algo_desc *aalg_desc; - struct crypto_hash *hash; esp->auth.key = x->aalg->alg_key; esp->auth.key_len = (x->aalg->alg_key_len+7)/8; - hash = crypto_alloc_hash(x->aalg->alg_name, 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(hash)) - goto error; - - esp->auth.tfm = hash; - if (crypto_hash_setkey(hash, esp->auth.key, esp->auth.key_len)) + esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); + if (esp->auth.tfm == NULL) goto error; + esp->auth.icv = esp_hmac_digest; aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0); BUG_ON(!aalg_desc); if (aalg_desc->uinfo.auth.icv_fullbits/8 != - crypto_hash_digestsize(hash)) { - NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n", - x->aalg->alg_name, - crypto_hash_digestsize(hash), - aalg_desc->uinfo.auth.icv_fullbits/8); - goto error; + crypto_tfm_alg_digestsize(esp->auth.tfm)) { + printk(KERN_INFO "ESP: %s digestsize %u != %hu\n", + x->aalg->alg_name, + crypto_tfm_alg_digestsize(esp->auth.tfm), + aalg_desc->uinfo.auth.icv_fullbits/8); + goto error; } esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; @@ -348,22 +327,24 @@ static int esp6_init_state(struct xfrm_state *x) } esp->conf.key = x->ealg->alg_key; esp->conf.key_len = (x->ealg->alg_key_len+7)/8; - tfm = crypto_alloc_blkcipher(x->ealg->alg_name, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(tfm)) + if (x->props.ealgo == SADB_EALG_NULL) + esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB); + else + esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC); + if (esp->conf.tfm == NULL) goto error; - esp->conf.tfm = tfm; - esp->conf.ivlen = crypto_blkcipher_ivsize(tfm); + esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm); esp->conf.padlen = 0; if (esp->conf.ivlen) { esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); if (unlikely(esp->conf.ivec == NULL)) goto error; - esp->conf.ivinitted = 0; + get_random_bytes(esp->conf.ivec, esp->conf.ivlen); } - if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len)) + if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len)) goto error; x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; - if (x->props.mode == XFRM_MODE_TUNNEL) + if (x->props.mode) x->props.header_len += sizeof(struct ipv6hdr); x->data = esp; return 0; @@ -384,8 +365,7 @@ static struct xfrm_type esp6_type = .destructor = esp6_destroy, .get_max_size = esp6_get_max_size, .input = esp6_input, - .output = esp6_output, - .hdr_offset = xfrm6_find_1stfragopt, + .output = esp6_output }; static struct inet6_protocol esp6_protocol = { diff --git a/trunk/net/ipv6/exthdrs.c b/trunk/net/ipv6/exthdrs.c index 88c96b10684c..9d0ee7f0eeb5 100644 --- a/trunk/net/ipv6/exthdrs.c +++ b/trunk/net/ipv6/exthdrs.c @@ -43,54 +43,9 @@ #include #include #include -#ifdef CONFIG_IPV6_MIP6 -#include -#endif #include -int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) -{ - int packet_len = skb->tail - skb->nh.raw; - struct ipv6_opt_hdr *hdr; - int len; - - if (offset + 2 > packet_len) - goto bad; - hdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); - len = ((hdr->hdrlen + 1) << 3); - - if (offset + len > packet_len) - goto bad; - - offset += 2; - len -= 2; - - while (len > 0) { - int opttype = skb->nh.raw[offset]; - int optlen; - - if (opttype == type) - return offset; - - switch (opttype) { - case IPV6_TLV_PAD0: - optlen = 1; - break; - default: - optlen = skb->nh.raw[offset + 1] + 2; - if (optlen > len) - goto bad; - break; - } - offset += optlen; - len -= optlen; - } - /* not_found */ - bad: - return -1; -} - /* * Parsing tlv encoded headers. * @@ -101,7 +56,7 @@ int ipv6_find_tlv(struct sk_buff *skb, int offset, int type) struct tlvtype_proc { int type; - int (*func)(struct sk_buff **skbp, int offset); + int (*func)(struct sk_buff *skb, int offset); }; /********************* @@ -110,10 +65,8 @@ struct tlvtype_proc { /* An unknown option is detected, decide what to do */ -static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff) +static int ip6_tlvopt_unknown(struct sk_buff *skb, int optoff) { - struct sk_buff *skb = *skbp; - switch ((skb->nh.raw[optoff] & 0xC0) >> 6) { case 0: /* ignore */ return 1; @@ -138,9 +91,8 @@ static int ip6_tlvopt_unknown(struct sk_buff **skbp, int optoff) /* Parse tlv encoded option header (hop-by-hop or destination) */ -static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) +static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb) { - struct sk_buff *skb = *skbp; struct tlvtype_proc *curr; int off = skb->h.raw - skb->nh.raw; int len = ((skb->h.raw[1]+1)<<3); @@ -170,13 +122,13 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) /* type specific length/alignment checks will be performed in the func(). */ - if (curr->func(skbp, off) == 0) + if (curr->func(skb, off) == 0) return 0; break; } } if (curr->type < 0) { - if (ip6_tlvopt_unknown(skbp, off) == 0) + if (ip6_tlvopt_unknown(skb, off) == 0) return 0; } break; @@ -195,85 +147,8 @@ static int ip6_parse_tlv(struct tlvtype_proc *procs, struct sk_buff **skbp) Destination options header. *****************************/ -#ifdef CONFIG_IPV6_MIP6 -static int ipv6_dest_hao(struct sk_buff **skbp, int optoff) -{ - struct sk_buff *skb = *skbp; - struct ipv6_destopt_hao *hao; - struct inet6_skb_parm *opt = IP6CB(skb); - struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb->nh.raw; - struct in6_addr tmp_addr; - int ret; - - if (opt->dsthao) { - LIMIT_NETDEBUG(KERN_DEBUG "hao duplicated\n"); - goto discard; - } - opt->dsthao = opt->dst1; - opt->dst1 = 0; - - hao = (struct ipv6_destopt_hao *)(skb->nh.raw + optoff); - - if (hao->length != 16) { - LIMIT_NETDEBUG( - KERN_DEBUG "hao invalid option length = %d\n", hao->length); - goto discard; - } - - if (!(ipv6_addr_type(&hao->addr) & IPV6_ADDR_UNICAST)) { - LIMIT_NETDEBUG( - KERN_DEBUG "hao is not an unicast addr: " NIP6_FMT "\n", NIP6(hao->addr)); - goto discard; - } - - ret = xfrm6_input_addr(skb, (xfrm_address_t *)&ipv6h->daddr, - (xfrm_address_t *)&hao->addr, IPPROTO_DSTOPTS); - if (unlikely(ret < 0)) - goto discard; - - if (skb_cloned(skb)) { - struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); - struct inet6_skb_parm *opt2; - - if (skb2 == NULL) - goto discard; - - opt2 = IP6CB(skb2); - memcpy(opt2, opt, sizeof(*opt2)); - - kfree_skb(skb); - - /* update all variable using below by copied skbuff */ - *skbp = skb = skb2; - hao = (struct ipv6_destopt_hao *)(skb2->nh.raw + optoff); - ipv6h = (struct ipv6hdr *)skb2->nh.raw; - } - - if (skb->ip_summed == CHECKSUM_COMPLETE) - skb->ip_summed = CHECKSUM_NONE; - - ipv6_addr_copy(&tmp_addr, &ipv6h->saddr); - ipv6_addr_copy(&ipv6h->saddr, &hao->addr); - ipv6_addr_copy(&hao->addr, &tmp_addr); - - if (skb->tstamp.off_sec == 0) - __net_timestamp(skb); - - return 1; - - discard: - kfree_skb(skb); - return 0; -} -#endif - static struct tlvtype_proc tlvprocdestopt_lst[] = { -#ifdef CONFIG_IPV6_MIP6 - { - .type = IPV6_TLV_HAO, - .func = ipv6_dest_hao, - }, -#endif + /* No destination options are defined now */ {-1, NULL} }; @@ -281,9 +156,6 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) { struct sk_buff *skb = *skbp; struct inet6_skb_parm *opt = IP6CB(skb); -#ifdef CONFIG_IPV6_MIP6 - __u16 dstbuf; -#endif if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { @@ -294,19 +166,10 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp) opt->lastopt = skb->h.raw - skb->nh.raw; opt->dst1 = skb->h.raw - skb->nh.raw; -#ifdef CONFIG_IPV6_MIP6 - dstbuf = opt->dst1; -#endif - if (ip6_parse_tlv(tlvprocdestopt_lst, skbp)) { - skb = *skbp; + if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { skb->h.raw += ((skb->h.raw[1]+1)<<3); - opt = IP6CB(skb); -#ifdef CONFIG_IPV6_MIP6 - opt->nhoff = dstbuf; -#else opt->nhoff = opt->dst1; -#endif return 1; } @@ -356,7 +219,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) { struct sk_buff *skb = *skbp; struct inet6_skb_parm *opt = IP6CB(skb); - struct in6_addr *addr = NULL; + struct in6_addr *addr; struct in6_addr daddr; int n, i; @@ -381,23 +244,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) looped_back: if (hdr->segments_left == 0) { - switch (hdr->type) { -#ifdef CONFIG_IPV6_MIP6 - case IPV6_SRCRT_TYPE_2: - /* Silently discard type 2 header unless it was - * processed by own - */ - if (!addr) { - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); - kfree_skb(skb); - return -1; - } - break; -#endif - default: - break; - } - opt->lastopt = skb->h.raw - skb->nh.raw; opt->srcrt = skb->h.raw - skb->nh.raw; skb->h.raw += (hdr->hdrlen + 1) << 3; @@ -407,29 +253,17 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) return 1; } - switch (hdr->type) { - case IPV6_SRCRT_TYPE_0: - if (hdr->hdrlen & 0x01) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); - icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); - return -1; - } - break; -#ifdef CONFIG_IPV6_MIP6 - case IPV6_SRCRT_TYPE_2: - /* Silently discard invalid RTH type 2 */ - if (hdr->hdrlen != 2 || hdr->segments_left != 1) { - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); - kfree_skb(skb); - return -1; - } - break; -#endif - default: + if (hdr->type != IPV6_SRCRT_TYPE_0) { IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); return -1; } + + if (hdr->hdrlen & 0x01) { + IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); + icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); + return -1; + } /* * This is the routing header forwarding algorithm from @@ -460,7 +294,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) hdr = (struct ipv6_rt_hdr *) skb2->h.raw; } - if (skb->ip_summed == CHECKSUM_COMPLETE) + if (skb->ip_summed == CHECKSUM_HW) skb->ip_summed = CHECKSUM_NONE; i = n - --hdr->segments_left; @@ -469,27 +303,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) addr = rthdr->addr; addr += i - 1; - switch (hdr->type) { -#ifdef CONFIG_IPV6_MIP6 - case IPV6_SRCRT_TYPE_2: - if (xfrm6_input_addr(skb, (xfrm_address_t *)addr, - (xfrm_address_t *)&skb->nh.ipv6h->saddr, - IPPROTO_ROUTING) < 0) { - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); - kfree_skb(skb); - return -1; - } - if (!ipv6_chk_home_addr(addr)) { - IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); - kfree_skb(skb); - return -1; - } - break; -#endif - default: - break; - } - if (ipv6_addr_is_multicast(addr)) { IP6_INC_STATS_BH(IPSTATS_MIB_INADDRERRORS); kfree_skb(skb); @@ -608,10 +421,8 @@ EXPORT_SYMBOL_GPL(ipv6_invert_rthdr); /* Router Alert as of RFC 2711 */ -static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) +static int ipv6_hop_ra(struct sk_buff *skb, int optoff) { - struct sk_buff *skb = *skbp; - if (skb->nh.raw[optoff+1] == 2) { IP6CB(skb)->ra = optoff; return 1; @@ -624,9 +435,8 @@ static int ipv6_hop_ra(struct sk_buff **skbp, int optoff) /* Jumbo payload */ -static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) +static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) { - struct sk_buff *skb = *skbp; u32 pkt_len; if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) { @@ -675,9 +485,8 @@ static struct tlvtype_proc tlvprochopopt_lst[] = { { -1, } }; -int ipv6_parse_hopopts(struct sk_buff **skbp) +int ipv6_parse_hopopts(struct sk_buff *skb) { - struct sk_buff *skb = *skbp; struct inet6_skb_parm *opt = IP6CB(skb); /* @@ -693,10 +502,8 @@ int ipv6_parse_hopopts(struct sk_buff **skbp) } opt->hop = sizeof(struct ipv6hdr); - if (ip6_parse_tlv(tlvprochopopt_lst, skbp)) { - skb = *skbp; + if (ip6_parse_tlv(tlvprochopopt_lst, skb)) { skb->h.raw += (skb->h.raw[1]+1)<<3; - opt = IP6CB(skb); opt->nhoff = sizeof(struct ipv6hdr); return 1; } @@ -828,17 +635,14 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, struct ipv6_txoptions *opt2; int err; - if (opt) { - if (newtype != IPV6_HOPOPTS && opt->hopopt) - tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt)); - if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt) - tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt)); - if (newtype != IPV6_RTHDR && opt->srcrt) - tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt)); - if (newtype != IPV6_DSTOPTS && opt->dst1opt) - tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt)); - } - + if (newtype != IPV6_HOPOPTS && opt->hopopt) + tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt)); + if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt) + tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt)); + if (newtype != IPV6_RTHDR && opt->srcrt) + tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt)); + if (newtype != IPV6_DSTOPTS && opt->dst1opt) + tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt)); if (newopt && newoptlen) tot_len += CMSG_ALIGN(newoptlen); @@ -855,25 +659,25 @@ ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, opt2->tot_len = tot_len; p = (char *)(opt2 + 1); - err = ipv6_renew_option(opt ? opt->hopopt : NULL, newopt, newoptlen, + err = ipv6_renew_option(opt->hopopt, newopt, newoptlen, newtype != IPV6_HOPOPTS, &opt2->hopopt, &p); if (err) goto out; - err = ipv6_renew_option(opt ? opt->dst0opt : NULL, newopt, newoptlen, + err = ipv6_renew_option(opt->dst0opt, newopt, newoptlen, newtype != IPV6_RTHDRDSTOPTS, &opt2->dst0opt, &p); if (err) goto out; - err = ipv6_renew_option(opt ? opt->srcrt : NULL, newopt, newoptlen, + err = ipv6_renew_option(opt->srcrt, newopt, newoptlen, newtype != IPV6_RTHDR, - (struct ipv6_opt_hdr **)&opt2->srcrt, &p); + (struct ipv6_opt_hdr **)opt2->srcrt, &p); if (err) goto out; - err = ipv6_renew_option(opt ? opt->dst1opt : NULL, newopt, newoptlen, + err = ipv6_renew_option(opt->dst1opt, newopt, newoptlen, newtype != IPV6_DSTOPTS, &opt2->dst1opt, &p); if (err) diff --git a/trunk/net/ipv6/fib6_rules.c b/trunk/net/ipv6/fib6_rules.c deleted file mode 100644 index 34f5bfaddfc2..000000000000 --- a/trunk/net/ipv6/fib6_rules.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * net/ipv6/fib6_rules.c IPv6 Routing Policy Rules - * - * Copyright (C)2003-2006 Helsinki University of Technology - * Copyright (C)2003-2006 USAGI/WIDE Project - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - * Authors - * Thomas Graf - * Ville Nuorvala - */ - -#include -#include - -#include -#include -#include -#include - -struct fib6_rule -{ - struct fib_rule common; - struct rt6key src; - struct rt6key dst; -#ifdef CONFIG_IPV6_ROUTE_FWMARK - u32 fwmark; - u32 fwmask; -#endif - u8 tclass; -}; - -static struct fib_rules_ops fib6_rules_ops; - -static struct fib6_rule main_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .pref = 0x7FFE, - .action = FR_ACT_TO_TBL, - .table = RT6_TABLE_MAIN, - }, -}; - -static struct fib6_rule local_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .pref = 0, - .action = FR_ACT_TO_TBL, - .table = RT6_TABLE_LOCAL, - .flags = FIB_RULE_PERMANENT, - }, -}; - -static LIST_HEAD(fib6_rules); - -struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags, - pol_lookup_t lookup) -{ - struct fib_lookup_arg arg = { - .lookup_ptr = lookup, - }; - - fib_rules_lookup(&fib6_rules_ops, fl, flags, &arg); - if (arg.rule) - fib_rule_put(arg.rule); - - if (arg.result) - return (struct dst_entry *) arg.result; - - dst_hold(&ip6_null_entry.u.dst); - return &ip6_null_entry.u.dst; -} - -static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, - int flags, struct fib_lookup_arg *arg) -{ - struct rt6_info *rt = NULL; - struct fib6_table *table; - pol_lookup_t lookup = arg->lookup_ptr; - - switch (rule->action) { - case FR_ACT_TO_TBL: - break; - case FR_ACT_UNREACHABLE: - rt = &ip6_null_entry; - goto discard_pkt; - default: - case FR_ACT_BLACKHOLE: - rt = &ip6_blk_hole_entry; - goto discard_pkt; - case FR_ACT_PROHIBIT: - rt = &ip6_prohibit_entry; - goto discard_pkt; - } - - table = fib6_get_table(rule->table); - if (table) - rt = lookup(table, flp, flags); - - if (rt != &ip6_null_entry) - goto out; - dst_release(&rt->u.dst); - rt = NULL; - goto out; - -discard_pkt: - dst_hold(&rt->u.dst); -out: - arg->result = rt; - return rt == NULL ? -EAGAIN : 0; -} - - -static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags) -{ - struct fib6_rule *r = (struct fib6_rule *) rule; - - if (!ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen)) - return 0; - - if ((flags & RT6_LOOKUP_F_HAS_SADDR) && - !ipv6_prefix_equal(&fl->fl6_src, &r->src.addr, r->src.plen)) - return 0; - - if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff)) - return 0; - -#ifdef CONFIG_IPV6_ROUTE_FWMARK - if ((r->fwmark ^ fl->fl6_fwmark) & r->fwmask) - return 0; -#endif - - return 1; -} - -static struct nla_policy fib6_rule_policy[FRA_MAX+1] __read_mostly = { - [FRA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, - [FRA_PRIORITY] = { .type = NLA_U32 }, - [FRA_SRC] = { .len = sizeof(struct in6_addr) }, - [FRA_DST] = { .len = sizeof(struct in6_addr) }, - [FRA_FWMARK] = { .type = NLA_U32 }, - [FRA_FWMASK] = { .type = NLA_U32 }, - [FRA_TABLE] = { .type = NLA_U32 }, -}; - -static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh, - struct nlattr **tb) -{ - int err = -EINVAL; - struct fib6_rule *rule6 = (struct fib6_rule *) rule; - - if (frh->src_len > 128 || frh->dst_len > 128 || - (frh->tos & ~IPV6_FLOWINFO_MASK)) - goto errout; - - if (rule->action == FR_ACT_TO_TBL) { - if (rule->table == RT6_TABLE_UNSPEC) - goto errout; - - if (fib6_new_table(rule->table) == NULL) { - err = -ENOBUFS; - goto errout; - } - } - - if (tb[FRA_SRC]) - nla_memcpy(&rule6->src.addr, tb[FRA_SRC], - sizeof(struct in6_addr)); - - if (tb[FRA_DST]) - nla_memcpy(&rule6->dst.addr, tb[FRA_DST], - sizeof(struct in6_addr)); - -#ifdef CONFIG_IPV6_ROUTE_FWMARK - if (tb[FRA_FWMARK]) { - rule6->fwmark = nla_get_u32(tb[FRA_FWMARK]); - if (rule6->fwmark) { - /* - * if the mark value is non-zero, - * all bits are compared by default - * unless a mask is explicitly specified. - */ - rule6->fwmask = 0xFFFFFFFF; - } - } - - if (tb[FRA_FWMASK]) - rule6->fwmask = nla_get_u32(tb[FRA_FWMASK]); -#endif - - rule6->src.plen = frh->src_len; - rule6->dst.plen = frh->dst_len; - rule6->tclass = frh->tos; - - err = 0; -errout: - return err; -} - -static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh, - struct nlattr **tb) -{ - struct fib6_rule *rule6 = (struct fib6_rule *) rule; - - if (frh->src_len && (rule6->src.plen != frh->src_len)) - return 0; - - if (frh->dst_len && (rule6->dst.plen != frh->dst_len)) - return 0; - - if (frh->tos && (rule6->tclass != frh->tos)) - return 0; - - if (tb[FRA_SRC] && - nla_memcmp(tb[FRA_SRC], &rule6->src.addr, sizeof(struct in6_addr))) - return 0; - - if (tb[FRA_DST] && - nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr))) - return 0; - -#ifdef CONFIG_IPV6_ROUTE_FWMARK - if (tb[FRA_FWMARK] && (rule6->fwmark != nla_get_u32(tb[FRA_FWMARK]))) - return 0; - - if (tb[FRA_FWMASK] && (rule6->fwmask != nla_get_u32(tb[FRA_FWMASK]))) - return 0; -#endif - - return 1; -} - -static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb, - struct nlmsghdr *nlh, struct fib_rule_hdr *frh) -{ - struct fib6_rule *rule6 = (struct fib6_rule *) rule; - - frh->family = AF_INET6; - frh->dst_len = rule6->dst.plen; - frh->src_len = rule6->src.plen; - frh->tos = rule6->tclass; - - if (rule6->dst.plen) - NLA_PUT(skb, FRA_DST, sizeof(struct in6_addr), - &rule6->dst.addr); - - if (rule6->src.plen) - NLA_PUT(skb, FRA_SRC, sizeof(struct in6_addr), - &rule6->src.addr); - -#ifdef CONFIG_IPV6_ROUTE_FWMARK - if (rule6->fwmark) - NLA_PUT_U32(skb, FRA_FWMARK, rule6->fwmark); - - if (rule6->fwmask || rule6->fwmark) - NLA_PUT_U32(skb, FRA_FWMASK, rule6->fwmask); -#endif - - return 0; - -nla_put_failure: - return -ENOBUFS; -} - -int fib6_rules_dump(struct sk_buff *skb, struct netlink_callback *cb) -{ - return fib_rules_dump(skb, cb, AF_INET6); -} - -static u32 fib6_rule_default_pref(void) -{ - return 0x3FFF; -} - -static struct fib_rules_ops fib6_rules_ops = { - .family = AF_INET6, - .rule_size = sizeof(struct fib6_rule), - .action = fib6_rule_action, - .match = fib6_rule_match, - .configure = fib6_rule_configure, - .compare = fib6_rule_compare, - .fill = fib6_rule_fill, - .default_pref = fib6_rule_default_pref, - .nlgroup = RTNLGRP_IPV6_RULE, - .policy = fib6_rule_policy, - .rules_list = &fib6_rules, - .owner = THIS_MODULE, -}; - -void __init fib6_rules_init(void) -{ - list_add_tail(&local_rule.common.list, &fib6_rules); - list_add_tail(&main_rule.common.list, &fib6_rules); - - fib_rules_register(&fib6_rules_ops); -} - -void fib6_rules_cleanup(void) -{ - fib_rules_unregister(&fib6_rules_ops); -} diff --git a/trunk/net/ipv6/icmp.c b/trunk/net/ipv6/icmp.c index 4ec876066b3f..1044b6fce0d5 100644 --- a/trunk/net/ipv6/icmp.c +++ b/trunk/net/ipv6/icmp.c @@ -151,7 +151,7 @@ static int is_ineligible(struct sk_buff *skb) return 0; } -static int sysctl_icmpv6_time __read_mostly = 1*HZ; +static int sysctl_icmpv6_time = 1*HZ; /* * Check the ICMP output rate limit @@ -273,29 +273,6 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st return 0; } -#ifdef CONFIG_IPV6_MIP6 -static void mip6_addr_swap(struct sk_buff *skb) -{ - struct ipv6hdr *iph = skb->nh.ipv6h; - struct inet6_skb_parm *opt = IP6CB(skb); - struct ipv6_destopt_hao *hao; - struct in6_addr tmp; - int off; - - if (opt->dsthao) { - off = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO); - if (likely(off >= 0)) { - hao = (struct ipv6_destopt_hao *)(skb->nh.raw + off); - ipv6_addr_copy(&tmp, &iph->saddr); - ipv6_addr_copy(&iph->saddr, &hao->addr); - ipv6_addr_copy(&hao->addr, &tmp); - } - } -} -#else -static inline void mip6_addr_swap(struct sk_buff *skb) {} -#endif - /* * Send an ICMP message in response to a packet in error */ @@ -373,8 +350,6 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, return; } - mip6_addr_swap(skb); - memset(&fl, 0, sizeof(fl)); fl.proto = IPPROTO_ICMPV6; ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr); @@ -383,7 +358,6 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, fl.oif = iif; fl.fl_icmp_type = type; fl.fl_icmp_code = code; - security_skb_classify_flow(skb, &fl); if (icmpv6_xmit_lock()) return; @@ -427,7 +401,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, if (hlimit < 0) hlimit = ipv6_get_hoplimit(dst->dev); - tclass = np->tclass; + tclass = np->cork.tclass; if (tclass < 0) tclass = 0; @@ -498,7 +472,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb) ipv6_addr_copy(&fl.fl6_src, saddr); fl.oif = skb->dev->ifindex; fl.fl_icmp_type = ICMPV6_ECHO_REPLY; - security_skb_classify_flow(skb, &fl); if (icmpv6_xmit_lock()) return; @@ -524,7 +497,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) if (hlimit < 0) hlimit = ipv6_get_hoplimit(dst->dev); - tclass = np->tclass; + tclass = np->cork.tclass; if (tclass < 0) tclass = 0; @@ -631,7 +604,7 @@ static int icmpv6_rcv(struct sk_buff **pskb) /* Perform checksum. */ switch (skb->ip_summed) { - case CHECKSUM_COMPLETE: + case CHECKSUM_HW: if (!csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, skb->csum)) break; @@ -739,11 +712,6 @@ static int icmpv6_rcv(struct sk_buff **pskb) return 0; } -/* - * Special lock-class for __icmpv6_socket: - */ -static struct lock_class_key icmpv6_socket_sk_dst_lock_key; - int __init icmpv6_init(struct net_proto_family *ops) { struct sock *sk; @@ -762,14 +730,6 @@ int __init icmpv6_init(struct net_proto_family *ops) sk = per_cpu(__icmpv6_socket, i)->sk; sk->sk_allocation = GFP_ATOMIC; - /* - * Split off their lock-class, because sk->sk_dst_lock - * gets used from softirqs, which is safe for - * __icmpv6_socket (because those never get directly used - * via userspace syscalls), but unsafe for normal sockets. - */ - lockdep_set_class(&sk->sk_dst_lock, - &icmpv6_socket_sk_dst_lock_key); /* Enough space for 2 64K ICMP packets, including * sk_buff struct overhead. diff --git a/trunk/net/ipv6/inet6_connection_sock.c b/trunk/net/ipv6/inet6_connection_sock.c index 827f41d1478b..5c950cc79d80 100644 --- a/trunk/net/ipv6/inet6_connection_sock.c +++ b/trunk/net/ipv6/inet6_connection_sock.c @@ -157,7 +157,6 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) fl.oif = sk->sk_bound_dev_if; fl.fl_ip_sport = inet->sport; fl.fl_ip_dport = inet->dport; - security_sk_classify_flow(sk, &fl); if (np->opt && np->opt->srcrt) { struct rt0_hdr *rt0 = (struct rt0_hdr *)np->opt->srcrt; @@ -186,7 +185,7 @@ int inet6_csk_xmit(struct sk_buff *skb, int ipfragok) return err; } - __ip6_dst_store(sk, dst, NULL, NULL); + ip6_dst_store(sk, dst, NULL); } skb->dst = dst_clone(dst); diff --git a/trunk/net/ipv6/ip6_fib.c b/trunk/net/ipv6/ip6_fib.c index 8fcae7a6510b..764221220afd 100644 --- a/trunk/net/ipv6/ip6_fib.c +++ b/trunk/net/ipv6/ip6_fib.c @@ -18,7 +18,6 @@ * Yuji SEKIYA @USAGI: Support default route on router node; * remove ip6_null_entry from the top of * routing table. - * Ville Nuorvala: Fixed routing subtrees. */ #include #include @@ -27,7 +26,6 @@ #include #include #include -#include #ifdef CONFIG_PROC_FS #include @@ -70,19 +68,19 @@ struct fib6_cleaner_t void *arg; }; -static DEFINE_RWLOCK(fib6_walker_lock); +DEFINE_RWLOCK(fib6_walker_lock); + #ifdef CONFIG_IPV6_SUBTREES #define FWS_INIT FWS_S +#define SUBTREE(fn) ((fn)->subtree) #else #define FWS_INIT FWS_L +#define SUBTREE(fn) NULL #endif static void fib6_prune_clones(struct fib6_node *fn, struct rt6_info *rt); -static struct rt6_info * fib6_find_prefix(struct fib6_node *fn); static struct fib6_node * fib6_repair_tree(struct fib6_node *fn); -static int fib6_walk(struct fib6_walker_t *w); -static int fib6_walk_continue(struct fib6_walker_t *w); /* * A routing update causes an increase of the serial number on the @@ -95,31 +93,13 @@ static __u32 rt_sernum; static DEFINE_TIMER(ip6_fib_timer, fib6_run_gc, 0, 0); -static struct fib6_walker_t fib6_walker_list = { +struct fib6_walker_t fib6_walker_list = { .prev = &fib6_walker_list, .next = &fib6_walker_list, }; #define FOR_WALKERS(w) for ((w)=fib6_walker_list.next; (w) != &fib6_walker_list; (w)=(w)->next) -static inline void fib6_walker_link(struct fib6_walker_t *w) -{ - write_lock_bh(&fib6_walker_lock); - w->next = fib6_walker_list.next; - w->prev = &fib6_walker_list; - w->next->prev = w; - w->prev->next = w; - write_unlock_bh(&fib6_walker_lock); -} - -static inline void fib6_walker_unlink(struct fib6_walker_t *w) -{ - write_lock_bh(&fib6_walker_lock); - w->next->prev = w->prev; - w->prev->next = w->next; - w->prev = w->next = w; - write_unlock_bh(&fib6_walker_lock); -} static __inline__ u32 fib6_new_sernum(void) { u32 n = ++rt_sernum; @@ -167,253 +147,6 @@ static __inline__ void rt6_release(struct rt6_info *rt) dst_free(&rt->u.dst); } -static struct fib6_table fib6_main_tbl = { - .tb6_id = RT6_TABLE_MAIN, - .tb6_lock = RW_LOCK_UNLOCKED, - .tb6_root = { - .leaf = &ip6_null_entry, - .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, - }, -}; - -#ifdef CONFIG_IPV6_MULTIPLE_TABLES -#define FIB_TABLE_HASHSZ 256 -#else -#define FIB_TABLE_HASHSZ 1 -#endif -static struct hlist_head fib_table_hash[FIB_TABLE_HASHSZ]; - -static void fib6_link_table(struct fib6_table *tb) -{ - unsigned int h; - - h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1); - - /* - * No protection necessary, this is the only list mutatation - * operation, tables never disappear once they exist. - */ - hlist_add_head_rcu(&tb->tb6_hlist, &fib_table_hash[h]); -} - -#ifdef CONFIG_IPV6_MULTIPLE_TABLES -static struct fib6_table fib6_local_tbl = { - .tb6_id = RT6_TABLE_LOCAL, - .tb6_lock = RW_LOCK_UNLOCKED, - .tb6_root = { - .leaf = &ip6_null_entry, - .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, - }, -}; - -static struct fib6_table *fib6_alloc_table(u32 id) -{ - struct fib6_table *table; - - table = kzalloc(sizeof(*table), GFP_ATOMIC); - if (table != NULL) { - table->tb6_id = id; - table->tb6_lock = RW_LOCK_UNLOCKED; - table->tb6_root.leaf = &ip6_null_entry; - table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; - } - - return table; -} - -struct fib6_table *fib6_new_table(u32 id) -{ - struct fib6_table *tb; - - if (id == 0) - id = RT6_TABLE_MAIN; - tb = fib6_get_table(id); - if (tb) - return tb; - - tb = fib6_alloc_table(id); - if (tb != NULL) - fib6_link_table(tb); - - return tb; -} - -struct fib6_table *fib6_get_table(u32 id) -{ - struct fib6_table *tb; - struct hlist_node *node; - unsigned int h; - - if (id == 0) - id = RT6_TABLE_MAIN; - h = id & (FIB_TABLE_HASHSZ - 1); - rcu_read_lock(); - hlist_for_each_entry_rcu(tb, node, &fib_table_hash[h], tb6_hlist) { - if (tb->tb6_id == id) { - rcu_read_unlock(); - return tb; - } - } - rcu_read_unlock(); - - return NULL; -} - -static void __init fib6_tables_init(void) -{ - fib6_link_table(&fib6_main_tbl); - fib6_link_table(&fib6_local_tbl); -} - -#else - -struct fib6_table *fib6_new_table(u32 id) -{ - return fib6_get_table(id); -} - -struct fib6_table *fib6_get_table(u32 id) -{ - return &fib6_main_tbl; -} - -struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags, - pol_lookup_t lookup) -{ - return (struct dst_entry *) lookup(&fib6_main_tbl, fl, flags); -} - -static void __init fib6_tables_init(void) -{ - fib6_link_table(&fib6_main_tbl); -} - -#endif - -static int fib6_dump_node(struct fib6_walker_t *w) -{ - int res; - struct rt6_info *rt; - - for (rt = w->leaf; rt; rt = rt->u.next) { - res = rt6_dump_route(rt, w->args); - if (res < 0) { - /* Frame is full, suspend walking */ - w->leaf = rt; - return 1; - } - BUG_TRAP(res!=0); - } - w->leaf = NULL; - return 0; -} - -static void fib6_dump_end(struct netlink_callback *cb) -{ - struct fib6_walker_t *w = (void*)cb->args[2]; - - if (w) { - cb->args[2] = 0; - kfree(w); - } - cb->done = (void*)cb->args[3]; - cb->args[1] = 3; -} - -static int fib6_dump_done(struct netlink_callback *cb) -{ - fib6_dump_end(cb); - return cb->done ? cb->done(cb) : 0; -} - -static int fib6_dump_table(struct fib6_table *table, struct sk_buff *skb, - struct netlink_callback *cb) -{ - struct fib6_walker_t *w; - int res; - - w = (void *)cb->args[2]; - w->root = &table->tb6_root; - - if (cb->args[4] == 0) { - read_lock_bh(&table->tb6_lock); - res = fib6_walk(w); - read_unlock_bh(&table->tb6_lock); - if (res > 0) - cb->args[4] = 1; - } else { - read_lock_bh(&table->tb6_lock); - res = fib6_walk_continue(w); - read_unlock_bh(&table->tb6_lock); - if (res != 0) { - if (res < 0) - fib6_walker_unlink(w); - goto end; - } - fib6_walker_unlink(w); - cb->args[4] = 0; - } -end: - return res; -} - -int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) -{ - unsigned int h, s_h; - unsigned int e = 0, s_e; - struct rt6_rtnl_dump_arg arg; - struct fib6_walker_t *w; - struct fib6_table *tb; - struct hlist_node *node; - int res = 0; - - s_h = cb->args[0]; - s_e = cb->args[1]; - - w = (void *)cb->args[2]; - if (w == NULL) { - /* New dump: - * - * 1. hook callback destructor. - */ - cb->args[3] = (long)cb->done; - cb->done = fib6_dump_done; - - /* - * 2. allocate and initialize walker. - */ - w = kzalloc(sizeof(*w), GFP_ATOMIC); - if (w == NULL) - return -ENOMEM; - w->func = fib6_dump_node; - cb->args[2] = (long)w; - } - - arg.skb = skb; - arg.cb = cb; - w->args = &arg; - - for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) { - e = 0; - hlist_for_each_entry(tb, node, &fib_table_hash[h], tb6_hlist) { - if (e < s_e) - goto next; - res = fib6_dump_table(tb, skb, cb); - if (res != 0) - goto out; -next: - e++; - } - } -out: - cb->args[1] = e; - cb->args[0] = h; - - res = res < 0 ? res : skb->len; - if (res <= 0) - fib6_dump_end(cb); - return res; -} /* * Routing Table @@ -610,7 +343,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, */ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, - struct nl_info *info) + struct nlmsghdr *nlh, struct netlink_skb_parms *req) { struct rt6_info *iter = NULL; struct rt6_info **ins; @@ -665,7 +398,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, *ins = rt; rt->rt6i_node = fn; atomic_inc(&rt->rt6i_ref); - inet6_rt_notify(RTM_NEWROUTE, rt, info); + inet6_rt_notify(RTM_NEWROUTE, rt, nlh, req); rt6_stats.fib_rt_entries++; if ((fn->fn_flags & RTN_RTINFO) == 0) { @@ -695,9 +428,10 @@ void fib6_force_start_gc(void) * with source addr info in sub-trees */ -int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) +int fib6_add(struct fib6_node *root, struct rt6_info *rt, + struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) { - struct fib6_node *fn, *pn = NULL; + struct fib6_node *fn; int err = -ENOMEM; fn = fib6_add_1(root, &rt->rt6i_dst.addr, sizeof(struct in6_addr), @@ -706,8 +440,6 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) if (fn == NULL) goto out; - pn = fn; - #ifdef CONFIG_IPV6_SUBTREES if (rt->rt6i_src.plen) { struct fib6_node *sn; @@ -753,6 +485,10 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) /* Now link new subtree to main tree */ sfn->parent = fn; fn->subtree = sfn; + if (fn->leaf == NULL) { + fn->leaf = rt; + atomic_inc(&rt->rt6i_ref); + } } else { sn = fib6_add_1(fn->subtree, &rt->rt6i_src.addr, sizeof(struct in6_addr), rt->rt6i_src.plen, @@ -762,42 +498,21 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) goto st_failure; } - if (fn->leaf == NULL) { - fn->leaf = rt; - atomic_inc(&rt->rt6i_ref); - } fn = sn; } #endif - err = fib6_add_rt2node(fn, rt, info); + err = fib6_add_rt2node(fn, rt, nlh, req); if (err == 0) { fib6_start_gc(rt); if (!(rt->rt6i_flags&RTF_CACHE)) - fib6_prune_clones(pn, rt); + fib6_prune_clones(fn, rt); } out: - if (err) { -#ifdef CONFIG_IPV6_SUBTREES - /* - * If fib6_add_1 has cleared the old leaf pointer in the - * super-tree leaf node we have to find a new one for it. - */ - if (pn != fn && !pn->leaf && !(pn->fn_flags & RTN_RTINFO)) { - pn->leaf = fib6_find_prefix(pn); -#if RT6_DEBUG >= 2 - if (!pn->leaf) { - BUG_TRAP(pn->leaf != NULL); - pn->leaf = &ip6_null_entry; - } -#endif - atomic_inc(&pn->leaf->rt6i_ref); - } -#endif + if (err) dst_free(&rt->u.dst); - } return err; #ifdef CONFIG_IPV6_SUBTREES @@ -828,9 +543,6 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root, struct fib6_node *fn; int dir; - if (unlikely(args->offset == 0)) - return NULL; - /* * Descend on a tree */ @@ -852,26 +564,33 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root, break; } - while(fn) { - if (FIB6_SUBTREE(fn) || fn->fn_flags & RTN_RTINFO) { + while ((fn->fn_flags & RTN_ROOT) == 0) { +#ifdef CONFIG_IPV6_SUBTREES + if (fn->subtree) { + struct fib6_node *st; + struct lookup_args *narg; + + narg = args + 1; + + if (narg->addr) { + st = fib6_lookup_1(fn->subtree, narg); + + if (st && !(st->fn_flags & RTN_ROOT)) + return st; + } + } +#endif + + if (fn->fn_flags & RTN_RTINFO) { struct rt6key *key; key = (struct rt6key *) ((u8 *) fn->leaf + args->offset); - if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) { -#ifdef CONFIG_IPV6_SUBTREES - if (fn->subtree) - fn = fib6_lookup_1(fn->subtree, args + 1); -#endif - if (!fn || fn->fn_flags & RTN_RTINFO) - return fn; - } + if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) + return fn; } - if (fn->fn_flags & RTN_ROOT) - break; - fn = fn->parent; } @@ -881,24 +600,18 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root, struct fib6_node * fib6_lookup(struct fib6_node *root, struct in6_addr *daddr, struct in6_addr *saddr) { + struct lookup_args args[2]; struct fib6_node *fn; - struct lookup_args args[] = { - { - .offset = offsetof(struct rt6_info, rt6i_dst), - .addr = daddr, - }, + + args[0].offset = offsetof(struct rt6_info, rt6i_dst); + args[0].addr = daddr; + #ifdef CONFIG_IPV6_SUBTREES - { - .offset = offsetof(struct rt6_info, rt6i_src), - .addr = saddr, - }, + args[1].offset = offsetof(struct rt6_info, rt6i_src); + args[1].addr = saddr; #endif - { - .offset = 0, /* sentinel */ - } - }; - fn = fib6_lookup_1(root, daddr ? args : args + 1); + fn = fib6_lookup_1(root, args); if (fn == NULL || fn->fn_flags & RTN_TL_ROOT) fn = root; @@ -954,8 +667,10 @@ struct fib6_node * fib6_locate(struct fib6_node *root, #ifdef CONFIG_IPV6_SUBTREES if (src_len) { BUG_TRAP(saddr!=NULL); - if (fn && fn->subtree) - fn = fib6_locate_1(fn->subtree, saddr, src_len, + if (fn == NULL) + fn = fn->subtree; + if (fn) + fn = fib6_locate_1(fn, saddr, src_len, offsetof(struct rt6_info, rt6i_src)); } #endif @@ -984,7 +699,7 @@ static struct rt6_info * fib6_find_prefix(struct fib6_node *fn) if(fn->right) return fn->right->leaf; - fn = FIB6_SUBTREE(fn); + fn = SUBTREE(fn); } return NULL; } @@ -1015,7 +730,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) if (fn->right) child = fn->right, children |= 1; if (fn->left) child = fn->left, children |= 2; - if (children == 3 || FIB6_SUBTREE(fn) + if (children == 3 || SUBTREE(fn) #ifdef CONFIG_IPV6_SUBTREES /* Subtree root (i.e. fn) may have one child */ || (children && fn->fn_flags&RTN_ROOT) @@ -1034,9 +749,9 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) pn = fn->parent; #ifdef CONFIG_IPV6_SUBTREES - if (FIB6_SUBTREE(pn) == fn) { + if (SUBTREE(pn) == fn) { BUG_TRAP(fn->fn_flags&RTN_ROOT); - FIB6_SUBTREE(pn) = NULL; + SUBTREE(pn) = NULL; nstate = FWS_L; } else { BUG_TRAP(!(fn->fn_flags&RTN_ROOT)); @@ -1084,7 +799,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) read_unlock(&fib6_walker_lock); node_free(fn); - if (pn->fn_flags&RTN_RTINFO || FIB6_SUBTREE(pn)) + if (pn->fn_flags&RTN_RTINFO || SUBTREE(pn)) return pn; rt6_release(pn->leaf); @@ -1094,7 +809,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) } static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, - struct nl_info *info) + struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) { struct fib6_walker_t *w; struct rt6_info *rt = *rtp; @@ -1150,11 +865,11 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, if (atomic_read(&rt->rt6i_ref) != 1) BUG(); } - inet6_rt_notify(RTM_DELROUTE, rt, info); + inet6_rt_notify(RTM_DELROUTE, rt, nlh, req); rt6_release(rt); } -int fib6_del(struct rt6_info *rt, struct nl_info *info) +int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) { struct fib6_node *fn = rt->rt6i_node; struct rt6_info **rtp; @@ -1170,18 +885,8 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) BUG_TRAP(fn->fn_flags&RTN_RTINFO); - if (!(rt->rt6i_flags&RTF_CACHE)) { - struct fib6_node *pn = fn; -#ifdef CONFIG_IPV6_SUBTREES - /* clones of this route might be in another subtree */ - if (rt->rt6i_src.plen) { - while (!(pn->fn_flags&RTN_ROOT)) - pn = pn->parent; - pn = pn->parent; - } -#endif - fib6_prune_clones(pn, rt); - } + if (!(rt->rt6i_flags&RTF_CACHE)) + fib6_prune_clones(fn, rt); /* * Walk the leaf entries looking for ourself @@ -1189,7 +894,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) { if (*rtp == rt) { - fib6_del_route(fn, rtp, info); + fib6_del_route(fn, rtp, nlh, _rtattr, req); return 0; } } @@ -1220,7 +925,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) * <0 -> walk is terminated by an error. */ -static int fib6_walk_continue(struct fib6_walker_t *w) +int fib6_walk_continue(struct fib6_walker_t *w) { struct fib6_node *fn, *pn; @@ -1237,8 +942,8 @@ static int fib6_walk_continue(struct fib6_walker_t *w) switch (w->state) { #ifdef CONFIG_IPV6_SUBTREES case FWS_S: - if (FIB6_SUBTREE(fn)) { - w->node = FIB6_SUBTREE(fn); + if (SUBTREE(fn)) { + w->node = SUBTREE(fn); continue; } w->state = FWS_L; @@ -1272,7 +977,7 @@ static int fib6_walk_continue(struct fib6_walker_t *w) pn = fn->parent; w->node = pn; #ifdef CONFIG_IPV6_SUBTREES - if (FIB6_SUBTREE(pn) == fn) { + if (SUBTREE(pn) == fn) { BUG_TRAP(fn->fn_flags&RTN_ROOT); w->state = FWS_L; continue; @@ -1294,7 +999,7 @@ static int fib6_walk_continue(struct fib6_walker_t *w) } } -static int fib6_walk(struct fib6_walker_t *w) +int fib6_walk(struct fib6_walker_t *w) { int res; @@ -1318,7 +1023,7 @@ static int fib6_clean_node(struct fib6_walker_t *w) res = c->func(rt, c->arg); if (res < 0) { w->leaf = rt; - res = fib6_del(rt, NULL); + res = fib6_del(rt, NULL, NULL, NULL); if (res) { #if RT6_DEBUG >= 2 printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res); @@ -1344,9 +1049,9 @@ static int fib6_clean_node(struct fib6_walker_t *w) * ignoring pure split nodes) will be scanned. */ -static void fib6_clean_tree(struct fib6_node *root, - int (*func)(struct rt6_info *, void *arg), - int prune, void *arg) +void fib6_clean_tree(struct fib6_node *root, + int (*func)(struct rt6_info *, void *arg), + int prune, void *arg) { struct fib6_cleaner_t c; @@ -1359,25 +1064,6 @@ static void fib6_clean_tree(struct fib6_node *root, fib6_walk(&c.w); } -void fib6_clean_all(int (*func)(struct rt6_info *, void *arg), - int prune, void *arg) -{ - struct fib6_table *table; - struct hlist_node *node; - unsigned int h; - - rcu_read_lock(); - for (h = 0; h < FIB_TABLE_HASHSZ; h++) { - hlist_for_each_entry_rcu(table, node, &fib_table_hash[h], - tb6_hlist) { - write_lock_bh(&table->tb6_lock); - fib6_clean_tree(&table->tb6_root, func, prune, arg); - write_unlock_bh(&table->tb6_lock); - } - } - rcu_read_unlock(); -} - static int fib6_prune_clone(struct rt6_info *rt, void *arg) { if (rt->rt6i_flags & RTF_CACHE) { @@ -1456,8 +1142,11 @@ void fib6_run_gc(unsigned long dummy) } gc_args.more = 0; + + write_lock_bh(&rt6_lock); ndisc_dst_gc(&gc_args.more); - fib6_clean_all(fib6_age, 0, NULL); + fib6_clean_tree(&ip6_routing_table, fib6_age, 0, NULL); + write_unlock_bh(&rt6_lock); if (gc_args.more) mod_timer(&ip6_fib_timer, jiffies + ip6_rt_gc_interval); @@ -1472,10 +1161,10 @@ void __init fib6_init(void) { fib6_node_kmem = kmem_cache_create("fib6_nodes", sizeof(struct fib6_node), - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - - fib6_tables_init(); + if (!fib6_node_kmem) + panic("cannot create fib6_nodes cache"); } void fib6_gc_cleanup(void) diff --git a/trunk/net/ipv6/ip6_input.c b/trunk/net/ipv6/ip6_input.c index 6b8e6d76a58b..25c2a9e03895 100644 --- a/trunk/net/ipv6/ip6_input.c +++ b/trunk/net/ipv6/ip6_input.c @@ -111,7 +111,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt } if (hdr->nexthdr == NEXTHDR_HOP) { - if (ipv6_parse_hopopts(&skb) < 0) { + if (ipv6_parse_hopopts(skb) < 0) { IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); return 0; } diff --git a/trunk/net/ipv6/ip6_output.c b/trunk/net/ipv6/ip6_output.c index 66716911962e..3bc74ce78800 100644 --- a/trunk/net/ipv6/ip6_output.c +++ b/trunk/net/ipv6/ip6_output.c @@ -308,56 +308,6 @@ static int ip6_call_ra_chain(struct sk_buff *skb, int sel) return 0; } -static int ip6_forward_proxy_check(struct sk_buff *skb) -{ - struct ipv6hdr *hdr = skb->nh.ipv6h; - u8 nexthdr = hdr->nexthdr; - int offset; - - if (ipv6_ext_hdr(nexthdr)) { - offset = ipv6_skip_exthdr(skb, sizeof(*hdr), &nexthdr); - if (offset < 0) - return 0; - } else - offset = sizeof(struct ipv6hdr); - - if (nexthdr == IPPROTO_ICMPV6) { - struct icmp6hdr *icmp6; - - if (!pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) - return 0; - - icmp6 = (struct icmp6hdr *)(skb->nh.raw + offset); - - switch (icmp6->icmp6_type) { - case NDISC_ROUTER_SOLICITATION: - case NDISC_ROUTER_ADVERTISEMENT: - case NDISC_NEIGHBOUR_SOLICITATION: - case NDISC_NEIGHBOUR_ADVERTISEMENT: - case NDISC_REDIRECT: - /* For reaction involving unicast neighbor discovery - * message destined to the proxied address, pass it to - * input function. - */ - return 1; - default: - break; - } - } - - /* - * The proxying router can't forward traffic sent to a link-local - * address, so signal the sender and discard the packet. This - * behavior is clarified by the MIPv6 specification. - */ - if (ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL) { - dst_link_failure(skb); - return -1; - } - - return 0; -} - static inline int ip6_forward_finish(struct sk_buff *skb) { return dst_output(skb); @@ -406,24 +356,11 @@ int ip6_forward(struct sk_buff *skb) skb->dev = dst->dev; icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, 0, skb->dev); - IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS); kfree_skb(skb); return -ETIMEDOUT; } - /* XXX: idev->cnf.proxy_ndp? */ - if (ipv6_devconf.proxy_ndp && - pneigh_lookup(&nd_tbl, &hdr->daddr, skb->dev, 0)) { - int proxied = ip6_forward_proxy_check(skb); - if (proxied > 0) - return ip6_input(skb); - else if (proxied < 0) { - IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); - goto drop; - } - } - if (!xfrm6_route_forward(skb)) { IP6_INC_STATS(IPSTATS_MIB_INDISCARDS); goto drop; @@ -537,25 +474,17 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) switch (**nexthdr) { case NEXTHDR_HOP: - break; case NEXTHDR_ROUTING: - found_rhdr = 1; - break; case NEXTHDR_DEST: -#ifdef CONFIG_IPV6_MIP6 - if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0) - break; -#endif - if (found_rhdr) - return offset; + if (**nexthdr == NEXTHDR_ROUTING) found_rhdr = 1; + if (**nexthdr == NEXTHDR_DEST && found_rhdr) return offset; + offset += ipv6_optlen(exthdr); + *nexthdr = &exthdr->nexthdr; + exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); break; default : return offset; } - - offset += ipv6_optlen(exthdr); - *nexthdr = &exthdr->nexthdr; - exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); } return offset; @@ -666,9 +595,6 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) } err = output(skb); - if(!err) - IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); - if (err || !frag) break; @@ -780,11 +706,12 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) /* * Put this fragment into the sending queue. */ + + IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); + err = output(frag); if (err) goto fail; - - IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES); } kfree_skb(skb); IP6_INC_STATS(IPSTATS_MIB_FRAGOKS); @@ -796,59 +723,48 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) return err; } -static inline int ip6_rt_check(struct rt6key *rt_key, - struct in6_addr *fl_addr, - struct in6_addr *addr_cache) -{ - return ((rt_key->plen != 128 || !ipv6_addr_equal(fl_addr, &rt_key->addr)) && - (addr_cache == NULL || !ipv6_addr_equal(fl_addr, addr_cache))); -} - -static struct dst_entry *ip6_sk_dst_check(struct sock *sk, - struct dst_entry *dst, - struct flowi *fl) +int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) { - struct ipv6_pinfo *np = inet6_sk(sk); - struct rt6_info *rt = (struct rt6_info *)dst; - - if (!dst) - goto out; + int err = 0; - /* Yes, checking route validity in not connected - * case is not very simple. Take into account, - * that we do not support routing by source, TOS, - * and MSG_DONTROUTE --ANK (980726) - * - * 1. ip6_rt_check(): If route was host route, - * check that cached destination is current. - * If it is network route, we still may - * check its validity using saved pointer - * to the last used address: daddr_cache. - * We do not want to save whole address now, - * (because main consumer of this service - * is tcp, which has not this problem), - * so that the last trick works only on connected - * sockets. - * 2. oif also should be the same. - */ - if (ip6_rt_check(&rt->rt6i_dst, &fl->fl6_dst, np->daddr_cache) || -#ifdef CONFIG_IPV6_SUBTREES - ip6_rt_check(&rt->rt6i_src, &fl->fl6_src, np->saddr_cache) || -#endif - (fl->oif && fl->oif != dst->dev->ifindex)) { - dst_release(dst); - dst = NULL; + *dst = NULL; + if (sk) { + struct ipv6_pinfo *np = inet6_sk(sk); + + *dst = sk_dst_check(sk, np->dst_cookie); + if (*dst) { + struct rt6_info *rt = (struct rt6_info*)*dst; + + /* Yes, checking route validity in not connected + * case is not very simple. Take into account, + * that we do not support routing by source, TOS, + * and MSG_DONTROUTE --ANK (980726) + * + * 1. If route was host route, check that + * cached destination is current. + * If it is network route, we still may + * check its validity using saved pointer + * to the last used address: daddr_cache. + * We do not want to save whole address now, + * (because main consumer of this service + * is tcp, which has not this problem), + * so that the last trick works only on connected + * sockets. + * 2. oif also should be the same. + */ + if (((rt->rt6i_dst.plen != 128 || + !ipv6_addr_equal(&fl->fl6_dst, + &rt->rt6i_dst.addr)) + && (np->daddr_cache == NULL || + !ipv6_addr_equal(&fl->fl6_dst, + np->daddr_cache))) + || (fl->oif && fl->oif != (*dst)->dev->ifindex)) { + dst_release(*dst); + *dst = NULL; + } + } } -out: - return dst; -} - -static int ip6_dst_lookup_tail(struct sock *sk, - struct dst_entry **dst, struct flowi *fl) -{ - int err; - if (*dst == NULL) *dst = ip6_route_output(sk, fl); @@ -857,6 +773,7 @@ static int ip6_dst_lookup_tail(struct sock *sk, if (ipv6_addr_any(&fl->fl6_src)) { err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src); + if (err) goto out_err_release; } @@ -869,48 +786,8 @@ static int ip6_dst_lookup_tail(struct sock *sk, return err; } -/** - * ip6_dst_lookup - perform route lookup on flow - * @sk: socket which provides route info - * @dst: pointer to dst_entry * for result - * @fl: flow to lookup - * - * This function performs a route lookup on the given flow. - * - * It returns zero on success, or a standard errno code on error. - */ -int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) -{ - *dst = NULL; - return ip6_dst_lookup_tail(sk, dst, fl); -} EXPORT_SYMBOL_GPL(ip6_dst_lookup); -/** - * ip6_sk_dst_lookup - perform socket cached route lookup on flow - * @sk: socket which provides the dst cache and route info - * @dst: pointer to dst_entry * for result - * @fl: flow to lookup - * - * This function performs a route lookup on the given flow with the - * possibility of using the cached route in the socket if it is valid. - * It will take the socket dst lock when operating on the dst cache. - * As a result, this function can only be used in process context. - * - * It returns zero on success, or a standard errno code on error. - */ -int ip6_sk_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl) -{ - *dst = NULL; - if (sk) { - *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie); - *dst = ip6_sk_dst_check(sk, *dst, fl); - } - - return ip6_dst_lookup_tail(sk, dst, fl); -} -EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup); - static inline int ip6_ufo_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), @@ -944,7 +821,7 @@ static inline int ip6_ufo_append_data(struct sock *sk, /* initialize protocol header pointer */ skb->h.raw = skb->data + fragheaderlen; - skb->ip_summed = CHECKSUM_PARTIAL; + skb->ip_summed = CHECKSUM_HW; skb->csum = 0; sk->sk_sndmsg_off = 0; } @@ -1041,7 +918,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); - fragheaderlen = sizeof(struct ipv6hdr) + rt->u.dst.nfheader_len + (opt ? opt->opt_nflen : 0); + fragheaderlen = sizeof(struct ipv6hdr) + (opt ? opt->opt_nflen : 0); maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { @@ -1173,7 +1050,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, skb_prev->csum = csum_sub(skb_prev->csum, skb->csum); data += fraggap; - pskb_trim_unique(skb_prev, maxfraglen); + skb_trim(skb_prev, maxfraglen); } copy = datalen - transhdrlen - fraggap; if (copy < 0) { diff --git a/trunk/net/ipv6/ipcomp6.c b/trunk/net/ipv6/ipcomp6.c index ad9c6e824e62..7e4d1c17bfbc 100644 --- a/trunk/net/ipv6/ipcomp6.c +++ b/trunk/net/ipv6/ipcomp6.c @@ -53,7 +53,7 @@ struct ipcomp6_tfms { struct list_head list; - struct crypto_comp **tfms; + struct crypto_tfm **tfms; int users; }; @@ -70,7 +70,7 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) int plen, dlen; struct ipcomp_data *ipcd = x->data; u8 *start, *scratch; - struct crypto_comp *tfm; + struct crypto_tfm *tfm; int cpu; if (skb_linearize_cow(skb)) @@ -129,7 +129,7 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb) struct ipcomp_data *ipcd = x->data; int plen, dlen; u8 *start, *scratch; - struct crypto_comp *tfm; + struct crypto_tfm *tfm; int cpu; hdr_len = skb->h.raw - skb->data; @@ -212,7 +212,7 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) memcpy(t->id.daddr.a6, x->id.daddr.a6, sizeof(struct in6_addr)); memcpy(&t->sel, &x->sel, sizeof(t->sel)); t->props.family = AF_INET6; - t->props.mode = XFRM_MODE_TUNNEL; + t->props.mode = 1; memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr)); if (xfrm_init_state(t)) @@ -301,7 +301,7 @@ static void **ipcomp6_alloc_scratches(void) return scratches; } -static void ipcomp6_free_tfms(struct crypto_comp **tfms) +static void ipcomp6_free_tfms(struct crypto_tfm **tfms) { struct ipcomp6_tfms *pos; int cpu; @@ -323,28 +323,28 @@ static void ipcomp6_free_tfms(struct crypto_comp **tfms) return; for_each_possible_cpu(cpu) { - struct crypto_comp *tfm = *per_cpu_ptr(tfms, cpu); - crypto_free_comp(tfm); + struct crypto_tfm *tfm = *per_cpu_ptr(tfms, cpu); + crypto_free_tfm(tfm); } free_percpu(tfms); } -static struct crypto_comp **ipcomp6_alloc_tfms(const char *alg_name) +static struct crypto_tfm **ipcomp6_alloc_tfms(const char *alg_name) { struct ipcomp6_tfms *pos; - struct crypto_comp **tfms; + struct crypto_tfm **tfms; int cpu; /* This can be any valid CPU ID so we don't need locking. */ cpu = raw_smp_processor_id(); list_for_each_entry(pos, &ipcomp6_tfms_list, list) { - struct crypto_comp *tfm; + struct crypto_tfm *tfm; tfms = pos->tfms; tfm = *per_cpu_ptr(tfms, cpu); - if (!strcmp(crypto_comp_name(tfm), alg_name)) { + if (!strcmp(crypto_tfm_alg_name(tfm), alg_name)) { pos->users++; return tfms; } @@ -358,13 +358,12 @@ static struct crypto_comp **ipcomp6_alloc_tfms(const char *alg_name) INIT_LIST_HEAD(&pos->list); list_add(&pos->list, &ipcomp6_tfms_list); - pos->tfms = tfms = alloc_percpu(struct crypto_comp *); + pos->tfms = tfms = alloc_percpu(struct crypto_tfm *); if (!tfms) goto error; for_each_possible_cpu(cpu) { - struct crypto_comp *tfm = crypto_alloc_comp(alg_name, 0, - CRYPTO_ALG_ASYNC); + struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0); if (!tfm) goto error; *per_cpu_ptr(tfms, cpu) = tfm; @@ -417,7 +416,7 @@ static int ipcomp6_init_state(struct xfrm_state *x) goto out; x->props.header_len = 0; - if (x->props.mode == XFRM_MODE_TUNNEL) + if (x->props.mode) x->props.header_len += sizeof(struct ipv6hdr); mutex_lock(&ipcomp6_resource_mutex); @@ -429,7 +428,7 @@ static int ipcomp6_init_state(struct xfrm_state *x) goto error; mutex_unlock(&ipcomp6_resource_mutex); - if (x->props.mode == XFRM_MODE_TUNNEL) { + if (x->props.mode) { err = ipcomp6_tunnel_attach(x); if (err) goto error_tunnel; @@ -461,7 +460,6 @@ static struct xfrm_type ipcomp6_type = .destructor = ipcomp6_destroy, .input = ipcomp6_input, .output = ipcomp6_output, - .hdr_offset = xfrm6_find_1stfragopt, }; static struct inet6_protocol ipcomp6_protocol = diff --git a/trunk/net/ipv6/ipv6_sockglue.c b/trunk/net/ipv6/ipv6_sockglue.c index 4f3bb7fcc8b5..43327264e69c 100644 --- a/trunk/net/ipv6/ipv6_sockglue.c +++ b/trunk/net/ipv6/ipv6_sockglue.c @@ -362,7 +362,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, break; case IPV6_TCLASS: - if (val < -1 || val > 0xff) + if (val < 0 || val > 0xff) goto e_inval; np->tclass = val; retv = 0; @@ -407,16 +407,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, /* routing header option needs extra check */ if (optname == IPV6_RTHDR && opt->srcrt) { struct ipv6_rt_hdr *rthdr = opt->srcrt; - switch (rthdr->type) { - case IPV6_SRCRT_TYPE_0: -#ifdef CONFIG_IPV6_MIP6 - case IPV6_SRCRT_TYPE_2: -#endif - break; - default: + if (rthdr->type) goto sticky_done; - } - if ((rthdr->hdrlen & 1) || (rthdr->hdrlen >> 1) != rthdr->segments_left) goto sticky_done; @@ -955,8 +947,6 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, case IPV6_TCLASS: val = np->tclass; - if (val < 0) - val = 0; break; case IPV6_RECVTCLASS: diff --git a/trunk/net/ipv6/ipv6_syms.c b/trunk/net/ipv6/ipv6_syms.c index 0e8e0676a033..dd4d1ce77769 100644 --- a/trunk/net/ipv6/ipv6_syms.c +++ b/trunk/net/ipv6/ipv6_syms.c @@ -14,6 +14,7 @@ EXPORT_SYMBOL(ndisc_mc_map); EXPORT_SYMBOL(register_inet6addr_notifier); EXPORT_SYMBOL(unregister_inet6addr_notifier); EXPORT_SYMBOL(ip6_route_output); +EXPORT_SYMBOL(addrconf_lock); EXPORT_SYMBOL(ipv6_setsockopt); EXPORT_SYMBOL(ipv6_getsockopt); EXPORT_SYMBOL(inet6_register_protosw); @@ -30,8 +31,6 @@ EXPORT_SYMBOL(ipv6_chk_addr); EXPORT_SYMBOL(in6_dev_finish_destroy); #ifdef CONFIG_XFRM EXPORT_SYMBOL(xfrm6_rcv); -EXPORT_SYMBOL(xfrm6_input_addr); -EXPORT_SYMBOL(xfrm6_find_1stfragopt); #endif EXPORT_SYMBOL(rt6_lookup); EXPORT_SYMBOL(ipv6_push_nfrag_opts); diff --git a/trunk/net/ipv6/mcast.c b/trunk/net/ipv6/mcast.c index 3b114e3fa2f8..9d697d4dcffc 100644 --- a/trunk/net/ipv6/mcast.c +++ b/trunk/net/ipv6/mcast.c @@ -171,7 +171,7 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, #define IPV6_MLD_MAX_MSF 64 -int sysctl_mld_max_msf __read_mostly = IPV6_MLD_MAX_MSF; +int sysctl_mld_max_msf = IPV6_MLD_MAX_MSF; /* * socket join on multicast group @@ -268,14 +268,13 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr) if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) { struct inet6_dev *idev = in6_dev_get(dev); - (void) ip6_mc_leave_src(sk, mc_lst, idev); if (idev) { + (void) ip6_mc_leave_src(sk,mc_lst,idev); __ipv6_dev_mc_dec(idev, &mc_lst->addr); in6_dev_put(idev); } dev_put(dev); - } else - (void) ip6_mc_leave_src(sk, mc_lst, NULL); + } sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); return 0; } @@ -335,14 +334,13 @@ void ipv6_sock_mc_close(struct sock *sk) if (dev) { struct inet6_dev *idev = in6_dev_get(dev); - (void) ip6_mc_leave_src(sk, mc_lst, idev); if (idev) { + (void) ip6_mc_leave_src(sk, mc_lst, idev); __ipv6_dev_mc_dec(idev, &mc_lst->addr); in6_dev_put(idev); } dev_put(dev); - } else - (void) ip6_mc_leave_src(sk, mc_lst, NULL); + } sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); diff --git a/trunk/net/ipv6/mip6.c b/trunk/net/ipv6/mip6.c deleted file mode 100644 index 99d116caecda..000000000000 --- a/trunk/net/ipv6/mip6.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - * Copyright (C)2003-2006 Helsinki University of Technology - * Copyright (C)2003-2006 USAGI/WIDE Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* - * Authors: - * Noriaki TAKAMIYA @USAGI - * Masahide NAKAMURA @USAGI - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static xfrm_address_t *mip6_xfrm_addr(struct xfrm_state *x, xfrm_address_t *addr) -{ - return x->coaddr; -} - -static inline unsigned int calc_padlen(unsigned int len, unsigned int n) -{ - return (n - len + 16) & 0x7; -} - -static inline void *mip6_padn(__u8 *data, __u8 padlen) -{ - if (!data) - return NULL; - if (padlen == 1) { - data[0] = MIP6_OPT_PAD_1; - } else if (padlen > 1) { - data[0] = MIP6_OPT_PAD_N; - data[1] = padlen - 2; - if (padlen > 2) - memset(data+2, 0, data[1]); - } - return data + padlen; -} - -static inline void mip6_param_prob(struct sk_buff *skb, int code, int pos) -{ - icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev); -} - -static int mip6_mh_len(int type) -{ - int len = 0; - - switch (type) { - case IP6_MH_TYPE_BRR: - len = 0; - break; - case IP6_MH_TYPE_HOTI: - case IP6_MH_TYPE_COTI: - case IP6_MH_TYPE_BU: - case IP6_MH_TYPE_BACK: - len = 1; - break; - case IP6_MH_TYPE_HOT: - case IP6_MH_TYPE_COT: - case IP6_MH_TYPE_BERROR: - len = 2; - break; - } - return len; -} - -int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) -{ - struct ip6_mh *mh; - int mhlen; - - if (!pskb_may_pull(skb, (skb->h.raw - skb->data) + 8) || - !pskb_may_pull(skb, (skb->h.raw - skb->data) + ((skb->h.raw[1] + 1) << 3))) - return -1; - - mh = (struct ip6_mh *)skb->h.raw; - - if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) { - LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n", - mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); - mip6_param_prob(skb, 0, (&mh->ip6mh_hdrlen) - skb->nh.raw); - return -1; - } - mhlen = (mh->ip6mh_hdrlen + 1) << 3; - - if (skb->ip_summed == CHECKSUM_COMPLETE) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, - &skb->nh.ipv6h->daddr, - mhlen, IPPROTO_MH, - skb->csum)) { - LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH hw checksum failed\n"); - skb->ip_summed = CHECKSUM_NONE; - } - } - if (skb->ip_summed == CHECKSUM_NONE) { - if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, - &skb->nh.ipv6h->daddr, - mhlen, IPPROTO_MH, - skb_checksum(skb, 0, mhlen, 0))) { - LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH checksum failed " - "[" NIP6_FMT " > " NIP6_FMT "]\n", - NIP6(skb->nh.ipv6h->saddr), - NIP6(skb->nh.ipv6h->daddr)); - return -1; - } - skb->ip_summed = CHECKSUM_UNNECESSARY; - } - - if (mh->ip6mh_proto != IPPROTO_NONE) { - LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n", - mh->ip6mh_proto); - mip6_param_prob(skb, 0, (&mh->ip6mh_proto) - skb->nh.raw); - return -1; - } - - return 0; -} - -struct mip6_report_rate_limiter { - spinlock_t lock; - struct timeval stamp; - int iif; - struct in6_addr src; - struct in6_addr dst; -}; - -static struct mip6_report_rate_limiter mip6_report_rl = { - .lock = SPIN_LOCK_UNLOCKED -}; - -static int mip6_destopt_input(struct xfrm_state *x, struct sk_buff *skb) -{ - struct ipv6hdr *iph = skb->nh.ipv6h; - struct ipv6_destopt_hdr *destopt = (struct ipv6_destopt_hdr *)skb->data; - - if (!ipv6_addr_equal(&iph->saddr, (struct in6_addr *)x->coaddr) && - !ipv6_addr_any((struct in6_addr *)x->coaddr)) - return -ENOENT; - - return destopt->nexthdr; -} - -/* Destination Option Header is inserted. - * IP Header's src address is replaced with Home Address Option in - * Destination Option Header. - */ -static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb) -{ - struct ipv6hdr *iph; - struct ipv6_destopt_hdr *dstopt; - struct ipv6_destopt_hao *hao; - u8 nexthdr; - int len; - - iph = (struct ipv6hdr *)skb->data; - iph->payload_len = htons(skb->len - sizeof(*iph)); - - nexthdr = *skb->nh.raw; - *skb->nh.raw = IPPROTO_DSTOPTS; - - dstopt = (struct ipv6_destopt_hdr *)skb->h.raw; - dstopt->nexthdr = nexthdr; - - hao = mip6_padn((char *)(dstopt + 1), - calc_padlen(sizeof(*dstopt), 6)); - - hao->type = IPV6_TLV_HAO; - hao->length = sizeof(*hao) - 2; - BUG_TRAP(hao->length == 16); - - len = ((char *)hao - (char *)dstopt) + sizeof(*hao); - - memcpy(&hao->addr, &iph->saddr, sizeof(hao->addr)); - memcpy(&iph->saddr, x->coaddr, sizeof(iph->saddr)); - - BUG_TRAP(len == x->props.header_len); - dstopt->hdrlen = (x->props.header_len >> 3) - 1; - - return 0; -} - -static inline int mip6_report_rl_allow(struct timeval *stamp, - struct in6_addr *dst, - struct in6_addr *src, int iif) -{ - int allow = 0; - - spin_lock_bh(&mip6_report_rl.lock); - if (mip6_report_rl.stamp.tv_sec != stamp->tv_sec || - mip6_report_rl.stamp.tv_usec != stamp->tv_usec || - mip6_report_rl.iif != iif || - !ipv6_addr_equal(&mip6_report_rl.src, src) || - !ipv6_addr_equal(&mip6_report_rl.dst, dst)) { - mip6_report_rl.stamp.tv_sec = stamp->tv_sec; - mip6_report_rl.stamp.tv_usec = stamp->tv_usec; - mip6_report_rl.iif = iif; - ipv6_addr_copy(&mip6_report_rl.src, src); - ipv6_addr_copy(&mip6_report_rl.dst, dst); - allow = 1; - } - spin_unlock_bh(&mip6_report_rl.lock); - return allow; -} - -static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct flowi *fl) -{ - struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; - struct ipv6_destopt_hao *hao = NULL; - struct xfrm_selector sel; - int offset; - struct timeval stamp; - int err = 0; - - if (unlikely(fl->proto == IPPROTO_MH && - fl->fl_mh_type <= IP6_MH_TYPE_MAX)) - goto out; - - if (likely(opt->dsthao)) { - offset = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO); - if (likely(offset >= 0)) - hao = (struct ipv6_destopt_hao *)(skb->nh.raw + offset); - } - - skb_get_timestamp(skb, &stamp); - - if (!mip6_report_rl_allow(&stamp, &skb->nh.ipv6h->daddr, - hao ? &hao->addr : &skb->nh.ipv6h->saddr, - opt->iif)) - goto out; - - memset(&sel, 0, sizeof(sel)); - memcpy(&sel.daddr, (xfrm_address_t *)&skb->nh.ipv6h->daddr, - sizeof(sel.daddr)); - sel.prefixlen_d = 128; - memcpy(&sel.saddr, (xfrm_address_t *)&skb->nh.ipv6h->saddr, - sizeof(sel.saddr)); - sel.prefixlen_s = 128; - sel.family = AF_INET6; - sel.proto = fl->proto; - sel.dport = xfrm_flowi_dport(fl); - if (sel.dport) - sel.dport_mask = ~((__u16)0); - sel.sport = xfrm_flowi_sport(fl); - if (sel.sport) - sel.sport_mask = ~((__u16)0); - sel.ifindex = fl->oif; - - err = km_report(IPPROTO_DSTOPTS, &sel, - (hao ? (xfrm_address_t *)&hao->addr : NULL)); - - out: - return err; -} - -static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb, - u8 **nexthdr) -{ - u16 offset = sizeof(struct ipv6hdr); - struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1); - unsigned int packet_len = skb->tail - skb->nh.raw; - int found_rhdr = 0; - - *nexthdr = &skb->nh.ipv6h->nexthdr; - - while (offset + 1 <= packet_len) { - - switch (**nexthdr) { - case NEXTHDR_HOP: - break; - case NEXTHDR_ROUTING: - found_rhdr = 1; - break; - case NEXTHDR_DEST: - /* - * HAO MUST NOT appear more than once. - * XXX: It is better to try to find by the end of - * XXX: packet if HAO exists. - */ - if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0) { - LIMIT_NETDEBUG(KERN_WARNING "mip6: hao exists already, override\n"); - return offset; - } - - if (found_rhdr) - return offset; - - break; - default: - return offset; - } - - offset += ipv6_optlen(exthdr); - *nexthdr = &exthdr->nexthdr; - exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); - } - - return offset; -} - -static int mip6_destopt_init_state(struct xfrm_state *x) -{ - if (x->id.spi) { - printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__, - x->id.spi); - return -EINVAL; - } - if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) { - printk(KERN_INFO "%s: state's mode is not %u: %u\n", - __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode); - return -EINVAL; - } - - x->props.header_len = sizeof(struct ipv6_destopt_hdr) + - calc_padlen(sizeof(struct ipv6_destopt_hdr), 6) + - sizeof(struct ipv6_destopt_hao); - BUG_TRAP(x->props.header_len == 24); - - return 0; -} - -/* - * Do nothing about destroying since it has no specific operation for - * destination options header unlike IPsec protocols. - */ -static void mip6_destopt_destroy(struct xfrm_state *x) -{ -} - -static struct xfrm_type mip6_destopt_type = -{ - .description = "MIP6DESTOPT", - .owner = THIS_MODULE, - .proto = IPPROTO_DSTOPTS, - .flags = XFRM_TYPE_NON_FRAGMENT, - .init_state = mip6_destopt_init_state, - .destructor = mip6_destopt_destroy, - .input = mip6_destopt_input, - .output = mip6_destopt_output, - .reject = mip6_destopt_reject, - .hdr_offset = mip6_destopt_offset, - .local_addr = mip6_xfrm_addr, -}; - -static int mip6_rthdr_input(struct xfrm_state *x, struct sk_buff *skb) -{ - struct rt2_hdr *rt2 = (struct rt2_hdr *)skb->data; - - if (!ipv6_addr_equal(&rt2->addr, (struct in6_addr *)x->coaddr) && - !ipv6_addr_any((struct in6_addr *)x->coaddr)) - return -ENOENT; - - return rt2->rt_hdr.nexthdr; -} - -/* Routing Header type 2 is inserted. - * IP Header's dst address is replaced with Routing Header's Home Address. - */ -static int mip6_rthdr_output(struct xfrm_state *x, struct sk_buff *skb) -{ - struct ipv6hdr *iph; - struct rt2_hdr *rt2; - u8 nexthdr; - - iph = (struct ipv6hdr *)skb->data; - iph->payload_len = htons(skb->len - sizeof(*iph)); - - nexthdr = *skb->nh.raw; - *skb->nh.raw = IPPROTO_ROUTING; - - rt2 = (struct rt2_hdr *)skb->h.raw; - rt2->rt_hdr.nexthdr = nexthdr; - rt2->rt_hdr.hdrlen = (x->props.header_len >> 3) - 1; - rt2->rt_hdr.type = IPV6_SRCRT_TYPE_2; - rt2->rt_hdr.segments_left = 1; - memset(&rt2->reserved, 0, sizeof(rt2->reserved)); - - BUG_TRAP(rt2->rt_hdr.hdrlen == 2); - - memcpy(&rt2->addr, &iph->daddr, sizeof(rt2->addr)); - memcpy(&iph->daddr, x->coaddr, sizeof(iph->daddr)); - - return 0; -} - -static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb, - u8 **nexthdr) -{ - u16 offset = sizeof(struct ipv6hdr); - struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.ipv6h + 1); - unsigned int packet_len = skb->tail - skb->nh.raw; - int found_rhdr = 0; - - *nexthdr = &skb->nh.ipv6h->nexthdr; - - while (offset + 1 <= packet_len) { - - switch (**nexthdr) { - case NEXTHDR_HOP: - break; - case NEXTHDR_ROUTING: - if (offset + 3 <= packet_len) { - struct ipv6_rt_hdr *rt; - rt = (struct ipv6_rt_hdr *)(skb->nh.raw + offset); - if (rt->type != 0) - return offset; - } - found_rhdr = 1; - break; - case NEXTHDR_DEST: - if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0) - return offset; - - if (found_rhdr) - return offset; - - break; - default: - return offset; - } - - offset += ipv6_optlen(exthdr); - *nexthdr = &exthdr->nexthdr; - exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); - } - - return offset; -} - -static int mip6_rthdr_init_state(struct xfrm_state *x) -{ - if (x->id.spi) { - printk(KERN_INFO "%s: spi is not 0: %u\n", __FUNCTION__, - x->id.spi); - return -EINVAL; - } - if (x->props.mode != XFRM_MODE_ROUTEOPTIMIZATION) { - printk(KERN_INFO "%s: state's mode is not %u: %u\n", - __FUNCTION__, XFRM_MODE_ROUTEOPTIMIZATION, x->props.mode); - return -EINVAL; - } - - x->props.header_len = sizeof(struct rt2_hdr); - - return 0; -} - -/* - * Do nothing about destroying since it has no specific operation for routing - * header type 2 unlike IPsec protocols. - */ -static void mip6_rthdr_destroy(struct xfrm_state *x) -{ -} - -static struct xfrm_type mip6_rthdr_type = -{ - .description = "MIP6RT", - .owner = THIS_MODULE, - .proto = IPPROTO_ROUTING, - .flags = XFRM_TYPE_NON_FRAGMENT, - .init_state = mip6_rthdr_init_state, - .destructor = mip6_rthdr_destroy, - .input = mip6_rthdr_input, - .output = mip6_rthdr_output, - .hdr_offset = mip6_rthdr_offset, - .remote_addr = mip6_xfrm_addr, -}; - -int __init mip6_init(void) -{ - printk(KERN_INFO "Mobile IPv6\n"); - - if (xfrm_register_type(&mip6_destopt_type, AF_INET6) < 0) { - printk(KERN_INFO "%s: can't add xfrm type(destopt)\n", __FUNCTION__); - goto mip6_destopt_xfrm_fail; - } - if (xfrm_register_type(&mip6_rthdr_type, AF_INET6) < 0) { - printk(KERN_INFO "%s: can't add xfrm type(rthdr)\n", __FUNCTION__); - goto mip6_rthdr_xfrm_fail; - } - return 0; - - mip6_rthdr_xfrm_fail: - xfrm_unregister_type(&mip6_destopt_type, AF_INET6); - mip6_destopt_xfrm_fail: - return -EAGAIN; -} - -void __exit mip6_fini(void) -{ - if (xfrm_unregister_type(&mip6_rthdr_type, AF_INET6) < 0) - printk(KERN_INFO "%s: can't remove xfrm type(rthdr)\n", __FUNCTION__); - if (xfrm_unregister_type(&mip6_destopt_type, AF_INET6) < 0) - printk(KERN_INFO "%s: can't remove xfrm type(destopt)\n", __FUNCTION__); -} diff --git a/trunk/net/ipv6/ndisc.c b/trunk/net/ipv6/ndisc.c index 0304b5fe8d6a..b50055b9278d 100644 --- a/trunk/net/ipv6/ndisc.c +++ b/trunk/net/ipv6/ndisc.c @@ -62,7 +62,6 @@ #include #endif -#include #include #include #include @@ -412,8 +411,7 @@ static void pndisc_destructor(struct pneigh_entry *n) */ static inline void ndisc_flow_init(struct flowi *fl, u8 type, - struct in6_addr *saddr, struct in6_addr *daddr, - int oif) + struct in6_addr *saddr, struct in6_addr *daddr) { memset(fl, 0, sizeof(*fl)); ipv6_addr_copy(&fl->fl6_src, saddr); @@ -421,8 +419,6 @@ static inline void ndisc_flow_init(struct flowi *fl, u8 type, fl->proto = IPPROTO_ICMPV6; fl->fl_icmp_type = type; fl->fl_icmp_code = 0; - fl->oif = oif; - security_sk_classify_flow(ndisc_socket->sk, fl); } static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, @@ -454,8 +450,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, src_addr = &tmpaddr; } - ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr, - dev->ifindex); + ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, src_addr, daddr); dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output); if (!dst) @@ -496,7 +491,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, msg->icmph.icmp6_unused = 0; msg->icmph.icmp6_router = router; msg->icmph.icmp6_solicited = solicited; - msg->icmph.icmp6_override = override; + msg->icmph.icmp6_override = !!override; /* Set the target address. */ ipv6_addr_copy(&msg->target, solicited_addr); @@ -545,8 +540,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, saddr = &addr_buf; } - ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr, - dev->ifindex); + ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr); dst = ndisc_dst_alloc(dev, neigh, daddr, ip6_output); if (!dst) @@ -621,8 +615,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, int len; int err; - ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr, - dev->ifindex); + ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr); dst = ndisc_dst_alloc(dev, NULL, daddr, ip6_output); if (!dst) @@ -736,10 +729,8 @@ static void ndisc_recv_ns(struct sk_buff *skb) struct inet6_ifaddr *ifp; struct inet6_dev *idev = NULL; struct neighbour *neigh; - struct pneigh_entry *pneigh = NULL; int dad = ipv6_addr_any(saddr); int inc; - int is_router; if (ipv6_addr_is_multicast(&msg->target)) { ND_PRINTK2(KERN_WARNING @@ -824,9 +815,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) if (ipv6_chk_acast_addr(dev, &msg->target) || (idev->cnf.forwarding && - (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) && - (pneigh = pneigh_lookup(&nd_tbl, - &msg->target, dev, 0)) != NULL)) { + pneigh_lookup(&nd_tbl, &msg->target, dev, 0))) { if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) && skb->pkt_type != PACKET_HOST && inc != 0 && @@ -847,14 +836,12 @@ static void ndisc_recv_ns(struct sk_buff *skb) goto out; } - is_router = !!(pneigh ? pneigh->flags & NTF_ROUTER : idev->cnf.forwarding); - if (dad) { struct in6_addr maddr; ipv6_addr_all_nodes(&maddr); ndisc_send_na(dev, NULL, &maddr, &msg->target, - is_router, 0, (ifp != NULL), 1); + idev->cnf.forwarding, 0, (ifp != NULL), 1); goto out; } @@ -875,7 +862,7 @@ static void ndisc_recv_ns(struct sk_buff *skb) NEIGH_UPDATE_F_OVERRIDE); if (neigh || !dev->hard_header) { ndisc_send_na(dev, neigh, saddr, &msg->target, - is_router, + idev->cnf.forwarding, 1, (ifp != NULL && inc), inc); if (neigh) neigh_release(neigh); @@ -958,20 +945,6 @@ static void ndisc_recv_na(struct sk_buff *skb) if (neigh->nud_state & NUD_FAILED) goto out; - /* - * Don't update the neighbor cache entry on a proxy NA from - * ourselves because either the proxied node is off link or it - * has already sent a NA to us. - */ - if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) && - ipv6_devconf.forwarding && ipv6_devconf.proxy_ndp && - pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) { - /* XXX: idev->cnf.prixy_ndp */ - WARN_ON(skb->dst != NULL && - ((struct rt6_info *)skb->dst)->rt6i_idev); - goto out; - } - neigh_update(neigh, lladdr, msg->icmph.icmp6_solicited ? NUD_REACHABLE : NUD_STALE, NEIGH_UPDATE_F_WEAK_OVERRIDE| @@ -986,7 +959,7 @@ static void ndisc_recv_na(struct sk_buff *skb) struct rt6_info *rt; rt = rt6_get_dflt_router(saddr, dev); if (rt) - ip6_del_rt(rt); + ip6_del_rt(rt, NULL, NULL, NULL); } out: @@ -1139,7 +1112,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) if (rt && lifetime == 0) { neigh_clone(neigh); - ip6_del_rt(rt); + ip6_del_rt(rt, NULL, NULL, NULL); rt = NULL; } @@ -1371,8 +1344,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) neigh = __neigh_lookup(&nd_tbl, target, skb->dev, 1); if (neigh) { - rt6_redirect(dest, &skb->nh.ipv6h->daddr, - &skb->nh.ipv6h->saddr, neigh, lladdr, + rt6_redirect(dest, &skb->nh.ipv6h->saddr, neigh, lladdr, on_link); neigh_release(neigh); } @@ -1408,8 +1380,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, return; } - ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr, - dev->ifindex); + ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr); dst = ip6_route_output(NULL, &fl); if (dst == NULL) diff --git a/trunk/net/ipv6/netfilter.c b/trunk/net/ipv6/netfilter.c index 580b1aba6722..395a417ba955 100644 --- a/trunk/net/ipv6/netfilter.c +++ b/trunk/net/ipv6/netfilter.c @@ -87,7 +87,7 @@ unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, unsigned int csum = 0; switch (skb->ip_summed) { - case CHECKSUM_COMPLETE: + case CHECKSUM_HW: if (hook != NF_IP6_PRE_ROUTING && hook != NF_IP6_LOCAL_IN) break; if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, diff --git a/trunk/net/ipv6/netfilter/Makefile b/trunk/net/ipv6/netfilter/Makefile index ac1dfebde175..eeeb57d4c9c5 100644 --- a/trunk/net/ipv6/netfilter/Makefile +++ b/trunk/net/ipv6/netfilter/Makefile @@ -5,7 +5,7 @@ # Link order matters here. obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o -obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o +obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o diff --git a/trunk/net/ipv6/netfilter/ip6_queue.c b/trunk/net/ipv6/netfilter/ip6_queue.c index 9510c24ca8d2..968a14be0d05 100644 --- a/trunk/net/ipv6/netfilter/ip6_queue.c +++ b/trunk/net/ipv6/netfilter/ip6_queue.c @@ -56,15 +56,15 @@ struct ipq_queue_entry { typedef int (*ipq_cmpfn)(struct ipq_queue_entry *, unsigned long); -static unsigned char copy_mode __read_mostly = IPQ_COPY_NONE; -static unsigned int queue_maxlen __read_mostly = IPQ_QMAX_DEFAULT; +static unsigned char copy_mode = IPQ_COPY_NONE; +static unsigned int queue_maxlen = IPQ_QMAX_DEFAULT; static DEFINE_RWLOCK(queue_lock); -static int peer_pid __read_mostly; -static unsigned int copy_range __read_mostly; +static int peer_pid; +static unsigned int copy_range; static unsigned int queue_total; static unsigned int queue_dropped = 0; static unsigned int queue_user_dropped = 0; -static struct sock *ipqnl __read_mostly; +static struct sock *ipqnl; static LIST_HEAD(queue_list); static DEFINE_MUTEX(ipqnl_mutex); @@ -206,9 +206,9 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp) break; case IPQ_COPY_PACKET: - if ((entry->skb->ip_summed == CHECKSUM_PARTIAL || - entry->skb->ip_summed == CHECKSUM_COMPLETE) && - (*errp = skb_checksum_help(entry->skb))) { + if (entry->skb->ip_summed == CHECKSUM_HW && + (*errp = skb_checksum_help(entry->skb, + entry->info->outdev == NULL))) { read_unlock_bh(&queue_lock); return NULL; } diff --git a/trunk/net/ipv6/netfilter/ip6_tables.c b/trunk/net/ipv6/netfilter/ip6_tables.c index 4ab368fa0b8f..f26898b00347 100644 --- a/trunk/net/ipv6/netfilter/ip6_tables.c +++ b/trunk/net/ipv6/netfilter/ip6_tables.c @@ -70,6 +70,9 @@ do { \ #define IP_NF_ASSERT(x) #endif + +#include + #if 0 /* All the better to debug you with... */ #define static @@ -217,7 +220,8 @@ ip6t_error(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { if (net_ratelimit()) printk("ip6_tables: error: `%s'\n", (char *)targinfo); @@ -254,7 +258,8 @@ ip6t_do_table(struct sk_buff **pskb, unsigned int hook, const struct net_device *in, const struct net_device *out, - struct xt_table *table) + struct xt_table *table, + void *userdata) { static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); int offset = 0; @@ -344,7 +349,8 @@ ip6t_do_table(struct sk_buff **pskb, in, out, hook, t->u.kernel.target, - t->data); + t->data, + userdata); #ifdef CONFIG_NETFILTER_DEBUG if (((struct ip6t_entry *)table_base)->comefrom @@ -501,7 +507,8 @@ cleanup_match(struct ip6t_entry_match *m, unsigned int *i) return 1; if (m->u.kernel.match->destroy) - m->u.kernel.match->destroy(m->u.kernel.match, m->data); + m->u.kernel.match->destroy(m->u.kernel.match, m->data, + m->u.match_size - sizeof(*m)); module_put(m->u.kernel.match->me); return 0; } @@ -554,6 +561,7 @@ check_match(struct ip6t_entry_match *m, if (m->u.kernel.match->checkentry && !m->u.kernel.match->checkentry(name, ipv6, match, m->data, + m->u.match_size - sizeof(*m), hookmask)) { duprintf("ip_tables: check failed for `%s'.\n", m->u.kernel.match->name); @@ -610,10 +618,12 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, if (t->u.kernel.target == &ip6t_standard_target) { if (!standard_check(t, size)) { ret = -EINVAL; - goto err; + goto cleanup_matches; } } else if (t->u.kernel.target->checkentry && !t->u.kernel.target->checkentry(name, e, target, t->data, + t->u.target_size + - sizeof(*t), e->comefrom)) { duprintf("ip_tables: check failed for `%s'.\n", t->u.kernel.target->name); @@ -685,7 +695,8 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i) IP6T_MATCH_ITERATE(e, cleanup_match, NULL); t = ip6t_get_target(e); if (t->u.kernel.target->destroy) - t->u.kernel.target->destroy(t->u.kernel.target, t->data); + t->u.kernel.target->destroy(t->u.kernel.target, t->data, + t->u.target_size - sizeof(*t)); module_put(t->u.kernel.target->me); return 0; } @@ -1341,6 +1352,7 @@ icmp6_checkentry(const char *tablename, const void *entry, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct ip6t_icmp *icmpinfo = matchinfo; @@ -1386,39 +1398,23 @@ static int __init ip6_tables_init(void) { int ret; - ret = xt_proto_init(AF_INET6); - if (ret < 0) - goto err1; + xt_proto_init(AF_INET6); /* Noone else will be downing sem now, so we won't sleep */ - ret = xt_register_target(&ip6t_standard_target); - if (ret < 0) - goto err2; - ret = xt_register_target(&ip6t_error_target); - if (ret < 0) - goto err3; - ret = xt_register_match(&icmp6_matchstruct); - if (ret < 0) - goto err4; + xt_register_target(&ip6t_standard_target); + xt_register_target(&ip6t_error_target); + xt_register_match(&icmp6_matchstruct); /* Register setsockopt */ ret = nf_register_sockopt(&ip6t_sockopts); - if (ret < 0) - goto err5; + if (ret < 0) { + duprintf("Unable to register sockopts.\n"); + xt_proto_fini(AF_INET6); + return ret; + } printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); return 0; - -err5: - xt_unregister_match(&icmp6_matchstruct); -err4: - xt_unregister_target(&ip6t_error_target); -err3: - xt_unregister_target(&ip6t_standard_target); -err2: - xt_proto_fini(AF_INET6); -err1: - return ret; } static void __exit ip6_tables_fini(void) diff --git a/trunk/net/ipv6/netfilter/ip6t_HL.c b/trunk/net/ipv6/netfilter/ip6t_HL.c index 435750f664dd..b8eff8ee69b1 100644 --- a/trunk/net/ipv6/netfilter/ip6t_HL.c +++ b/trunk/net/ipv6/netfilter/ip6t_HL.c @@ -22,10 +22,11 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, void *userinfo) { struct ipv6hdr *ip6h; const struct ip6t_HL_info *info = targinfo; + u_int16_t diffs[2]; int new_hl; if (!skb_make_writable(pskb, (*pskb)->len)) @@ -52,8 +53,11 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb, break; } - if (new_hl != ip6h->hop_limit) + if (new_hl != ip6h->hop_limit) { + diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF; ip6h->hop_limit = new_hl; + diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8); + } return IP6T_CONTINUE; } @@ -62,6 +66,7 @@ static int ip6t_hl_checkentry(const char *tablename, const void *entry, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { struct ip6t_HL_info *info = targinfo; diff --git a/trunk/net/ipv6/netfilter/ip6t_LOG.c b/trunk/net/ipv6/netfilter/ip6t_LOG.c index 0cf537d30185..73c6300109d6 100644 --- a/trunk/net/ipv6/netfilter/ip6t_LOG.c +++ b/trunk/net/ipv6/netfilter/ip6t_LOG.c @@ -427,7 +427,8 @@ ip6t_log_target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { const struct ip6t_log_info *loginfo = targinfo; struct nf_loginfo li; @@ -451,6 +452,7 @@ static int ip6t_log_checkentry(const char *tablename, const void *entry, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { const struct ip6t_log_info *loginfo = targinfo; diff --git a/trunk/net/ipv6/netfilter/ip6t_REJECT.c b/trunk/net/ipv6/netfilter/ip6t_REJECT.c index 311eae82feb3..8629ba195d2d 100644 --- a/trunk/net/ipv6/netfilter/ip6t_REJECT.c +++ b/trunk/net/ipv6/netfilter/ip6t_REJECT.c @@ -96,7 +96,6 @@ static void send_reset(struct sk_buff *oldskb) ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr); fl.fl_ip_sport = otcph.dest; fl.fl_ip_dport = otcph.source; - security_skb_classify_flow(oldskb, &fl); dst = ip6_route_output(NULL, &fl); if (dst == NULL) return; @@ -180,7 +179,8 @@ static unsigned int reject6_target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { const struct ip6t_reject_info *reject = targinfo; @@ -223,6 +223,7 @@ static int check(const char *tablename, const void *entry, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { const struct ip6t_reject_info *rejinfo = targinfo; @@ -255,7 +256,9 @@ static struct ip6t_target ip6t_reject_reg = { static int __init ip6t_reject_init(void) { - return ip6t_register_target(&ip6t_reject_reg); + if (ip6t_register_target(&ip6t_reject_reg)) + return -EINVAL; + return 0; } static void __exit ip6t_reject_fini(void) diff --git a/trunk/net/ipv6/netfilter/ip6t_ah.c b/trunk/net/ipv6/netfilter/ip6t_ah.c index ec1b1608156c..2f7bb20c758b 100644 --- a/trunk/net/ipv6/netfilter/ip6t_ah.c +++ b/trunk/net/ipv6/netfilter/ip6t_ah.c @@ -102,6 +102,7 @@ checkentry(const char *tablename, const void *entry, const struct xt_match *match, void *matchinfo, + unsigned int matchinfosize, unsigned int hook_mask) { const struct ip6t_ah *ahinfo = matchinfo; diff --git a/trunk/net/ipv6/netfilter/ip6t_dst.c b/trunk/net/ipv6/netfilter/ip6t_dst.c new file mode 100644 index 000000000000..9422413d0571 --- /dev/null +++ b/trunk/net/ipv6/netfilter/ip6t_dst.c @@ -0,0 +1,220 @@ +/* Kernel module to match Hop-by-Hop and Destination parameters. */ + +/* (C) 2001-2002 Andras Kis-Szabo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define HOPBYHOP 0 + +MODULE_LICENSE("GPL"); +#if HOPBYHOP +MODULE_DESCRIPTION("IPv6 HbH match"); +#else +MODULE_DESCRIPTION("IPv6 DST match"); +#endif +MODULE_AUTHOR("Andras Kis-Szabo "); + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +/* + * (Type & 0xC0) >> 6 + * 0 -> ignorable + * 1 -> must drop the packet + * 2 -> send ICMP PARM PROB regardless and drop packet + * 3 -> Send ICMP if not a multicast address and drop packet + * (Type & 0x20) >> 5 + * 0 -> invariant + * 1 -> can change the routing + * (Type & 0x1F) Type + * 0 -> Pad1 (only 1 byte!) + * 1 -> PadN LENGTH info (total length = length + 2) + * C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k ) + * 5 -> RTALERT 2 x x + */ + +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const struct xt_match *match, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + struct ipv6_opt_hdr _optsh, *oh; + const struct ip6t_opts *optinfo = matchinfo; + unsigned int temp; + unsigned int ptr; + unsigned int hdrlen = 0; + unsigned int ret = 0; + u8 _opttype, *tp = NULL; + u8 _optlen, *lp = NULL; + unsigned int optlen; + +#if HOPBYHOP + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP, NULL) < 0) +#else + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST, NULL) < 0) +#endif + return 0; + + oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); + if (oh == NULL) { + *hotdrop = 1; + return 0; + } + + hdrlen = ipv6_optlen(oh); + if (skb->len - ptr < hdrlen) { + /* Packet smaller than it's length field */ + return 0; + } + + DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); + + DEBUGP("len %02X %04X %02X ", + optinfo->hdrlen, hdrlen, + (!(optinfo->flags & IP6T_OPTS_LEN) || + ((optinfo->hdrlen == hdrlen) ^ + !!(optinfo->invflags & IP6T_OPTS_INV_LEN)))); + + ret = (oh != NULL) && + (!(optinfo->flags & IP6T_OPTS_LEN) || + ((optinfo->hdrlen == hdrlen) ^ + !!(optinfo->invflags & IP6T_OPTS_INV_LEN))); + + ptr += 2; + hdrlen -= 2; + if (!(optinfo->flags & IP6T_OPTS_OPTS)) { + return ret; + } else if (optinfo->flags & IP6T_OPTS_NSTRICT) { + DEBUGP("Not strict - not implemented"); + } else { + DEBUGP("Strict "); + DEBUGP("#%d ", optinfo->optsnr); + for (temp = 0; temp < optinfo->optsnr; temp++) { + /* type field exists ? */ + if (hdrlen < 1) + break; + tp = skb_header_pointer(skb, ptr, sizeof(_opttype), + &_opttype); + if (tp == NULL) + break; + + /* Type check */ + if (*tp != (optinfo->opts[temp] & 0xFF00) >> 8) { + DEBUGP("Tbad %02X %02X\n", + *tp, + (optinfo->opts[temp] & 0xFF00) >> 8); + return 0; + } else { + DEBUGP("Tok "); + } + /* Length check */ + if (*tp) { + u16 spec_len; + + /* length field exists ? */ + if (hdrlen < 2) + break; + lp = skb_header_pointer(skb, ptr + 1, + sizeof(_optlen), + &_optlen); + if (lp == NULL) + break; + spec_len = optinfo->opts[temp] & 0x00FF; + + if (spec_len != 0x00FF && spec_len != *lp) { + DEBUGP("Lbad %02X %04X\n", *lp, + spec_len); + return 0; + } + DEBUGP("Lok "); + optlen = *lp + 2; + } else { + DEBUGP("Pad1\n"); + optlen = 1; + } + + /* Step to the next */ + DEBUGP("len%04X \n", optlen); + + if ((ptr > skb->len - optlen || hdrlen < optlen) && + (temp < optinfo->optsnr - 1)) { + DEBUGP("new pointer is too large! \n"); + break; + } + ptr += optlen; + hdrlen -= optlen; + } + if (temp == optinfo->optsnr) + return ret; + else + return 0; + } + + return 0; +} + +/* Called when user tries to insert an entry of this type. */ +static int +checkentry(const char *tablename, + const void *info, + const struct xt_match *match, + void *matchinfo, + unsigned int matchinfosize, + unsigned int hook_mask) +{ + const struct ip6t_opts *optsinfo = matchinfo; + + if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) { + DEBUGP("ip6t_opts: unknown flags %X\n", optsinfo->invflags); + return 0; + } + return 1; +} + +static struct ip6t_match opts_match = { +#if HOPBYHOP + .name = "hbh", +#else + .name = "dst", +#endif + .match = match, + .matchsize = sizeof(struct ip6t_opts), + .checkentry = checkentry, + .me = THIS_MODULE, +}; + +static int __init ip6t_dst_init(void) +{ + return ip6t_register_match(&opts_match); +} + +static void __exit ip6t_dst_fini(void) +{ + ip6t_unregister_match(&opts_match); +} + +module_init(ip6t_dst_init); +module_exit(ip6t_dst_fini); diff --git a/trunk/net/ipv6/netfilter/ip6t_frag.c b/trunk/net/ipv6/netfilter/ip6t_frag.c index 78d9c8b9e28a..06768c84bd31 100644 --- a/trunk/net/ipv6/netfilter/ip6t_frag.c +++ b/trunk/net/ipv6/netfilter/ip6t_frag.c @@ -119,6 +119,7 @@ checkentry(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, + unsigned int matchinfosize, unsigned int hook_mask) { const struct ip6t_frag *fraginfo = matchinfo; diff --git a/trunk/net/ipv6/netfilter/ip6t_hbh.c b/trunk/net/ipv6/netfilter/ip6t_hbh.c index d32a205e3af2..374f1be85c0d 100644 --- a/trunk/net/ipv6/netfilter/ip6t_hbh.c +++ b/trunk/net/ipv6/netfilter/ip6t_hbh.c @@ -19,10 +19,15 @@ #include #include +#define HOPBYHOP 1 + MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("IPv6 opts match"); +#if HOPBYHOP +MODULE_DESCRIPTION("IPv6 HbH match"); +#else +MODULE_DESCRIPTION("IPv6 DST match"); +#endif MODULE_AUTHOR("Andras Kis-Szabo "); -MODULE_ALIAS("ip6t_dst"); #if 0 #define DEBUGP printk @@ -66,7 +71,11 @@ match(const struct sk_buff *skb, u8 _optlen, *lp = NULL; unsigned int optlen; - if (ipv6_find_hdr(skb, &ptr, match->data, NULL) < 0) +#if HOPBYHOP + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP, NULL) < 0) +#else + if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST, NULL) < 0) +#endif return 0; oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); @@ -173,6 +182,7 @@ checkentry(const char *tablename, const void *entry, const struct xt_match *match, void *matchinfo, + unsigned int matchinfosize, unsigned int hook_mask) { const struct ip6t_opts *optsinfo = matchinfo; @@ -184,35 +194,26 @@ checkentry(const char *tablename, return 1; } -static struct xt_match opts_match[] = { - { - .name = "hbh", - .family = AF_INET6, - .match = match, - .matchsize = sizeof(struct ip6t_opts), - .checkentry = checkentry, - .me = THIS_MODULE, - .data = NEXTHDR_HOP, - }, - { - .name = "dst", - .family = AF_INET6, - .match = match, - .matchsize = sizeof(struct ip6t_opts), - .checkentry = checkentry, - .me = THIS_MODULE, - .data = NEXTHDR_DEST, - }, +static struct ip6t_match opts_match = { +#if HOPBYHOP + .name = "hbh", +#else + .name = "dst", +#endif + .match = match, + .matchsize = sizeof(struct ip6t_opts), + .checkentry = checkentry, + .me = THIS_MODULE, }; static int __init ip6t_hbh_init(void) { - return xt_register_matches(opts_match, ARRAY_SIZE(opts_match)); + return ip6t_register_match(&opts_match); } static void __exit ip6t_hbh_fini(void) { - xt_unregister_matches(opts_match, ARRAY_SIZE(opts_match)); + ip6t_unregister_match(&opts_match); } module_init(ip6t_hbh_init); diff --git a/trunk/net/ipv6/netfilter/ip6t_ipv6header.c b/trunk/net/ipv6/netfilter/ip6t_ipv6header.c index 3093c398002f..9375eeb1369f 100644 --- a/trunk/net/ipv6/netfilter/ip6t_ipv6header.c +++ b/trunk/net/ipv6/netfilter/ip6t_ipv6header.c @@ -128,6 +128,7 @@ ipv6header_checkentry(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct ip6t_ipv6header_info *info = matchinfo; diff --git a/trunk/net/ipv6/netfilter/ip6t_owner.c b/trunk/net/ipv6/netfilter/ip6t_owner.c index 4eb9bbc4ebc3..5d047990cd44 100644 --- a/trunk/net/ipv6/netfilter/ip6t_owner.c +++ b/trunk/net/ipv6/netfilter/ip6t_owner.c @@ -57,6 +57,7 @@ checkentry(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct ip6t_owner_info *info = matchinfo; diff --git a/trunk/net/ipv6/netfilter/ip6t_rt.c b/trunk/net/ipv6/netfilter/ip6t_rt.c index bcb2e168a5bc..fbb0184a41d8 100644 --- a/trunk/net/ipv6/netfilter/ip6t_rt.c +++ b/trunk/net/ipv6/netfilter/ip6t_rt.c @@ -197,6 +197,7 @@ checkentry(const char *tablename, const void *entry, const struct xt_match *match, void *matchinfo, + unsigned int matchinfosize, unsigned int hook_mask) { const struct ip6t_rt *rtinfo = matchinfo; diff --git a/trunk/net/ipv6/netfilter/ip6table_filter.c b/trunk/net/ipv6/netfilter/ip6table_filter.c index 2fc07c74decf..60976c0c58e8 100644 --- a/trunk/net/ipv6/netfilter/ip6table_filter.c +++ b/trunk/net/ipv6/netfilter/ip6table_filter.c @@ -108,7 +108,7 @@ ip6t_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return ip6t_do_table(pskb, hook, in, out, &packet_filter); + return ip6t_do_table(pskb, hook, in, out, &packet_filter, NULL); } static unsigned int @@ -128,7 +128,7 @@ ip6t_local_out_hook(unsigned int hook, } #endif - return ip6t_do_table(pskb, hook, in, out, &packet_filter); + return ip6t_do_table(pskb, hook, in, out, &packet_filter, NULL); } static struct nf_hook_ops ip6t_ops[] = { diff --git a/trunk/net/ipv6/netfilter/ip6table_mangle.c b/trunk/net/ipv6/netfilter/ip6table_mangle.c index 386ea260e767..03a13eab1dae 100644 --- a/trunk/net/ipv6/netfilter/ip6table_mangle.c +++ b/trunk/net/ipv6/netfilter/ip6table_mangle.c @@ -138,7 +138,7 @@ ip6t_route_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return ip6t_do_table(pskb, hook, in, out, &packet_mangler); + return ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL); } static unsigned int @@ -174,14 +174,18 @@ ip6t_local_hook(unsigned int hook, /* flowlabel and prio (includes version, which shouldn't change either */ flowlabel = *((u_int32_t *) (*pskb)->nh.ipv6h); - ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler); + ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL); if (ret != NF_DROP && ret != NF_STOLEN && (memcmp(&(*pskb)->nh.ipv6h->saddr, &saddr, sizeof(saddr)) || memcmp(&(*pskb)->nh.ipv6h->daddr, &daddr, sizeof(daddr)) || (*pskb)->nfmark != nfmark - || (*pskb)->nh.ipv6h->hop_limit != hop_limit)) - return ip6_route_me_harder(*pskb) == 0 ? ret : NF_DROP; + || (*pskb)->nh.ipv6h->hop_limit != hop_limit)) { + + /* something which could affect routing has changed */ + + DEBUGP("ip6table_mangle: we'd need to re-route a packet\n"); + } return ret; } diff --git a/trunk/net/ipv6/netfilter/ip6table_raw.c b/trunk/net/ipv6/netfilter/ip6table_raw.c index b4154da575c0..61a7c58e99f8 100644 --- a/trunk/net/ipv6/netfilter/ip6table_raw.c +++ b/trunk/net/ipv6/netfilter/ip6table_raw.c @@ -122,7 +122,7 @@ ip6t_hook(unsigned int hook, const struct net_device *out, int (*okfn)(struct sk_buff *)) { - return ip6t_do_table(pskb, hook, in, out, &packet_raw); + return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL); } static struct nf_hook_ops ip6t_ops[] = { diff --git a/trunk/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/trunk/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index e5e53fff9e38..c2ab38ff46af 100644 --- a/trunk/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/trunk/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c @@ -335,7 +335,7 @@ static struct nf_hook_ops ipv6_conntrack_ops[] = { /* From nf_conntrack_proto_icmpv6.c */ extern unsigned int nf_ct_icmpv6_timeout; -/* From nf_conntrack_reasm.c */ +/* From nf_conntrack_frag6.c */ extern unsigned int nf_ct_frag6_timeout; extern unsigned int nf_ct_frag6_low_thresh; extern unsigned int nf_ct_frag6_high_thresh; diff --git a/trunk/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/trunk/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index 34d447208ffd..ef18a7b7014b 100644 --- a/trunk/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/trunk/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -33,7 +33,7 @@ #include #include -unsigned long nf_ct_icmpv6_timeout __read_mostly = 30*HZ; +unsigned long nf_ct_icmpv6_timeout = 30*HZ; #if 0 #define DEBUGP printk diff --git a/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c b/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c index bf93c1ea6be9..00d5583807f7 100644 --- a/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/trunk/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -54,9 +54,9 @@ #define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */ #define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT -unsigned int nf_ct_frag6_high_thresh __read_mostly = 256*1024; -unsigned int nf_ct_frag6_low_thresh __read_mostly = 192*1024; -unsigned long nf_ct_frag6_timeout __read_mostly = IPV6_FRAG_TIMEOUT; +unsigned int nf_ct_frag6_high_thresh = 256*1024; +unsigned int nf_ct_frag6_low_thresh = 192*1024; +unsigned long nf_ct_frag6_timeout = IPV6_FRAG_TIMEOUT; struct nf_ct_frag6_skb_cb { @@ -408,7 +408,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, return -1; } - if (skb->ip_summed == CHECKSUM_COMPLETE) + if (skb->ip_summed == CHECKSUM_HW) skb->csum = csum_sub(skb->csum, csum_partial(skb->nh.raw, (u8*)(fhdr + 1) - skb->nh.raw, @@ -640,7 +640,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) head->len += fp->len; if (head->ip_summed != fp->ip_summed) head->ip_summed = CHECKSUM_NONE; - else if (head->ip_summed == CHECKSUM_COMPLETE) + else if (head->ip_summed == CHECKSUM_HW) head->csum = csum_add(head->csum, fp->csum); head->truesize += fp->truesize; atomic_sub(fp->truesize, &nf_ct_frag6_mem); @@ -652,7 +652,7 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) head->nh.ipv6h->payload_len = htons(payload_len); /* Yes, and fold redundant checksum back. 8) */ - if (head->ip_summed == CHECKSUM_COMPLETE) + if (head->ip_summed == CHECKSUM_HW) head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); fq->fragments = NULL; diff --git a/trunk/net/ipv6/raw.c b/trunk/net/ipv6/raw.c index d09329ca3267..d57e61ce4a7d 100644 --- a/trunk/net/ipv6/raw.c +++ b/trunk/net/ipv6/raw.c @@ -50,9 +50,6 @@ #include #include #include -#ifdef CONFIG_IPV6_MIP6 -#include -#endif #include #include @@ -172,32 +169,8 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, IP6CB(skb)->iif); while (sk) { - int filtered; - delivered = 1; - switch (nexthdr) { - case IPPROTO_ICMPV6: - filtered = icmpv6_filter(sk, skb); - break; -#ifdef CONFIG_IPV6_MIP6 - case IPPROTO_MH: - /* XXX: To validate MH only once for each packet, - * this is placed here. It should be after checking - * xfrm policy, however it doesn't. The checking xfrm - * policy is placed in rawv6_rcv() because it is - * required for each socket. - */ - filtered = mip6_mh_filter(sk, skb); - break; -#endif - default: - filtered = 0; - break; - } - - if (filtered < 0) - break; - if (filtered == 0) { + if (nexthdr != IPPROTO_ICMPV6 || !icmpv6_filter(sk, skb)) { struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); /* Not releasing hash table! */ @@ -361,7 +334,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb) if (!rp->checksum) skb->ip_summed = CHECKSUM_UNNECESSARY; - if (skb->ip_summed == CHECKSUM_COMPLETE) { + if (skb->ip_summed == CHECKSUM_HW) { skb_postpull_rcsum(skb, skb->nh.raw, skb->h.raw - skb->nh.raw); if (!csum_ipv6_magic(&skb->nh.ipv6h->saddr, @@ -609,9 +582,6 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) struct iovec *iov; u8 __user *type = NULL; u8 __user *code = NULL; -#ifdef CONFIG_IPV6_MIP6 - u8 len = 0; -#endif int probed = 0; int i; @@ -643,20 +613,6 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) probed = 1; } break; -#ifdef CONFIG_IPV6_MIP6 - case IPPROTO_MH: - if (iov->iov_base && iov->iov_len < 1) - break; - /* check if type field is readable or not. */ - if (iov->iov_len > 2 - len) { - u8 __user *p = iov->iov_base; - get_user(fl->fl_mh_type, &p[2 - len]); - probed = 1; - } else - len += iov->iov_len; - - break; -#endif default: probed = 1; break; @@ -803,7 +759,6 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) fl.oif = np->mcast_oif; - security_sk_classify_flow(sk, &fl); err = ip6_dst_lookup(sk, &dst, &fl); if (err) @@ -826,7 +781,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, } if (tclass < 0) { - tclass = np->tclass; + tclass = np->cork.tclass; if (tclass < 0) tclass = 0; } diff --git a/trunk/net/ipv6/reassembly.c b/trunk/net/ipv6/reassembly.c index f39bbedd1327..4e299c69e1c6 100644 --- a/trunk/net/ipv6/reassembly.c +++ b/trunk/net/ipv6/reassembly.c @@ -53,10 +53,10 @@ #include #include -int sysctl_ip6frag_high_thresh __read_mostly = 256*1024; -int sysctl_ip6frag_low_thresh __read_mostly = 192*1024; +int sysctl_ip6frag_high_thresh = 256*1024; +int sysctl_ip6frag_low_thresh = 192*1024; -int sysctl_ip6frag_time __read_mostly = IPV6_FRAG_TIMEOUT; +int sysctl_ip6frag_time = IPV6_FRAG_TIMEOUT; struct ip6frag_skb_cb { @@ -152,7 +152,7 @@ static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr, } static struct timer_list ip6_frag_secret_timer; -int sysctl_ip6frag_secret_interval __read_mostly = 10 * 60 * HZ; +int sysctl_ip6frag_secret_interval = 10 * 60 * HZ; static void ip6_frag_secret_rebuild(unsigned long dummy) { @@ -433,7 +433,7 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, return; } - if (skb->ip_summed == CHECKSUM_COMPLETE) + if (skb->ip_summed == CHECKSUM_HW) skb->csum = csum_sub(skb->csum, csum_partial(skb->nh.raw, (u8*)(fhdr+1)-skb->nh.raw, 0)); @@ -647,7 +647,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, head->len += fp->len; if (head->ip_summed != fp->ip_summed) head->ip_summed = CHECKSUM_NONE; - else if (head->ip_summed == CHECKSUM_COMPLETE) + else if (head->ip_summed == CHECKSUM_HW) head->csum = csum_add(head->csum, fp->csum); head->truesize += fp->truesize; atomic_sub(fp->truesize, &ip6_frag_mem); @@ -662,7 +662,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, *skb_in = head; /* Yes, and fold redundant checksum back. 8) */ - if (head->ip_summed == CHECKSUM_COMPLETE) + if (head->ip_summed == CHECKSUM_HW) head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); IP6_INC_STATS_BH(IPSTATS_MIB_REASMOKS); diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index d6b4b4f48d18..87c39c978cd0 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -22,8 +22,6 @@ * routers in REACHABLE, STALE, DELAY or PROBE states). * - always select the same router if it is (probably) * reachable. otherwise, round-robin the list. - * Ville Nuorvala - * Fixed routing subtrees. */ #include @@ -37,6 +35,7 @@ #include #include #include +#include #include #ifdef CONFIG_PROC_FS @@ -54,8 +53,6 @@ #include #include #include -#include -#include #include @@ -76,6 +73,9 @@ #define CLONE_OFFLINK_ROUTE 0 +#define RT6_SELECT_F_IFACE 0x1 +#define RT6_SELECT_F_REACHABLE 0x2 + static int ip6_rt_max_size = 4096; static int ip6_rt_gc_min_interval = HZ / 2; static int ip6_rt_gc_timeout = 60*HZ; @@ -139,49 +139,15 @@ struct rt6_info ip6_null_entry = { .rt6i_ref = ATOMIC_INIT(1), }; -#ifdef CONFIG_IPV6_MULTIPLE_TABLES - -struct rt6_info ip6_prohibit_entry = { - .u = { - .dst = { - .__refcnt = ATOMIC_INIT(1), - .__use = 1, - .dev = &loopback_dev, - .obsolete = -1, - .error = -EACCES, - .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, - .input = ip6_pkt_discard, - .output = ip6_pkt_discard_out, - .ops = &ip6_dst_ops, - .path = (struct dst_entry*)&ip6_prohibit_entry, - } - }, - .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), - .rt6i_metric = ~(u32) 0, - .rt6i_ref = ATOMIC_INIT(1), +struct fib6_node ip6_routing_table = { + .leaf = &ip6_null_entry, + .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, }; -struct rt6_info ip6_blk_hole_entry = { - .u = { - .dst = { - .__refcnt = ATOMIC_INIT(1), - .__use = 1, - .dev = &loopback_dev, - .obsolete = -1, - .error = -EINVAL, - .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, - .input = ip6_pkt_discard, - .output = ip6_pkt_discard_out, - .ops = &ip6_dst_ops, - .path = (struct dst_entry*)&ip6_blk_hole_entry, - } - }, - .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), - .rt6i_metric = ~(u32) 0, - .rt6i_ref = ATOMIC_INIT(1), -}; +/* Protects all the ip6 fib */ + +DEFINE_RWLOCK(rt6_lock); -#endif /* allocate dst with ip6_dst_ops */ static __inline__ struct rt6_info *ip6_dst_alloc(void) @@ -221,14 +187,8 @@ static __inline__ int rt6_check_expired(const struct rt6_info *rt) time_after(jiffies, rt->rt6i_expires)); } -static inline int rt6_need_strict(struct in6_addr *daddr) -{ - return (ipv6_addr_type(daddr) & - (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL)); -} - /* - * Route lookup. Any table->tb6_lock is implied. + * Route lookup. Any rt6_lock is implied. */ static __inline__ struct rt6_info *rt6_device_match(struct rt6_info *rt, @@ -337,7 +297,7 @@ static int rt6_score_route(struct rt6_info *rt, int oif, int m, n; m = rt6_check_dev(rt, oif); - if (!m && (strict & RT6_LOOKUP_F_IFACE)) + if (!m && (strict & RT6_SELECT_F_IFACE)) return -1; #ifdef CONFIG_IPV6_ROUTER_PREF m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2; @@ -345,7 +305,7 @@ static int rt6_score_route(struct rt6_info *rt, int oif, n = rt6_check_neigh(rt); if (n > 1) m |= 16; - else if (!n && strict & RT6_LOOKUP_F_REACHABLE) + else if (!n && strict & RT6_SELECT_F_REACHABLE) return -1; return m; } @@ -385,7 +345,7 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif, } if (!match && - (strict & RT6_LOOKUP_F_REACHABLE) && + (strict & RT6_SELECT_F_REACHABLE) && last && last != rt0) { /* no entries matched; do round-robin */ static DEFINE_SPINLOCK(lock); @@ -456,7 +416,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, rt = rt6_get_route_info(prefix, rinfo->prefix_len, gwaddr, dev->ifindex); if (rt && !lifetime) { - ip6_del_rt(rt); + ip6_del_rt(rt, NULL, NULL, NULL); rt = NULL; } @@ -480,95 +440,44 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, } #endif -#define BACKTRACK(saddr) \ -do { \ - if (rt == &ip6_null_entry) { \ - struct fib6_node *pn; \ - while (fn) { \ - if (fn->fn_flags & RTN_TL_ROOT) \ - goto out; \ - pn = fn->parent; \ - if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn) \ - fn = fib6_lookup(pn->subtree, NULL, saddr); \ - else \ - fn = pn; \ - if (fn->fn_flags & RTN_RTINFO) \ - goto restart; \ - } \ - } \ -} while(0) - -static struct rt6_info *ip6_pol_route_lookup(struct fib6_table *table, - struct flowi *fl, int flags) +struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, + int oif, int strict) { struct fib6_node *fn; struct rt6_info *rt; - read_lock_bh(&table->tb6_lock); - fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); -restart: - rt = fn->leaf; - rt = rt6_device_match(rt, fl->oif, flags); - BACKTRACK(&fl->fl6_src); -out: + read_lock_bh(&rt6_lock); + fn = fib6_lookup(&ip6_routing_table, daddr, saddr); + rt = rt6_device_match(fn->leaf, oif, strict); dst_hold(&rt->u.dst); - read_unlock_bh(&table->tb6_lock); - - rt->u.dst.lastuse = jiffies; rt->u.dst.__use++; + read_unlock_bh(&rt6_lock); - return rt; - -} - -struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, - int oif, int strict) -{ - struct flowi fl = { - .oif = oif, - .nl_u = { - .ip6_u = { - .daddr = *daddr, - /* TODO: saddr */ - }, - }, - }; - struct dst_entry *dst; - int flags = strict ? RT6_LOOKUP_F_IFACE : 0; - - dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_lookup); - if (dst->error == 0) - return (struct rt6_info *) dst; - - dst_release(dst); - + rt->u.dst.lastuse = jiffies; + if (rt->u.dst.error == 0) + return rt; + dst_release(&rt->u.dst); return NULL; } -/* ip6_ins_rt is called with FREE table->tb6_lock. +/* ip6_ins_rt is called with FREE rt6_lock. It takes new route entry, the addition fails by any reason the route is freed. In any case, if caller does not hold it, it may be destroyed. */ -static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info) +int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, + void *_rtattr, struct netlink_skb_parms *req) { int err; - struct fib6_table *table; - table = rt->rt6i_table; - write_lock_bh(&table->tb6_lock); - err = fib6_add(&table->tb6_root, rt, info); - write_unlock_bh(&table->tb6_lock); + write_lock_bh(&rt6_lock); + err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr, req); + write_unlock_bh(&rt6_lock); return err; } -int ip6_ins_rt(struct rt6_info *rt) -{ - return __ip6_ins_rt(rt, NULL); -} - static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *daddr, struct in6_addr *saddr) { @@ -622,39 +531,51 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d return rt; } -static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, - struct flowi *fl, int flags) +#define BACKTRACK() \ +if (rt == &ip6_null_entry) { \ + while ((fn = fn->parent) != NULL) { \ + if (fn->fn_flags & RTN_ROOT) { \ + goto out; \ + } \ + if (fn->fn_flags & RTN_RTINFO) \ + goto restart; \ + } \ +} + + +void ip6_route_input(struct sk_buff *skb) { struct fib6_node *fn; struct rt6_info *rt, *nrt; - int strict = 0; + int strict; int attempts = 3; int err; - int reachable = RT6_LOOKUP_F_REACHABLE; + int reachable = RT6_SELECT_F_REACHABLE; - strict |= flags & RT6_LOOKUP_F_IFACE; + strict = ipv6_addr_type(&skb->nh.ipv6h->daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0; relookup: - read_lock_bh(&table->tb6_lock); + read_lock_bh(&rt6_lock); restart_2: - fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); + fn = fib6_lookup(&ip6_routing_table, &skb->nh.ipv6h->daddr, + &skb->nh.ipv6h->saddr); restart: - rt = rt6_select(&fn->leaf, fl->iif, strict | reachable); - BACKTRACK(&fl->fl6_src); + rt = rt6_select(&fn->leaf, skb->dev->ifindex, strict | reachable); + BACKTRACK(); if (rt == &ip6_null_entry || rt->rt6i_flags & RTF_CACHE) goto out; dst_hold(&rt->u.dst); - read_unlock_bh(&table->tb6_lock); + read_unlock_bh(&rt6_lock); if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) - nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); + nrt = rt6_alloc_cow(rt, &skb->nh.ipv6h->daddr, &skb->nh.ipv6h->saddr); else { #if CLONE_OFFLINK_ROUTE - nrt = rt6_alloc_clone(rt, &fl->fl6_dst); + nrt = rt6_alloc_clone(rt, &skb->nh.ipv6h->daddr); #else goto out2; #endif @@ -665,7 +586,7 @@ static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, dst_hold(&rt->u.dst); if (nrt) { - err = ip6_ins_rt(nrt); + err = ip6_ins_rt(nrt, NULL, NULL, &NETLINK_CB(skb)); if (!err) goto out2; } @@ -674,7 +595,7 @@ static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, goto out2; /* - * Race condition! In the gap, when table->tb6_lock was + * Race condition! In the gap, when rt6_lock was * released someone could insert this route. Relookup. */ dst_release(&rt->u.dst); @@ -686,63 +607,40 @@ static struct rt6_info *ip6_pol_route_input(struct fib6_table *table, goto restart_2; } dst_hold(&rt->u.dst); - read_unlock_bh(&table->tb6_lock); + read_unlock_bh(&rt6_lock); out2: rt->u.dst.lastuse = jiffies; rt->u.dst.__use++; - - return rt; -} - -void ip6_route_input(struct sk_buff *skb) -{ - struct ipv6hdr *iph = skb->nh.ipv6h; - struct flowi fl = { - .iif = skb->dev->ifindex, - .nl_u = { - .ip6_u = { - .daddr = iph->daddr, - .saddr = iph->saddr, -#ifdef CONFIG_IPV6_ROUTE_FWMARK - .fwmark = skb->nfmark, -#endif - .flowlabel = (* (u32 *) iph)&IPV6_FLOWINFO_MASK, - }, - }, - .proto = iph->nexthdr, - }; - int flags = rt6_need_strict(&iph->daddr) ? RT6_LOOKUP_F_IFACE : 0; - - skb->dst = fib6_rule_lookup(&fl, flags, ip6_pol_route_input); + skb->dst = (struct dst_entry *) rt; + return; } -static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, - struct flowi *fl, int flags) +struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) { struct fib6_node *fn; struct rt6_info *rt, *nrt; - int strict = 0; + int strict; int attempts = 3; int err; - int reachable = RT6_LOOKUP_F_REACHABLE; + int reachable = RT6_SELECT_F_REACHABLE; - strict |= flags & RT6_LOOKUP_F_IFACE; + strict = ipv6_addr_type(&fl->fl6_dst) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL) ? RT6_SELECT_F_IFACE : 0; relookup: - read_lock_bh(&table->tb6_lock); + read_lock_bh(&rt6_lock); restart_2: - fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); + fn = fib6_lookup(&ip6_routing_table, &fl->fl6_dst, &fl->fl6_src); restart: rt = rt6_select(&fn->leaf, fl->oif, strict | reachable); - BACKTRACK(&fl->fl6_src); + BACKTRACK(); if (rt == &ip6_null_entry || rt->rt6i_flags & RTF_CACHE) goto out; dst_hold(&rt->u.dst); - read_unlock_bh(&table->tb6_lock); + read_unlock_bh(&rt6_lock); if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src); @@ -759,7 +657,7 @@ static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, dst_hold(&rt->u.dst); if (nrt) { - err = ip6_ins_rt(nrt); + err = ip6_ins_rt(nrt, NULL, NULL, NULL); if (!err) goto out2; } @@ -768,7 +666,7 @@ static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, goto out2; /* - * Race condition! In the gap, when table->tb6_lock was + * Race condition! In the gap, when rt6_lock was * released someone could insert this route. Relookup. */ dst_release(&rt->u.dst); @@ -780,21 +678,11 @@ static struct rt6_info *ip6_pol_route_output(struct fib6_table *table, goto restart_2; } dst_hold(&rt->u.dst); - read_unlock_bh(&table->tb6_lock); + read_unlock_bh(&rt6_lock); out2: rt->u.dst.lastuse = jiffies; rt->u.dst.__use++; - return rt; -} - -struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) -{ - int flags = 0; - - if (rt6_need_strict(&fl->fl6_dst)) - flags |= RT6_LOOKUP_F_IFACE; - - return fib6_rule_lookup(fl, flags, ip6_pol_route_output); + return &rt->u.dst; } @@ -820,7 +708,7 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) if (rt) { if (rt->rt6i_flags & RTF_CACHE) - ip6_del_rt(rt); + ip6_del_rt(rt, NULL, NULL, NULL); else dst_release(dst); } @@ -854,10 +742,11 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) dst->metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; } dst->metrics[RTAX_MTU-1] = mtu; - call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); } } +/* Protected by rt6_lock. */ +static struct dst_entry *ndisc_dst_gc_list; static int ipv6_get_mtu(struct net_device *dev); static inline unsigned int ipv6_advmss(unsigned int mtu) @@ -878,9 +767,6 @@ static inline unsigned int ipv6_advmss(unsigned int mtu) return mtu; } -static struct dst_entry *ndisc_dst_gc_list; -static DEFINE_SPINLOCK(ndisc_lock); - struct dst_entry *ndisc_dst_alloc(struct net_device *dev, struct neighbour *neigh, struct in6_addr *addr, @@ -921,10 +807,10 @@ struct dst_entry *ndisc_dst_alloc(struct net_device *dev, rt->rt6i_dst.plen = 128; #endif - spin_lock_bh(&ndisc_lock); + write_lock_bh(&rt6_lock); rt->u.dst.next = ndisc_dst_gc_list; ndisc_dst_gc_list = &rt->u.dst; - spin_unlock_bh(&ndisc_lock); + write_unlock_bh(&rt6_lock); fib6_force_start_gc(); @@ -938,11 +824,8 @@ int ndisc_dst_gc(int *more) int freed; next = NULL; - freed = 0; - - spin_lock_bh(&ndisc_lock); pprev = &ndisc_dst_gc_list; - + freed = 0; while ((dst = *pprev) != NULL) { if (!atomic_read(&dst->__refcnt)) { *pprev = dst->next; @@ -954,8 +837,6 @@ int ndisc_dst_gc(int *more) } } - spin_unlock_bh(&ndisc_lock); - return freed; } @@ -1016,24 +897,28 @@ int ipv6_get_hoplimit(struct net_device *dev) * */ -int ip6_route_add(struct fib6_config *cfg) +int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, + void *_rtattr, struct netlink_skb_parms *req) { int err; + struct rtmsg *r; + struct rtattr **rta; struct rt6_info *rt = NULL; struct net_device *dev = NULL; struct inet6_dev *idev = NULL; - struct fib6_table *table; int addr_type; - if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128) + rta = (struct rtattr **) _rtattr; + + if (rtmsg->rtmsg_dst_len > 128 || rtmsg->rtmsg_src_len > 128) return -EINVAL; #ifndef CONFIG_IPV6_SUBTREES - if (cfg->fc_src_len) + if (rtmsg->rtmsg_src_len) return -EINVAL; #endif - if (cfg->fc_ifindex) { + if (rtmsg->rtmsg_ifindex) { err = -ENODEV; - dev = dev_get_by_index(cfg->fc_ifindex); + dev = dev_get_by_index(rtmsg->rtmsg_ifindex); if (!dev) goto out; idev = in6_dev_get(dev); @@ -1041,14 +926,8 @@ int ip6_route_add(struct fib6_config *cfg) goto out; } - if (cfg->fc_metric == 0) - cfg->fc_metric = IP6_RT_PRIO_USER; - - table = fib6_new_table(cfg->fc_table); - if (table == NULL) { - err = -ENOBUFS; - goto out; - } + if (rtmsg->rtmsg_metric == 0) + rtmsg->rtmsg_metric = IP6_RT_PRIO_USER; rt = ip6_dst_alloc(); @@ -1058,13 +937,14 @@ int ip6_route_add(struct fib6_config *cfg) } rt->u.dst.obsolete = -1; - rt->rt6i_expires = jiffies + clock_t_to_jiffies(cfg->fc_expires); - - if (cfg->fc_protocol == RTPROT_UNSPEC) - cfg->fc_protocol = RTPROT_BOOT; - rt->rt6i_protocol = cfg->fc_protocol; + rt->rt6i_expires = jiffies + clock_t_to_jiffies(rtmsg->rtmsg_info); + if (nlh && (r = NLMSG_DATA(nlh))) { + rt->rt6i_protocol = r->rtm_protocol; + } else { + rt->rt6i_protocol = RTPROT_BOOT; + } - addr_type = ipv6_addr_type(&cfg->fc_dst); + addr_type = ipv6_addr_type(&rtmsg->rtmsg_dst); if (addr_type & IPV6_ADDR_MULTICAST) rt->u.dst.input = ip6_mc_input; @@ -1073,22 +953,24 @@ int ip6_route_add(struct fib6_config *cfg) rt->u.dst.output = ip6_output; - ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); - rt->rt6i_dst.plen = cfg->fc_dst_len; + ipv6_addr_prefix(&rt->rt6i_dst.addr, + &rtmsg->rtmsg_dst, rtmsg->rtmsg_dst_len); + rt->rt6i_dst.plen = rtmsg->rtmsg_dst_len; if (rt->rt6i_dst.plen == 128) rt->u.dst.flags = DST_HOST; #ifdef CONFIG_IPV6_SUBTREES - ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); - rt->rt6i_src.plen = cfg->fc_src_len; + ipv6_addr_prefix(&rt->rt6i_src.addr, + &rtmsg->rtmsg_src, rtmsg->rtmsg_src_len); + rt->rt6i_src.plen = rtmsg->rtmsg_src_len; #endif - rt->rt6i_metric = cfg->fc_metric; + rt->rt6i_metric = rtmsg->rtmsg_metric; /* We cannot add true routes via loopback here, they would result in kernel looping; promote them to reject routes */ - if ((cfg->fc_flags & RTF_REJECT) || + if ((rtmsg->rtmsg_flags&RTF_REJECT) || (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) { /* hold loopback dev/idev if we haven't done so. */ if (dev != &loopback_dev) { @@ -1111,12 +993,12 @@ int ip6_route_add(struct fib6_config *cfg) goto install_route; } - if (cfg->fc_flags & RTF_GATEWAY) { + if (rtmsg->rtmsg_flags & RTF_GATEWAY) { struct in6_addr *gw_addr; int gwa_type; - gw_addr = &cfg->fc_gateway; - ipv6_addr_copy(&rt->rt6i_gateway, gw_addr); + gw_addr = &rtmsg->rtmsg_gateway; + ipv6_addr_copy(&rt->rt6i_gateway, &rtmsg->rtmsg_gateway); gwa_type = ipv6_addr_type(gw_addr); if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) { @@ -1133,7 +1015,7 @@ int ip6_route_add(struct fib6_config *cfg) if (!(gwa_type&IPV6_ADDR_UNICAST)) goto out; - grt = rt6_lookup(gw_addr, NULL, cfg->fc_ifindex, 1); + grt = rt6_lookup(gw_addr, NULL, rtmsg->rtmsg_ifindex, 1); err = -EHOSTUNREACH; if (grt == NULL) @@ -1165,7 +1047,7 @@ int ip6_route_add(struct fib6_config *cfg) if (dev == NULL) goto out; - if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { + if (rtmsg->rtmsg_flags & (RTF_GATEWAY|RTF_NONEXTHOP)) { rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev); if (IS_ERR(rt->rt6i_nexthop)) { err = PTR_ERR(rt->rt6i_nexthop); @@ -1174,24 +1056,24 @@ int ip6_route_add(struct fib6_config *cfg) } } - rt->rt6i_flags = cfg->fc_flags; + rt->rt6i_flags = rtmsg->rtmsg_flags; install_route: - if (cfg->fc_mx) { - struct nlattr *nla; - int remaining; - - nla_for_each_attr(nla, cfg->fc_mx, cfg->fc_mx_len, remaining) { - int type = nla->nla_type; - - if (type) { - if (type > RTAX_MAX) { + if (rta && rta[RTA_METRICS-1]) { + int attrlen = RTA_PAYLOAD(rta[RTA_METRICS-1]); + struct rtattr *attr = RTA_DATA(rta[RTA_METRICS-1]); + + while (RTA_OK(attr, attrlen)) { + unsigned flavor = attr->rta_type; + if (flavor) { + if (flavor > RTAX_MAX) { err = -EINVAL; goto out; } - - rt->u.dst.metrics[type - 1] = nla_get_u32(nla); + rt->u.dst.metrics[flavor-1] = + *(u32 *)RTA_DATA(attr); } + attr = RTA_NEXT(attr, attrlen); } } @@ -1203,8 +1085,7 @@ int ip6_route_add(struct fib6_config *cfg) rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst)); rt->u.dst.dev = dev; rt->rt6i_idev = idev; - rt->rt6i_table = table; - return __ip6_ins_rt(rt, &cfg->fc_nlinfo); + return ip6_ins_rt(rt, nlh, _rtattr, req); out: if (dev) @@ -1216,65 +1097,51 @@ int ip6_route_add(struct fib6_config *cfg) return err; } -static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) +int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) { int err; - struct fib6_table *table; - if (rt == &ip6_null_entry) - return -ENOENT; + write_lock_bh(&rt6_lock); - table = rt->rt6i_table; - write_lock_bh(&table->tb6_lock); - - err = fib6_del(rt, info); + err = fib6_del(rt, nlh, _rtattr, req); dst_release(&rt->u.dst); - write_unlock_bh(&table->tb6_lock); + write_unlock_bh(&rt6_lock); return err; } -int ip6_del_rt(struct rt6_info *rt) +static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) { - return __ip6_del_rt(rt, NULL); -} - -static int ip6_route_del(struct fib6_config *cfg) -{ - struct fib6_table *table; struct fib6_node *fn; struct rt6_info *rt; int err = -ESRCH; - table = fib6_get_table(cfg->fc_table); - if (table == NULL) - return err; + read_lock_bh(&rt6_lock); - read_lock_bh(&table->tb6_lock); - - fn = fib6_locate(&table->tb6_root, - &cfg->fc_dst, cfg->fc_dst_len, - &cfg->fc_src, cfg->fc_src_len); + fn = fib6_locate(&ip6_routing_table, + &rtmsg->rtmsg_dst, rtmsg->rtmsg_dst_len, + &rtmsg->rtmsg_src, rtmsg->rtmsg_src_len); if (fn) { for (rt = fn->leaf; rt; rt = rt->u.next) { - if (cfg->fc_ifindex && + if (rtmsg->rtmsg_ifindex && (rt->rt6i_dev == NULL || - rt->rt6i_dev->ifindex != cfg->fc_ifindex)) + rt->rt6i_dev->ifindex != rtmsg->rtmsg_ifindex)) continue; - if (cfg->fc_flags & RTF_GATEWAY && - !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway)) + if (rtmsg->rtmsg_flags&RTF_GATEWAY && + !ipv6_addr_equal(&rtmsg->rtmsg_gateway, &rt->rt6i_gateway)) continue; - if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric) + if (rtmsg->rtmsg_metric && + rtmsg->rtmsg_metric != rt->rt6i_metric) continue; dst_hold(&rt->u.dst); - read_unlock_bh(&table->tb6_lock); + read_unlock_bh(&rt6_lock); - return __ip6_del_rt(rt, &cfg->fc_nlinfo); + return ip6_del_rt(rt, nlh, _rtattr, req); } } - read_unlock_bh(&table->tb6_lock); + read_unlock_bh(&rt6_lock); return err; } @@ -1282,17 +1149,11 @@ static int ip6_route_del(struct fib6_config *cfg) /* * Handle redirects */ -struct ip6rd_flowi { - struct flowi fl; - struct in6_addr gateway; -}; - -static struct rt6_info *__ip6_route_redirect(struct fib6_table *table, - struct flowi *fl, - int flags) +void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, + struct neighbour *neigh, u8 *lladdr, int on_link) { - struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl; - struct rt6_info *rt; + struct rt6_info *rt, *nrt = NULL; + int strict; struct fib6_node *fn; /* @@ -1305,9 +1166,10 @@ static struct rt6_info *__ip6_route_redirect(struct fib6_table *table, * is a bit fuzzy and one might need to check all possible * routes. */ + strict = ipv6_addr_type(dest) & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL); - read_lock_bh(&table->tb6_lock); - fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src); + read_lock_bh(&rt6_lock); + fn = fib6_lookup(&ip6_routing_table, dest, NULL); restart: for (rt = fn->leaf; rt; rt = rt->u.next) { /* @@ -1322,60 +1184,29 @@ static struct rt6_info *__ip6_route_redirect(struct fib6_table *table, continue; if (!(rt->rt6i_flags & RTF_GATEWAY)) continue; - if (fl->oif != rt->rt6i_dev->ifindex) + if (neigh->dev != rt->rt6i_dev) continue; - if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway)) + if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway)) continue; break; } + if (rt) + dst_hold(&rt->u.dst); + else if (strict) { + while ((fn = fn->parent) != NULL) { + if (fn->fn_flags & RTN_ROOT) + break; + if (fn->fn_flags & RTN_RTINFO) + goto restart; + } + } + read_unlock_bh(&rt6_lock); - if (!rt) - rt = &ip6_null_entry; - BACKTRACK(&fl->fl6_src); -out: - dst_hold(&rt->u.dst); - - read_unlock_bh(&table->tb6_lock); - - return rt; -}; - -static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, - struct in6_addr *src, - struct in6_addr *gateway, - struct net_device *dev) -{ - struct ip6rd_flowi rdfl = { - .fl = { - .oif = dev->ifindex, - .nl_u = { - .ip6_u = { - .daddr = *dest, - .saddr = *src, - }, - }, - }, - .gateway = *gateway, - }; - int flags = rt6_need_strict(dest) ? RT6_LOOKUP_F_IFACE : 0; - - return (struct rt6_info *)fib6_rule_lookup((struct flowi *)&rdfl, flags, __ip6_route_redirect); -} - -void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, - struct in6_addr *saddr, - struct neighbour *neigh, u8 *lladdr, int on_link) -{ - struct rt6_info *rt, *nrt = NULL; - struct netevent_redirect netevent; - - rt = ip6_route_redirect(dest, src, saddr, neigh->dev); - - if (rt == &ip6_null_entry) { + if (!rt) { if (net_ratelimit()) printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " "for redirect target\n"); - goto out; + return; } /* @@ -1418,15 +1249,11 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst)); - if (ip6_ins_rt(nrt)) + if (ip6_ins_rt(nrt, NULL, NULL, NULL)) goto out; - netevent.old = &rt->u.dst; - netevent.new = &nrt->u.dst; - call_netevent_notifiers(NETEVENT_REDIRECT, &netevent); - if (rt->rt6i_flags&RTF_CACHE) { - ip6_del_rt(rt); + ip6_del_rt(rt, NULL, NULL, NULL); return; } @@ -1508,7 +1335,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires); nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; - ip6_ins_rt(nrt); + ip6_ins_rt(nrt, NULL, NULL, NULL); } out: dst_release(&rt->u.dst); @@ -1544,7 +1371,6 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) #ifdef CONFIG_IPV6_SUBTREES memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); #endif - rt->rt6i_table = ort->rt6i_table; } return rt; } @@ -1555,14 +1381,9 @@ static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixle { struct fib6_node *fn; struct rt6_info *rt = NULL; - struct fib6_table *table; - table = fib6_get_table(RT6_TABLE_INFO); - if (table == NULL) - return NULL; - - write_lock_bh(&table->tb6_lock); - fn = fib6_locate(&table->tb6_root, prefix ,prefixlen, NULL, 0); + write_lock_bh(&rt6_lock); + fn = fib6_locate(&ip6_routing_table, prefix ,prefixlen, NULL, 0); if (!fn) goto out; @@ -1577,7 +1398,7 @@ static struct rt6_info *rt6_get_route_info(struct in6_addr *prefix, int prefixle break; } out: - write_unlock_bh(&table->tb6_lock); + write_unlock_bh(&rt6_lock); return rt; } @@ -1585,23 +1406,21 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle struct in6_addr *gwaddr, int ifindex, unsigned pref) { - struct fib6_config cfg = { - .fc_table = RT6_TABLE_INFO, - .fc_metric = 1024, - .fc_ifindex = ifindex, - .fc_dst_len = prefixlen, - .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | - RTF_UP | RTF_PREF(pref), - }; - - ipv6_addr_copy(&cfg.fc_dst, prefix); - ipv6_addr_copy(&cfg.fc_gateway, gwaddr); + struct in6_rtmsg rtmsg; + memset(&rtmsg, 0, sizeof(rtmsg)); + rtmsg.rtmsg_type = RTMSG_NEWROUTE; + ipv6_addr_copy(&rtmsg.rtmsg_dst, prefix); + rtmsg.rtmsg_dst_len = prefixlen; + ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr); + rtmsg.rtmsg_metric = 1024; + rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | RTF_UP | RTF_PREF(pref); /* We should treat it as a default route if prefix length is 0. */ if (!prefixlen) - cfg.fc_flags |= RTF_DEFAULT; + rtmsg.rtmsg_flags |= RTF_DEFAULT; + rtmsg.rtmsg_ifindex = ifindex; - ip6_route_add(&cfg); + ip6_route_add(&rtmsg, NULL, NULL, NULL); return rt6_get_route_info(prefix, prefixlen, gwaddr, ifindex); } @@ -1610,14 +1429,12 @@ static struct rt6_info *rt6_add_route_info(struct in6_addr *prefix, int prefixle struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev) { struct rt6_info *rt; - struct fib6_table *table; + struct fib6_node *fn; - table = fib6_get_table(RT6_TABLE_DFLT); - if (table == NULL) - return NULL; + fn = &ip6_routing_table; - write_lock_bh(&table->tb6_lock); - for (rt = table->tb6_root.leaf; rt; rt=rt->u.next) { + write_lock_bh(&rt6_lock); + for (rt = fn->leaf; rt; rt=rt->u.next) { if (dev == rt->rt6i_dev && ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && ipv6_addr_equal(&rt->rt6i_gateway, addr)) @@ -1625,7 +1442,7 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d } if (rt) dst_hold(&rt->u.dst); - write_unlock_bh(&table->tb6_lock); + write_unlock_bh(&rt6_lock); return rt; } @@ -1633,65 +1450,43 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, struct net_device *dev, unsigned int pref) { - struct fib6_config cfg = { - .fc_table = RT6_TABLE_DFLT, - .fc_metric = 1024, - .fc_ifindex = dev->ifindex, - .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | - RTF_UP | RTF_EXPIRES | RTF_PREF(pref), - }; + struct in6_rtmsg rtmsg; - ipv6_addr_copy(&cfg.fc_gateway, gwaddr); + memset(&rtmsg, 0, sizeof(struct in6_rtmsg)); + rtmsg.rtmsg_type = RTMSG_NEWROUTE; + ipv6_addr_copy(&rtmsg.rtmsg_gateway, gwaddr); + rtmsg.rtmsg_metric = 1024; + rtmsg.rtmsg_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | RTF_UP | RTF_EXPIRES | + RTF_PREF(pref); - ip6_route_add(&cfg); + rtmsg.rtmsg_ifindex = dev->ifindex; + ip6_route_add(&rtmsg, NULL, NULL, NULL); return rt6_get_dflt_router(gwaddr, dev); } void rt6_purge_dflt_routers(void) { struct rt6_info *rt; - struct fib6_table *table; - - /* NOTE: Keep consistent with rt6_get_dflt_router */ - table = fib6_get_table(RT6_TABLE_DFLT); - if (table == NULL) - return; restart: - read_lock_bh(&table->tb6_lock); - for (rt = table->tb6_root.leaf; rt; rt = rt->u.next) { + read_lock_bh(&rt6_lock); + for (rt = ip6_routing_table.leaf; rt; rt = rt->u.next) { if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) { dst_hold(&rt->u.dst); - read_unlock_bh(&table->tb6_lock); - ip6_del_rt(rt); - goto restart; - } - } - read_unlock_bh(&table->tb6_lock); -} -static void rtmsg_to_fib6_config(struct in6_rtmsg *rtmsg, - struct fib6_config *cfg) -{ - memset(cfg, 0, sizeof(*cfg)); + read_unlock_bh(&rt6_lock); - cfg->fc_table = RT6_TABLE_MAIN; - cfg->fc_ifindex = rtmsg->rtmsg_ifindex; - cfg->fc_metric = rtmsg->rtmsg_metric; - cfg->fc_expires = rtmsg->rtmsg_info; - cfg->fc_dst_len = rtmsg->rtmsg_dst_len; - cfg->fc_src_len = rtmsg->rtmsg_src_len; - cfg->fc_flags = rtmsg->rtmsg_flags; + ip6_del_rt(rt, NULL, NULL, NULL); - ipv6_addr_copy(&cfg->fc_dst, &rtmsg->rtmsg_dst); - ipv6_addr_copy(&cfg->fc_src, &rtmsg->rtmsg_src); - ipv6_addr_copy(&cfg->fc_gateway, &rtmsg->rtmsg_gateway); + goto restart; + } + } + read_unlock_bh(&rt6_lock); } int ipv6_route_ioctl(unsigned int cmd, void __user *arg) { - struct fib6_config cfg; struct in6_rtmsg rtmsg; int err; @@ -1704,16 +1499,14 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) sizeof(struct in6_rtmsg)); if (err) return -EFAULT; - - rtmsg_to_fib6_config(&rtmsg, &cfg); - + rtnl_lock(); switch (cmd) { case SIOCADDRT: - err = ip6_route_add(&cfg); + err = ip6_route_add(&rtmsg, NULL, NULL, NULL); break; case SIOCDELRT: - err = ip6_route_del(&cfg); + err = ip6_route_del(&rtmsg, NULL, NULL, NULL); break; default: err = -EINVAL; @@ -1732,10 +1525,6 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) static int ip6_pkt_discard(struct sk_buff *skb) { - int type = ipv6_addr_type(&skb->nh.ipv6h->daddr); - if (type == IPV6_ADDR_ANY || type == IPV6_ADDR_RESERVED) - IP6_INC_STATS(IPSTATS_MIB_INADDRERRORS); - IP6_INC_STATS(IPSTATS_MIB_OUTNOROUTES); icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev); kfree_skb(skb); @@ -1787,7 +1576,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, ipv6_addr_copy(&rt->rt6i_dst.addr, addr); rt->rt6i_dst.plen = 128; - rt->rt6i_table = fib6_get_table(RT6_TABLE_LOCAL); atomic_set(&rt->u.dst.__refcnt, 1); @@ -1806,7 +1594,9 @@ static int fib6_ifdown(struct rt6_info *rt, void *arg) void rt6_ifdown(struct net_device *dev) { - fib6_clean_all(fib6_ifdown, 0, dev); + write_lock_bh(&rt6_lock); + fib6_clean_tree(&ip6_routing_table, fib6_ifdown, 0, dev); + write_unlock_bh(&rt6_lock); } struct rt6_mtu_change_arg @@ -1856,124 +1646,90 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) void rt6_mtu_change(struct net_device *dev, unsigned mtu) { - struct rt6_mtu_change_arg arg = { - .dev = dev, - .mtu = mtu, - }; + struct rt6_mtu_change_arg arg; - fib6_clean_all(rt6_mtu_change_route, 0, &arg); + arg.dev = dev; + arg.mtu = mtu; + read_lock_bh(&rt6_lock); + fib6_clean_tree(&ip6_routing_table, rt6_mtu_change_route, 0, &arg); + read_unlock_bh(&rt6_lock); } -static struct nla_policy rtm_ipv6_policy[RTA_MAX+1] __read_mostly = { - [RTA_GATEWAY] = { .len = sizeof(struct in6_addr) }, - [RTA_OIF] = { .type = NLA_U32 }, - [RTA_IIF] = { .type = NLA_U32 }, - [RTA_PRIORITY] = { .type = NLA_U32 }, - [RTA_METRICS] = { .type = NLA_NESTED }, -}; - -static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, - struct fib6_config *cfg) +static int inet6_rtm_to_rtmsg(struct rtmsg *r, struct rtattr **rta, + struct in6_rtmsg *rtmsg) { - struct rtmsg *rtm; - struct nlattr *tb[RTA_MAX+1]; - int err; + memset(rtmsg, 0, sizeof(*rtmsg)); - err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); - if (err < 0) - goto errout; + rtmsg->rtmsg_dst_len = r->rtm_dst_len; + rtmsg->rtmsg_src_len = r->rtm_src_len; + rtmsg->rtmsg_flags = RTF_UP; + if (r->rtm_type == RTN_UNREACHABLE) + rtmsg->rtmsg_flags |= RTF_REJECT; - err = -EINVAL; - rtm = nlmsg_data(nlh); - memset(cfg, 0, sizeof(*cfg)); - - cfg->fc_table = rtm->rtm_table; - cfg->fc_dst_len = rtm->rtm_dst_len; - cfg->fc_src_len = rtm->rtm_src_len; - cfg->fc_flags = RTF_UP; - cfg->fc_protocol = rtm->rtm_protocol; - - if (rtm->rtm_type == RTN_UNREACHABLE) - cfg->fc_flags |= RTF_REJECT; - - cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid; - cfg->fc_nlinfo.nlh = nlh; - - if (tb[RTA_GATEWAY]) { - nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16); - cfg->fc_flags |= RTF_GATEWAY; + if (rta[RTA_GATEWAY-1]) { + if (rta[RTA_GATEWAY-1]->rta_len != RTA_LENGTH(16)) + return -EINVAL; + memcpy(&rtmsg->rtmsg_gateway, RTA_DATA(rta[RTA_GATEWAY-1]), 16); + rtmsg->rtmsg_flags |= RTF_GATEWAY; } - - if (tb[RTA_DST]) { - int plen = (rtm->rtm_dst_len + 7) >> 3; - - if (nla_len(tb[RTA_DST]) < plen) - goto errout; - - nla_memcpy(&cfg->fc_dst, tb[RTA_DST], plen); + if (rta[RTA_DST-1]) { + if (RTA_PAYLOAD(rta[RTA_DST-1]) < ((r->rtm_dst_len+7)>>3)) + return -EINVAL; + memcpy(&rtmsg->rtmsg_dst, RTA_DATA(rta[RTA_DST-1]), ((r->rtm_dst_len+7)>>3)); } - - if (tb[RTA_SRC]) { - int plen = (rtm->rtm_src_len + 7) >> 3; - - if (nla_len(tb[RTA_SRC]) < plen) - goto errout; - - nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen); + if (rta[RTA_SRC-1]) { + if (RTA_PAYLOAD(rta[RTA_SRC-1]) < ((r->rtm_src_len+7)>>3)) + return -EINVAL; + memcpy(&rtmsg->rtmsg_src, RTA_DATA(rta[RTA_SRC-1]), ((r->rtm_src_len+7)>>3)); } - - if (tb[RTA_OIF]) - cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]); - - if (tb[RTA_PRIORITY]) - cfg->fc_metric = nla_get_u32(tb[RTA_PRIORITY]); - - if (tb[RTA_METRICS]) { - cfg->fc_mx = nla_data(tb[RTA_METRICS]); - cfg->fc_mx_len = nla_len(tb[RTA_METRICS]); + if (rta[RTA_OIF-1]) { + if (rta[RTA_OIF-1]->rta_len != RTA_LENGTH(sizeof(int))) + return -EINVAL; + memcpy(&rtmsg->rtmsg_ifindex, RTA_DATA(rta[RTA_OIF-1]), sizeof(int)); } - - if (tb[RTA_TABLE]) - cfg->fc_table = nla_get_u32(tb[RTA_TABLE]); - - err = 0; -errout: - return err; + if (rta[RTA_PRIORITY-1]) { + if (rta[RTA_PRIORITY-1]->rta_len != RTA_LENGTH(4)) + return -EINVAL; + memcpy(&rtmsg->rtmsg_metric, RTA_DATA(rta[RTA_PRIORITY-1]), 4); + } + return 0; } int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) { - struct fib6_config cfg; - int err; - - err = rtm_to_fib6_config(skb, nlh, &cfg); - if (err < 0) - return err; + struct rtmsg *r = NLMSG_DATA(nlh); + struct in6_rtmsg rtmsg; - return ip6_route_del(&cfg); + if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) + return -EINVAL; + return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb)); } int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) { - struct fib6_config cfg; - int err; - - err = rtm_to_fib6_config(skb, nlh, &cfg); - if (err < 0) - return err; + struct rtmsg *r = NLMSG_DATA(nlh); + struct in6_rtmsg rtmsg; - return ip6_route_add(&cfg); + if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) + return -EINVAL; + return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb)); } +struct rt6_rtnl_dump_arg +{ + struct sk_buff *skb; + struct netlink_callback *cb; +}; + static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, struct in6_addr *dst, struct in6_addr *src, int iif, int type, u32 pid, u32 seq, int prefix, unsigned int flags) { struct rtmsg *rtm; - struct nlmsghdr *nlh; + struct nlmsghdr *nlh; + unsigned char *b = skb->tail; struct rta_cacheinfo ci; - u32 table; if (prefix) { /* user wants prefix routes only */ if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { @@ -1982,21 +1738,13 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, } } - nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags); - if (nlh == NULL) - return -ENOBUFS; - - rtm = nlmsg_data(nlh); + nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*rtm), flags); + rtm = NLMSG_DATA(nlh); rtm->rtm_family = AF_INET6; rtm->rtm_dst_len = rt->rt6i_dst.plen; rtm->rtm_src_len = rt->rt6i_src.plen; rtm->rtm_tos = 0; - if (rt->rt6i_table) - table = rt->rt6i_table->tb6_id; - else - table = RT6_TABLE_UNSPEC; - rtm->rtm_table = table; - NLA_PUT_U32(skb, RTA_TABLE, table); + rtm->rtm_table = RT_TABLE_MAIN; if (rt->rt6i_flags&RTF_REJECT) rtm->rtm_type = RTN_UNREACHABLE; else if (rt->rt6i_dev && (rt->rt6i_dev->flags&IFF_LOOPBACK)) @@ -2017,35 +1765,31 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, rtm->rtm_flags |= RTM_F_CLONED; if (dst) { - NLA_PUT(skb, RTA_DST, 16, dst); + RTA_PUT(skb, RTA_DST, 16, dst); rtm->rtm_dst_len = 128; } else if (rtm->rtm_dst_len) - NLA_PUT(skb, RTA_DST, 16, &rt->rt6i_dst.addr); + RTA_PUT(skb, RTA_DST, 16, &rt->rt6i_dst.addr); #ifdef CONFIG_IPV6_SUBTREES if (src) { - NLA_PUT(skb, RTA_SRC, 16, src); + RTA_PUT(skb, RTA_SRC, 16, src); rtm->rtm_src_len = 128; } else if (rtm->rtm_src_len) - NLA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr); + RTA_PUT(skb, RTA_SRC, 16, &rt->rt6i_src.addr); #endif if (iif) - NLA_PUT_U32(skb, RTA_IIF, iif); + RTA_PUT(skb, RTA_IIF, 4, &iif); else if (dst) { struct in6_addr saddr_buf; if (ipv6_get_saddr(&rt->u.dst, dst, &saddr_buf) == 0) - NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); + RTA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); } - if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) - goto nla_put_failure; - + goto rtattr_failure; if (rt->u.dst.neighbour) - NLA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key); - + RTA_PUT(skb, RTA_GATEWAY, 16, &rt->u.dst.neighbour->primary_key); if (rt->u.dst.dev) - NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); - - NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); + RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->rt6i_dev->ifindex); + RTA_PUT(skb, RTA_PRIORITY, 4, &rt->rt6i_metric); ci.rta_lastuse = jiffies_to_clock_t(jiffies - rt->u.dst.lastuse); if (rt->rt6i_expires) ci.rta_expires = jiffies_to_clock_t(rt->rt6i_expires - jiffies); @@ -2057,21 +1801,23 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, ci.rta_id = 0; ci.rta_ts = 0; ci.rta_tsage = 0; - NLA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); + RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); + nlh->nlmsg_len = skb->tail - b; + return skb->len; - return nlmsg_end(skb, nlh); - -nla_put_failure: - return nlmsg_cancel(skb, nlh); +nlmsg_failure: +rtattr_failure: + skb_trim(skb, b - skb->data); + return -1; } -int rt6_dump_route(struct rt6_info *rt, void *p_arg) +static int rt6_dump_route(struct rt6_info *rt, void *p_arg) { struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg; int prefix; - if (nlmsg_len(arg->cb->nlh) >= sizeof(struct rtmsg)) { - struct rtmsg *rtm = nlmsg_data(arg->cb->nlh); + if (arg->cb->nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(struct rtmsg))) { + struct rtmsg *rtm = NLMSG_DATA(arg->cb->nlh); prefix = (rtm->rtm_flags & RTM_F_PREFIX) != 0; } else prefix = 0; @@ -2081,108 +1827,189 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) prefix, NLM_F_MULTI); } -int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) +static int fib6_dump_node(struct fib6_walker_t *w) { - struct nlattr *tb[RTA_MAX+1]; + int res; struct rt6_info *rt; - struct sk_buff *skb; - struct rtmsg *rtm; - struct flowi fl; - int err, iif = 0; - err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy); - if (err < 0) - goto errout; - - err = -EINVAL; - memset(&fl, 0, sizeof(fl)); + for (rt = w->leaf; rt; rt = rt->u.next) { + res = rt6_dump_route(rt, w->args); + if (res < 0) { + /* Frame is full, suspend walking */ + w->leaf = rt; + return 1; + } + BUG_TRAP(res!=0); + } + w->leaf = NULL; + return 0; +} - if (tb[RTA_SRC]) { - if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr)) - goto errout; +static void fib6_dump_end(struct netlink_callback *cb) +{ + struct fib6_walker_t *w = (void*)cb->args[0]; - ipv6_addr_copy(&fl.fl6_src, nla_data(tb[RTA_SRC])); + if (w) { + cb->args[0] = 0; + fib6_walker_unlink(w); + kfree(w); } + cb->done = (void*)cb->args[1]; + cb->args[1] = 0; +} - if (tb[RTA_DST]) { - if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr)) - goto errout; +static int fib6_dump_done(struct netlink_callback *cb) +{ + fib6_dump_end(cb); + return cb->done ? cb->done(cb) : 0; +} + +int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct rt6_rtnl_dump_arg arg; + struct fib6_walker_t *w; + int res; - ipv6_addr_copy(&fl.fl6_dst, nla_data(tb[RTA_DST])); + arg.skb = skb; + arg.cb = cb; + + w = (void*)cb->args[0]; + if (w == NULL) { + /* New dump: + * + * 1. hook callback destructor. + */ + cb->args[1] = (long)cb->done; + cb->done = fib6_dump_done; + + /* + * 2. allocate and initialize walker. + */ + w = kzalloc(sizeof(*w), GFP_ATOMIC); + if (w == NULL) + return -ENOMEM; + RT6_TRACE("dump<%p", w); + w->root = &ip6_routing_table; + w->func = fib6_dump_node; + w->args = &arg; + cb->args[0] = (long)w; + read_lock_bh(&rt6_lock); + res = fib6_walk(w); + read_unlock_bh(&rt6_lock); + } else { + w->args = &arg; + read_lock_bh(&rt6_lock); + res = fib6_walk_continue(w); + read_unlock_bh(&rt6_lock); } +#if RT6_DEBUG >= 3 + if (res <= 0 && skb->len == 0) + RT6_TRACE("%p>dump end\n", w); +#endif + res = res < 0 ? res : skb->len; + /* res < 0 is an error. (really, impossible) + res == 0 means that dump is complete, but skb still can contain data. + res > 0 dump is not complete, but frame is full. + */ + /* Destroy walker, if dump of this table is complete. */ + if (res <= 0) + fib6_dump_end(cb); + return res; +} + +int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) +{ + struct rtattr **rta = arg; + int iif = 0; + int err = -ENOBUFS; + struct sk_buff *skb; + struct flowi fl; + struct rt6_info *rt; - if (tb[RTA_IIF]) - iif = nla_get_u32(tb[RTA_IIF]); + skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); + if (skb == NULL) + goto out; + + /* Reserve room for dummy headers, this skb can pass + through good chunk of routing engine. + */ + skb->mac.raw = skb->data; + skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); - if (tb[RTA_OIF]) - fl.oif = nla_get_u32(tb[RTA_OIF]); + memset(&fl, 0, sizeof(fl)); + if (rta[RTA_SRC-1]) + ipv6_addr_copy(&fl.fl6_src, + (struct in6_addr*)RTA_DATA(rta[RTA_SRC-1])); + if (rta[RTA_DST-1]) + ipv6_addr_copy(&fl.fl6_dst, + (struct in6_addr*)RTA_DATA(rta[RTA_DST-1])); + + if (rta[RTA_IIF-1]) + memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int)); if (iif) { struct net_device *dev; dev = __dev_get_by_index(iif); if (!dev) { err = -ENODEV; - goto errout; + goto out_free; } } - skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); - if (skb == NULL) { - err = -ENOBUFS; - goto errout; - } + fl.oif = 0; + if (rta[RTA_OIF-1]) + memcpy(&fl.oif, RTA_DATA(rta[RTA_OIF-1]), sizeof(int)); - /* Reserve room for dummy headers, this skb can pass - through good chunk of routing engine. - */ - skb->mac.raw = skb->data; - skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr)); + rt = (struct rt6_info*)ip6_route_output(NULL, &fl); - rt = (struct rt6_info*) ip6_route_output(NULL, &fl); skb->dst = &rt->u.dst; - err = rt6_fill_node(skb, rt, &fl.fl6_dst, &fl.fl6_src, iif, + NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; + err = rt6_fill_node(skb, rt, + &fl.fl6_dst, &fl.fl6_src, + iif, RTM_NEWROUTE, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, 0, 0); if (err < 0) { - kfree_skb(skb); - goto errout; + err = -EMSGSIZE; + goto out_free; } - err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid); -errout: + err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); + if (err > 0) + err = 0; +out: return err; +out_free: + kfree_skb(skb); + goto out; } -void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) +void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh, + struct netlink_skb_parms *req) { struct sk_buff *skb; - u32 pid = 0, seq = 0; - struct nlmsghdr *nlh = NULL; - int payload = sizeof(struct rtmsg) + 256; - int err = -ENOBUFS; - - if (info) { - pid = info->pid; - nlh = info->nlh; - if (nlh) - seq = nlh->nlmsg_seq; + int size = NLMSG_SPACE(sizeof(struct rtmsg)+256); + u32 pid = current->pid; + u32 seq = 0; + + if (req) + pid = req->pid; + if (nlh) + seq = nlh->nlmsg_seq; + + skb = alloc_skb(size, gfp_any()); + if (!skb) { + netlink_set_err(rtnl, 0, RTNLGRP_IPV6_ROUTE, ENOBUFS); + return; } - - skb = nlmsg_new(nlmsg_total_size(payload), gfp_any()); - if (skb == NULL) - goto errout; - - err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0); - if (err < 0) { + if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0) < 0) { kfree_skb(skb); - goto errout; + netlink_set_err(rtnl, 0, RTNLGRP_IPV6_ROUTE, EINVAL); + return; } - - err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any()); -errout: - if (err < 0) - rtnl_set_sk_err(RTNLGRP_IPV6_ROUTE, err); + NETLINK_CB(skb).dst_group = RTNLGRP_IPV6_ROUTE; + netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_ROUTE, gfp_any()); } /* @@ -2258,13 +2085,16 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) static int rt6_proc_info(char *buffer, char **start, off_t offset, int length) { - struct rt6_proc_arg arg = { - .buffer = buffer, - .offset = offset, - .length = length, - }; + struct rt6_proc_arg arg; + arg.buffer = buffer; + arg.offset = offset; + arg.length = length; + arg.skip = 0; + arg.len = 0; - fib6_clean_all(rt6_info_route, 0, &arg); + read_lock_bh(&rt6_lock); + fib6_clean_tree(&ip6_routing_table, rt6_info_route, 0, &arg); + read_unlock_bh(&rt6_lock); *start = buffer; if (offset) @@ -2419,9 +2249,13 @@ void __init ip6_route_init(void) { struct proc_dir_entry *p; - ip6_dst_ops.kmem_cachep = - kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, - SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); + ip6_dst_ops.kmem_cachep = kmem_cache_create("ip6_dst_cache", + sizeof(struct rt6_info), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + if (!ip6_dst_ops.kmem_cachep) + panic("cannot create ip6_dst_cache"); + fib6_init(); #ifdef CONFIG_PROC_FS p = proc_net_create("ipv6_route", 0, rt6_proc_info); @@ -2433,16 +2267,10 @@ void __init ip6_route_init(void) #ifdef CONFIG_XFRM xfrm6_init(); #endif -#ifdef CONFIG_IPV6_MULTIPLE_TABLES - fib6_rules_init(); -#endif } void ip6_route_cleanup(void) { -#ifdef CONFIG_IPV6_MULTIPLE_TABLES - fib6_rules_cleanup(); -#endif #ifdef CONFIG_PROC_FS proc_net_remove("ipv6_route"); proc_net_remove("rt6_stats"); diff --git a/trunk/net/ipv6/tcp_ipv6.c b/trunk/net/ipv6/tcp_ipv6.c index 2546fc9f0a78..923989d0520d 100644 --- a/trunk/net/ipv6/tcp_ipv6.c +++ b/trunk/net/ipv6/tcp_ipv6.c @@ -251,8 +251,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, final_p = &final; } - security_sk_classify_flow(sk, &fl); - err = ip6_dst_lookup(sk, &dst, &fl); if (err) goto failure; @@ -272,7 +270,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, inet->rcv_saddr = LOOPBACK4_IPV6; sk->sk_gso_type = SKB_GSO_TCPV6; - __ip6_dst_store(sk, dst, NULL, NULL); + ip6_dst_store(sk, dst, NULL); icsk->icsk_ext_hdr_len = 0; if (np->opt) @@ -376,7 +374,6 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, fl.oif = sk->sk_bound_dev_if; fl.fl_ip_dport = inet->dport; fl.fl_ip_sport = inet->sport; - security_skb_classify_flow(skb, &fl); if ((err = ip6_dst_lookup(sk, &dst, &fl))) { sk->sk_err_soft = -err; @@ -430,6 +427,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, case TCP_SYN_RECV: /* Cannot happen. It can, it SYNs are crossed. --ANK */ if (!sock_owned_by_user(sk)) { + TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); sk->sk_err = err; sk->sk_error_report(sk); /* Wake people up to see the error (see connect in sock.c) */ @@ -470,7 +468,6 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, fl.oif = treq->iif; fl.fl_ip_dport = inet_rsk(req)->rmt_port; fl.fl_ip_sport = inet_sk(sk)->sport; - security_req_classify_flow(req, &fl); if (dst == NULL) { opt = np->opt; @@ -545,7 +542,7 @@ static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) struct ipv6_pinfo *np = inet6_sk(sk); struct tcphdr *th = skb->h.th; - if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (skb->ip_summed == CHECKSUM_HW) { th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); skb->csum = offsetof(struct tcphdr, check); } else { @@ -570,7 +567,7 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len, IPPROTO_TCP, 0); skb->csum = offsetof(struct tcphdr, check); - skb->ip_summed = CHECKSUM_PARTIAL; + skb->ip_summed = CHECKSUM_HW; return 0; } @@ -629,7 +626,6 @@ static void tcp_v6_send_reset(struct sk_buff *skb) fl.oif = inet6_iif(skb); fl.fl_ip_dport = t1->dest; fl.fl_ip_sport = t1->source; - security_skb_classify_flow(skb, &fl); /* sk = NULL, but it is safe for now. RST socket required. */ if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { @@ -696,7 +692,6 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 fl.oif = inet6_iif(skb); fl.fl_ip_dport = t1->dest; fl.fl_ip_sport = t1->source; - security_skb_classify_flow(skb, &fl); if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { @@ -826,8 +821,6 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) tcp_rsk(req)->snt_isn = isn; - security_inet_conn_request(sk, skb, req); - if (tcp_v6_send_synack(sk, req, NULL)) goto drop; @@ -838,6 +831,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) if (req) reqsk_free(req); + TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS); return 0; /* don't send reset */ } @@ -931,7 +925,6 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, fl.oif = sk->sk_bound_dev_if; fl.fl_ip_dport = inet_rsk(req)->rmt_port; fl.fl_ip_sport = inet_sk(sk)->sport; - security_req_classify_flow(req, &fl); if (ip6_dst_lookup(sk, &dst, &fl)) goto out; @@ -953,8 +946,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, * comment in that function for the gory details. -acme */ - newsk->sk_gso_type = SKB_GSO_TCPV6; - __ip6_dst_store(newsk, dst, NULL, NULL); + sk->sk_gso_type = SKB_GSO_TCPV6; + ip6_dst_store(newsk, dst, NULL); newtcp6sk = (struct tcp6_sock *)newsk; inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; @@ -1033,7 +1026,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, static int tcp_v6_checksum_init(struct sk_buff *skb) { - if (skb->ip_summed == CHECKSUM_COMPLETE) { + if (skb->ip_summed == CHECKSUM_HW) { if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr,skb->csum)) { skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -1075,7 +1068,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) if (skb->protocol == htons(ETH_P_IP)) return tcp_v4_do_rcv(sk, skb); - if (sk_filter(sk, skb)) + if (sk_filter(sk, skb, 0)) goto discard; /* @@ -1232,7 +1225,7 @@ static int tcp_v6_rcv(struct sk_buff **pskb) if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_and_relse; - if (sk_filter(sk, skb)) + if (sk_filter(sk, skb, 0)) goto discard_and_relse; skb->dev = NULL; diff --git a/trunk/net/ipv6/udp.c b/trunk/net/ipv6/udp.c index 9662561701d1..ccc57f434cd3 100644 --- a/trunk/net/ipv6/udp.c +++ b/trunk/net/ipv6/udp.c @@ -61,9 +61,81 @@ DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly; -static inline int udp_v6_get_port(struct sock *sk, unsigned short snum) +/* Grrr, addr_type already calculated by caller, but I don't want + * to add some silly "cookie" argument to this method just for that. + */ +static int udp_v6_get_port(struct sock *sk, unsigned short snum) { - return udp_get_port(sk, snum, ipv6_rcv_saddr_equal); + struct sock *sk2; + struct hlist_node *node; + + write_lock_bh(&udp_hash_lock); + if (snum == 0) { + int best_size_so_far, best, result, i; + + if (udp_port_rover > sysctl_local_port_range[1] || + udp_port_rover < sysctl_local_port_range[0]) + udp_port_rover = sysctl_local_port_range[0]; + best_size_so_far = 32767; + best = result = udp_port_rover; + for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) { + int size; + struct hlist_head *list; + + list = &udp_hash[result & (UDP_HTABLE_SIZE - 1)]; + if (hlist_empty(list)) { + if (result > sysctl_local_port_range[1]) + result = sysctl_local_port_range[0] + + ((result - sysctl_local_port_range[0]) & + (UDP_HTABLE_SIZE - 1)); + goto gotit; + } + size = 0; + sk_for_each(sk2, node, list) + if (++size >= best_size_so_far) + goto next; + best_size_so_far = size; + best = result; + next:; + } + result = best; + for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) { + if (result > sysctl_local_port_range[1]) + result = sysctl_local_port_range[0] + + ((result - sysctl_local_port_range[0]) & + (UDP_HTABLE_SIZE - 1)); + if (!udp_lport_inuse(result)) + break; + } + if (i >= (1 << 16) / UDP_HTABLE_SIZE) + goto fail; +gotit: + udp_port_rover = snum = result; + } else { + sk_for_each(sk2, node, + &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]) { + if (inet_sk(sk2)->num == snum && + sk2 != sk && + (!sk2->sk_bound_dev_if || + !sk->sk_bound_dev_if || + sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && + (!sk2->sk_reuse || !sk->sk_reuse) && + ipv6_rcv_saddr_equal(sk, sk2)) + goto fail; + } + } + + inet_sk(sk)->num = snum; + if (sk_unhashed(sk)) { + sk_add_node(sk, &udp_hash[snum & (UDP_HTABLE_SIZE - 1)]); + sock_prot_inc_use(sk->sk_prot); + } + write_unlock_bh(&udp_hash_lock); + return 0; + +fail: + write_unlock_bh(&udp_hash_lock); + return 1; } static void udp_v6_hash(struct sock *sk) @@ -273,8 +345,6 @@ static void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) { - int rc; - if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) { kfree_skb(skb); return -1; @@ -286,10 +356,7 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) return 0; } - if ((rc = sock_queue_rcv_skb(sk,skb)) < 0) { - /* Note that an ENOMEM error is charged twice */ - if (rc == -ENOMEM) - UDP6_INC_STATS_BH(UDP_MIB_RCVBUFERRORS); + if (sock_queue_rcv_skb(sk,skb)<0) { UDP6_INC_STATS_BH(UDP_MIB_INERRORS); kfree_skb(skb); return 0; @@ -408,7 +475,7 @@ static int udpv6_rcv(struct sk_buff **pskb) uh = skb->h.uh; } - if (skb->ip_summed == CHECKSUM_COMPLETE && + if (skb->ip_summed == CHECKSUM_HW && !csum_ipv6_magic(saddr, daddr, ulen, IPPROTO_UDP, skb->csum)) skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -715,9 +782,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, connected = 0; } - security_sk_classify_flow(sk, fl); - - err = ip6_sk_dst_lookup(sk, &dst, fl); + err = ip6_dst_lookup(sk, &dst, fl); if (err) goto out; if (final_p) @@ -775,12 +840,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, if (connected) { ip6_dst_store(sk, dst, ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? - &np->daddr : NULL, -#ifdef CONFIG_IPV6_SUBTREES - ipv6_addr_equal(&fl->fl6_src, &np->saddr) ? - &np->saddr : -#endif - NULL); + &np->daddr : NULL); } else { dst_release(dst); } @@ -795,16 +855,6 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, UDP6_INC_STATS_USER(UDP_MIB_OUTDATAGRAMS); return len; } - /* - * ENOBUFS = no kernel mem, SOCK_NOSPACE = no sndbuf space. Reporting - * ENOBUFS might not be good (it's not tunable per se), but otherwise - * we don't have a good statistic (IpOutDiscards but it can be too many - * things). We could add another new stat but at least for now that - * seems like overkill. - */ - if (err == -ENOBUFS || test_bit(SOCK_NOSPACE, &sk->sk_socket->flags)) { - UDP6_INC_STATS_USER(UDP_MIB_SNDBUFERRORS); - } return err; do_confirm: diff --git a/trunk/net/ipv6/xfrm6_input.c b/trunk/net/ipv6/xfrm6_input.c index a40a05789013..0405d74ff910 100644 --- a/trunk/net/ipv6/xfrm6_input.c +++ b/trunk/net/ipv6/xfrm6_input.c @@ -72,7 +72,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) if (x->mode->input(x, skb)) goto drop; - if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */ + if (x->props.mode) { /* XXX */ decaps = 1; break; } @@ -138,111 +138,3 @@ int xfrm6_rcv(struct sk_buff **pskb) { return xfrm6_rcv_spi(*pskb, 0); } - -int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, - xfrm_address_t *saddr, u8 proto) -{ - struct xfrm_state *x = NULL; - int wildcard = 0; - struct in6_addr any; - xfrm_address_t *xany; - struct xfrm_state *xfrm_vec_one = NULL; - int nh = 0; - int i = 0; - - ipv6_addr_set(&any, 0, 0, 0, 0); - xany = (xfrm_address_t *)&any; - - for (i = 0; i < 3; i++) { - xfrm_address_t *dst, *src; - switch (i) { - case 0: - dst = daddr; - src = saddr; - break; - case 1: - /* lookup state with wild-card source address */ - wildcard = 1; - dst = daddr; - src = xany; - break; - case 2: - default: - /* lookup state with wild-card addresses */ - wildcard = 1; /* XXX */ - dst = xany; - src = xany; - break; - } - - x = xfrm_state_lookup_byaddr(dst, src, proto, AF_INET6); - if (!x) - continue; - - spin_lock(&x->lock); - - if (wildcard) { - if ((x->props.flags & XFRM_STATE_WILDRECV) == 0) { - spin_unlock(&x->lock); - xfrm_state_put(x); - x = NULL; - continue; - } - } - - if (unlikely(x->km.state != XFRM_STATE_VALID)) { - spin_unlock(&x->lock); - xfrm_state_put(x); - x = NULL; - continue; - } - if (xfrm_state_check_expire(x)) { - spin_unlock(&x->lock); - xfrm_state_put(x); - x = NULL; - continue; - } - - nh = x->type->input(x, skb); - if (nh <= 0) { - spin_unlock(&x->lock); - xfrm_state_put(x); - x = NULL; - continue; - } - - x->curlft.bytes += skb->len; - x->curlft.packets++; - - spin_unlock(&x->lock); - - xfrm_vec_one = x; - break; - } - - if (!xfrm_vec_one) - goto drop; - - /* Allocate new secpath or COW existing one. */ - if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { - struct sec_path *sp; - sp = secpath_dup(skb->sp); - if (!sp) - goto drop; - if (skb->sp) - secpath_put(skb->sp); - skb->sp = sp; - } - - if (1 + skb->sp->len > XFRM_MAX_DEPTH) - goto drop; - - skb->sp->xvec[skb->sp->len] = xfrm_vec_one; - skb->sp->len ++; - - return 1; -drop: - if (xfrm_vec_one) - xfrm_state_put(xfrm_vec_one); - return -1; -} diff --git a/trunk/net/ipv6/xfrm6_mode_ro.c b/trunk/net/ipv6/xfrm6_mode_ro.c deleted file mode 100644 index 6031c16d46ca..000000000000 --- a/trunk/net/ipv6/xfrm6_mode_ro.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * xfrm6_mode_ro.c - Route optimization mode for IPv6. - * - * Copyright (C)2003-2006 Helsinki University of Technology - * Copyright (C)2003-2006 USAGI/WIDE Project - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* - * Authors: - * Noriaki TAKAMIYA @USAGI - * Masahide NAKAMURA @USAGI - */ - -#include -#include -#include -#include -#include -#include -#include - -/* Add route optimization header space. - * - * The IP header and mutable extension headers will be moved forward to make - * space for the route optimization header. - * - * On exit, skb->h will be set to the start of the encapsulation header to be - * filled in by x->type->output and skb->nh will be set to the nextheader field - * of the extension header directly preceding the encapsulation header, or in - * its absence, that of the top IP header. The value of skb->data will always - * point to the top IP header. - */ -static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb) -{ - struct ipv6hdr *iph; - u8 *prevhdr; - int hdr_len; - - skb_push(skb, x->props.header_len); - iph = skb->nh.ipv6h; - - hdr_len = x->type->hdr_offset(x, skb, &prevhdr); - skb->nh.raw = prevhdr - x->props.header_len; - skb->h.raw = skb->data + hdr_len; - memmove(skb->data, iph, hdr_len); - return 0; -} - -/* - * Do nothing about routing optimization header unlike IPsec. - */ -static int xfrm6_ro_input(struct xfrm_state *x, struct sk_buff *skb) -{ - return 0; -} - -static struct xfrm_mode xfrm6_ro_mode = { - .input = xfrm6_ro_input, - .output = xfrm6_ro_output, - .owner = THIS_MODULE, - .encap = XFRM_MODE_ROUTEOPTIMIZATION, -}; - -static int __init xfrm6_ro_init(void) -{ - return xfrm_register_mode(&xfrm6_ro_mode, AF_INET6); -} - -static void __exit xfrm6_ro_exit(void) -{ - int err; - - err = xfrm_unregister_mode(&xfrm6_ro_mode, AF_INET6); - BUG_ON(err); -} - -module_init(xfrm6_ro_init); -module_exit(xfrm6_ro_exit); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_ROUTEOPTIMIZATION); diff --git a/trunk/net/ipv6/xfrm6_mode_transport.c b/trunk/net/ipv6/xfrm6_mode_transport.c index 3a4b39b12bad..711d713e36d8 100644 --- a/trunk/net/ipv6/xfrm6_mode_transport.c +++ b/trunk/net/ipv6/xfrm6_mode_transport.c @@ -25,8 +25,9 @@ * its absence, that of the top IP header. The value of skb->data will always * point to the top IP header. */ -static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb) +static int xfrm6_transport_output(struct sk_buff *skb) { + struct xfrm_state *x = skb->dst->xfrm; struct ipv6hdr *iph; u8 *prevhdr; int hdr_len; @@ -34,7 +35,7 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb) skb_push(skb, x->props.header_len); iph = skb->nh.ipv6h; - hdr_len = x->type->hdr_offset(x, skb, &prevhdr); + hdr_len = ip6_find_1stfragopt(skb, &prevhdr); skb->nh.raw = prevhdr - x->props.header_len; skb->h.raw = skb->data + hdr_len; memmove(skb->data, iph, hdr_len); diff --git a/trunk/net/ipv6/xfrm6_mode_tunnel.c b/trunk/net/ipv6/xfrm6_mode_tunnel.c index 5e7d8a7d6414..8af79be2edca 100644 --- a/trunk/net/ipv6/xfrm6_mode_tunnel.c +++ b/trunk/net/ipv6/xfrm6_mode_tunnel.c @@ -37,9 +37,10 @@ static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) * its absence, that of the top IP header. The value of skb->data will always * point to the top IP header. */ -static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) +static int xfrm6_tunnel_output(struct sk_buff *skb) { struct dst_entry *dst = skb->dst; + struct xfrm_state *x = dst->xfrm; struct ipv6hdr *iph, *top_iph; int dsfield; diff --git a/trunk/net/ipv6/xfrm6_output.c b/trunk/net/ipv6/xfrm6_output.c index c260ea104c52..0eea60ea9ebc 100644 --- a/trunk/net/ipv6/xfrm6_output.c +++ b/trunk/net/ipv6/xfrm6_output.c @@ -17,12 +17,6 @@ #include #include -int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, - u8 **prevhdr) -{ - return ip6_find_1stfragopt(skb, prevhdr); -} - static int xfrm6_tunnel_check_size(struct sk_buff *skb) { int mtu, ret = 0; @@ -47,13 +41,13 @@ static int xfrm6_output_one(struct sk_buff *skb) struct xfrm_state *x = dst->xfrm; int err; - if (skb->ip_summed == CHECKSUM_PARTIAL) { - err = skb_checksum_help(skb); + if (skb->ip_summed == CHECKSUM_HW) { + err = skb_checksum_help(skb, 0); if (err) goto error_nolock; } - if (x->props.mode == XFRM_MODE_TUNNEL) { + if (x->props.mode) { err = xfrm6_tunnel_check_size(skb); if (err) goto error_nolock; @@ -65,7 +59,7 @@ static int xfrm6_output_one(struct sk_buff *skb) if (err) goto error; - err = x->mode->output(x, skb); + err = x->mode->output(skb); if (err) goto error; @@ -75,8 +69,6 @@ static int xfrm6_output_one(struct sk_buff *skb) x->curlft.bytes += skb->len; x->curlft.packets++; - if (x->props.mode == XFRM_MODE_ROUTEOPTIMIZATION) - x->lastused = (u64)xtime.tv_sec; spin_unlock_bh(&x->lock); @@ -88,7 +80,7 @@ static int xfrm6_output_one(struct sk_buff *skb) } dst = skb->dst; x = dst->xfrm; - } while (x && (x->props.mode != XFRM_MODE_TUNNEL)); + } while (x && !x->props.mode); IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; err = 0; @@ -133,7 +125,7 @@ static int xfrm6_output_finish(struct sk_buff *skb) if (!skb_is_gso(skb)) return xfrm6_output_finish2(skb); - skb->protocol = htons(ETH_P_IPV6); + skb->protocol = htons(ETH_P_IP); segs = skb_gso_segment(skb, 0); kfree_skb(skb); if (unlikely(IS_ERR(segs))) diff --git a/trunk/net/ipv6/xfrm6_policy.c b/trunk/net/ipv6/xfrm6_policy.c index 6a252e2134d1..73cd250aecbb 100644 --- a/trunk/net/ipv6/xfrm6_policy.c +++ b/trunk/net/ipv6/xfrm6_policy.c @@ -18,9 +18,6 @@ #include #include #include -#ifdef CONFIG_IPV6_MIP6 -#include -#endif static struct dst_ops xfrm6_dst_ops; static struct xfrm_policy_afinfo xfrm6_policy_afinfo; @@ -34,26 +31,6 @@ static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) return err; } -static int xfrm6_get_saddr(xfrm_address_t *saddr, xfrm_address_t *daddr) -{ - struct rt6_info *rt; - struct flowi fl_tunnel = { - .nl_u = { - .ip6_u = { - .daddr = *(struct in6_addr *)&daddr->a6, - }, - }, - }; - - if (!xfrm6_dst_lookup((struct xfrm_dst **)&rt, &fl_tunnel)) { - ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)&daddr->a6, - (struct in6_addr *)&saddr->a6); - dst_release(&rt->u.dst); - return 0; - } - return -EHOSTUNREACH; -} - static struct dst_entry * __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy) { @@ -73,9 +50,7 @@ __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy) xdst->u.rt6.rt6i_src.plen); if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) && ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) && - xfrm_bundle_ok(xdst, fl, AF_INET6, - (xdst->u.rt6.rt6i_dst.plen != 128 || - xdst->u.rt6.rt6i_src.plen != 128))) { + xfrm_bundle_ok(xdst, fl, AF_INET6)) { dst_clone(dst); break; } @@ -84,40 +59,6 @@ __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy) return dst; } -static inline struct in6_addr* -__xfrm6_bundle_addr_remote(struct xfrm_state *x, struct in6_addr *addr) -{ - return (x->type->remote_addr) ? - (struct in6_addr*)x->type->remote_addr(x, (xfrm_address_t *)addr) : - (struct in6_addr*)&x->id.daddr; -} - -static inline struct in6_addr* -__xfrm6_bundle_addr_local(struct xfrm_state *x, struct in6_addr *addr) -{ - return (x->type->local_addr) ? - (struct in6_addr*)x->type->local_addr(x, (xfrm_address_t *)addr) : - (struct in6_addr*)&x->props.saddr; -} - -static inline void -__xfrm6_bundle_len_inc(int *len, int *nflen, struct xfrm_state *x) -{ - if (x->type->flags & XFRM_TYPE_NON_FRAGMENT) - *nflen += x->props.header_len; - else - *len += x->props.header_len; -} - -static inline void -__xfrm6_bundle_len_dec(int *len, int *nflen, struct xfrm_state *x) -{ - if (x->type->flags & XFRM_TYPE_NON_FRAGMENT) - *nflen -= x->props.header_len; - else - *len -= x->props.header_len; -} - /* Allocate chain of dst_entry's, attach known xfrm's, calculate * all the metrics... Shortly, bundle a bundle. */ @@ -142,7 +83,6 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int int i; int err = 0; int header_len = 0; - int nfheader_len = 0; int trailer_len = 0; dst = dst_prev = NULL; @@ -169,18 +109,17 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int xdst = (struct xfrm_dst *)dst1; xdst->route = &rt->u.dst; - xdst->genid = xfrm[i]->genid; if (rt->rt6i_node) xdst->route_cookie = rt->rt6i_node->fn_sernum; dst1->next = dst_prev; dst_prev = dst1; - if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { - remote = __xfrm6_bundle_addr_remote(xfrm[i], remote); - local = __xfrm6_bundle_addr_local(xfrm[i], local); + if (xfrm[i]->props.mode) { + remote = (struct in6_addr*)&xfrm[i]->id.daddr; + local = (struct in6_addr*)&xfrm[i]->props.saddr; tunnel = 1; } - __xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]); + header_len += xfrm[i]->props.header_len; trailer_len += xfrm[i]->props.trailer_len; if (tunnel) { @@ -215,7 +154,6 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int dst_prev->flags |= DST_HOST; dst_prev->lastuse = jiffies; dst_prev->header_len = header_len; - dst_prev->nfheader_len = nfheader_len; dst_prev->trailer_len = trailer_len; memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics)); @@ -234,7 +172,7 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int x->u.rt6.rt6i_src = rt0->rt6i_src; x->u.rt6.rt6i_idev = rt0->rt6i_idev; in6_dev_hold(rt0->rt6i_idev); - __xfrm6_bundle_len_dec(&header_len, &nfheader_len, x->u.dst.xfrm); + header_len -= x->u.dst.xfrm->props.header_len; trailer_len -= x->u.dst.xfrm->props.trailer_len; } @@ -294,18 +232,6 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl) fl->proto = nexthdr; return; -#ifdef CONFIG_IPV6_MIP6 - case IPPROTO_MH: - if (pskb_may_pull(skb, skb->nh.raw + offset + 3 - skb->data)) { - struct ip6_mh *mh; - mh = (struct ip6_mh *)exthdr; - - fl->fl_mh_type = mh->ip6mh_type; - } - fl->proto = nexthdr; - return; -#endif - /* XXX Why are there these headers? */ case IPPROTO_AH: case IPPROTO_ESP: @@ -382,7 +308,6 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { .family = AF_INET6, .dst_ops = &xfrm6_dst_ops, .dst_lookup = xfrm6_dst_lookup, - .get_saddr = xfrm6_get_saddr, .find_bundle = __xfrm6_find_bundle, .bundle_create = __xfrm6_bundle_create, .decode_session = _decode_session6, diff --git a/trunk/net/ipv6/xfrm6_state.c b/trunk/net/ipv6/xfrm6_state.c index 711bfafb2472..b33296b3f6de 100644 --- a/trunk/net/ipv6/xfrm6_state.c +++ b/trunk/net/ipv6/xfrm6_state.c @@ -42,135 +42,102 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); if (ipv6_addr_any((struct in6_addr*)&x->props.saddr)) memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); + if (tmpl->mode && ipv6_addr_any((struct in6_addr*)&x->props.saddr)) { + struct rt6_info *rt; + struct flowi fl_tunnel = { + .nl_u = { + .ip6_u = { + .daddr = *(struct in6_addr *)daddr, + } + } + }; + if (!xfrm_dst_lookup((struct xfrm_dst **)&rt, + &fl_tunnel, AF_INET6)) { + ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)daddr, + (struct in6_addr *)&x->props.saddr); + dst_release(&rt->u.dst); + } + } x->props.mode = tmpl->mode; x->props.reqid = tmpl->reqid; x->props.family = AF_INET6; } -static int -__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) +static struct xfrm_state * +__xfrm6_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto) { - int i; - int j = 0; - - /* Rule 1: select IPsec transport except AH */ - for (i = 0; i < n; i++) { - if (src[i]->props.mode == XFRM_MODE_TRANSPORT && - src[i]->id.proto != IPPROTO_AH) { - dst[j++] = src[i]; - src[i] = NULL; - } - } - if (j == n) - goto end; - - /* Rule 2: select MIPv6 RO or inbound trigger */ -#ifdef CONFIG_IPV6_MIP6 - for (i = 0; i < n; i++) { - if (src[i] && - (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION || - src[i]->props.mode == XFRM_MODE_IN_TRIGGER)) { - dst[j++] = src[i]; - src[i] = NULL; - } - } - if (j == n) - goto end; -#endif - - /* Rule 3: select IPsec transport AH */ - for (i = 0; i < n; i++) { - if (src[i] && - src[i]->props.mode == XFRM_MODE_TRANSPORT && - src[i]->id.proto == IPPROTO_AH) { - dst[j++] = src[i]; - src[i] = NULL; + unsigned h = __xfrm6_spi_hash(daddr, spi, proto); + struct xfrm_state *x; + + list_for_each_entry(x, xfrm6_state_afinfo.state_byspi+h, byspi) { + if (x->props.family == AF_INET6 && + spi == x->id.spi && + ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) && + proto == x->id.proto) { + xfrm_state_hold(x); + return x; } } - if (j == n) - goto end; - - /* Rule 4: select IPsec tunnel */ - for (i = 0; i < n; i++) { - if (src[i] && - src[i]->props.mode == XFRM_MODE_TUNNEL) { - dst[j++] = src[i]; - src[i] = NULL; - } - } - if (likely(j == n)) - goto end; - - /* Final rule */ - for (i = 0; i < n; i++) { - if (src[i]) { - dst[j++] = src[i]; - src[i] = NULL; - } - } - - end: - return 0; + return NULL; } -static int -__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) +static struct xfrm_state * +__xfrm6_find_acq(u8 mode, u32 reqid, u8 proto, + xfrm_address_t *daddr, xfrm_address_t *saddr, + int create) { - int i; - int j = 0; - - /* Rule 1: select IPsec transport */ - for (i = 0; i < n; i++) { - if (src[i]->mode == XFRM_MODE_TRANSPORT) { - dst[j++] = src[i]; - src[i] = NULL; - } + struct xfrm_state *x, *x0; + unsigned h = __xfrm6_dst_hash(daddr); + + x0 = NULL; + + list_for_each_entry(x, xfrm6_state_afinfo.state_bydst+h, bydst) { + if (x->props.family == AF_INET6 && + ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) && + mode == x->props.mode && + proto == x->id.proto && + ipv6_addr_equal((struct in6_addr *)saddr, (struct in6_addr *)x->props.saddr.a6) && + reqid == x->props.reqid && + x->km.state == XFRM_STATE_ACQ && + !x->id.spi) { + x0 = x; + break; + } } - if (j == n) - goto end; - - /* Rule 2: select MIPv6 RO or inbound trigger */ -#ifdef CONFIG_IPV6_MIP6 - for (i = 0; i < n; i++) { - if (src[i] && - (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION || - src[i]->mode == XFRM_MODE_IN_TRIGGER)) { - dst[j++] = src[i]; - src[i] = NULL; - } + if (!x0 && create && (x0 = xfrm_state_alloc()) != NULL) { + ipv6_addr_copy((struct in6_addr *)x0->sel.daddr.a6, + (struct in6_addr *)daddr); + ipv6_addr_copy((struct in6_addr *)x0->sel.saddr.a6, + (struct in6_addr *)saddr); + x0->sel.prefixlen_d = 128; + x0->sel.prefixlen_s = 128; + ipv6_addr_copy((struct in6_addr *)x0->props.saddr.a6, + (struct in6_addr *)saddr); + x0->km.state = XFRM_STATE_ACQ; + ipv6_addr_copy((struct in6_addr *)x0->id.daddr.a6, + (struct in6_addr *)daddr); + x0->id.proto = proto; + x0->props.family = AF_INET6; + x0->props.mode = mode; + x0->props.reqid = reqid; + x0->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES; + xfrm_state_hold(x0); + x0->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; + add_timer(&x0->timer); + xfrm_state_hold(x0); + list_add_tail(&x0->bydst, xfrm6_state_afinfo.state_bydst+h); + wake_up(&km_waitq); } - if (j == n) - goto end; -#endif - - /* Rule 3: select IPsec tunnel */ - for (i = 0; i < n; i++) { - if (src[i] && - src[i]->mode == XFRM_MODE_TUNNEL) { - dst[j++] = src[i]; - src[i] = NULL; - } - } - if (likely(j == n)) - goto end; - - /* Final rule */ - for (i = 0; i < n; i++) { - if (src[i]) { - dst[j++] = src[i]; - src[i] = NULL; - } - } - - end: - return 0; + if (x0) + xfrm_state_hold(x0); + return x0; } static struct xfrm_state_afinfo xfrm6_state_afinfo = { .family = AF_INET6, .init_tempsel = __xfrm6_init_tempsel, - .tmpl_sort = __xfrm6_tmpl_sort, - .state_sort = __xfrm6_state_sort, + .state_lookup = __xfrm6_state_lookup, + .find_acq = __xfrm6_find_acq, }; void __init xfrm6_state_init(void) diff --git a/trunk/net/ipv6/xfrm6_tunnel.c b/trunk/net/ipv6/xfrm6_tunnel.c index 59685ee8f700..c8f9369c2a87 100644 --- a/trunk/net/ipv6/xfrm6_tunnel.c +++ b/trunk/net/ipv6/xfrm6_tunnel.c @@ -307,7 +307,7 @@ static int xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt, static int xfrm6_tunnel_init_state(struct xfrm_state *x) { - if (x->props.mode != XFRM_MODE_TUNNEL) + if (!x->props.mode) return -EINVAL; if (x->encap) diff --git a/trunk/net/ipx/af_ipx.c b/trunk/net/ipx/af_ipx.c index bef3f61569f7..aa34ff4b707c 100644 --- a/trunk/net/ipx/af_ipx.c +++ b/trunk/net/ipx/af_ipx.c @@ -1642,17 +1642,13 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) goto out; - if (!pskb_may_pull(skb, sizeof(struct ipxhdr))) - goto drop; - - ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize); + ipx = ipx_hdr(skb); + ipx_pktsize = ntohs(ipx->ipx_pktsize); /* Too small or invalid header? */ - if (ipx_pktsize < sizeof(struct ipxhdr) || - !pskb_may_pull(skb, ipx_pktsize)) + if (ipx_pktsize < sizeof(struct ipxhdr) || ipx_pktsize > skb->len) goto drop; - ipx = ipx_hdr(skb); if (ipx->ipx_checksum != IPX_NO_CHECKSUM && ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize)) goto drop; diff --git a/trunk/net/key/af_key.c b/trunk/net/key/af_key.c index 83b443ddc72f..3a95b2ee4690 100644 --- a/trunk/net/key/af_key.c +++ b/trunk/net/key/af_key.c @@ -1731,8 +1731,7 @@ static u32 gen_reqid(void) ++reqid; if (reqid == 0) reqid = IPSEC_MANUAL_REQID_MAX+1; - if (xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, check_reqid, - (void*)&reqid) != -EEXIST) + if (xfrm_policy_walk(check_reqid, (void*)&reqid) != -EEXIST) return reqid; } while (reqid != start); return 0; @@ -1766,7 +1765,7 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq) } /* addresses present only in tunnel mode */ - if (t->mode == XFRM_MODE_TUNNEL) { + if (t->mode) { switch (xp->family) { case AF_INET: sin = (void*)(rq+1); @@ -1998,7 +1997,7 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i int req_size; req_size = sizeof(struct sadb_x_ipsecrequest); - if (t->mode == XFRM_MODE_TUNNEL) + if (t->mode) req_size += 2*socklen; else size -= 2*socklen; @@ -2014,7 +2013,7 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i if (t->optional) rq->sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE; rq->sadb_x_ipsecrequest_reqid = t->reqid; - if (t->mode == XFRM_MODE_TUNNEL) { + if (t->mode) { switch (xp->family) { case AF_INET: sin = (void*)(rq+1); @@ -2269,8 +2268,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg return err; } - xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1, - &sel, tmp.security, 1); + xp = xfrm_policy_bysel_ctx(pol->sadb_x_policy_dir-1, &sel, tmp.security, 1); security_xfrm_policy_free(&tmp); if (xp == NULL) return -ENOENT; @@ -2332,7 +2330,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h if (dir >= XFRM_POLICY_MAX) return -EINVAL; - xp = xfrm_policy_byid(XFRM_POLICY_TYPE_MAIN, dir, pol->sadb_x_policy_id, + xp = xfrm_policy_byid(dir, pol->sadb_x_policy_id, hdr->sadb_msg_type == SADB_X_SPDDELETE2); if (xp == NULL) return -ENOENT; @@ -2380,7 +2378,7 @@ static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg * { struct pfkey_dump_data data = { .skb = skb, .hdr = hdr, .sk = sk }; - return xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, dump_sp, &data); + return xfrm_policy_walk(dump_sp, &data); } static int key_notify_policy_flush(struct km_event *c) @@ -2407,8 +2405,7 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg { struct km_event c; - xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN); - c.data.type = XFRM_POLICY_TYPE_MAIN; + xfrm_policy_flush(); c.event = XFRM_MSG_FLUSHPOLICY; c.pid = hdr->sadb_msg_pid; c.seq = hdr->sadb_msg_seq; @@ -2670,9 +2667,6 @@ static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c) static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c) { - if (xp && xp->type != XFRM_POLICY_TYPE_MAIN) - return 0; - switch (c->event) { case XFRM_MSG_POLEXPIRE: return key_notify_policy_expire(xp, c); @@ -2681,8 +2675,6 @@ static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_e case XFRM_MSG_UPDPOLICY: return key_notify_policy(xp, dir, c); case XFRM_MSG_FLUSHPOLICY: - if (c->data.type != XFRM_POLICY_TYPE_MAIN) - break; return key_notify_policy_flush(c); default: printk("pfkey: Unknown policy event %d\n", c->event); @@ -2716,9 +2708,6 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct #endif int sockaddr_size; int size; - struct sadb_x_sec_ctx *sec_ctx; - struct xfrm_sec_ctx *xfrm_ctx; - int ctx_size = 0; sockaddr_size = pfkey_sockaddr_size(x->props.family); if (!sockaddr_size) @@ -2734,11 +2723,6 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct else if (x->id.proto == IPPROTO_ESP) size += count_esp_combs(t); - if ((xfrm_ctx = x->security)) { - ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len); - size += sizeof(struct sadb_x_sec_ctx) + ctx_size; - } - skb = alloc_skb(size + 16, GFP_ATOMIC); if (skb == NULL) return -ENOMEM; @@ -2834,31 +2818,17 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct else if (x->id.proto == IPPROTO_ESP) dump_esp_combs(skb, t); - /* security context */ - if (xfrm_ctx) { - sec_ctx = (struct sadb_x_sec_ctx *) skb_put(skb, - sizeof(struct sadb_x_sec_ctx) + ctx_size); - sec_ctx->sadb_x_sec_len = - (sizeof(struct sadb_x_sec_ctx) + ctx_size) / sizeof(uint64_t); - sec_ctx->sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX; - sec_ctx->sadb_x_ctx_doi = xfrm_ctx->ctx_doi; - sec_ctx->sadb_x_ctx_alg = xfrm_ctx->ctx_alg; - sec_ctx->sadb_x_ctx_len = xfrm_ctx->ctx_len; - memcpy(sec_ctx + 1, xfrm_ctx->ctx_str, - xfrm_ctx->ctx_len); - } - return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL); } -static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, +static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt, u8 *data, int len, int *dir) { struct xfrm_policy *xp; struct sadb_x_policy *pol = (struct sadb_x_policy*)data; struct sadb_x_sec_ctx *sec_ctx; - switch (sk->sk_family) { + switch (family) { case AF_INET: if (opt != IP_IPSEC_POLICY) { *dir = -EOPNOTSUPP; @@ -2899,7 +2869,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, xp->lft.hard_byte_limit = XFRM_INF; xp->lft.soft_packet_limit = XFRM_INF; xp->lft.hard_packet_limit = XFRM_INF; - xp->family = sk->sk_family; + xp->family = family; xp->xfrm_nr = 0; if (pol->sadb_x_policy_type == IPSEC_POLICY_IPSEC && @@ -2915,10 +2885,8 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, p += pol->sadb_x_policy_len*8; sec_ctx = (struct sadb_x_sec_ctx *)p; if (len < pol->sadb_x_policy_len*8 + - sec_ctx->sadb_x_sec_len) { - *dir = -EINVAL; + sec_ctx->sadb_x_sec_len) goto out; - } if ((*dir = verify_sec_ctx_len(p))) goto out; uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); @@ -2928,11 +2896,6 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, if (*dir) goto out; } - else { - *dir = security_xfrm_sock_policy_alloc(xp, sk); - if (*dir) - goto out; - } *dir = pol->sadb_x_policy_dir-1; return xp; diff --git a/trunk/net/lapb/lapb_iface.c b/trunk/net/lapb/lapb_iface.c index 7e6bc41eeb21..d504eed416f6 100644 --- a/trunk/net/lapb/lapb_iface.c +++ b/trunk/net/lapb/lapb_iface.c @@ -238,13 +238,11 @@ int lapb_setparms(struct net_device *dev, struct lapb_parms_struct *parms) goto out_put; if (lapb->state == LAPB_STATE_0) { - if (parms->mode & LAPB_EXTENDED) { - if (parms->window < 1 || parms->window > 127) - goto out_put; - } else { - if (parms->window < 1 || parms->window > 7) - goto out_put; - } + if (((parms->mode & LAPB_EXTENDED) && + (parms->window < 1 || parms->window > 127)) || + (parms->window < 1 || parms->window > 7)) + goto out_put; + lapb->mode = parms->mode; lapb->window = parms->window; } diff --git a/trunk/net/llc/af_llc.c b/trunk/net/llc/af_llc.c index 2652ead96c64..d6cfe84d521b 100644 --- a/trunk/net/llc/af_llc.c +++ b/trunk/net/llc/af_llc.c @@ -784,20 +784,24 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, copied += used; len -= used; + if (used + offset < skb->len) + continue; + if (!(flags & MSG_PEEK)) { sk_eat_skb(sk, skb, 0); *seq = 0; } - - /* For non stream protcols we get one packet per recvmsg call */ - if (sk->sk_type != SOCK_STREAM) - goto copy_uaddr; - - /* Partial read */ - if (used + offset < skb->len) - continue; } while (len > 0); + /* + * According to UNIX98, msg_name/msg_namelen are ignored + * on connected socket. -ANK + * But... af_llc still doesn't have separate sets of methods for + * SOCK_DGRAM and SOCK_STREAM :-( So we have to do this test, will + * eventually fix this tho :-) -acme + */ + if (sk->sk_type == SOCK_DGRAM) + goto copy_uaddr; out: release_sock(sk); return copied; diff --git a/trunk/net/llc/llc_sap.c b/trunk/net/llc/llc_sap.c index 61cb8cf7d153..20c4eb5c1ac6 100644 --- a/trunk/net/llc/llc_sap.c +++ b/trunk/net/llc/llc_sap.c @@ -51,10 +51,10 @@ void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim) { struct sockaddr_llc *addr; + if (skb->sk->sk_type == SOCK_STREAM) /* See UNIX98 */ + return; /* save primitive for use by the user. */ addr = llc_ui_skb_cb(skb); - - memset(addr, 0, sizeof(*addr)); addr->sllc_family = sk->sk_family; addr->sllc_arphrd = skb->dev->type; addr->sllc_test = prim == LLC_TEST_PRIM; @@ -330,9 +330,6 @@ static void llc_sap_mcast(struct llc_sap *sap, if (llc->laddr.lsap != laddr->lsap) continue; - if (llc->dev != skb->dev) - continue; - skb1 = skb_clone(skb, GFP_ATOMIC); if (!skb1) break; diff --git a/trunk/net/netfilter/Kconfig b/trunk/net/netfilter/Kconfig index 0a28d2c5c44f..a9894ddfd72a 100644 --- a/trunk/net/netfilter/Kconfig +++ b/trunk/net/netfilter/Kconfig @@ -148,18 +148,6 @@ config NETFILTER_XT_TARGET_CONNMARK . The module will be called ipt_CONNMARK.o. If unsure, say `N'. -config NETFILTER_XT_TARGET_DSCP - tristate '"DSCP" target support' - depends on NETFILTER_XTABLES - depends on IP_NF_MANGLE || IP6_NF_MANGLE - help - This option adds a `DSCP' target, which allows you to manipulate - the IPv4/IPv6 header DSCP field (differentiated services codepoint). - - The DSCP field can have any value between 0x0 and 0x3f inclusive. - - To compile it as a module, choose M here. If unsure, say N. - config NETFILTER_XT_TARGET_MARK tristate '"MARK" target support' depends on NETFILTER_XTABLES @@ -275,17 +263,6 @@ config NETFILTER_XT_MATCH_DCCP If you want to compile it as a module, say M here and read . If unsure, say `N'. -config NETFILTER_XT_MATCH_DSCP - tristate '"DSCP" match support' - depends on NETFILTER_XTABLES - help - This option adds a `DSCP' match, which allows you to match against - the IPv4/IPv6 header DSCP field (differentiated services codepoint). - - The DSCP field can have any value between 0x0 and 0x3f inclusive. - - To compile it as a module, choose M here. If unsure, say N. - config NETFILTER_XT_MATCH_ESP tristate '"ESP" match support' depends on NETFILTER_XTABLES diff --git a/trunk/net/netfilter/Makefile b/trunk/net/netfilter/Makefile index a74be492fd0a..6fa4b7580458 100644 --- a/trunk/net/netfilter/Makefile +++ b/trunk/net/netfilter/Makefile @@ -25,7 +25,6 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o # targets obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o -obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o @@ -38,7 +37,6 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o -obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o diff --git a/trunk/net/netfilter/core.c b/trunk/net/netfilter/core.c index d80b935b3a92..5d29d5e23624 100644 --- a/trunk/net/netfilter/core.c +++ b/trunk/net/netfilter/core.c @@ -182,7 +182,7 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb, ret = -EPERM; } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) { NFDEBUG("nf_hook: Verdict = QUEUE.\n"); - if (!nf_queue(*pskb, elem, pf, hook, indev, outdev, okfn, + if (!nf_queue(pskb, elem, pf, hook, indev, outdev, okfn, verdict >> NF_VERDICT_BITS)) goto next_hook; } @@ -222,28 +222,6 @@ int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len) } EXPORT_SYMBOL(skb_make_writable); -u_int16_t nf_csum_update(u_int32_t oldval, u_int32_t newval, u_int32_t csum) -{ - u_int32_t diff[] = { oldval, newval }; - - return csum_fold(csum_partial((char *)diff, sizeof(diff), ~csum)); -} -EXPORT_SYMBOL(nf_csum_update); - -u_int16_t nf_proto_csum_update(struct sk_buff *skb, - u_int32_t oldval, u_int32_t newval, - u_int16_t csum, int pseudohdr) -{ - if (skb->ip_summed != CHECKSUM_PARTIAL) { - csum = nf_csum_update(oldval, newval, csum); - if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) - skb->csum = nf_csum_update(oldval, newval, skb->csum); - } else if (pseudohdr) - csum = ~nf_csum_update(oldval, newval, ~csum); - - return csum; -} -EXPORT_SYMBOL(nf_proto_csum_update); /* This does not belong here, but locally generated errors need it if connection tracking in use: without this, connection may not be in hash table, and hence diff --git a/trunk/net/netfilter/nf_conntrack_core.c b/trunk/net/netfilter/nf_conntrack_core.c index 093b3ddc513c..8f2261965a68 100644 --- a/trunk/net/netfilter/nf_conntrack_core.c +++ b/trunk/net/netfilter/nf_conntrack_core.c @@ -57,6 +57,7 @@ #include #include #include +#include #define NF_CONNTRACK_VERSION "0.5.0" @@ -73,17 +74,17 @@ atomic_t nf_conntrack_count = ATOMIC_INIT(0); void (*nf_conntrack_destroyed)(struct nf_conn *conntrack) = NULL; LIST_HEAD(nf_conntrack_expect_list); -struct nf_conntrack_protocol **nf_ct_protos[PF_MAX] __read_mostly; -struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX] __read_mostly; +struct nf_conntrack_protocol **nf_ct_protos[PF_MAX]; +struct nf_conntrack_l3proto *nf_ct_l3protos[PF_MAX]; static LIST_HEAD(helpers); -unsigned int nf_conntrack_htable_size __read_mostly = 0; -int nf_conntrack_max __read_mostly; -struct list_head *nf_conntrack_hash __read_mostly; -static kmem_cache_t *nf_conntrack_expect_cachep __read_mostly; +unsigned int nf_conntrack_htable_size = 0; +int nf_conntrack_max; +struct list_head *nf_conntrack_hash; +static kmem_cache_t *nf_conntrack_expect_cachep; struct nf_conn nf_conntrack_untracked; -unsigned int nf_ct_log_invalid __read_mostly; +unsigned int nf_ct_log_invalid; static LIST_HEAD(unconfirmed); -static int nf_conntrack_vmalloc __read_mostly; +static int nf_conntrack_vmalloc; static unsigned int nf_conntrack_next_id; static unsigned int nf_conntrack_expect_next_id; @@ -538,10 +539,15 @@ void nf_ct_remove_expectations(struct nf_conn *ct) static void clean_from_lists(struct nf_conn *ct) { + unsigned int ho, hr; + DEBUGP("clean_from_lists(%p)\n", ct); ASSERT_WRITE_LOCK(&nf_conntrack_lock); - list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); - list_del(&ct->tuplehash[IP_CT_DIR_REPLY].list); + + ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); + hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); + LIST_DELETE(&nf_conntrack_hash[ho], &ct->tuplehash[IP_CT_DIR_ORIGINAL]); + LIST_DELETE(&nf_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]); /* Destroy all pending expectations */ nf_ct_remove_expectations(ct); @@ -611,6 +617,16 @@ static void death_by_timeout(unsigned long ul_conntrack) nf_ct_put(ct); } +static inline int +conntrack_tuple_cmp(const struct nf_conntrack_tuple_hash *i, + const struct nf_conntrack_tuple *tuple, + const struct nf_conn *ignored_conntrack) +{ + ASSERT_READ_LOCK(&nf_conntrack_lock); + return nf_ct_tuplehash_to_ctrack(i) != ignored_conntrack + && nf_ct_tuple_equal(tuple, &i->tuple); +} + struct nf_conntrack_tuple_hash * __nf_conntrack_find(const struct nf_conntrack_tuple *tuple, const struct nf_conn *ignored_conntrack) @@ -620,8 +636,7 @@ __nf_conntrack_find(const struct nf_conntrack_tuple *tuple, ASSERT_READ_LOCK(&nf_conntrack_lock); list_for_each_entry(h, &nf_conntrack_hash[hash], list) { - if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && - nf_ct_tuple_equal(tuple, &h->tuple)) { + if (conntrack_tuple_cmp(h, tuple, ignored_conntrack)) { NF_CT_STAT_INC(found); return h; } @@ -652,10 +667,10 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct, unsigned int repl_hash) { ct->id = ++nf_conntrack_next_id; - list_add(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list, - &nf_conntrack_hash[hash]); - list_add(&ct->tuplehash[IP_CT_DIR_REPLY].list, - &nf_conntrack_hash[repl_hash]); + list_prepend(&nf_conntrack_hash[hash], + &ct->tuplehash[IP_CT_DIR_ORIGINAL].list); + list_prepend(&nf_conntrack_hash[repl_hash], + &ct->tuplehash[IP_CT_DIR_REPLY].list); } void nf_conntrack_hash_insert(struct nf_conn *ct) @@ -675,9 +690,7 @@ int __nf_conntrack_confirm(struct sk_buff **pskb) { unsigned int hash, repl_hash; - struct nf_conntrack_tuple_hash *h; struct nf_conn *ct; - struct nf_conn_help *help; enum ip_conntrack_info ctinfo; ct = nf_ct_get(*pskb, &ctinfo); @@ -707,41 +720,41 @@ __nf_conntrack_confirm(struct sk_buff **pskb) /* See if there's one in the list already, including reverse: NAT could have grabbed it without realizing, since we're not in the hash. If there is, we lost race. */ - list_for_each_entry(h, &nf_conntrack_hash[hash], list) - if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, - &h->tuple)) - goto out; - list_for_each_entry(h, &nf_conntrack_hash[repl_hash], list) - if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, - &h->tuple)) - goto out; - - /* Remove from unconfirmed list */ - list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); + if (!LIST_FIND(&nf_conntrack_hash[hash], + conntrack_tuple_cmp, + struct nf_conntrack_tuple_hash *, + &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, NULL) + && !LIST_FIND(&nf_conntrack_hash[repl_hash], + conntrack_tuple_cmp, + struct nf_conntrack_tuple_hash *, + &ct->tuplehash[IP_CT_DIR_REPLY].tuple, NULL)) { + struct nf_conn_help *help; + /* Remove from unconfirmed list */ + list_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].list); - __nf_conntrack_hash_insert(ct, hash, repl_hash); - /* Timer relative to confirmation time, not original - setting time, otherwise we'd get timer wrap in - weird delay cases. */ - ct->timeout.expires += jiffies; - add_timer(&ct->timeout); - atomic_inc(&ct->ct_general.use); - set_bit(IPS_CONFIRMED_BIT, &ct->status); - NF_CT_STAT_INC(insert); - write_unlock_bh(&nf_conntrack_lock); - help = nfct_help(ct); - if (help && help->helper) - nf_conntrack_event_cache(IPCT_HELPER, *pskb); + __nf_conntrack_hash_insert(ct, hash, repl_hash); + /* Timer relative to confirmation time, not original + setting time, otherwise we'd get timer wrap in + weird delay cases. */ + ct->timeout.expires += jiffies; + add_timer(&ct->timeout); + atomic_inc(&ct->ct_general.use); + set_bit(IPS_CONFIRMED_BIT, &ct->status); + NF_CT_STAT_INC(insert); + write_unlock_bh(&nf_conntrack_lock); + help = nfct_help(ct); + if (help && help->helper) + nf_conntrack_event_cache(IPCT_HELPER, *pskb); #ifdef CONFIG_NF_NAT_NEEDED - if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || - test_bit(IPS_DST_NAT_DONE_BIT, &ct->status)) - nf_conntrack_event_cache(IPCT_NATINFO, *pskb); + if (test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status) || + test_bit(IPS_DST_NAT_DONE_BIT, &ct->status)) + nf_conntrack_event_cache(IPCT_NATINFO, *pskb); #endif - nf_conntrack_event_cache(master_ct(ct) ? - IPCT_RELATED : IPCT_NEW, *pskb); - return NF_ACCEPT; + nf_conntrack_event_cache(master_ct(ct) ? + IPCT_RELATED : IPCT_NEW, *pskb); + return NF_ACCEPT; + } -out: NF_CT_STAT_INC(insert_failed); write_unlock_bh(&nf_conntrack_lock); return NF_DROP; @@ -764,21 +777,24 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, /* There's a small race here where we may free a just-assured connection. Too bad: we're in trouble anyway. */ +static inline int unreplied(const struct nf_conntrack_tuple_hash *i) +{ + return !(test_bit(IPS_ASSURED_BIT, + &nf_ct_tuplehash_to_ctrack(i)->status)); +} + static int early_drop(struct list_head *chain) { /* Traverse backwards: gives us oldest, which is roughly LRU */ struct nf_conntrack_tuple_hash *h; - struct nf_conn *ct = NULL, *tmp; + struct nf_conn *ct = NULL; int dropped = 0; read_lock_bh(&nf_conntrack_lock); - list_for_each_entry_reverse(h, chain, list) { - tmp = nf_ct_tuplehash_to_ctrack(h); - if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) { - ct = tmp; - atomic_inc(&ct->ct_general.use); - break; - } + h = LIST_FIND_B(chain, unreplied, struct nf_conntrack_tuple_hash *); + if (h) { + ct = nf_ct_tuplehash_to_ctrack(h); + atomic_inc(&ct->ct_general.use); } read_unlock_bh(&nf_conntrack_lock); @@ -794,16 +810,18 @@ static int early_drop(struct list_head *chain) return dropped; } +static inline int helper_cmp(const struct nf_conntrack_helper *i, + const struct nf_conntrack_tuple *rtuple) +{ + return nf_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask); +} + static struct nf_conntrack_helper * __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple) { - struct nf_conntrack_helper *h; - - list_for_each_entry(h, &helpers, list) { - if (nf_ct_tuple_mask_cmp(tuple, &h->tuple, &h->mask)) - return h; - } - return NULL; + return LIST_FIND(&helpers, helper_cmp, + struct nf_conntrack_helper *, + tuple); } struct nf_conntrack_helper * @@ -848,15 +866,11 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, nf_conntrack_hash_rnd_initted = 1; } - /* We don't want any race condition at early drop stage */ - atomic_inc(&nf_conntrack_count); - if (nf_conntrack_max - && atomic_read(&nf_conntrack_count) > nf_conntrack_max) { + && atomic_read(&nf_conntrack_count) >= nf_conntrack_max) { unsigned int hash = hash_conntrack(orig); /* Try dropping from this hash chain. */ if (!early_drop(&nf_conntrack_hash[hash])) { - atomic_dec(&nf_conntrack_count); if (net_ratelimit()) printk(KERN_WARNING "nf_conntrack: table full, dropping" @@ -907,12 +921,10 @@ __nf_conntrack_alloc(const struct nf_conntrack_tuple *orig, init_timer(&conntrack->timeout); conntrack->timeout.data = (unsigned long)conntrack; conntrack->timeout.function = death_by_timeout; - read_unlock_bh(&nf_ct_cache_lock); - return conntrack; + atomic_inc(&nf_conntrack_count); out: read_unlock_bh(&nf_ct_cache_lock); - atomic_dec(&nf_conntrack_count); return conntrack; } @@ -1311,7 +1323,7 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me) return ret; } write_lock_bh(&nf_conntrack_lock); - list_add(&me->list, &helpers); + list_prepend(&helpers, me); write_unlock_bh(&nf_conntrack_lock); return 0; @@ -1330,8 +1342,8 @@ __nf_conntrack_helper_find_byname(const char *name) return NULL; } -static inline void unhelp(struct nf_conntrack_tuple_hash *i, - const struct nf_conntrack_helper *me) +static inline int unhelp(struct nf_conntrack_tuple_hash *i, + const struct nf_conntrack_helper *me) { struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); struct nf_conn_help *help = nfct_help(ct); @@ -1340,17 +1352,17 @@ static inline void unhelp(struct nf_conntrack_tuple_hash *i, nf_conntrack_event(IPCT_HELPER, ct); help->helper = NULL; } + return 0; } void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) { unsigned int i; - struct nf_conntrack_tuple_hash *h; struct nf_conntrack_expect *exp, *tmp; /* Need write lock here, to delete helper. */ write_lock_bh(&nf_conntrack_lock); - list_del(&me->list); + LIST_DELETE(&helpers, me); /* Get rid of expectations */ list_for_each_entry_safe(exp, tmp, &nf_conntrack_expect_list, list) { @@ -1362,12 +1374,10 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) } /* Get rid of expecteds, set helpers to NULL. */ - list_for_each_entry(h, &unconfirmed, list) - unhelp(h, me); - for (i = 0; i < nf_conntrack_htable_size; i++) { - list_for_each_entry(h, &nf_conntrack_hash[i], list) - unhelp(h, me); - } + LIST_FIND_W(&unconfirmed, unhelp, struct nf_conntrack_tuple_hash*, me); + for (i = 0; i < nf_conntrack_htable_size; i++) + LIST_FIND_W(&nf_conntrack_hash[i], unhelp, + struct nf_conntrack_tuple_hash *, me); write_unlock_bh(&nf_conntrack_lock); /* Someone could be still looking at the helper in a bh. */ @@ -1500,40 +1510,37 @@ do_iter(const struct nf_conntrack_tuple_hash *i, } /* Bring out ya dead! */ -static struct nf_conn * +static struct nf_conntrack_tuple_hash * get_next_corpse(int (*iter)(struct nf_conn *i, void *data), void *data, unsigned int *bucket) { - struct nf_conntrack_tuple_hash *h; - struct nf_conn *ct; + struct nf_conntrack_tuple_hash *h = NULL; write_lock_bh(&nf_conntrack_lock); for (; *bucket < nf_conntrack_htable_size; (*bucket)++) { - list_for_each_entry(h, &nf_conntrack_hash[*bucket], list) { - ct = nf_ct_tuplehash_to_ctrack(h); - if (iter(ct, data)) - goto found; - } + h = LIST_FIND_W(&nf_conntrack_hash[*bucket], do_iter, + struct nf_conntrack_tuple_hash *, iter, data); + if (h) + break; } - list_for_each_entry(h, &unconfirmed, list) { - ct = nf_ct_tuplehash_to_ctrack(h); - if (iter(ct, data)) - goto found; - } - return NULL; -found: - atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use); + if (!h) + h = LIST_FIND_W(&unconfirmed, do_iter, + struct nf_conntrack_tuple_hash *, iter, data); + if (h) + atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use); write_unlock_bh(&nf_conntrack_lock); - return ct; + + return h; } void nf_ct_iterate_cleanup(int (*iter)(struct nf_conn *i, void *data), void *data) { - struct nf_conn *ct; + struct nf_conntrack_tuple_hash *h; unsigned int bucket = 0; - while ((ct = get_next_corpse(iter, data, &bucket)) != NULL) { + while ((h = get_next_corpse(iter, data, &bucket)) != NULL) { + struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); /* Time to push up daises... */ if (del_timer(&ct->timeout)) death_by_timeout((unsigned long)ct); diff --git a/trunk/net/netfilter/nf_conntrack_ftp.c b/trunk/net/netfilter/nf_conntrack_ftp.c index 0c17a5bd112b..960972d225f9 100644 --- a/trunk/net/netfilter/nf_conntrack_ftp.c +++ b/trunk/net/netfilter/nf_conntrack_ftp.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -112,14 +111,101 @@ static struct ftp_search { }, }; +/* This code is based on inet_pton() in glibc-2.2.4 */ static int get_ipv6_addr(const char *src, size_t dlen, struct in6_addr *dst, u_int8_t term) { - const char *end; - int ret = in6_pton(src, min_t(size_t, dlen, 0xffff), (u8 *)dst, term, &end); - if (ret > 0) - return (int)(end - src); - return 0; + static const char xdigits[] = "0123456789abcdef"; + u_int8_t tmp[16], *tp, *endp, *colonp; + int ch, saw_xdigit; + u_int32_t val; + size_t clen = 0; + + tp = memset(tmp, '\0', sizeof(tmp)); + endp = tp + sizeof(tmp); + colonp = NULL; + + /* Leading :: requires some special handling. */ + if (*src == ':'){ + if (*++src != ':') { + DEBUGP("invalid \":\" at the head of addr\n"); + return 0; + } + clen++; + } + + saw_xdigit = 0; + val = 0; + while ((clen < dlen) && (*src != term)) { + const char *pch; + + ch = tolower(*src++); + clen++; + + pch = strchr(xdigits, ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return 0; + + saw_xdigit = 1; + continue; + } + if (ch != ':') { + DEBUGP("get_ipv6_addr: invalid char. \'%c\'\n", ch); + return 0; + } + + if (!saw_xdigit) { + if (colonp) { + DEBUGP("invalid location of \"::\".\n"); + return 0; + } + colonp = tp; + continue; + } else if (*src == term) { + DEBUGP("trancated IPv6 addr\n"); + return 0; + } + + if (tp + 2 > endp) + return 0; + *tp++ = (u_int8_t) (val >> 8) & 0xff; + *tp++ = (u_int8_t) val & 0xff; + + saw_xdigit = 0; + val = 0; + continue; + } + if (saw_xdigit) { + if (tp + 2 > endp) + return 0; + *tp++ = (u_int8_t) (val >> 8) & 0xff; + *tp++ = (u_int8_t) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + return 0; + + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp || (*src != term)) + return 0; + + memcpy(dst->s6_addr, tmp, sizeof(dst->s6_addr)); + return clen; } static int try_number(const char *data, size_t dlen, u_int32_t array[], diff --git a/trunk/net/netfilter/nf_conntrack_netlink.c b/trunk/net/netfilter/nf_conntrack_netlink.c index 1721f7c78c77..af4845971f70 100644 --- a/trunk/net/netfilter/nf_conntrack_netlink.c +++ b/trunk/net/netfilter/nf_conntrack_netlink.c @@ -339,7 +339,11 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, /* dump everything */ events = ~0UL; group = NFNLGRP_CONNTRACK_NEW; - } else if (events & (IPCT_STATUS | IPCT_PROTOINFO)) { + } else if (events & (IPCT_STATUS | + IPCT_PROTOINFO | + IPCT_HELPER | + IPCT_HELPINFO | + IPCT_NATINFO)) { type = IPCTNL_MSG_CT_NEW; group = NFNLGRP_CONNTRACK_UPDATE; } else @@ -391,10 +395,6 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0) goto nfattr_failure; - if (events & IPCT_MARK - && ctnetlink_dump_mark(skb, ct) < 0) - goto nfattr_failure; - nlh->nlmsg_len = skb->tail - b; nfnetlink_send(skb, 0, group, 0); return NOTIFY_DONE; @@ -429,9 +429,9 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) cb->args[0], *id); read_lock_bh(&nf_conntrack_lock); - last = (struct nf_conn *)cb->args[1]; for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) { restart: + last = (struct nf_conn *)cb->args[1]; list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) { h = (struct nf_conntrack_tuple_hash *) i; if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) @@ -442,10 +442,13 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) * then dump everything. */ if (l3proto && L3PROTO(ct) != l3proto) continue; - if (cb->args[1]) { - if (ct != last) + if (last != NULL) { + if (ct == last) { + nf_ct_put(last); + cb->args[1] = 0; + last = NULL; + } else continue; - cb->args[1] = 0; } if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, @@ -455,26 +458,65 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) cb->args[1] = (unsigned long)ct; goto out; } -#ifdef CONFIG_NF_CT_ACCT - if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == - IPCTNL_MSG_CT_GET_CTRZERO) - memset(&ct->counters, 0, sizeof(ct->counters)); -#endif } - if (cb->args[1]) { + if (last != NULL) { + nf_ct_put(last); cb->args[1] = 0; goto restart; } } out: read_unlock_bh(&nf_conntrack_lock); - if (last) - nf_ct_put(last); DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); + return skb->len; } +#ifdef CONFIG_NF_CT_ACCT +static int +ctnetlink_dump_table_w(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct nf_conn *ct = NULL; + struct nf_conntrack_tuple_hash *h; + struct list_head *i; + u_int32_t *id = (u_int32_t *) &cb->args[1]; + struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh); + u_int8_t l3proto = nfmsg->nfgen_family; + + DEBUGP("entered %s, last bucket=%u id=%u\n", __FUNCTION__, + cb->args[0], *id); + + write_lock_bh(&nf_conntrack_lock); + for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++, *id = 0) { + list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) { + h = (struct nf_conntrack_tuple_hash *) i; + if (DIRECTION(h) != IP_CT_DIR_ORIGINAL) + continue; + ct = nf_ct_tuplehash_to_ctrack(h); + if (l3proto && L3PROTO(ct) != l3proto) + continue; + if (ct->id <= *id) + continue; + if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, + IPCTNL_MSG_CT_NEW, + 1, ct) < 0) + goto out; + *id = ct->id; + + memset(&ct->counters, 0, sizeof(ct->counters)); + } + } +out: + write_unlock_bh(&nf_conntrack_lock); + + DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id); + + return skb->len; +} +#endif + static inline int ctnetlink_parse_tuple_ip(struct nfattr *attr, struct nf_conntrack_tuple *tuple) { @@ -749,14 +791,22 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, if (nlh->nlmsg_flags & NLM_F_DUMP) { u32 rlen; -#ifndef CONFIG_NF_CT_ACCT - if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO) + if (NFNL_MSG_TYPE(nlh->nlmsg_type) == + IPCTNL_MSG_CT_GET_CTRZERO) { +#ifdef CONFIG_NF_CT_ACCT + if ((*errp = netlink_dump_start(ctnl, skb, nlh, + ctnetlink_dump_table_w, + ctnetlink_done)) != 0) + return -EINVAL; +#else return -ENOTSUPP; #endif - if ((*errp = netlink_dump_start(ctnl, skb, nlh, - ctnetlink_dump_table, - ctnetlink_done)) != 0) + } else { + if ((*errp = netlink_dump_start(ctnl, skb, nlh, + ctnetlink_dump_table, + ctnetlink_done)) != 0) return -EINVAL; + } rlen = NLMSG_ALIGN(nlh->nlmsg_len); if (rlen > skb->len) @@ -1227,9 +1277,6 @@ static int ctnetlink_expect_event(struct notifier_block *this, } else return NOTIFY_DONE; - if (!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW)) - return NOTIFY_DONE; - skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); if (!skb) return NOTIFY_DONE; diff --git a/trunk/net/netfilter/nf_conntrack_proto_generic.c b/trunk/net/netfilter/nf_conntrack_proto_generic.c index 26408bb0955b..46bc27e2756d 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_generic.c +++ b/trunk/net/netfilter/nf_conntrack_proto_generic.c @@ -17,7 +17,7 @@ #include #include -unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ; +unsigned int nf_ct_generic_timeout = 600*HZ; static int generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, diff --git a/trunk/net/netfilter/nf_conntrack_proto_sctp.c b/trunk/net/netfilter/nf_conntrack_proto_sctp.c index af568777372b..9bd8a7877fd5 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_sctp.c +++ b/trunk/net/netfilter/nf_conntrack_proto_sctp.c @@ -64,13 +64,13 @@ static const char *sctp_conntrack_names[] = { #define HOURS * 60 MINS #define DAYS * 24 HOURS -static unsigned int nf_ct_sctp_timeout_closed __read_mostly = 10 SECS; -static unsigned int nf_ct_sctp_timeout_cookie_wait __read_mostly = 3 SECS; -static unsigned int nf_ct_sctp_timeout_cookie_echoed __read_mostly = 3 SECS; -static unsigned int nf_ct_sctp_timeout_established __read_mostly = 5 DAYS; -static unsigned int nf_ct_sctp_timeout_shutdown_sent __read_mostly = 300 SECS / 1000; -static unsigned int nf_ct_sctp_timeout_shutdown_recd __read_mostly = 300 SECS / 1000; -static unsigned int nf_ct_sctp_timeout_shutdown_ack_sent __read_mostly = 3 SECS; +static unsigned int nf_ct_sctp_timeout_closed = 10 SECS; +static unsigned int nf_ct_sctp_timeout_cookie_wait = 3 SECS; +static unsigned int nf_ct_sctp_timeout_cookie_echoed = 3 SECS; +static unsigned int nf_ct_sctp_timeout_established = 5 DAYS; +static unsigned int nf_ct_sctp_timeout_shutdown_sent = 300 SECS / 1000; +static unsigned int nf_ct_sctp_timeout_shutdown_recd = 300 SECS / 1000; +static unsigned int nf_ct_sctp_timeout_shutdown_ack_sent = 3 SECS; static unsigned int * sctp_timeouts[] = { NULL, /* SCTP_CONNTRACK_NONE */ diff --git a/trunk/net/netfilter/nf_conntrack_proto_tcp.c b/trunk/net/netfilter/nf_conntrack_proto_tcp.c index 238bbb5b72ef..af8adcba23a7 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_tcp.c +++ b/trunk/net/netfilter/nf_conntrack_proto_tcp.c @@ -57,19 +57,19 @@ static DEFINE_RWLOCK(tcp_lock); /* "Be conservative in what you do, be liberal in what you accept from others." If it's non-zero, we mark only out of window RST segments as INVALID. */ -int nf_ct_tcp_be_liberal __read_mostly = 0; +int nf_ct_tcp_be_liberal = 0; /* When connection is picked up from the middle, how many packets are required to pass in each direction when we assume we are in sync - if any side uses window scaling, we lost the game. If it is set to zero, we disable picking up already established connections. */ -int nf_ct_tcp_loose __read_mostly = 3; +int nf_ct_tcp_loose = 3; /* Max number of the retransmitted packets without receiving an (acceptable) ACK from the destination. If this number is reached, a shorter timer will be started. */ -int nf_ct_tcp_max_retrans __read_mostly = 3; +int nf_ct_tcp_max_retrans = 3; /* FIXME: Examine ipfilter's timeouts and conntrack transitions more closely. They're more complex. --RR */ @@ -92,19 +92,19 @@ static const char *tcp_conntrack_names[] = { #define HOURS * 60 MINS #define DAYS * 24 HOURS -unsigned int nf_ct_tcp_timeout_syn_sent __read_mostly = 2 MINS; -unsigned int nf_ct_tcp_timeout_syn_recv __read_mostly = 60 SECS; -unsigned int nf_ct_tcp_timeout_established __read_mostly = 5 DAYS; -unsigned int nf_ct_tcp_timeout_fin_wait __read_mostly = 2 MINS; -unsigned int nf_ct_tcp_timeout_close_wait __read_mostly = 60 SECS; -unsigned int nf_ct_tcp_timeout_last_ack __read_mostly = 30 SECS; -unsigned int nf_ct_tcp_timeout_time_wait __read_mostly = 2 MINS; -unsigned int nf_ct_tcp_timeout_close __read_mostly = 10 SECS; +unsigned int nf_ct_tcp_timeout_syn_sent = 2 MINS; +unsigned int nf_ct_tcp_timeout_syn_recv = 60 SECS; +unsigned int nf_ct_tcp_timeout_established = 5 DAYS; +unsigned int nf_ct_tcp_timeout_fin_wait = 2 MINS; +unsigned int nf_ct_tcp_timeout_close_wait = 60 SECS; +unsigned int nf_ct_tcp_timeout_last_ack = 30 SECS; +unsigned int nf_ct_tcp_timeout_time_wait = 2 MINS; +unsigned int nf_ct_tcp_timeout_close = 10 SECS; /* RFC1122 says the R2 limit should be at least 100 seconds. Linux uses 15 packets as limit, which corresponds to ~13-30min depending on RTO. */ -unsigned int nf_ct_tcp_timeout_max_retrans __read_mostly = 5 MINS; +unsigned int nf_ct_tcp_timeout_max_retrans = 5 MINS; static unsigned int * tcp_timeouts[] = { NULL, /* TCP_CONNTRACK_NONE */ @@ -688,15 +688,13 @@ static int tcp_in_window(struct ip_ct_tcp *state, if (state->last_dir == dir && state->last_seq == seq && state->last_ack == ack - && state->last_end == end - && state->last_win == win) + && state->last_end == end) state->retrans++; else { state->last_dir = dir; state->last_seq = seq; state->last_ack = ack; state->last_end = end; - state->last_win = win; state->retrans = 0; } } @@ -825,7 +823,8 @@ static int tcp_error(struct sk_buff *skb, /* Checksum invalid? Ignore. * We skip checking packets on the outgoing path - * because the checksum is assumed to be correct. + * because the semantic of CHECKSUM_HW is different there + * and moreover root might send raw packets. */ /* FIXME: Source route IP option packets --RR */ if (nf_conntrack_checksum && diff --git a/trunk/net/netfilter/nf_conntrack_proto_udp.c b/trunk/net/netfilter/nf_conntrack_proto_udp.c index d28981cf9af5..ae07ebe3ab37 100644 --- a/trunk/net/netfilter/nf_conntrack_proto_udp.c +++ b/trunk/net/netfilter/nf_conntrack_proto_udp.c @@ -27,8 +27,8 @@ #include #include -unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ; -unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ; +unsigned int nf_ct_udp_timeout = 30*HZ; +unsigned int nf_ct_udp_timeout_stream = 180*HZ; static int udp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, @@ -131,7 +131,8 @@ static int udp_error(struct sk_buff *skb, unsigned int dataoff, /* Checksum invalid? Ignore. * We skip checking packets on the outgoing path - * because the checksum is assumed to be correct. + * because the semantic of CHECKSUM_HW is different there + * and moreover root might send raw packets. * FIXME: Source route IP option packets --RR */ if (nf_conntrack_checksum && ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) || diff --git a/trunk/net/netfilter/nf_conntrack_standalone.c b/trunk/net/netfilter/nf_conntrack_standalone.c index 5954f6773810..4ef836699962 100644 --- a/trunk/net/netfilter/nf_conntrack_standalone.c +++ b/trunk/net/netfilter/nf_conntrack_standalone.c @@ -37,6 +37,7 @@ #include #include #include +#include #if 0 #define DEBUGP printk @@ -427,7 +428,7 @@ static struct file_operations ct_cpu_seq_fops = { /* Sysctl support */ -int nf_conntrack_checksum __read_mostly = 1; +int nf_conntrack_checksum = 1; #ifdef CONFIG_SYSCTL diff --git a/trunk/net/netfilter/nf_internals.h b/trunk/net/netfilter/nf_internals.h index a981971ce1d5..86e392bfe833 100644 --- a/trunk/net/netfilter/nf_internals.h +++ b/trunk/net/netfilter/nf_internals.h @@ -23,7 +23,7 @@ extern unsigned int nf_iterate(struct list_head *head, int hook_thresh); /* nf_queue.c */ -extern int nf_queue(struct sk_buff *skb, +extern int nf_queue(struct sk_buff **skb, struct list_head *elem, int pf, unsigned int hook, struct net_device *indev, diff --git a/trunk/net/netfilter/nf_queue.c b/trunk/net/netfilter/nf_queue.c index 4d8936ed581d..662a869593bf 100644 --- a/trunk/net/netfilter/nf_queue.c +++ b/trunk/net/netfilter/nf_queue.c @@ -74,13 +74,13 @@ EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers); * Any packet that leaves via this function must come back * through nf_reinject(). */ -static int __nf_queue(struct sk_buff *skb, - struct list_head *elem, - int pf, unsigned int hook, - struct net_device *indev, - struct net_device *outdev, - int (*okfn)(struct sk_buff *), - unsigned int queuenum) +int nf_queue(struct sk_buff **skb, + struct list_head *elem, + int pf, unsigned int hook, + struct net_device *indev, + struct net_device *outdev, + int (*okfn)(struct sk_buff *), + unsigned int queuenum) { int status; struct nf_info *info; @@ -94,14 +94,14 @@ static int __nf_queue(struct sk_buff *skb, read_lock(&queue_handler_lock); if (!queue_handler[pf]) { read_unlock(&queue_handler_lock); - kfree_skb(skb); + kfree_skb(*skb); return 1; } afinfo = nf_get_afinfo(pf); if (!afinfo) { read_unlock(&queue_handler_lock); - kfree_skb(skb); + kfree_skb(*skb); return 1; } @@ -109,9 +109,9 @@ static int __nf_queue(struct sk_buff *skb, if (!info) { if (net_ratelimit()) printk(KERN_ERR "OOM queueing packet %p\n", - skb); + *skb); read_unlock(&queue_handler_lock); - kfree_skb(skb); + kfree_skb(*skb); return 1; } @@ -130,15 +130,15 @@ static int __nf_queue(struct sk_buff *skb, if (outdev) dev_hold(outdev); #ifdef CONFIG_BRIDGE_NETFILTER - if (skb->nf_bridge) { - physindev = skb->nf_bridge->physindev; + if ((*skb)->nf_bridge) { + physindev = (*skb)->nf_bridge->physindev; if (physindev) dev_hold(physindev); - physoutdev = skb->nf_bridge->physoutdev; + physoutdev = (*skb)->nf_bridge->physoutdev; if (physoutdev) dev_hold(physoutdev); } #endif - afinfo->saveroute(skb, info); - status = queue_handler[pf]->outfn(skb, info, queuenum, + afinfo->saveroute(*skb, info); + status = queue_handler[pf]->outfn(*skb, info, queuenum, queue_handler[pf]->data); read_unlock(&queue_handler_lock); @@ -153,7 +153,7 @@ static int __nf_queue(struct sk_buff *skb, #endif module_put(info->elem->owner); kfree(info); - kfree_skb(skb); + kfree_skb(*skb); return 1; } @@ -161,46 +161,6 @@ static int __nf_queue(struct sk_buff *skb, return 1; } -int nf_queue(struct sk_buff *skb, - struct list_head *elem, - int pf, unsigned int hook, - struct net_device *indev, - struct net_device *outdev, - int (*okfn)(struct sk_buff *), - unsigned int queuenum) -{ - struct sk_buff *segs; - - if (!skb_is_gso(skb)) - return __nf_queue(skb, elem, pf, hook, indev, outdev, okfn, - queuenum); - - switch (pf) { - case AF_INET: - skb->protocol = htons(ETH_P_IP); - break; - case AF_INET6: - skb->protocol = htons(ETH_P_IPV6); - break; - } - - segs = skb_gso_segment(skb, 0); - kfree_skb(skb); - if (unlikely(IS_ERR(segs))) - return 1; - - do { - struct sk_buff *nskb = segs->next; - - segs->next = NULL; - if (!__nf_queue(segs, elem, pf, hook, indev, outdev, okfn, - queuenum)) - kfree_skb(segs); - segs = nskb; - } while (segs); - return 1; -} - void nf_reinject(struct sk_buff *skb, struct nf_info *info, unsigned int verdict) { @@ -264,9 +224,9 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info, case NF_STOLEN: break; case NF_QUEUE: - if (!__nf_queue(skb, elem, info->pf, info->hook, - info->indev, info->outdev, info->okfn, - verdict >> NF_VERDICT_BITS)) + if (!nf_queue(&skb, elem, info->pf, info->hook, + info->indev, info->outdev, info->okfn, + verdict >> NF_VERDICT_BITS)) goto next_hook; break; default: diff --git a/trunk/net/netfilter/nfnetlink_log.c b/trunk/net/netfilter/nfnetlink_log.c index b59d3b2bde21..61cdda4e5d3b 100644 --- a/trunk/net/netfilter/nfnetlink_log.c +++ b/trunk/net/netfilter/nfnetlink_log.c @@ -366,9 +366,6 @@ __nfulnl_send(struct nfulnl_instance *inst) if (timer_pending(&inst->timer)) del_timer(&inst->timer); - if (!inst->skb) - return 0; - if (inst->qlen > 1) inst->lastnlh->nlmsg_type = NLMSG_DONE; diff --git a/trunk/net/netfilter/nfnetlink_queue.c b/trunk/net/netfilter/nfnetlink_queue.c index 8eb2473d83e1..49ef41e34c48 100644 --- a/trunk/net/netfilter/nfnetlink_queue.c +++ b/trunk/net/netfilter/nfnetlink_queue.c @@ -377,9 +377,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, break; case NFQNL_COPY_PACKET: - if ((entskb->ip_summed == CHECKSUM_PARTIAL || - entskb->ip_summed == CHECKSUM_COMPLETE) && - (*errp = skb_checksum_help(entskb))) { + if (entskb->ip_summed == CHECKSUM_HW && + (*errp = skb_checksum_help(entskb, + outdev == NULL))) { spin_unlock_bh(&queue->lock); return NULL; } @@ -584,7 +584,7 @@ nfqnl_enqueue_packet(struct sk_buff *skb, struct nf_info *info, queue->queue_dropped++; status = -ENOSPC; if (net_ratelimit()) - printk(KERN_WARNING "nf_queue: full at %d entries, " + printk(KERN_WARNING "ip_queue: full at %d entries, " "dropping packets(s). Dropped: %d\n", queue->queue_total, queue->queue_dropped); goto err_out_free_nskb; @@ -635,7 +635,7 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) diff, GFP_ATOMIC); if (newskb == NULL) { - printk(KERN_WARNING "nf_queue: OOM " + printk(KERN_WARNING "ip_queue: OOM " "in mangle, dropping packet\n"); return -ENOMEM; } diff --git a/trunk/net/netfilter/x_tables.c b/trunk/net/netfilter/x_tables.c index 58522fc65d33..174e8f970095 100644 --- a/trunk/net/netfilter/x_tables.c +++ b/trunk/net/netfilter/x_tables.c @@ -81,41 +81,11 @@ xt_unregister_target(struct xt_target *target) int af = target->family; mutex_lock(&xt[af].mutex); - list_del(&target->list); + LIST_DELETE(&xt[af].target, target); mutex_unlock(&xt[af].mutex); } EXPORT_SYMBOL(xt_unregister_target); -int -xt_register_targets(struct xt_target *target, unsigned int n) -{ - unsigned int i; - int err = 0; - - for (i = 0; i < n; i++) { - err = xt_register_target(&target[i]); - if (err) - goto err; - } - return err; - -err: - if (i > 0) - xt_unregister_targets(target, i); - return err; -} -EXPORT_SYMBOL(xt_register_targets); - -void -xt_unregister_targets(struct xt_target *target, unsigned int n) -{ - unsigned int i; - - for (i = 0; i < n; i++) - xt_unregister_target(&target[i]); -} -EXPORT_SYMBOL(xt_unregister_targets); - int xt_register_match(struct xt_match *match) { @@ -138,41 +108,11 @@ xt_unregister_match(struct xt_match *match) int af = match->family; mutex_lock(&xt[af].mutex); - list_del(&match->list); + LIST_DELETE(&xt[af].match, match); mutex_unlock(&xt[af].mutex); } EXPORT_SYMBOL(xt_unregister_match); -int -xt_register_matches(struct xt_match *match, unsigned int n) -{ - unsigned int i; - int err = 0; - - for (i = 0; i < n; i++) { - err = xt_register_match(&match[i]); - if (err) - goto err; - } - return err; - -err: - if (i > 0) - xt_unregister_matches(match, i); - return err; -} -EXPORT_SYMBOL(xt_register_matches); - -void -xt_unregister_matches(struct xt_match *match, unsigned int n) -{ - unsigned int i; - - for (i = 0; i < n; i++) - xt_unregister_match(&match[i]); -} -EXPORT_SYMBOL(xt_unregister_matches); - /* * These are weird, but module loading must not be done with mutex @@ -333,65 +273,52 @@ int xt_check_match(const struct xt_match *match, unsigned short family, EXPORT_SYMBOL_GPL(xt_check_match); #ifdef CONFIG_COMPAT -int xt_compat_match_offset(struct xt_match *match) -{ - u_int16_t csize = match->compatsize ? : match->matchsize; - return XT_ALIGN(match->matchsize) - COMPAT_XT_ALIGN(csize); -} -EXPORT_SYMBOL_GPL(xt_compat_match_offset); - -void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, - int *size) -{ - struct xt_match *match = m->u.kernel.match; - struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m; - int pad, off = xt_compat_match_offset(match); - u_int16_t msize = cm->u.user.match_size; - - m = *dstptr; - memcpy(m, cm, sizeof(*cm)); - if (match->compat_from_user) - match->compat_from_user(m->data, cm->data); - else - memcpy(m->data, cm->data, msize - sizeof(*cm)); - pad = XT_ALIGN(match->matchsize) - match->matchsize; - if (pad > 0) - memset(m->data + match->matchsize, 0, pad); - - msize += off; - m->u.user.match_size = msize; - - *size += off; - *dstptr += msize; -} -EXPORT_SYMBOL_GPL(xt_compat_match_from_user); - -int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr, - int *size) +int xt_compat_match(void *match, void **dstptr, int *size, int convert) { - struct xt_match *match = m->u.kernel.match; - struct compat_xt_entry_match __user *cm = *dstptr; - int off = xt_compat_match_offset(match); - u_int16_t msize = m->u.user.match_size - off; - - if (copy_to_user(cm, m, sizeof(*cm)) || - put_user(msize, &cm->u.user.match_size)) - return -EFAULT; + struct xt_match *m; + struct compat_xt_entry_match *pcompat_m; + struct xt_entry_match *pm; + u_int16_t msize; + int off, ret; - if (match->compat_to_user) { - if (match->compat_to_user((void __user *)cm->data, m->data)) - return -EFAULT; - } else { - if (copy_to_user(cm->data, m->data, msize - sizeof(*cm))) - return -EFAULT; + ret = 0; + m = ((struct xt_entry_match *)match)->u.kernel.match; + off = XT_ALIGN(m->matchsize) - COMPAT_XT_ALIGN(m->matchsize); + switch (convert) { + case COMPAT_TO_USER: + pm = (struct xt_entry_match *)match; + msize = pm->u.user.match_size; + if (copy_to_user(*dstptr, pm, msize)) { + ret = -EFAULT; + break; + } + msize -= off; + if (put_user(msize, (u_int16_t *)*dstptr)) + ret = -EFAULT; + *size -= off; + *dstptr += msize; + break; + case COMPAT_FROM_USER: + pcompat_m = (struct compat_xt_entry_match *)match; + pm = (struct xt_entry_match *)*dstptr; + msize = pcompat_m->u.user.match_size; + memcpy(pm, pcompat_m, msize); + msize += off; + pm->u.user.match_size = msize; + *size += off; + *dstptr += msize; + break; + case COMPAT_CALC_SIZE: + *size += off; + break; + default: + ret = -ENOPROTOOPT; + break; } - - *size -= off; - *dstptr += msize; - return 0; + return ret; } -EXPORT_SYMBOL_GPL(xt_compat_match_to_user); -#endif /* CONFIG_COMPAT */ +EXPORT_SYMBOL_GPL(xt_compat_match); +#endif int xt_check_target(const struct xt_target *target, unsigned short family, unsigned int size, const char *table, unsigned int hook_mask, @@ -423,64 +350,51 @@ int xt_check_target(const struct xt_target *target, unsigned short family, EXPORT_SYMBOL_GPL(xt_check_target); #ifdef CONFIG_COMPAT -int xt_compat_target_offset(struct xt_target *target) +int xt_compat_target(void *target, void **dstptr, int *size, int convert) { - u_int16_t csize = target->compatsize ? : target->targetsize; - return XT_ALIGN(target->targetsize) - COMPAT_XT_ALIGN(csize); -} -EXPORT_SYMBOL_GPL(xt_compat_target_offset); - -void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, - int *size) -{ - struct xt_target *target = t->u.kernel.target; - struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t; - int pad, off = xt_compat_target_offset(target); - u_int16_t tsize = ct->u.user.target_size; - - t = *dstptr; - memcpy(t, ct, sizeof(*ct)); - if (target->compat_from_user) - target->compat_from_user(t->data, ct->data); - else - memcpy(t->data, ct->data, tsize - sizeof(*ct)); - pad = XT_ALIGN(target->targetsize) - target->targetsize; - if (pad > 0) - memset(t->data + target->targetsize, 0, pad); - - tsize += off; - t->u.user.target_size = tsize; - - *size += off; - *dstptr += tsize; -} -EXPORT_SYMBOL_GPL(xt_compat_target_from_user); - -int xt_compat_target_to_user(struct xt_entry_target *t, void __user **dstptr, - int *size) -{ - struct xt_target *target = t->u.kernel.target; - struct compat_xt_entry_target __user *ct = *dstptr; - int off = xt_compat_target_offset(target); - u_int16_t tsize = t->u.user.target_size - off; - - if (copy_to_user(ct, t, sizeof(*ct)) || - put_user(tsize, &ct->u.user.target_size)) - return -EFAULT; + struct xt_target *t; + struct compat_xt_entry_target *pcompat; + struct xt_entry_target *pt; + u_int16_t tsize; + int off, ret; - if (target->compat_to_user) { - if (target->compat_to_user((void __user *)ct->data, t->data)) - return -EFAULT; - } else { - if (copy_to_user(ct->data, t->data, tsize - sizeof(*ct))) - return -EFAULT; + ret = 0; + t = ((struct xt_entry_target *)target)->u.kernel.target; + off = XT_ALIGN(t->targetsize) - COMPAT_XT_ALIGN(t->targetsize); + switch (convert) { + case COMPAT_TO_USER: + pt = (struct xt_entry_target *)target; + tsize = pt->u.user.target_size; + if (copy_to_user(*dstptr, pt, tsize)) { + ret = -EFAULT; + break; + } + tsize -= off; + if (put_user(tsize, (u_int16_t *)*dstptr)) + ret = -EFAULT; + *size -= off; + *dstptr += tsize; + break; + case COMPAT_FROM_USER: + pcompat = (struct compat_xt_entry_target *)target; + pt = (struct xt_entry_target *)*dstptr; + tsize = pcompat->u.user.target_size; + memcpy(pt, pcompat, tsize); + tsize += off; + pt->u.user.target_size = tsize; + *size += off; + *dstptr += tsize; + break; + case COMPAT_CALC_SIZE: + *size += off; + break; + default: + ret = -ENOPROTOOPT; + break; } - - *size -= off; - *dstptr += tsize; - return 0; + return ret; } -EXPORT_SYMBOL_GPL(xt_compat_target_to_user); +EXPORT_SYMBOL_GPL(xt_compat_target); #endif struct xt_table_info *xt_alloc_table_info(unsigned int size) @@ -601,18 +515,15 @@ int xt_register_table(struct xt_table *table, { int ret; struct xt_table_info *private; - struct xt_table *t; ret = mutex_lock_interruptible(&xt[table->af].mutex); if (ret != 0) return ret; /* Don't autoload: we'd eat our tail... */ - list_for_each_entry(t, &xt[table->af].tables, list) { - if (strcmp(t->name, table->name) == 0) { - ret = -EEXIST; - goto unlock; - } + if (list_named_find(&xt[table->af].tables, table->name)) { + ret = -EEXIST; + goto unlock; } /* Simplifies replace_table code. */ @@ -627,7 +538,7 @@ int xt_register_table(struct xt_table *table, /* save number of initial entries */ private->initial_entries = private->number; - list_add(&table->list, &xt[table->af].tables); + list_prepend(&xt[table->af].tables, table); ret = 0; unlock: @@ -642,7 +553,7 @@ void *xt_unregister_table(struct xt_table *table) mutex_lock(&xt[table->af].mutex); private = table->private; - list_del(&table->list); + LIST_DELETE(&xt[table->af].tables, table); mutex_unlock(&xt[table->af].mutex); return private; diff --git a/trunk/net/netfilter/xt_CLASSIFY.c b/trunk/net/netfilter/xt_CLASSIFY.c index 50de965bb104..e54e57730012 100644 --- a/trunk/net/netfilter/xt_CLASSIFY.c +++ b/trunk/net/netfilter/xt_CLASSIFY.c @@ -29,7 +29,8 @@ target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { const struct xt_classify_target_info *clinfo = targinfo; @@ -39,41 +40,47 @@ target(struct sk_buff **pskb, return XT_CONTINUE; } -static struct xt_target xt_classify_target[] = { - { - .family = AF_INET, - .name = "CLASSIFY", - .target = target, - .targetsize = sizeof(struct xt_classify_target_info), - .table = "mangle", - .hooks = (1 << NF_IP_LOCAL_OUT) | - (1 << NF_IP_FORWARD) | - (1 << NF_IP_POST_ROUTING), - .me = THIS_MODULE, - }, - { - .name = "CLASSIFY", - .family = AF_INET6, - .target = target, - .targetsize = sizeof(struct xt_classify_target_info), - .table = "mangle", - .hooks = (1 << NF_IP_LOCAL_OUT) | - (1 << NF_IP_FORWARD) | - (1 << NF_IP_POST_ROUTING), - .me = THIS_MODULE, - }, +static struct xt_target classify_reg = { + .name = "CLASSIFY", + .target = target, + .targetsize = sizeof(struct xt_classify_target_info), + .table = "mangle", + .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) | + (1 << NF_IP_POST_ROUTING), + .family = AF_INET, + .me = THIS_MODULE, }; +static struct xt_target classify6_reg = { + .name = "CLASSIFY", + .target = target, + .targetsize = sizeof(struct xt_classify_target_info), + .table = "mangle", + .hooks = (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_FORWARD) | + (1 << NF_IP_POST_ROUTING), + .family = AF_INET6, + .me = THIS_MODULE, +}; + static int __init xt_classify_init(void) { - return xt_register_targets(xt_classify_target, - ARRAY_SIZE(xt_classify_target)); + int ret; + + ret = xt_register_target(&classify_reg); + if (ret) + return ret; + + ret = xt_register_target(&classify6_reg); + if (ret) + xt_unregister_target(&classify_reg); + + return ret; } static void __exit xt_classify_fini(void) { - xt_unregister_targets(xt_classify_target, - ARRAY_SIZE(xt_classify_target)); + xt_unregister_target(&classify_reg); + xt_unregister_target(&classify6_reg); } module_init(xt_classify_init); diff --git a/trunk/net/netfilter/xt_CONNMARK.c b/trunk/net/netfilter/xt_CONNMARK.c index c01524f817f0..60c375d36f01 100644 --- a/trunk/net/netfilter/xt_CONNMARK.c +++ b/trunk/net/netfilter/xt_CONNMARK.c @@ -38,7 +38,8 @@ target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { const struct xt_connmark_target_info *markinfo = targinfo; u_int32_t diff; @@ -48,37 +49,24 @@ target(struct sk_buff **pskb, u_int32_t *ctmark = nf_ct_get_mark(*pskb, &ctinfo); if (ctmark) { - switch(markinfo->mode) { - case XT_CONNMARK_SET: - newmark = (*ctmark & ~markinfo->mask) | markinfo->mark; - if (newmark != *ctmark) { - *ctmark = newmark; -#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) - ip_conntrack_event_cache(IPCT_MARK, *pskb); -#else - nf_conntrack_event_cache(IPCT_MARK, *pskb); -#endif - } - break; - case XT_CONNMARK_SAVE: - newmark = (*ctmark & ~markinfo->mask) | - ((*pskb)->nfmark & markinfo->mask); - if (*ctmark != newmark) { - *ctmark = newmark; -#if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) - ip_conntrack_event_cache(IPCT_MARK, *pskb); -#else - nf_conntrack_event_cache(IPCT_MARK, *pskb); -#endif - } - break; - case XT_CONNMARK_RESTORE: - nfmark = (*pskb)->nfmark; - diff = (*ctmark ^ nfmark) & markinfo->mask; - if (diff != 0) - (*pskb)->nfmark = nfmark ^ diff; - break; - } + switch(markinfo->mode) { + case XT_CONNMARK_SET: + newmark = (*ctmark & ~markinfo->mask) | markinfo->mark; + if (newmark != *ctmark) + *ctmark = newmark; + break; + case XT_CONNMARK_SAVE: + newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); + if (*ctmark != newmark) + *ctmark = newmark; + break; + case XT_CONNMARK_RESTORE: + nfmark = (*pskb)->nfmark; + diff = (*ctmark ^ nfmark) & markinfo->mask; + if (diff != 0) + (*pskb)->nfmark = nfmark ^ diff; + break; + } } return XT_CONTINUE; @@ -89,91 +77,65 @@ checkentry(const char *tablename, const void *entry, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { struct xt_connmark_target_info *matchinfo = targinfo; if (matchinfo->mode == XT_CONNMARK_RESTORE) { - if (strcmp(tablename, "mangle") != 0) { - printk(KERN_WARNING "CONNMARK: restore can only be " - "called from \"mangle\" table, not \"%s\"\n", - tablename); - return 0; - } + if (strcmp(tablename, "mangle") != 0) { + printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename); + return 0; + } } + if (matchinfo->mark > 0xffffffff || matchinfo->mask > 0xffffffff) { printk(KERN_WARNING "CONNMARK: Only supports 32bit mark\n"); return 0; } + return 1; } -#ifdef CONFIG_COMPAT -struct compat_xt_connmark_target_info { - compat_ulong_t mark, mask; - u_int8_t mode; - u_int8_t __pad1; - u_int16_t __pad2; +static struct xt_target connmark_reg = { + .name = "CONNMARK", + .target = target, + .targetsize = sizeof(struct xt_connmark_target_info), + .checkentry = checkentry, + .family = AF_INET, + .me = THIS_MODULE }; -static void compat_from_user(void *dst, void *src) -{ - struct compat_xt_connmark_target_info *cm = src; - struct xt_connmark_target_info m = { - .mark = cm->mark, - .mask = cm->mask, - .mode = cm->mode, - }; - memcpy(dst, &m, sizeof(m)); -} - -static int compat_to_user(void __user *dst, void *src) -{ - struct xt_connmark_target_info *m = src; - struct compat_xt_connmark_target_info cm = { - .mark = m->mark, - .mask = m->mask, - .mode = m->mode, - }; - return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; -} -#endif /* CONFIG_COMPAT */ - -static struct xt_target xt_connmark_target[] = { - { - .name = "CONNMARK", - .family = AF_INET, - .checkentry = checkentry, - .target = target, - .targetsize = sizeof(struct xt_connmark_target_info), -#ifdef CONFIG_COMPAT - .compatsize = sizeof(struct compat_xt_connmark_target_info), - .compat_from_user = compat_from_user, - .compat_to_user = compat_to_user, -#endif - .me = THIS_MODULE - }, - { - .name = "CONNMARK", - .family = AF_INET6, - .checkentry = checkentry, - .target = target, - .targetsize = sizeof(struct xt_connmark_target_info), - .me = THIS_MODULE - }, +static struct xt_target connmark6_reg = { + .name = "CONNMARK", + .target = target, + .targetsize = sizeof(struct xt_connmark_target_info), + .checkentry = checkentry, + .family = AF_INET6, + .me = THIS_MODULE }; static int __init xt_connmark_init(void) { + int ret; + need_conntrack(); - return xt_register_targets(xt_connmark_target, - ARRAY_SIZE(xt_connmark_target)); + + ret = xt_register_target(&connmark_reg); + if (ret) + return ret; + + ret = xt_register_target(&connmark6_reg); + if (ret) + xt_unregister_target(&connmark_reg); + + return ret; } static void __exit xt_connmark_fini(void) { - xt_unregister_targets(xt_connmark_target, - ARRAY_SIZE(xt_connmark_target)); + xt_unregister_target(&connmark_reg); + xt_unregister_target(&connmark6_reg); } module_init(xt_connmark_init); diff --git a/trunk/net/netfilter/xt_CONNSECMARK.c b/trunk/net/netfilter/xt_CONNSECMARK.c index 467386266674..8c011e020769 100644 --- a/trunk/net/netfilter/xt_CONNSECMARK.c +++ b/trunk/net/netfilter/xt_CONNSECMARK.c @@ -66,7 +66,7 @@ static void secmark_restore(struct sk_buff *skb) static unsigned int target(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, void *userinfo) { struct sk_buff *skb = *pskb; const struct xt_connsecmark_target_info *info = targinfo; @@ -89,7 +89,7 @@ static unsigned int target(struct sk_buff **pskb, const struct net_device *in, static int checkentry(const char *tablename, const void *entry, const struct xt_target *target, void *targinfo, - unsigned int hook_mask) + unsigned int targinfosize, unsigned int hook_mask) { struct xt_connsecmark_target_info *info = targinfo; @@ -106,38 +106,49 @@ static int checkentry(const char *tablename, const void *entry, return 1; } -static struct xt_target xt_connsecmark_target[] = { - { - .name = "CONNSECMARK", - .family = AF_INET, - .checkentry = checkentry, - .target = target, - .targetsize = sizeof(struct xt_connsecmark_target_info), - .table = "mangle", - .me = THIS_MODULE, - }, - { - .name = "CONNSECMARK", - .family = AF_INET6, - .checkentry = checkentry, - .target = target, - .targetsize = sizeof(struct xt_connsecmark_target_info), - .table = "mangle", - .me = THIS_MODULE, - }, +static struct xt_target ipt_connsecmark_reg = { + .name = "CONNSECMARK", + .target = target, + .targetsize = sizeof(struct xt_connsecmark_target_info), + .table = "mangle", + .checkentry = checkentry, + .me = THIS_MODULE, + .family = AF_INET, + .revision = 0, +}; + +static struct xt_target ip6t_connsecmark_reg = { + .name = "CONNSECMARK", + .target = target, + .targetsize = sizeof(struct xt_connsecmark_target_info), + .table = "mangle", + .checkentry = checkentry, + .me = THIS_MODULE, + .family = AF_INET6, + .revision = 0, }; static int __init xt_connsecmark_init(void) { + int err; + need_conntrack(); - return xt_register_targets(xt_connsecmark_target, - ARRAY_SIZE(xt_connsecmark_target)); + + err = xt_register_target(&ipt_connsecmark_reg); + if (err) + return err; + + err = xt_register_target(&ip6t_connsecmark_reg); + if (err) + xt_unregister_target(&ipt_connsecmark_reg); + + return err; } static void __exit xt_connsecmark_fini(void) { - xt_unregister_targets(xt_connsecmark_target, - ARRAY_SIZE(xt_connsecmark_target)); + xt_unregister_target(&ip6t_connsecmark_reg); + xt_unregister_target(&ipt_connsecmark_reg); } module_init(xt_connsecmark_init); diff --git a/trunk/net/netfilter/xt_DSCP.c b/trunk/net/netfilter/xt_DSCP.c deleted file mode 100644 index a7cc75aeb38d..000000000000 --- a/trunk/net/netfilter/xt_DSCP.c +++ /dev/null @@ -1,118 +0,0 @@ -/* x_tables module for setting the IPv4/IPv6 DSCP field, Version 1.8 - * - * (C) 2002 by Harald Welte - * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * See RFC2474 for a description of the DSCP field within the IP Header. - * - * xt_DSCP.c,v 1.8 2002/08/06 18:41:57 laforge Exp -*/ - -#include -#include -#include -#include -#include - -#include -#include - -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("x_tables DSCP modification module"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("ipt_DSCP"); -MODULE_ALIAS("ip6t_DSCP"); - -static unsigned int target(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const struct xt_target *target, - const void *targinfo) -{ - const struct xt_DSCP_info *dinfo = targinfo; - u_int8_t dscp = ipv4_get_dsfield((*pskb)->nh.iph) >> XT_DSCP_SHIFT; - - if (dscp != dinfo->dscp) { - if (!skb_make_writable(pskb, sizeof(struct iphdr))) - return NF_DROP; - - ipv4_change_dsfield((*pskb)->nh.iph, (__u8)(~XT_DSCP_MASK), - dinfo->dscp << XT_DSCP_SHIFT); - - } - return XT_CONTINUE; -} - -static unsigned int target6(struct sk_buff **pskb, - const struct net_device *in, - const struct net_device *out, - unsigned int hooknum, - const struct xt_target *target, - const void *targinfo) -{ - const struct xt_DSCP_info *dinfo = targinfo; - u_int8_t dscp = ipv6_get_dsfield((*pskb)->nh.ipv6h) >> XT_DSCP_SHIFT; - - if (dscp != dinfo->dscp) { - if (!skb_make_writable(pskb, sizeof(struct ipv6hdr))) - return NF_DROP; - - ipv6_change_dsfield((*pskb)->nh.ipv6h, (__u8)(~XT_DSCP_MASK), - dinfo->dscp << XT_DSCP_SHIFT); - } - return XT_CONTINUE; -} - -static int checkentry(const char *tablename, - const void *e_void, - const struct xt_target *target, - void *targinfo, - unsigned int hook_mask) -{ - const u_int8_t dscp = ((struct xt_DSCP_info *)targinfo)->dscp; - - if ((dscp > XT_DSCP_MAX)) { - printk(KERN_WARNING "DSCP: dscp %x out of range\n", dscp); - return 0; - } - return 1; -} - -static struct xt_target xt_dscp_target[] = { - { - .name = "DSCP", - .family = AF_INET, - .checkentry = checkentry, - .target = target, - .targetsize = sizeof(struct xt_DSCP_info), - .table = "mangle", - .me = THIS_MODULE, - }, - { - .name = "DSCP", - .family = AF_INET6, - .checkentry = checkentry, - .target = target6, - .targetsize = sizeof(struct xt_DSCP_info), - .table = "mangle", - .me = THIS_MODULE, - }, -}; - -static int __init xt_dscp_target_init(void) -{ - return xt_register_targets(xt_dscp_target, ARRAY_SIZE(xt_dscp_target)); -} - -static void __exit xt_dscp_target_fini(void) -{ - xt_unregister_targets(xt_dscp_target, ARRAY_SIZE(xt_dscp_target)); -} - -module_init(xt_dscp_target_init); -module_exit(xt_dscp_target_fini); diff --git a/trunk/net/netfilter/xt_MARK.c b/trunk/net/netfilter/xt_MARK.c index c6e860a7114f..ee9c34edc76c 100644 --- a/trunk/net/netfilter/xt_MARK.c +++ b/trunk/net/netfilter/xt_MARK.c @@ -27,7 +27,8 @@ target_v0(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { const struct xt_mark_target_info *markinfo = targinfo; @@ -43,7 +44,8 @@ target_v1(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { const struct xt_mark_target_info_v1 *markinfo = targinfo; int mark = 0; @@ -74,6 +76,7 @@ checkentry_v0(const char *tablename, const void *entry, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { struct xt_mark_target_info *markinfo = targinfo; @@ -90,6 +93,7 @@ checkentry_v1(const char *tablename, const void *entry, const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) { struct xt_mark_target_info_v1 *markinfo = targinfo; @@ -108,81 +112,65 @@ checkentry_v1(const char *tablename, return 1; } -#ifdef CONFIG_COMPAT -struct compat_xt_mark_target_info_v1 { - compat_ulong_t mark; - u_int8_t mode; - u_int8_t __pad1; - u_int16_t __pad2; +static struct xt_target ipt_mark_reg_v0 = { + .name = "MARK", + .target = target_v0, + .targetsize = sizeof(struct xt_mark_target_info), + .table = "mangle", + .checkentry = checkentry_v0, + .me = THIS_MODULE, + .family = AF_INET, + .revision = 0, }; -static void compat_from_user_v1(void *dst, void *src) -{ - struct compat_xt_mark_target_info_v1 *cm = src; - struct xt_mark_target_info_v1 m = { - .mark = cm->mark, - .mode = cm->mode, - }; - memcpy(dst, &m, sizeof(m)); -} +static struct xt_target ipt_mark_reg_v1 = { + .name = "MARK", + .target = target_v1, + .targetsize = sizeof(struct xt_mark_target_info_v1), + .table = "mangle", + .checkentry = checkentry_v1, + .me = THIS_MODULE, + .family = AF_INET, + .revision = 1, +}; -static int compat_to_user_v1(void __user *dst, void *src) -{ - struct xt_mark_target_info_v1 *m = src; - struct compat_xt_mark_target_info_v1 cm = { - .mark = m->mark, - .mode = m->mode, - }; - return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; -} -#endif /* CONFIG_COMPAT */ - -static struct xt_target xt_mark_target[] = { - { - .name = "MARK", - .family = AF_INET, - .revision = 0, - .checkentry = checkentry_v0, - .target = target_v0, - .targetsize = sizeof(struct xt_mark_target_info), - .table = "mangle", - .me = THIS_MODULE, - }, - { - .name = "MARK", - .family = AF_INET, - .revision = 1, - .checkentry = checkentry_v1, - .target = target_v1, - .targetsize = sizeof(struct xt_mark_target_info_v1), -#ifdef CONFIG_COMPAT - .compatsize = sizeof(struct compat_xt_mark_target_info_v1), - .compat_from_user = compat_from_user_v1, - .compat_to_user = compat_to_user_v1, -#endif - .table = "mangle", - .me = THIS_MODULE, - }, - { - .name = "MARK", - .family = AF_INET6, - .revision = 0, - .checkentry = checkentry_v0, - .target = target_v0, - .targetsize = sizeof(struct xt_mark_target_info), - .table = "mangle", - .me = THIS_MODULE, - }, +static struct xt_target ip6t_mark_reg_v0 = { + .name = "MARK", + .target = target_v0, + .targetsize = sizeof(struct xt_mark_target_info), + .table = "mangle", + .checkentry = checkentry_v0, + .me = THIS_MODULE, + .family = AF_INET6, + .revision = 0, }; static int __init xt_mark_init(void) { - return xt_register_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target)); + int err; + + err = xt_register_target(&ipt_mark_reg_v0); + if (err) + return err; + + err = xt_register_target(&ipt_mark_reg_v1); + if (err) + xt_unregister_target(&ipt_mark_reg_v0); + + err = xt_register_target(&ip6t_mark_reg_v0); + if (err) { + xt_unregister_target(&ipt_mark_reg_v0); + xt_unregister_target(&ipt_mark_reg_v1); + } + + return err; } static void __exit xt_mark_fini(void) { - xt_unregister_targets(xt_mark_target, ARRAY_SIZE(xt_mark_target)); + xt_unregister_target(&ipt_mark_reg_v0); + xt_unregister_target(&ipt_mark_reg_v1); + xt_unregister_target(&ip6t_mark_reg_v0); } module_init(xt_mark_init); diff --git a/trunk/net/netfilter/xt_NFQUEUE.c b/trunk/net/netfilter/xt_NFQUEUE.c index db9b896e57c8..86ccceb61fdd 100644 --- a/trunk/net/netfilter/xt_NFQUEUE.c +++ b/trunk/net/netfilter/xt_NFQUEUE.c @@ -29,46 +29,65 @@ target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { const struct xt_NFQ_info *tinfo = targinfo; return NF_QUEUE_NR(tinfo->queuenum); } -static struct xt_target xt_nfqueue_target[] = { - { - .name = "NFQUEUE", - .family = AF_INET, - .target = target, - .targetsize = sizeof(struct xt_NFQ_info), - .me = THIS_MODULE, - }, - { - .name = "NFQUEUE", - .family = AF_INET6, - .target = target, - .targetsize = sizeof(struct xt_NFQ_info), - .me = THIS_MODULE, - }, - { - .name = "NFQUEUE", - .family = NF_ARP, - .target = target, - .targetsize = sizeof(struct xt_NFQ_info), - .me = THIS_MODULE, - }, +static struct xt_target ipt_NFQ_reg = { + .name = "NFQUEUE", + .target = target, + .targetsize = sizeof(struct xt_NFQ_info), + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_target ip6t_NFQ_reg = { + .name = "NFQUEUE", + .target = target, + .targetsize = sizeof(struct xt_NFQ_info), + .family = AF_INET6, + .me = THIS_MODULE, +}; + +static struct xt_target arpt_NFQ_reg = { + .name = "NFQUEUE", + .target = target, + .targetsize = sizeof(struct xt_NFQ_info), + .family = NF_ARP, + .me = THIS_MODULE, }; static int __init xt_nfqueue_init(void) { - return xt_register_targets(xt_nfqueue_target, - ARRAY_SIZE(xt_nfqueue_target)); + int ret; + ret = xt_register_target(&ipt_NFQ_reg); + if (ret) + return ret; + ret = xt_register_target(&ip6t_NFQ_reg); + if (ret) + goto out_ip; + ret = xt_register_target(&arpt_NFQ_reg); + if (ret) + goto out_ip6; + + return ret; +out_ip6: + xt_unregister_target(&ip6t_NFQ_reg); +out_ip: + xt_unregister_target(&ipt_NFQ_reg); + + return ret; } static void __exit xt_nfqueue_fini(void) { - xt_register_targets(xt_nfqueue_target, ARRAY_SIZE(xt_nfqueue_target)); + xt_unregister_target(&arpt_NFQ_reg); + xt_unregister_target(&ip6t_NFQ_reg); + xt_unregister_target(&ipt_NFQ_reg); } module_init(xt_nfqueue_init); diff --git a/trunk/net/netfilter/xt_NOTRACK.c b/trunk/net/netfilter/xt_NOTRACK.c index 6d00dcaed238..98f4b5363ce8 100644 --- a/trunk/net/netfilter/xt_NOTRACK.c +++ b/trunk/net/netfilter/xt_NOTRACK.c @@ -16,7 +16,8 @@ target(struct sk_buff **pskb, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, + void *userinfo) { /* Previously seen (loopback)? Ignore. */ if ((*pskb)->nfct != NULL) @@ -33,32 +34,43 @@ target(struct sk_buff **pskb, return XT_CONTINUE; } -static struct xt_target xt_notrack_target[] = { - { - .name = "NOTRACK", - .family = AF_INET, - .target = target, - .table = "raw", - .me = THIS_MODULE, - }, - { - .name = "NOTRACK", - .family = AF_INET6, - .target = target, - .table = "raw", - .me = THIS_MODULE, - }, +static struct xt_target notrack_reg = { + .name = "NOTRACK", + .target = target, + .targetsize = 0, + .table = "raw", + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_target notrack6_reg = { + .name = "NOTRACK", + .target = target, + .targetsize = 0, + .table = "raw", + .family = AF_INET6, + .me = THIS_MODULE, }; static int __init xt_notrack_init(void) { - return xt_register_targets(xt_notrack_target, - ARRAY_SIZE(xt_notrack_target)); + int ret; + + ret = xt_register_target(¬rack_reg); + if (ret) + return ret; + + ret = xt_register_target(¬rack6_reg); + if (ret) + xt_unregister_target(¬rack_reg); + + return ret; } static void __exit xt_notrack_fini(void) { - xt_unregister_targets(xt_notrack_target, ARRAY_SIZE(xt_notrack_target)); + xt_unregister_target(¬rack6_reg); + xt_unregister_target(¬rack_reg); } module_init(xt_notrack_init); diff --git a/trunk/net/netfilter/xt_SECMARK.c b/trunk/net/netfilter/xt_SECMARK.c index add752196290..c2ce9c4011cc 100644 --- a/trunk/net/netfilter/xt_SECMARK.c +++ b/trunk/net/netfilter/xt_SECMARK.c @@ -31,7 +31,7 @@ static u8 mode; static unsigned int target(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, const struct xt_target *target, - const void *targinfo) + const void *targinfo, void *userinfo) { u32 secmark = 0; const struct xt_secmark_target_info *info = targinfo; @@ -57,8 +57,6 @@ static int checkentry_selinux(struct xt_secmark_target_info *info) { int err; struct xt_secmark_target_selinux_info *sel = &info->u.sel; - - sel->selctx[SECMARK_SELCTX_MAX - 1] = '\0'; err = selinux_string_to_sid(sel->selctx, &sel->selsid); if (err) { @@ -85,7 +83,7 @@ static int checkentry_selinux(struct xt_secmark_target_info *info) static int checkentry(const char *tablename, const void *entry, const struct xt_target *target, void *targinfo, - unsigned int hook_mask) + unsigned int targinfosize, unsigned int hook_mask) { struct xt_secmark_target_info *info = targinfo; @@ -111,36 +109,47 @@ static int checkentry(const char *tablename, const void *entry, return 1; } -static struct xt_target xt_secmark_target[] = { - { - .name = "SECMARK", - .family = AF_INET, - .checkentry = checkentry, - .target = target, - .targetsize = sizeof(struct xt_secmark_target_info), - .table = "mangle", - .me = THIS_MODULE, - }, - { - .name = "SECMARK", - .family = AF_INET6, - .checkentry = checkentry, - .target = target, - .targetsize = sizeof(struct xt_secmark_target_info), - .table = "mangle", - .me = THIS_MODULE, - }, +static struct xt_target ipt_secmark_reg = { + .name = "SECMARK", + .target = target, + .targetsize = sizeof(struct xt_secmark_target_info), + .table = "mangle", + .checkentry = checkentry, + .me = THIS_MODULE, + .family = AF_INET, + .revision = 0, +}; + +static struct xt_target ip6t_secmark_reg = { + .name = "SECMARK", + .target = target, + .targetsize = sizeof(struct xt_secmark_target_info), + .table = "mangle", + .checkentry = checkentry, + .me = THIS_MODULE, + .family = AF_INET6, + .revision = 0, }; static int __init xt_secmark_init(void) { - return xt_register_targets(xt_secmark_target, - ARRAY_SIZE(xt_secmark_target)); + int err; + + err = xt_register_target(&ipt_secmark_reg); + if (err) + return err; + + err = xt_register_target(&ip6t_secmark_reg); + if (err) + xt_unregister_target(&ipt_secmark_reg); + + return err; } static void __exit xt_secmark_fini(void) { - xt_unregister_targets(xt_secmark_target, ARRAY_SIZE(xt_secmark_target)); + xt_unregister_target(&ip6t_secmark_reg); + xt_unregister_target(&ipt_secmark_reg); } module_init(xt_secmark_init); diff --git a/trunk/net/netfilter/xt_comment.c b/trunk/net/netfilter/xt_comment.c index 7db492d65220..197609cb06d7 100644 --- a/trunk/net/netfilter/xt_comment.c +++ b/trunk/net/netfilter/xt_comment.c @@ -29,32 +29,41 @@ match(const struct sk_buff *skb, return 1; } -static struct xt_match xt_comment_match[] = { - { - .name = "comment", - .family = AF_INET, - .match = match, - .matchsize = sizeof(struct xt_comment_info), - .me = THIS_MODULE - }, - { - .name = "comment", - .family = AF_INET6, - .match = match, - .matchsize = sizeof(struct xt_comment_info), - .me = THIS_MODULE - }, +static struct xt_match comment_match = { + .name = "comment", + .match = match, + .matchsize = sizeof(struct xt_comment_info), + .family = AF_INET, + .me = THIS_MODULE +}; + +static struct xt_match comment6_match = { + .name = "comment", + .match = match, + .matchsize = sizeof(struct xt_comment_info), + .family = AF_INET6, + .me = THIS_MODULE }; static int __init xt_comment_init(void) { - return xt_register_matches(xt_comment_match, - ARRAY_SIZE(xt_comment_match)); + int ret; + + ret = xt_register_match(&comment_match); + if (ret) + return ret; + + ret = xt_register_match(&comment6_match); + if (ret) + xt_unregister_match(&comment_match); + + return ret; } static void __exit xt_comment_fini(void) { - xt_unregister_matches(xt_comment_match, ARRAY_SIZE(xt_comment_match)); + xt_unregister_match(&comment_match); + xt_unregister_match(&comment6_match); } module_init(xt_comment_init); diff --git a/trunk/net/netfilter/xt_connbytes.c b/trunk/net/netfilter/xt_connbytes.c index dcc497ea8183..1396fe2d07c1 100644 --- a/trunk/net/netfilter/xt_connbytes.c +++ b/trunk/net/netfilter/xt_connbytes.c @@ -125,6 +125,7 @@ static int check(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct xt_connbytes_info *sinfo = matchinfo; @@ -142,35 +143,40 @@ static int check(const char *tablename, return 1; } -static struct xt_match xt_connbytes_match[] = { - { - .name = "connbytes", - .family = AF_INET, - .checkentry = check, - .match = match, - .matchsize = sizeof(struct xt_connbytes_info), - .me = THIS_MODULE - }, - { - .name = "connbytes", - .family = AF_INET6, - .checkentry = check, - .match = match, - .matchsize = sizeof(struct xt_connbytes_info), - .me = THIS_MODULE - }, +static struct xt_match connbytes_match = { + .name = "connbytes", + .match = match, + .checkentry = check, + .matchsize = sizeof(struct xt_connbytes_info), + .family = AF_INET, + .me = THIS_MODULE +}; +static struct xt_match connbytes6_match = { + .name = "connbytes", + .match = match, + .checkentry = check, + .matchsize = sizeof(struct xt_connbytes_info), + .family = AF_INET6, + .me = THIS_MODULE }; static int __init xt_connbytes_init(void) { - return xt_register_matches(xt_connbytes_match, - ARRAY_SIZE(xt_connbytes_match)); + int ret; + ret = xt_register_match(&connbytes_match); + if (ret) + return ret; + + ret = xt_register_match(&connbytes6_match); + if (ret) + xt_unregister_match(&connbytes_match); + return ret; } static void __exit xt_connbytes_fini(void) { - xt_unregister_matches(xt_connbytes_match, - ARRAY_SIZE(xt_connbytes_match)); + xt_unregister_match(&connbytes_match); + xt_unregister_match(&connbytes6_match); } module_init(xt_connbytes_init); diff --git a/trunk/net/netfilter/xt_connmark.c b/trunk/net/netfilter/xt_connmark.c index 92a5726ef237..56324c8aff0a 100644 --- a/trunk/net/netfilter/xt_connmark.c +++ b/trunk/net/netfilter/xt_connmark.c @@ -55,6 +55,7 @@ checkentry(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { struct xt_connmark_info *cm = matchinfo; @@ -74,80 +75,53 @@ checkentry(const char *tablename, } static void -destroy(const struct xt_match *match, void *matchinfo) +destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize) { #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) nf_ct_l3proto_module_put(match->family); #endif } -#ifdef CONFIG_COMPAT -struct compat_xt_connmark_info { - compat_ulong_t mark, mask; - u_int8_t invert; - u_int8_t __pad1; - u_int16_t __pad2; +static struct xt_match connmark_match = { + .name = "connmark", + .match = match, + .matchsize = sizeof(struct xt_connmark_info), + .checkentry = checkentry, + .destroy = destroy, + .family = AF_INET, + .me = THIS_MODULE }; -static void compat_from_user(void *dst, void *src) -{ - struct compat_xt_connmark_info *cm = src; - struct xt_connmark_info m = { - .mark = cm->mark, - .mask = cm->mask, - .invert = cm->invert, - }; - memcpy(dst, &m, sizeof(m)); -} - -static int compat_to_user(void __user *dst, void *src) -{ - struct xt_connmark_info *m = src; - struct compat_xt_connmark_info cm = { - .mark = m->mark, - .mask = m->mask, - .invert = m->invert, - }; - return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; -} -#endif /* CONFIG_COMPAT */ - -static struct xt_match xt_connmark_match[] = { - { - .name = "connmark", - .family = AF_INET, - .checkentry = checkentry, - .match = match, - .destroy = destroy, - .matchsize = sizeof(struct xt_connmark_info), -#ifdef CONFIG_COMPAT - .compatsize = sizeof(struct compat_xt_connmark_info), - .compat_from_user = compat_from_user, - .compat_to_user = compat_to_user, -#endif - .me = THIS_MODULE - }, - { - .name = "connmark", - .family = AF_INET6, - .checkentry = checkentry, - .match = match, - .destroy = destroy, - .matchsize = sizeof(struct xt_connmark_info), - .me = THIS_MODULE - }, +static struct xt_match connmark6_match = { + .name = "connmark", + .match = match, + .matchsize = sizeof(struct xt_connmark_info), + .checkentry = checkentry, + .destroy = destroy, + .family = AF_INET6, + .me = THIS_MODULE }; static int __init xt_connmark_init(void) { + int ret; + need_conntrack(); - return xt_register_matches(xt_connmark_match, - ARRAY_SIZE(xt_connmark_match)); + + ret = xt_register_match(&connmark_match); + if (ret) + return ret; + + ret = xt_register_match(&connmark6_match); + if (ret) + xt_unregister_match(&connmark_match); + return ret; } static void __exit xt_connmark_fini(void) { - xt_register_matches(xt_connmark_match, ARRAY_SIZE(xt_connmark_match)); + xt_unregister_match(&connmark6_match); + xt_unregister_match(&connmark_match); } module_init(xt_connmark_init); diff --git a/trunk/net/netfilter/xt_conntrack.c b/trunk/net/netfilter/xt_conntrack.c index 0ea501a2fda5..145489a4c3f2 100644 --- a/trunk/net/netfilter/xt_conntrack.c +++ b/trunk/net/netfilter/xt_conntrack.c @@ -45,7 +45,7 @@ match(const struct sk_buff *skb, ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); -#define FWINV(bool, invflg) ((bool) ^ !!(sinfo->invflags & invflg)) +#define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) if (ct == &ip_conntrack_untracked) statebit = XT_CONNTRACK_STATE_UNTRACKED; @@ -54,72 +54,63 @@ match(const struct sk_buff *skb, else statebit = XT_CONNTRACK_STATE_INVALID; - if (sinfo->flags & XT_CONNTRACK_STATE) { + if(sinfo->flags & XT_CONNTRACK_STATE) { if (ct) { - if (test_bit(IPS_SRC_NAT_BIT, &ct->status)) + if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) statebit |= XT_CONNTRACK_STATE_SNAT; - if (test_bit(IPS_DST_NAT_BIT, &ct->status)) + + if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip != + ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip) statebit |= XT_CONNTRACK_STATE_DNAT; } - if (FWINV((statebit & sinfo->statemask) == 0, - XT_CONNTRACK_STATE)) + + if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE)) return 0; } - if (ct == NULL) { - if (sinfo->flags & ~XT_CONNTRACK_STATE) + if(sinfo->flags & XT_CONNTRACK_PROTO) { + if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO)) + return 0; + } + + if(sinfo->flags & XT_CONNTRACK_ORIGSRC) { + 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)) return 0; - return 1; } - if (sinfo->flags & XT_CONNTRACK_PROTO && - FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != - sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, - XT_CONNTRACK_PROTO)) - return 0; - - if (sinfo->flags & XT_CONNTRACK_ORIGSRC && - 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)) - return 0; + if(sinfo->flags & XT_CONNTRACK_ORIGDST) { + 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)) + return 0; + } - if (sinfo->flags & XT_CONNTRACK_ORIGDST && - 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)) - return 0; + if(sinfo->flags & XT_CONNTRACK_REPLSRC) { + 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)) + return 0; + } - if (sinfo->flags & XT_CONNTRACK_REPLSRC && - 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)) - return 0; + if(sinfo->flags & XT_CONNTRACK_REPLDST) { + 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)) + return 0; + } - if (sinfo->flags & XT_CONNTRACK_REPLDST && - 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)) - return 0; + if(sinfo->flags & XT_CONNTRACK_STATUS) { + if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS)) + return 0; + } - if (sinfo->flags & XT_CONNTRACK_STATUS && - FWINV((ct->status & sinfo->statusmask) == 0, - XT_CONNTRACK_STATUS)) - return 0; + if(sinfo->flags & XT_CONNTRACK_EXPIRES) { + unsigned long expires; + + if(!ct) + return 0; - if (sinfo->flags & XT_CONNTRACK_EXPIRES) { - unsigned long expires = timer_pending(&ct->timeout) ? - (ct->timeout.expires - jiffies)/HZ : 0; + expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; - if (FWINV(!(expires >= sinfo->expires_min && - expires <= sinfo->expires_max), - XT_CONNTRACK_EXPIRES)) + if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES)) return 0; } + return 1; } @@ -150,72 +141,63 @@ match(const struct sk_buff *skb, else statebit = XT_CONNTRACK_STATE_INVALID; - if (sinfo->flags & XT_CONNTRACK_STATE) { + if(sinfo->flags & XT_CONNTRACK_STATE) { if (ct) { - if (test_bit(IPS_SRC_NAT_BIT, &ct->status)) + if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip != + ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip) statebit |= XT_CONNTRACK_STATE_SNAT; - if (test_bit(IPS_DST_NAT_BIT, &ct->status)) + + if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip != + ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip) statebit |= XT_CONNTRACK_STATE_DNAT; } - if (FWINV((statebit & sinfo->statemask) == 0, - XT_CONNTRACK_STATE)) + + if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE)) return 0; } - if (ct == NULL) { - if (sinfo->flags & ~XT_CONNTRACK_STATE) - return 0; - return 1; + if(sinfo->flags & XT_CONNTRACK_PROTO) { + if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO)) + return 0; } - if (sinfo->flags & XT_CONNTRACK_PROTO && - FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != - sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, - XT_CONNTRACK_PROTO)) - return 0; - - if (sinfo->flags & XT_CONNTRACK_ORIGSRC && - FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip & - sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != - sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, - XT_CONNTRACK_ORIGSRC)) - return 0; + if(sinfo->flags & XT_CONNTRACK_ORIGSRC) { + 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)) + return 0; + } - if (sinfo->flags & XT_CONNTRACK_ORIGDST && - FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip & - sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != - sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, - XT_CONNTRACK_ORIGDST)) - return 0; + if(sinfo->flags & XT_CONNTRACK_ORIGDST) { + 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)) + return 0; + } - if (sinfo->flags & XT_CONNTRACK_REPLSRC && - FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip & - sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != - sinfo->tuple[IP_CT_DIR_REPLY].src.ip, - XT_CONNTRACK_REPLSRC)) - return 0; + if(sinfo->flags & XT_CONNTRACK_REPLSRC) { + 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)) + return 0; + } - if (sinfo->flags & XT_CONNTRACK_REPLDST && - FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip & - sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != - sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, - XT_CONNTRACK_REPLDST)) - return 0; + if(sinfo->flags & XT_CONNTRACK_REPLDST) { + 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)) + return 0; + } - if (sinfo->flags & XT_CONNTRACK_STATUS && - FWINV((ct->status & sinfo->statusmask) == 0, - XT_CONNTRACK_STATUS)) - return 0; + if(sinfo->flags & XT_CONNTRACK_STATUS) { + if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS)) + return 0; + } if(sinfo->flags & XT_CONNTRACK_EXPIRES) { - unsigned long expires = timer_pending(&ct->timeout) ? - (ct->timeout.expires - jiffies)/HZ : 0; + unsigned long expires; - if (FWINV(!(expires >= sinfo->expires_min && - expires <= sinfo->expires_max), - XT_CONNTRACK_EXPIRES)) + if(!ct) + return 0; + + expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; + + if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES)) return 0; } + return 1; } @@ -226,6 +208,7 @@ checkentry(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) @@ -238,7 +221,8 @@ checkentry(const char *tablename, return 1; } -static void destroy(const struct xt_match *match, void *matchinfo) +static void +destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize) { #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) nf_ct_l3proto_module_put(match->family); @@ -257,8 +241,11 @@ static struct xt_match conntrack_match = { static int __init xt_conntrack_init(void) { + int ret; need_conntrack(); - return xt_register_match(&conntrack_match); + ret = xt_register_match(&conntrack_match); + + return ret; } static void __exit xt_conntrack_fini(void) diff --git a/trunk/net/netfilter/xt_dccp.c b/trunk/net/netfilter/xt_dccp.c index 3e6cf430e518..2e2f825dad4c 100644 --- a/trunk/net/netfilter/xt_dccp.c +++ b/trunk/net/netfilter/xt_dccp.c @@ -131,6 +131,7 @@ checkentry(const char *tablename, const void *inf, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct xt_dccp_info *info = matchinfo; @@ -140,26 +141,27 @@ checkentry(const char *tablename, && !(info->invflags & ~info->flags); } -static struct xt_match xt_dccp_match[] = { - { - .name = "dccp", - .family = AF_INET, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_dccp_info), - .proto = IPPROTO_DCCP, - .me = THIS_MODULE, - }, - { - .name = "dccp", - .family = AF_INET6, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_dccp_info), - .proto = IPPROTO_DCCP, - .me = THIS_MODULE, - }, +static struct xt_match dccp_match = +{ + .name = "dccp", + .match = match, + .matchsize = sizeof(struct xt_dccp_info), + .proto = IPPROTO_DCCP, + .checkentry = checkentry, + .family = AF_INET, + .me = THIS_MODULE, }; +static struct xt_match dccp6_match = +{ + .name = "dccp", + .match = match, + .matchsize = sizeof(struct xt_dccp_info), + .proto = IPPROTO_DCCP, + .checkentry = checkentry, + .family = AF_INET6, + .me = THIS_MODULE, +}; + static int __init xt_dccp_init(void) { @@ -171,19 +173,27 @@ static int __init xt_dccp_init(void) dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL); if (!dccp_optbuf) return -ENOMEM; - ret = xt_register_matches(xt_dccp_match, ARRAY_SIZE(xt_dccp_match)); + ret = xt_register_match(&dccp_match); if (ret) goto out_kfree; + ret = xt_register_match(&dccp6_match); + if (ret) + goto out_unreg; + return ret; +out_unreg: + xt_unregister_match(&dccp_match); out_kfree: kfree(dccp_optbuf); + return ret; } static void __exit xt_dccp_fini(void) { - xt_unregister_matches(xt_dccp_match, ARRAY_SIZE(xt_dccp_match)); + xt_unregister_match(&dccp6_match); + xt_unregister_match(&dccp_match); kfree(dccp_optbuf); } diff --git a/trunk/net/netfilter/xt_dscp.c b/trunk/net/netfilter/xt_dscp.c deleted file mode 100644 index 26c7f4ad102a..000000000000 --- a/trunk/net/netfilter/xt_dscp.c +++ /dev/null @@ -1,103 +0,0 @@ -/* IP tables module for matching the value of the IPv4/IPv6 DSCP field - * - * xt_dscp.c,v 1.3 2002/08/05 19:00:21 laforge Exp - * - * (C) 2002 by Harald Welte - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include - -#include -#include - -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("x_tables DSCP matching module"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("ipt_dscp"); -MODULE_ALIAS("ip6t_dscp"); - -static int match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const struct xt_match *match, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - const struct xt_dscp_info *info = matchinfo; - u_int8_t dscp = ipv4_get_dsfield(skb->nh.iph) >> XT_DSCP_SHIFT; - - return (dscp == info->dscp) ^ !!info->invert; -} - -static int match6(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const struct xt_match *match, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) -{ - const struct xt_dscp_info *info = matchinfo; - u_int8_t dscp = ipv6_get_dsfield(skb->nh.ipv6h) >> XT_DSCP_SHIFT; - - return (dscp == info->dscp) ^ !!info->invert; -} - -static int checkentry(const char *tablename, - const void *info, - const struct xt_match *match, - void *matchinfo, - unsigned int hook_mask) -{ - const u_int8_t dscp = ((struct xt_dscp_info *)matchinfo)->dscp; - - if (dscp > XT_DSCP_MAX) { - printk(KERN_ERR "xt_dscp: dscp %x out of range\n", dscp); - return 0; - } - - return 1; -} - -static struct xt_match xt_dscp_match[] = { - { - .name = "dscp", - .family = AF_INET, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_dscp_info), - .me = THIS_MODULE, - }, - { - .name = "dscp", - .family = AF_INET6, - .checkentry = checkentry, - .match = match6, - .matchsize = sizeof(struct xt_dscp_info), - .me = THIS_MODULE, - }, -}; - -static int __init xt_dscp_match_init(void) -{ - return xt_register_matches(xt_dscp_match, ARRAY_SIZE(xt_dscp_match)); -} - -static void __exit xt_dscp_match_fini(void) -{ - xt_unregister_matches(xt_dscp_match, ARRAY_SIZE(xt_dscp_match)); -} - -module_init(xt_dscp_match_init); -module_exit(xt_dscp_match_fini); diff --git a/trunk/net/netfilter/xt_esp.c b/trunk/net/netfilter/xt_esp.c index 7c95f149d942..9dad6281e0c1 100644 --- a/trunk/net/netfilter/xt_esp.c +++ b/trunk/net/netfilter/xt_esp.c @@ -79,6 +79,7 @@ checkentry(const char *tablename, const void *ip_void, const struct xt_match *match, void *matchinfo, + unsigned int matchinfosize, unsigned int hook_mask) { const struct xt_esp *espinfo = matchinfo; @@ -91,35 +92,44 @@ checkentry(const char *tablename, return 1; } -static struct xt_match xt_esp_match[] = { - { - .name = "esp", - .family = AF_INET, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_esp), - .proto = IPPROTO_ESP, - .me = THIS_MODULE, - }, - { - .name = "esp", - .family = AF_INET6, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_esp), - .proto = IPPROTO_ESP, - .me = THIS_MODULE, - }, +static struct xt_match esp_match = { + .name = "esp", + .family = AF_INET, + .proto = IPPROTO_ESP, + .match = &match, + .matchsize = sizeof(struct xt_esp), + .checkentry = &checkentry, + .me = THIS_MODULE, +}; + +static struct xt_match esp6_match = { + .name = "esp", + .family = AF_INET6, + .proto = IPPROTO_ESP, + .match = &match, + .matchsize = sizeof(struct xt_esp), + .checkentry = &checkentry, + .me = THIS_MODULE, }; static int __init xt_esp_init(void) { - return xt_register_matches(xt_esp_match, ARRAY_SIZE(xt_esp_match)); + int ret; + ret = xt_register_match(&esp_match); + if (ret) + return ret; + + ret = xt_register_match(&esp6_match); + if (ret) + xt_unregister_match(&esp_match); + + return ret; } static void __exit xt_esp_cleanup(void) { - xt_unregister_matches(xt_esp_match, ARRAY_SIZE(xt_esp_match)); + xt_unregister_match(&esp_match); + xt_unregister_match(&esp6_match); } module_init(xt_esp_init); diff --git a/trunk/net/netfilter/xt_helper.c b/trunk/net/netfilter/xt_helper.c index 5d7818b73e3a..799c2a43e3b9 100644 --- a/trunk/net/netfilter/xt_helper.c +++ b/trunk/net/netfilter/xt_helper.c @@ -139,6 +139,7 @@ static int check(const char *tablename, const void *inf, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { struct xt_helper_info *info = matchinfo; @@ -155,44 +156,52 @@ static int check(const char *tablename, } static void -destroy(const struct xt_match *match, void *matchinfo) +destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize) { #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) nf_ct_l3proto_module_put(match->family); #endif } -static struct xt_match xt_helper_match[] = { - { - .name = "helper", - .family = AF_INET, - .checkentry = check, - .match = match, - .destroy = destroy, - .matchsize = sizeof(struct xt_helper_info), - .me = THIS_MODULE, - }, - { - .name = "helper", - .family = AF_INET6, - .checkentry = check, - .match = match, - .destroy = destroy, - .matchsize = sizeof(struct xt_helper_info), - .me = THIS_MODULE, - }, +static struct xt_match helper_match = { + .name = "helper", + .match = match, + .matchsize = sizeof(struct xt_helper_info), + .checkentry = check, + .destroy = destroy, + .family = AF_INET, + .me = THIS_MODULE, +}; +static struct xt_match helper6_match = { + .name = "helper", + .match = match, + .matchsize = sizeof(struct xt_helper_info), + .checkentry = check, + .destroy = destroy, + .family = AF_INET6, + .me = THIS_MODULE, }; static int __init xt_helper_init(void) { + int ret; need_conntrack(); - return xt_register_matches(xt_helper_match, - ARRAY_SIZE(xt_helper_match)); + + ret = xt_register_match(&helper_match); + if (ret < 0) + return ret; + + ret = xt_register_match(&helper6_match); + if (ret < 0) + xt_unregister_match(&helper_match); + + return ret; } static void __exit xt_helper_fini(void) { - xt_unregister_matches(xt_helper_match, ARRAY_SIZE(xt_helper_match)); + xt_unregister_match(&helper_match); + xt_unregister_match(&helper6_match); } module_init(xt_helper_init); diff --git a/trunk/net/netfilter/xt_length.c b/trunk/net/netfilter/xt_length.c index 67fd30d9f303..109132c9a146 100644 --- a/trunk/net/netfilter/xt_length.c +++ b/trunk/net/netfilter/xt_length.c @@ -52,32 +52,39 @@ match6(const struct sk_buff *skb, return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; } -static struct xt_match xt_length_match[] = { - { - .name = "length", - .family = AF_INET, - .match = match, - .matchsize = sizeof(struct xt_length_info), - .me = THIS_MODULE, - }, - { - .name = "length", - .family = AF_INET6, - .match = match6, - .matchsize = sizeof(struct xt_length_info), - .me = THIS_MODULE, - }, +static struct xt_match length_match = { + .name = "length", + .match = match, + .matchsize = sizeof(struct xt_length_info), + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_match length6_match = { + .name = "length", + .match = match6, + .matchsize = sizeof(struct xt_length_info), + .family = AF_INET6, + .me = THIS_MODULE, }; static int __init xt_length_init(void) { - return xt_register_matches(xt_length_match, - ARRAY_SIZE(xt_length_match)); + int ret; + ret = xt_register_match(&length_match); + if (ret) + return ret; + ret = xt_register_match(&length6_match); + if (ret) + xt_unregister_match(&length_match); + + return ret; } static void __exit xt_length_fini(void) { - xt_unregister_matches(xt_length_match, ARRAY_SIZE(xt_length_match)); + xt_unregister_match(&length_match); + xt_unregister_match(&length6_match); } module_init(xt_length_init); diff --git a/trunk/net/netfilter/xt_limit.c b/trunk/net/netfilter/xt_limit.c index fda7b7dec27d..ce7fdb7e4e07 100644 --- a/trunk/net/netfilter/xt_limit.c +++ b/trunk/net/netfilter/xt_limit.c @@ -110,6 +110,7 @@ ipt_limit_checkentry(const char *tablename, const void *inf, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { struct xt_rateinfo *r = matchinfo; @@ -122,95 +123,55 @@ ipt_limit_checkentry(const char *tablename, return 0; } + /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * + 128. */ + r->prev = jiffies; + r->credit = user2credits(r->avg * r->burst); /* Credits full. */ + r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ + r->cost = user2credits(r->avg); + /* For SMP, we only want to use one set of counters. */ r->master = r; - if (r->cost == 0) { - /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * - 128. */ - r->prev = jiffies; - r->credit = user2credits(r->avg * r->burst); /* Credits full. */ - r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ - r->cost = user2credits(r->avg); - } + return 1; } -#ifdef CONFIG_COMPAT -struct compat_xt_rateinfo { - u_int32_t avg; - u_int32_t burst; - - compat_ulong_t prev; - u_int32_t credit; - u_int32_t credit_cap, cost; - - u_int32_t master; +static struct xt_match ipt_limit_reg = { + .name = "limit", + .match = ipt_limit_match, + .matchsize = sizeof(struct xt_rateinfo), + .checkentry = ipt_limit_checkentry, + .family = AF_INET, + .me = THIS_MODULE, }; - -/* To keep the full "prev" timestamp, the upper 32 bits are stored in the - * master pointer, which does not need to be preserved. */ -static void compat_from_user(void *dst, void *src) -{ - struct compat_xt_rateinfo *cm = src; - struct xt_rateinfo m = { - .avg = cm->avg, - .burst = cm->burst, - .prev = cm->prev | (unsigned long)cm->master << 32, - .credit = cm->credit, - .credit_cap = cm->credit_cap, - .cost = cm->cost, - }; - memcpy(dst, &m, sizeof(m)); -} - -static int compat_to_user(void __user *dst, void *src) -{ - struct xt_rateinfo *m = src; - struct compat_xt_rateinfo cm = { - .avg = m->avg, - .burst = m->burst, - .prev = m->prev, - .credit = m->credit, - .credit_cap = m->credit_cap, - .cost = m->cost, - .master = m->prev >> 32, - }; - return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; -} -#endif /* CONFIG_COMPAT */ - -static struct xt_match xt_limit_match[] = { - { - .name = "limit", - .family = AF_INET, - .checkentry = ipt_limit_checkentry, - .match = ipt_limit_match, - .matchsize = sizeof(struct xt_rateinfo), -#ifdef CONFIG_COMPAT - .compatsize = sizeof(struct compat_xt_rateinfo), - .compat_from_user = compat_from_user, - .compat_to_user = compat_to_user, -#endif - .me = THIS_MODULE, - }, - { - .name = "limit", - .family = AF_INET6, - .checkentry = ipt_limit_checkentry, - .match = ipt_limit_match, - .matchsize = sizeof(struct xt_rateinfo), - .me = THIS_MODULE, - }, +static struct xt_match limit6_reg = { + .name = "limit", + .match = ipt_limit_match, + .matchsize = sizeof(struct xt_rateinfo), + .checkentry = ipt_limit_checkentry, + .family = AF_INET6, + .me = THIS_MODULE, }; static int __init xt_limit_init(void) { - return xt_register_matches(xt_limit_match, ARRAY_SIZE(xt_limit_match)); + int ret; + + ret = xt_register_match(&ipt_limit_reg); + if (ret) + return ret; + + ret = xt_register_match(&limit6_reg); + if (ret) + xt_unregister_match(&ipt_limit_reg); + + return ret; } static void __exit xt_limit_fini(void) { - xt_unregister_matches(xt_limit_match, ARRAY_SIZE(xt_limit_match)); + xt_unregister_match(&ipt_limit_reg); + xt_unregister_match(&limit6_reg); } module_init(xt_limit_init); diff --git a/trunk/net/netfilter/xt_mac.c b/trunk/net/netfilter/xt_mac.c index 425fc21e31f5..356290ffe386 100644 --- a/trunk/net/netfilter/xt_mac.c +++ b/trunk/net/netfilter/xt_mac.c @@ -43,37 +43,43 @@ match(const struct sk_buff *skb, ^ info->invert)); } -static struct xt_match xt_mac_match[] = { - { - .name = "mac", - .family = AF_INET, - .match = match, - .matchsize = sizeof(struct xt_mac_info), - .hooks = (1 << NF_IP_PRE_ROUTING) | - (1 << NF_IP_LOCAL_IN) | - (1 << NF_IP_FORWARD), - .me = THIS_MODULE, - }, - { - .name = "mac", - .family = AF_INET6, - .match = match, - .matchsize = sizeof(struct xt_mac_info), - .hooks = (1 << NF_IP_PRE_ROUTING) | - (1 << NF_IP_LOCAL_IN) | - (1 << NF_IP_FORWARD), - .me = THIS_MODULE, - }, +static struct xt_match mac_match = { + .name = "mac", + .match = match, + .matchsize = sizeof(struct xt_mac_info), + .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | + (1 << NF_IP_FORWARD), + .family = AF_INET, + .me = THIS_MODULE, +}; +static struct xt_match mac6_match = { + .name = "mac", + .match = match, + .matchsize = sizeof(struct xt_mac_info), + .hooks = (1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | + (1 << NF_IP_FORWARD), + .family = AF_INET6, + .me = THIS_MODULE, }; static int __init xt_mac_init(void) { - return xt_register_matches(xt_mac_match, ARRAY_SIZE(xt_mac_match)); + int ret; + ret = xt_register_match(&mac_match); + if (ret) + return ret; + + ret = xt_register_match(&mac6_match); + if (ret) + xt_unregister_match(&mac_match); + + return ret; } static void __exit xt_mac_fini(void) { - xt_unregister_matches(xt_mac_match, ARRAY_SIZE(xt_mac_match)); + xt_unregister_match(&mac_match); + xt_unregister_match(&mac6_match); } module_init(xt_mac_init); diff --git a/trunk/net/netfilter/xt_mark.c b/trunk/net/netfilter/xt_mark.c index 934dddfbcd23..876bc5797738 100644 --- a/trunk/net/netfilter/xt_mark.c +++ b/trunk/net/netfilter/xt_mark.c @@ -39,6 +39,7 @@ checkentry(const char *tablename, const void *entry, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct xt_mark_info *minfo = matchinfo; @@ -50,69 +51,42 @@ checkentry(const char *tablename, return 1; } -#ifdef CONFIG_COMPAT -struct compat_xt_mark_info { - compat_ulong_t mark, mask; - u_int8_t invert; - u_int8_t __pad1; - u_int16_t __pad2; +static struct xt_match mark_match = { + .name = "mark", + .match = match, + .matchsize = sizeof(struct xt_mark_info), + .checkentry = checkentry, + .family = AF_INET, + .me = THIS_MODULE, }; -static void compat_from_user(void *dst, void *src) -{ - struct compat_xt_mark_info *cm = src; - struct xt_mark_info m = { - .mark = cm->mark, - .mask = cm->mask, - .invert = cm->invert, - }; - memcpy(dst, &m, sizeof(m)); -} - -static int compat_to_user(void __user *dst, void *src) -{ - struct xt_mark_info *m = src; - struct compat_xt_mark_info cm = { - .mark = m->mark, - .mask = m->mask, - .invert = m->invert, - }; - return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; -} -#endif /* CONFIG_COMPAT */ - -static struct xt_match xt_mark_match[] = { - { - .name = "mark", - .family = AF_INET, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_mark_info), -#ifdef CONFIG_COMPAT - .compatsize = sizeof(struct compat_xt_mark_info), - .compat_from_user = compat_from_user, - .compat_to_user = compat_to_user, -#endif - .me = THIS_MODULE, - }, - { - .name = "mark", - .family = AF_INET6, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_mark_info), - .me = THIS_MODULE, - }, +static struct xt_match mark6_match = { + .name = "mark", + .match = match, + .matchsize = sizeof(struct xt_mark_info), + .checkentry = checkentry, + .family = AF_INET6, + .me = THIS_MODULE, }; static int __init xt_mark_init(void) { - return xt_register_matches(xt_mark_match, ARRAY_SIZE(xt_mark_match)); + int ret; + ret = xt_register_match(&mark_match); + if (ret) + return ret; + + ret = xt_register_match(&mark6_match); + if (ret) + xt_unregister_match(&mark_match); + + return ret; } static void __exit xt_mark_fini(void) { - xt_unregister_matches(xt_mark_match, ARRAY_SIZE(xt_mark_match)); + xt_unregister_match(&mark_match); + xt_unregister_match(&mark6_match); } module_init(xt_mark_init); diff --git a/trunk/net/netfilter/xt_multiport.c b/trunk/net/netfilter/xt_multiport.c index d3aefd380930..1ff0a25396e7 100644 --- a/trunk/net/netfilter/xt_multiport.c +++ b/trunk/net/netfilter/xt_multiport.c @@ -176,6 +176,7 @@ checkentry(const char *tablename, const void *info, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct ipt_ip *ip = info; @@ -190,6 +191,7 @@ checkentry_v1(const char *tablename, const void *info, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct ipt_ip *ip = info; @@ -204,6 +206,7 @@ checkentry6(const char *tablename, const void *info, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct ip6t_ip6 *ip = info; @@ -218,6 +221,7 @@ checkentry6_v1(const char *tablename, const void *info, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct ip6t_ip6 *ip = info; @@ -227,55 +231,84 @@ checkentry6_v1(const char *tablename, multiinfo->count); } -static struct xt_match xt_multiport_match[] = { - { - .name = "multiport", - .family = AF_INET, - .revision = 0, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_multiport), - .me = THIS_MODULE, - }, - { - .name = "multiport", - .family = AF_INET, - .revision = 1, - .checkentry = checkentry_v1, - .match = match_v1, - .matchsize = sizeof(struct xt_multiport_v1), - .me = THIS_MODULE, - }, - { - .name = "multiport", - .family = AF_INET6, - .revision = 0, - .checkentry = checkentry6, - .match = match, - .matchsize = sizeof(struct xt_multiport), - .me = THIS_MODULE, - }, - { - .name = "multiport", - .family = AF_INET6, - .revision = 1, - .checkentry = checkentry6_v1, - .match = match_v1, - .matchsize = sizeof(struct xt_multiport_v1), - .me = THIS_MODULE, - }, +static struct xt_match multiport_match = { + .name = "multiport", + .revision = 0, + .matchsize = sizeof(struct xt_multiport), + .match = &match, + .checkentry = &checkentry, + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_match multiport_match_v1 = { + .name = "multiport", + .revision = 1, + .matchsize = sizeof(struct xt_multiport_v1), + .match = &match_v1, + .checkentry = &checkentry_v1, + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_match multiport6_match = { + .name = "multiport", + .revision = 0, + .matchsize = sizeof(struct xt_multiport), + .match = &match, + .checkentry = &checkentry6, + .family = AF_INET6, + .me = THIS_MODULE, +}; + +static struct xt_match multiport6_match_v1 = { + .name = "multiport", + .revision = 1, + .matchsize = sizeof(struct xt_multiport_v1), + .match = &match_v1, + .checkentry = &checkentry6_v1, + .family = AF_INET6, + .me = THIS_MODULE, }; static int __init xt_multiport_init(void) { - return xt_register_matches(xt_multiport_match, - ARRAY_SIZE(xt_multiport_match)); + int ret; + + ret = xt_register_match(&multiport_match); + if (ret) + goto out; + + ret = xt_register_match(&multiport_match_v1); + if (ret) + goto out_unreg_multi_v0; + + ret = xt_register_match(&multiport6_match); + if (ret) + goto out_unreg_multi_v1; + + ret = xt_register_match(&multiport6_match_v1); + if (ret) + goto out_unreg_multi6_v0; + + return ret; + +out_unreg_multi6_v0: + xt_unregister_match(&multiport6_match); +out_unreg_multi_v1: + xt_unregister_match(&multiport_match_v1); +out_unreg_multi_v0: + xt_unregister_match(&multiport_match); +out: + return ret; } static void __exit xt_multiport_fini(void) { - xt_unregister_matches(xt_multiport_match, - ARRAY_SIZE(xt_multiport_match)); + xt_unregister_match(&multiport_match); + xt_unregister_match(&multiport_match_v1); + xt_unregister_match(&multiport6_match); + xt_unregister_match(&multiport6_match_v1); } module_init(xt_multiport_init); diff --git a/trunk/net/netfilter/xt_physdev.c b/trunk/net/netfilter/xt_physdev.c index fd8f954cded5..a9f4f6f3c628 100644 --- a/trunk/net/netfilter/xt_physdev.c +++ b/trunk/net/netfilter/xt_physdev.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include @@ -106,6 +105,7 @@ checkentry(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct xt_physdev_info *info = matchinfo; @@ -131,34 +131,43 @@ checkentry(const char *tablename, return 1; } -static struct xt_match xt_physdev_match[] = { - { - .name = "physdev", - .family = AF_INET, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_physdev_info), - .me = THIS_MODULE, - }, - { - .name = "physdev", - .family = AF_INET6, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_physdev_info), - .me = THIS_MODULE, - }, +static struct xt_match physdev_match = { + .name = "physdev", + .match = match, + .matchsize = sizeof(struct xt_physdev_info), + .checkentry = checkentry, + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_match physdev6_match = { + .name = "physdev", + .match = match, + .matchsize = sizeof(struct xt_physdev_info), + .checkentry = checkentry, + .family = AF_INET6, + .me = THIS_MODULE, }; static int __init xt_physdev_init(void) { - return xt_register_matches(xt_physdev_match, - ARRAY_SIZE(xt_physdev_match)); + int ret; + + ret = xt_register_match(&physdev_match); + if (ret < 0) + return ret; + + ret = xt_register_match(&physdev6_match); + if (ret < 0) + xt_unregister_match(&physdev_match); + + return ret; } static void __exit xt_physdev_fini(void) { - xt_unregister_matches(xt_physdev_match, ARRAY_SIZE(xt_physdev_match)); + xt_unregister_match(&physdev_match); + xt_unregister_match(&physdev6_match); } module_init(xt_physdev_init); diff --git a/trunk/net/netfilter/xt_pkttype.c b/trunk/net/netfilter/xt_pkttype.c index 16e7b0804287..d2f5320a80bf 100644 --- a/trunk/net/netfilter/xt_pkttype.c +++ b/trunk/net/netfilter/xt_pkttype.c @@ -43,32 +43,40 @@ static int match(const struct sk_buff *skb, return (type == info->pkttype) ^ info->invert; } -static struct xt_match xt_pkttype_match[] = { - { - .name = "pkttype", - .family = AF_INET, - .match = match, - .matchsize = sizeof(struct xt_pkttype_info), - .me = THIS_MODULE, - }, - { - .name = "pkttype", - .family = AF_INET6, - .match = match, - .matchsize = sizeof(struct xt_pkttype_info), - .me = THIS_MODULE, - }, +static struct xt_match pkttype_match = { + .name = "pkttype", + .match = match, + .matchsize = sizeof(struct xt_pkttype_info), + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_match pkttype6_match = { + .name = "pkttype", + .match = match, + .matchsize = sizeof(struct xt_pkttype_info), + .family = AF_INET6, + .me = THIS_MODULE, }; static int __init xt_pkttype_init(void) { - return xt_register_matches(xt_pkttype_match, - ARRAY_SIZE(xt_pkttype_match)); + int ret; + ret = xt_register_match(&pkttype_match); + if (ret) + return ret; + + ret = xt_register_match(&pkttype6_match); + if (ret) + xt_unregister_match(&pkttype_match); + + return ret; } static void __exit xt_pkttype_fini(void) { - xt_unregister_matches(xt_pkttype_match, ARRAY_SIZE(xt_pkttype_match)); + xt_unregister_match(&pkttype_match); + xt_unregister_match(&pkttype6_match); } module_init(xt_pkttype_init); diff --git a/trunk/net/netfilter/xt_policy.c b/trunk/net/netfilter/xt_policy.c index 46bde2b1e1e0..ba1ca03abad3 100644 --- a/trunk/net/netfilter/xt_policy.c +++ b/trunk/net/netfilter/xt_policy.c @@ -135,7 +135,8 @@ static int match(const struct sk_buff *skb, static int checkentry(const char *tablename, const void *ip_void, const struct xt_match *match, - void *matchinfo, unsigned int hook_mask) + void *matchinfo, unsigned int matchsize, + unsigned int hook_mask) { struct xt_policy_info *info = matchinfo; @@ -164,34 +165,43 @@ static int checkentry(const char *tablename, const void *ip_void, return 1; } -static struct xt_match xt_policy_match[] = { - { - .name = "policy", - .family = AF_INET, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_policy_info), - .me = THIS_MODULE, - }, - { - .name = "policy", - .family = AF_INET6, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_policy_info), - .me = THIS_MODULE, - }, +static struct xt_match policy_match = { + .name = "policy", + .family = AF_INET, + .match = match, + .matchsize = sizeof(struct xt_policy_info), + .checkentry = checkentry, + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_match policy6_match = { + .name = "policy", + .family = AF_INET6, + .match = match, + .matchsize = sizeof(struct xt_policy_info), + .checkentry = checkentry, + .family = AF_INET6, + .me = THIS_MODULE, }; static int __init init(void) { - return xt_register_matches(xt_policy_match, - ARRAY_SIZE(xt_policy_match)); + int ret; + + ret = xt_register_match(&policy_match); + if (ret) + return ret; + ret = xt_register_match(&policy6_match); + if (ret) + xt_unregister_match(&policy_match); + return ret; } static void __exit fini(void) { - xt_unregister_matches(xt_policy_match, ARRAY_SIZE(xt_policy_match)); + xt_unregister_match(&policy6_match); + xt_unregister_match(&policy_match); } module_init(init); diff --git a/trunk/net/netfilter/xt_quota.c b/trunk/net/netfilter/xt_quota.c index b75fa2c70e66..4cdba7469dc4 100644 --- a/trunk/net/netfilter/xt_quota.c +++ b/trunk/net/netfilter/xt_quota.c @@ -11,8 +11,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Sam Johnston "); -MODULE_ALIAS("ipt_quota"); -MODULE_ALIAS("ip6t_quota"); static DEFINE_SPINLOCK(quota_lock); @@ -41,7 +39,7 @@ match(const struct sk_buff *skb, static int checkentry(const char *tablename, const void *entry, const struct xt_match *match, void *matchinfo, - unsigned int hook_mask) + unsigned int matchsize, unsigned int hook_mask) { struct xt_quota_info *q = (struct xt_quota_info *)matchinfo; @@ -52,33 +50,46 @@ checkentry(const char *tablename, const void *entry, return 1; } -static struct xt_match xt_quota_match[] = { - { - .name = "quota", - .family = AF_INET, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_quota_info), - .me = THIS_MODULE - }, - { - .name = "quota", - .family = AF_INET6, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_quota_info), - .me = THIS_MODULE - }, +static struct xt_match quota_match = { + .name = "quota", + .family = AF_INET, + .match = match, + .matchsize = sizeof(struct xt_quota_info), + .checkentry = checkentry, + .me = THIS_MODULE +}; + +static struct xt_match quota_match6 = { + .name = "quota", + .family = AF_INET6, + .match = match, + .matchsize = sizeof(struct xt_quota_info), + .checkentry = checkentry, + .me = THIS_MODULE }; static int __init xt_quota_init(void) { - return xt_register_matches(xt_quota_match, ARRAY_SIZE(xt_quota_match)); + int ret; + + ret = xt_register_match("a_match); + if (ret) + goto err1; + ret = xt_register_match("a_match6); + if (ret) + goto err2; + return ret; + +err2: + xt_unregister_match("a_match); +err1: + return ret; } static void __exit xt_quota_fini(void) { - xt_unregister_matches(xt_quota_match, ARRAY_SIZE(xt_quota_match)); + xt_unregister_match("a_match6); + xt_unregister_match("a_match); } module_init(xt_quota_init); diff --git a/trunk/net/netfilter/xt_sctp.c b/trunk/net/netfilter/xt_sctp.c index 7956acaaa24b..843383e01d41 100644 --- a/trunk/net/netfilter/xt_sctp.c +++ b/trunk/net/netfilter/xt_sctp.c @@ -163,6 +163,7 @@ checkentry(const char *tablename, const void *inf, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct xt_sctp_info *info = matchinfo; @@ -177,35 +178,44 @@ checkentry(const char *tablename, | SCTP_CHUNK_MATCH_ONLY))); } -static struct xt_match xt_sctp_match[] = { - { - .name = "sctp", - .family = AF_INET, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_sctp_info), - .proto = IPPROTO_SCTP, - .me = THIS_MODULE - }, - { - .name = "sctp", - .family = AF_INET6, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_sctp_info), - .proto = IPPROTO_SCTP, - .me = THIS_MODULE - }, +static struct xt_match sctp_match = { + .name = "sctp", + .match = match, + .matchsize = sizeof(struct xt_sctp_info), + .proto = IPPROTO_SCTP, + .checkentry = checkentry, + .family = AF_INET, + .me = THIS_MODULE +}; + +static struct xt_match sctp6_match = { + .name = "sctp", + .match = match, + .matchsize = sizeof(struct xt_sctp_info), + .proto = IPPROTO_SCTP, + .checkentry = checkentry, + .family = AF_INET6, + .me = THIS_MODULE }; static int __init xt_sctp_init(void) { - return xt_register_matches(xt_sctp_match, ARRAY_SIZE(xt_sctp_match)); + int ret; + ret = xt_register_match(&sctp_match); + if (ret) + return ret; + + ret = xt_register_match(&sctp6_match); + if (ret) + xt_unregister_match(&sctp_match); + + return ret; } static void __exit xt_sctp_fini(void) { - xt_unregister_matches(xt_sctp_match, ARRAY_SIZE(xt_sctp_match)); + xt_unregister_match(&sctp6_match); + xt_unregister_match(&sctp_match); } module_init(xt_sctp_init); diff --git a/trunk/net/netfilter/xt_state.c b/trunk/net/netfilter/xt_state.c index d9010b16a1f9..f9e304dc4504 100644 --- a/trunk/net/netfilter/xt_state.c +++ b/trunk/net/netfilter/xt_state.c @@ -48,6 +48,7 @@ static int check(const char *tablename, const void *inf, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) @@ -61,43 +62,54 @@ static int check(const char *tablename, } static void -destroy(const struct xt_match *match, void *matchinfo) +destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize) { #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) nf_ct_l3proto_module_put(match->family); #endif } -static struct xt_match xt_state_match[] = { - { - .name = "state", - .family = AF_INET, - .checkentry = check, - .match = match, - .destroy = destroy, - .matchsize = sizeof(struct xt_state_info), - .me = THIS_MODULE, - }, - { - .name = "state", - .family = AF_INET6, - .checkentry = check, - .match = match, - .destroy = destroy, - .matchsize = sizeof(struct xt_state_info), - .me = THIS_MODULE, - }, +static struct xt_match state_match = { + .name = "state", + .match = match, + .checkentry = check, + .destroy = destroy, + .matchsize = sizeof(struct xt_state_info), + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_match state6_match = { + .name = "state", + .match = match, + .checkentry = check, + .destroy = destroy, + .matchsize = sizeof(struct xt_state_info), + .family = AF_INET6, + .me = THIS_MODULE, }; static int __init xt_state_init(void) { + int ret; + need_conntrack(); - return xt_register_matches(xt_state_match, ARRAY_SIZE(xt_state_match)); + + ret = xt_register_match(&state_match); + if (ret < 0) + return ret; + + ret = xt_register_match(&state6_match); + if (ret < 0) + xt_unregister_match(&state_match); + + return ret; } static void __exit xt_state_fini(void) { - xt_unregister_matches(xt_state_match, ARRAY_SIZE(xt_state_match)); + xt_unregister_match(&state_match); + xt_unregister_match(&state6_match); } module_init(xt_state_init); diff --git a/trunk/net/netfilter/xt_statistic.c b/trunk/net/netfilter/xt_statistic.c index 091a9f89f5d5..de1037f58596 100644 --- a/trunk/net/netfilter/xt_statistic.c +++ b/trunk/net/netfilter/xt_statistic.c @@ -55,7 +55,7 @@ match(const struct sk_buff *skb, static int checkentry(const char *tablename, const void *entry, const struct xt_match *match, void *matchinfo, - unsigned int hook_mask) + unsigned int matchsize, unsigned int hook_mask) { struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo; @@ -66,35 +66,46 @@ checkentry(const char *tablename, const void *entry, return 1; } -static struct xt_match xt_statistic_match[] = { - { - .name = "statistic", - .family = AF_INET, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_statistic_info), - .me = THIS_MODULE, - }, - { - .name = "statistic", - .family = AF_INET6, - .checkentry = checkentry, - .match = match, - .matchsize = sizeof(struct xt_statistic_info), - .me = THIS_MODULE, - }, +static struct xt_match statistic_match = { + .name = "statistic", + .match = match, + .matchsize = sizeof(struct xt_statistic_info), + .checkentry = checkentry, + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_match statistic_match6 = { + .name = "statistic", + .match = match, + .matchsize = sizeof(struct xt_statistic_info), + .checkentry = checkentry, + .family = AF_INET6, + .me = THIS_MODULE, }; static int __init xt_statistic_init(void) { - return xt_register_matches(xt_statistic_match, - ARRAY_SIZE(xt_statistic_match)); + int ret; + + ret = xt_register_match(&statistic_match); + if (ret) + goto err1; + + ret = xt_register_match(&statistic_match6); + if (ret) + goto err2; + return ret; +err2: + xt_unregister_match(&statistic_match); +err1: + return ret; } static void __exit xt_statistic_fini(void) { - xt_unregister_matches(xt_statistic_match, - ARRAY_SIZE(xt_statistic_match)); + xt_unregister_match(&statistic_match6); + xt_unregister_match(&statistic_match); } module_init(xt_statistic_init); diff --git a/trunk/net/netfilter/xt_string.c b/trunk/net/netfilter/xt_string.c index 4453252400aa..0ebb6ac2c8c7 100644 --- a/trunk/net/netfilter/xt_string.c +++ b/trunk/net/netfilter/xt_string.c @@ -37,7 +37,7 @@ static int match(const struct sk_buff *skb, return (skb_find_text((struct sk_buff *)skb, conf->from_offset, conf->to_offset, conf->config, &state) - != UINT_MAX) ^ conf->invert; + != UINT_MAX) && !conf->invert; } #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m) @@ -46,6 +46,7 @@ static int checkentry(const char *tablename, const void *ip, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { struct xt_string_info *conf = matchinfo; @@ -54,10 +55,7 @@ static int checkentry(const char *tablename, /* Damn, can't handle this case properly with iptables... */ if (conf->from_offset > conf->to_offset) return 0; - if (conf->algo[XT_STRING_MAX_ALGO_NAME_SIZE - 1] != '\0') - return 0; - if (conf->patlen > XT_STRING_MAX_PATTERN_SIZE) - return 0; + ts_conf = textsearch_prepare(conf->algo, conf->pattern, conf->patlen, GFP_KERNEL, TS_AUTOLOAD); if (IS_ERR(ts_conf)) @@ -68,40 +66,49 @@ static int checkentry(const char *tablename, return 1; } -static void destroy(const struct xt_match *match, void *matchinfo) +static void destroy(const struct xt_match *match, void *matchinfo, + unsigned int matchsize) { textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config); } -static struct xt_match xt_string_match[] = { - { - .name = "string", - .family = AF_INET, - .checkentry = checkentry, - .match = match, - .destroy = destroy, - .matchsize = sizeof(struct xt_string_info), - .me = THIS_MODULE - }, - { - .name = "string", - .family = AF_INET6, - .checkentry = checkentry, - .match = match, - .destroy = destroy, - .matchsize = sizeof(struct xt_string_info), - .me = THIS_MODULE - }, +static struct xt_match string_match = { + .name = "string", + .match = match, + .matchsize = sizeof(struct xt_string_info), + .checkentry = checkentry, + .destroy = destroy, + .family = AF_INET, + .me = THIS_MODULE +}; +static struct xt_match string6_match = { + .name = "string", + .match = match, + .matchsize = sizeof(struct xt_string_info), + .checkentry = checkentry, + .destroy = destroy, + .family = AF_INET6, + .me = THIS_MODULE }; static int __init xt_string_init(void) { - return xt_register_matches(xt_string_match, ARRAY_SIZE(xt_string_match)); + int ret; + + ret = xt_register_match(&string_match); + if (ret) + return ret; + ret = xt_register_match(&string6_match); + if (ret) + xt_unregister_match(&string_match); + + return ret; } static void __exit xt_string_fini(void) { - xt_unregister_matches(xt_string_match, ARRAY_SIZE(xt_string_match)); + xt_unregister_match(&string_match); + xt_unregister_match(&string6_match); } module_init(xt_string_init); diff --git a/trunk/net/netfilter/xt_tcpmss.c b/trunk/net/netfilter/xt_tcpmss.c index a3682fe2f192..cf7d335cadcd 100644 --- a/trunk/net/netfilter/xt_tcpmss.c +++ b/trunk/net/netfilter/xt_tcpmss.c @@ -18,22 +18,21 @@ #include #include +#define TH_SYN 0x02 + MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marc Boucher "); MODULE_DESCRIPTION("iptables TCP MSS match module"); MODULE_ALIAS("ipt_tcpmss"); -static int -match(const struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - const struct xt_match *match, - const void *matchinfo, - int offset, - unsigned int protoff, - int *hotdrop) +/* Returns 1 if the mss option is set and matched by the range, 0 otherwise */ +static inline int +mssoption_match(u_int16_t min, u_int16_t max, + const struct sk_buff *skb, + unsigned int protoff, + int invert, + int *hotdrop) { - const struct xt_tcpmss_match_info *info = matchinfo; struct tcphdr _tcph, *th; /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ u8 _opt[15 * 4 - sizeof(_tcph)], *op; @@ -65,50 +64,72 @@ match(const struct sk_buff *skb, mssval = (op[i+2] << 8) | op[i+3]; - return (mssval >= info->mss_min && - mssval <= info->mss_max) ^ info->invert; + return (mssval >= min && mssval <= max) ^ invert; } - if (op[i] < 2) - i++; - else - i += op[i+1] ? : 1; + if (op[i] < 2) i++; + else i += op[i+1]?:1; } out: - return info->invert; + return invert; -dropit: + dropit: *hotdrop = 1; return 0; } -static struct xt_match xt_tcpmss_match[] = { - { - .name = "tcpmss", - .family = AF_INET, - .match = match, - .matchsize = sizeof(struct xt_tcpmss_match_info), - .proto = IPPROTO_TCP, - .me = THIS_MODULE, - }, - { - .name = "tcpmss", - .family = AF_INET6, - .match = match, - .matchsize = sizeof(struct xt_tcpmss_match_info), - .proto = IPPROTO_TCP, - .me = THIS_MODULE, - }, +static int +match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const struct xt_match *match, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +{ + const struct xt_tcpmss_match_info *info = matchinfo; + + return mssoption_match(info->mss_min, info->mss_max, skb, protoff, + info->invert, hotdrop); +} + +static struct xt_match tcpmss_match = { + .name = "tcpmss", + .match = match, + .matchsize = sizeof(struct xt_tcpmss_match_info), + .proto = IPPROTO_TCP, + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_match tcpmss6_match = { + .name = "tcpmss", + .match = match, + .matchsize = sizeof(struct xt_tcpmss_match_info), + .proto = IPPROTO_TCP, + .family = AF_INET6, + .me = THIS_MODULE, }; + static int __init xt_tcpmss_init(void) { - return xt_register_matches(xt_tcpmss_match, - ARRAY_SIZE(xt_tcpmss_match)); + int ret; + ret = xt_register_match(&tcpmss_match); + if (ret) + return ret; + + ret = xt_register_match(&tcpmss6_match); + if (ret) + xt_unregister_match(&tcpmss_match); + + return ret; } static void __exit xt_tcpmss_fini(void) { - xt_unregister_matches(xt_tcpmss_match, ARRAY_SIZE(xt_tcpmss_match)); + xt_unregister_match(&tcpmss6_match); + xt_unregister_match(&tcpmss_match); } module_init(xt_tcpmss_init); diff --git a/trunk/net/netfilter/xt_tcpudp.c b/trunk/net/netfilter/xt_tcpudp.c index e76a68e0bc66..a9a63aa68936 100644 --- a/trunk/net/netfilter/xt_tcpudp.c +++ b/trunk/net/netfilter/xt_tcpudp.c @@ -141,6 +141,7 @@ tcp_checkentry(const char *tablename, const void *info, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct xt_tcp *tcpinfo = matchinfo; @@ -189,6 +190,7 @@ udp_checkentry(const char *tablename, const void *info, const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) { const struct xt_tcp *udpinfo = matchinfo; @@ -197,54 +199,81 @@ udp_checkentry(const char *tablename, return !(udpinfo->invflags & ~XT_UDP_INV_MASK); } -static struct xt_match xt_tcpudp_match[] = { - { - .name = "tcp", - .family = AF_INET, - .checkentry = tcp_checkentry, - .match = tcp_match, - .matchsize = sizeof(struct xt_tcp), - .proto = IPPROTO_TCP, - .me = THIS_MODULE, - }, - { - .name = "tcp", - .family = AF_INET6, - .checkentry = tcp_checkentry, - .match = tcp_match, - .matchsize = sizeof(struct xt_tcp), - .proto = IPPROTO_TCP, - .me = THIS_MODULE, - }, - { - .name = "udp", - .family = AF_INET, - .checkentry = udp_checkentry, - .match = udp_match, - .matchsize = sizeof(struct xt_udp), - .proto = IPPROTO_UDP, - .me = THIS_MODULE, - }, - { - .name = "udp", - .family = AF_INET6, - .checkentry = udp_checkentry, - .match = udp_match, - .matchsize = sizeof(struct xt_udp), - .proto = IPPROTO_UDP, - .me = THIS_MODULE, - }, +static struct xt_match tcp_matchstruct = { + .name = "tcp", + .match = tcp_match, + .matchsize = sizeof(struct xt_tcp), + .proto = IPPROTO_TCP, + .family = AF_INET, + .checkentry = tcp_checkentry, + .me = THIS_MODULE, +}; + +static struct xt_match tcp6_matchstruct = { + .name = "tcp", + .match = tcp_match, + .matchsize = sizeof(struct xt_tcp), + .proto = IPPROTO_TCP, + .family = AF_INET6, + .checkentry = tcp_checkentry, + .me = THIS_MODULE, +}; + +static struct xt_match udp_matchstruct = { + .name = "udp", + .match = udp_match, + .matchsize = sizeof(struct xt_udp), + .proto = IPPROTO_UDP, + .family = AF_INET, + .checkentry = udp_checkentry, + .me = THIS_MODULE, +}; +static struct xt_match udp6_matchstruct = { + .name = "udp", + .match = udp_match, + .matchsize = sizeof(struct xt_udp), + .proto = IPPROTO_UDP, + .family = AF_INET6, + .checkentry = udp_checkentry, + .me = THIS_MODULE, }; static int __init xt_tcpudp_init(void) { - return xt_register_matches(xt_tcpudp_match, - ARRAY_SIZE(xt_tcpudp_match)); + int ret; + ret = xt_register_match(&tcp_matchstruct); + if (ret) + return ret; + + ret = xt_register_match(&tcp6_matchstruct); + if (ret) + goto out_unreg_tcp; + + ret = xt_register_match(&udp_matchstruct); + if (ret) + goto out_unreg_tcp6; + + ret = xt_register_match(&udp6_matchstruct); + if (ret) + goto out_unreg_udp; + + return ret; + +out_unreg_udp: + xt_unregister_match(&udp_matchstruct); +out_unreg_tcp6: + xt_unregister_match(&tcp6_matchstruct); +out_unreg_tcp: + xt_unregister_match(&tcp_matchstruct); + return ret; } static void __exit xt_tcpudp_fini(void) { - xt_unregister_matches(xt_tcpudp_match, ARRAY_SIZE(xt_tcpudp_match)); + xt_unregister_match(&udp6_matchstruct); + xt_unregister_match(&udp_matchstruct); + xt_unregister_match(&tcp6_matchstruct); + xt_unregister_match(&tcp_matchstruct); } module_init(xt_tcpudp_init); diff --git a/trunk/net/netlabel/Kconfig b/trunk/net/netlabel/Kconfig deleted file mode 100644 index fe23cb7f1e87..000000000000 --- a/trunk/net/netlabel/Kconfig +++ /dev/null @@ -1,14 +0,0 @@ -# -# NetLabel configuration -# - -config NETLABEL - bool "NetLabel subsystem support" - depends on NET && SECURITY - default n - ---help--- - NetLabel provides support for explicit network packet labeling - protocols such as CIPSO and RIPSO. For more information see - Documentation/netlabel. - - If you are unsure, say N. diff --git a/trunk/net/netlabel/Makefile b/trunk/net/netlabel/Makefile deleted file mode 100644 index 8af18c0a47d9..000000000000 --- a/trunk/net/netlabel/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# -# Makefile for the NetLabel subsystem. -# -# Feb 9, 2006, Paul Moore -# - -# base objects -obj-y := netlabel_user.o netlabel_kapi.o netlabel_domainhash.o - -# management objects -obj-y += netlabel_mgmt.o - -# protocol modules -obj-y += netlabel_unlabeled.o -obj-y += netlabel_cipso_v4.o - diff --git a/trunk/net/netlabel/netlabel_cipso_v4.c b/trunk/net/netlabel/netlabel_cipso_v4.c deleted file mode 100644 index a4f40adc447b..000000000000 --- a/trunk/net/netlabel/netlabel_cipso_v4.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * NetLabel CIPSO/IPv4 Support - * - * This file defines the CIPSO/IPv4 functions for the NetLabel system. The - * NetLabel system manages static and dynamic label mappings for network - * protocols such as CIPSO and RIPSO. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "netlabel_user.h" -#include "netlabel_cipso_v4.h" - -/* NetLabel Generic NETLINK CIPSOv4 family */ -static struct genl_family netlbl_cipsov4_gnl_family = { - .id = GENL_ID_GENERATE, - .hdrsize = 0, - .name = NETLBL_NLTYPE_CIPSOV4_NAME, - .version = NETLBL_PROTO_VERSION, - .maxattr = 0, -}; - - -/* - * Helper Functions - */ - -/** - * netlbl_cipsov4_doi_free - Frees a CIPSO V4 DOI definition - * @entry: the entry's RCU field - * - * Description: - * This function is designed to be used as a callback to the call_rcu() - * function so that the memory allocated to the DOI definition can be released - * safely. - * - */ -static void netlbl_cipsov4_doi_free(struct rcu_head *entry) -{ - struct cipso_v4_doi *ptr; - - ptr = container_of(entry, struct cipso_v4_doi, rcu); - switch (ptr->type) { - case CIPSO_V4_MAP_STD: - kfree(ptr->map.std->lvl.cipso); - kfree(ptr->map.std->lvl.local); - kfree(ptr->map.std->cat.cipso); - kfree(ptr->map.std->cat.local); - break; - } - kfree(ptr); -} - - -/* - * NetLabel Command Handlers - */ - -/** - * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition - * @doi: the DOI value - * @msg: the ADD message data - * @msg_size: the size of the ADD message buffer - * - * Description: - * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message - * and add it to the CIPSO V4 engine. Return zero on success and non-zero on - * error. - * - */ -static int netlbl_cipsov4_add_std(u32 doi, struct nlattr *msg, size_t msg_size) -{ - int ret_val = -EINVAL; - int msg_len = msg_size; - u32 num_tags; - u32 num_lvls; - u32 num_cats; - struct cipso_v4_doi *doi_def = NULL; - u32 iter; - u32 tmp_val_a; - u32 tmp_val_b; - - if (msg_len < NETLBL_LEN_U32) - goto add_std_failure; - num_tags = netlbl_getinc_u32(&msg, &msg_len); - if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT) - goto add_std_failure; - - doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); - if (doi_def == NULL) { - ret_val = -ENOMEM; - goto add_std_failure; - } - doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL); - if (doi_def->map.std == NULL) { - ret_val = -ENOMEM; - goto add_std_failure; - } - doi_def->type = CIPSO_V4_MAP_STD; - - for (iter = 0; iter < num_tags; iter++) { - if (msg_len < NETLBL_LEN_U8) - goto add_std_failure; - doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len); - switch (doi_def->tags[iter]) { - case CIPSO_V4_TAG_RBITMAP: - break; - default: - goto add_std_failure; - } - } - if (iter < CIPSO_V4_TAG_MAXCNT) - doi_def->tags[iter] = CIPSO_V4_TAG_INVALID; - - if (msg_len < 6 * NETLBL_LEN_U32) - goto add_std_failure; - - num_lvls = netlbl_getinc_u32(&msg, &msg_len); - if (num_lvls == 0) - goto add_std_failure; - doi_def->map.std->lvl.local_size = netlbl_getinc_u32(&msg, &msg_len); - if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS) - goto add_std_failure; - doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size, - sizeof(u32), - GFP_KERNEL); - if (doi_def->map.std->lvl.local == NULL) { - ret_val = -ENOMEM; - goto add_std_failure; - } - doi_def->map.std->lvl.cipso_size = netlbl_getinc_u8(&msg, &msg_len); - if (doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS) - goto add_std_failure; - doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size, - sizeof(u32), - GFP_KERNEL); - if (doi_def->map.std->lvl.cipso == NULL) { - ret_val = -ENOMEM; - goto add_std_failure; - } - - num_cats = netlbl_getinc_u32(&msg, &msg_len); - doi_def->map.std->cat.local_size = netlbl_getinc_u32(&msg, &msg_len); - if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS) - goto add_std_failure; - doi_def->map.std->cat.local = kcalloc(doi_def->map.std->cat.local_size, - sizeof(u32), - GFP_KERNEL); - if (doi_def->map.std->cat.local == NULL) { - ret_val = -ENOMEM; - goto add_std_failure; - } - doi_def->map.std->cat.cipso_size = netlbl_getinc_u16(&msg, &msg_len); - if (doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS) - goto add_std_failure; - doi_def->map.std->cat.cipso = kcalloc(doi_def->map.std->cat.cipso_size, - sizeof(u32), - GFP_KERNEL); - if (doi_def->map.std->cat.cipso == NULL) { - ret_val = -ENOMEM; - goto add_std_failure; - } - - if (msg_len < - num_lvls * (NETLBL_LEN_U32 + NETLBL_LEN_U8) + - num_cats * (NETLBL_LEN_U32 + NETLBL_LEN_U16)) - goto add_std_failure; - - for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++) - doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL; - for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++) - doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL; - for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++) - doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT; - for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++) - doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT; - - for (iter = 0; iter < num_lvls; iter++) { - tmp_val_a = netlbl_getinc_u32(&msg, &msg_len); - tmp_val_b = netlbl_getinc_u8(&msg, &msg_len); - - if (tmp_val_a >= doi_def->map.std->lvl.local_size || - tmp_val_b >= doi_def->map.std->lvl.cipso_size) - goto add_std_failure; - - doi_def->map.std->lvl.cipso[tmp_val_b] = tmp_val_a; - doi_def->map.std->lvl.local[tmp_val_a] = tmp_val_b; - } - - for (iter = 0; iter < num_cats; iter++) { - tmp_val_a = netlbl_getinc_u32(&msg, &msg_len); - tmp_val_b = netlbl_getinc_u16(&msg, &msg_len); - - if (tmp_val_a >= doi_def->map.std->cat.local_size || - tmp_val_b >= doi_def->map.std->cat.cipso_size) - goto add_std_failure; - - doi_def->map.std->cat.cipso[tmp_val_b] = tmp_val_a; - doi_def->map.std->cat.local[tmp_val_a] = tmp_val_b; - } - - doi_def->doi = doi; - ret_val = cipso_v4_doi_add(doi_def); - if (ret_val != 0) - goto add_std_failure; - return 0; - -add_std_failure: - if (doi_def) - netlbl_cipsov4_doi_free(&doi_def->rcu); - return ret_val; -} - -/** - * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition - * @doi: the DOI value - * @msg: the ADD message data - * @msg_size: the size of the ADD message buffer - * - * Description: - * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message - * and add it to the CIPSO V4 engine. Return zero on success and non-zero on - * error. - * - */ -static int netlbl_cipsov4_add_pass(u32 doi, - struct nlattr *msg, - size_t msg_size) -{ - int ret_val = -EINVAL; - int msg_len = msg_size; - u32 num_tags; - struct cipso_v4_doi *doi_def = NULL; - u32 iter; - - if (msg_len < NETLBL_LEN_U32) - goto add_pass_failure; - num_tags = netlbl_getinc_u32(&msg, &msg_len); - if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT) - goto add_pass_failure; - - doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL); - if (doi_def == NULL) { - ret_val = -ENOMEM; - goto add_pass_failure; - } - doi_def->type = CIPSO_V4_MAP_PASS; - - for (iter = 0; iter < num_tags; iter++) { - if (msg_len < NETLBL_LEN_U8) - goto add_pass_failure; - doi_def->tags[iter] = netlbl_getinc_u8(&msg, &msg_len); - switch (doi_def->tags[iter]) { - case CIPSO_V4_TAG_RBITMAP: - break; - default: - goto add_pass_failure; - } - } - if (iter < CIPSO_V4_TAG_MAXCNT) - doi_def->tags[iter] = CIPSO_V4_TAG_INVALID; - - doi_def->doi = doi; - ret_val = cipso_v4_doi_add(doi_def); - if (ret_val != 0) - goto add_pass_failure; - return 0; - -add_pass_failure: - if (doi_def) - netlbl_cipsov4_doi_free(&doi_def->rcu); - return ret_val; -} - -/** - * netlbl_cipsov4_add - Handle an ADD message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Create a new DOI definition based on the given ADD message and add it to the - * CIPSO V4 engine. Returns zero on success, negative values on failure. - * - */ -static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) - -{ - int ret_val = -EINVAL; - u32 doi; - u32 map_type; - int msg_len = netlbl_netlink_payload_len(skb); - struct nlattr *msg = netlbl_netlink_payload_data(skb); - - ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); - if (ret_val != 0) - goto add_return; - - if (msg_len < 2 * NETLBL_LEN_U32) - goto add_return; - - doi = netlbl_getinc_u32(&msg, &msg_len); - map_type = netlbl_getinc_u32(&msg, &msg_len); - switch (map_type) { - case CIPSO_V4_MAP_STD: - ret_val = netlbl_cipsov4_add_std(doi, msg, msg_len); - break; - case CIPSO_V4_MAP_PASS: - ret_val = netlbl_cipsov4_add_pass(doi, msg, msg_len); - break; - } - -add_return: - netlbl_netlink_send_ack(info, - netlbl_cipsov4_gnl_family.id, - NLBL_CIPSOV4_C_ACK, - -ret_val); - return ret_val; -} - -/** - * netlbl_cipsov4_list - Handle a LIST message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Process a user generated LIST message and respond accordingly. Returns - * zero on success and negative values on error. - * - */ -static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) -{ - int ret_val = -EINVAL; - u32 doi; - struct nlattr *msg = netlbl_netlink_payload_data(skb); - struct sk_buff *ans_skb; - - if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32) - goto list_failure; - - doi = nla_get_u32(msg); - ans_skb = cipso_v4_doi_dump(doi, NLMSG_SPACE(GENL_HDRLEN)); - if (ans_skb == NULL) { - ret_val = -ENOMEM; - goto list_failure; - } - netlbl_netlink_hdr_push(ans_skb, - info->snd_pid, - 0, - netlbl_cipsov4_gnl_family.id, - NLBL_CIPSOV4_C_LIST); - - ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); - if (ret_val != 0) - goto list_failure; - - return 0; - -list_failure: - netlbl_netlink_send_ack(info, - netlbl_cipsov4_gnl_family.id, - NLBL_CIPSOV4_C_ACK, - -ret_val); - return ret_val; -} - -/** - * netlbl_cipsov4_listall - Handle a LISTALL message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Process a user generated LISTALL message and respond accordingly. Returns - * zero on success and negative values on error. - * - */ -static int netlbl_cipsov4_listall(struct sk_buff *skb, struct genl_info *info) -{ - int ret_val = -EINVAL; - struct sk_buff *ans_skb; - - ans_skb = cipso_v4_doi_dump_all(NLMSG_SPACE(GENL_HDRLEN)); - if (ans_skb == NULL) { - ret_val = -ENOMEM; - goto listall_failure; - } - netlbl_netlink_hdr_push(ans_skb, - info->snd_pid, - 0, - netlbl_cipsov4_gnl_family.id, - NLBL_CIPSOV4_C_LISTALL); - - ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); - if (ret_val != 0) - goto listall_failure; - - return 0; - -listall_failure: - netlbl_netlink_send_ack(info, - netlbl_cipsov4_gnl_family.id, - NLBL_CIPSOV4_C_ACK, - -ret_val); - return ret_val; -} - -/** - * netlbl_cipsov4_remove - Handle a REMOVE message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Process a user generated REMOVE message and respond accordingly. Returns - * zero on success, negative values on failure. - * - */ -static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info) -{ - int ret_val; - u32 doi; - struct nlattr *msg = netlbl_netlink_payload_data(skb); - - ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); - if (ret_val != 0) - goto remove_return; - - if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32) { - ret_val = -EINVAL; - goto remove_return; - } - - doi = nla_get_u32(msg); - ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free); - -remove_return: - netlbl_netlink_send_ack(info, - netlbl_cipsov4_gnl_family.id, - NLBL_CIPSOV4_C_ACK, - -ret_val); - return ret_val; -} - -/* - * NetLabel Generic NETLINK Command Definitions - */ - -static struct genl_ops netlbl_cipsov4_genl_c_add = { - .cmd = NLBL_CIPSOV4_C_ADD, - .flags = 0, - .doit = netlbl_cipsov4_add, - .dumpit = NULL, -}; - -static struct genl_ops netlbl_cipsov4_genl_c_remove = { - .cmd = NLBL_CIPSOV4_C_REMOVE, - .flags = 0, - .doit = netlbl_cipsov4_remove, - .dumpit = NULL, -}; - -static struct genl_ops netlbl_cipsov4_genl_c_list = { - .cmd = NLBL_CIPSOV4_C_LIST, - .flags = 0, - .doit = netlbl_cipsov4_list, - .dumpit = NULL, -}; - -static struct genl_ops netlbl_cipsov4_genl_c_listall = { - .cmd = NLBL_CIPSOV4_C_LISTALL, - .flags = 0, - .doit = netlbl_cipsov4_listall, - .dumpit = NULL, -}; - -/* - * NetLabel Generic NETLINK Protocol Functions - */ - -/** - * netlbl_cipsov4_genl_init - Register the CIPSOv4 NetLabel component - * - * Description: - * Register the CIPSOv4 packet NetLabel component with the Generic NETLINK - * mechanism. Returns zero on success, negative values on failure. - * - */ -int netlbl_cipsov4_genl_init(void) -{ - int ret_val; - - ret_val = genl_register_family(&netlbl_cipsov4_gnl_family); - if (ret_val != 0) - return ret_val; - - ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, - &netlbl_cipsov4_genl_c_add); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, - &netlbl_cipsov4_genl_c_remove); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, - &netlbl_cipsov4_genl_c_list); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family, - &netlbl_cipsov4_genl_c_listall); - if (ret_val != 0) - return ret_val; - - return 0; -} diff --git a/trunk/net/netlabel/netlabel_cipso_v4.h b/trunk/net/netlabel/netlabel_cipso_v4.h deleted file mode 100644 index 4c6ff4b93004..000000000000 --- a/trunk/net/netlabel/netlabel_cipso_v4.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * NetLabel CIPSO/IPv4 Support - * - * This file defines the CIPSO/IPv4 functions for the NetLabel system. The - * NetLabel system manages static and dynamic label mappings for network - * protocols such as CIPSO and RIPSO. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _NETLABEL_CIPSO_V4 -#define _NETLABEL_CIPSO_V4 - -#include - -/* - * The following NetLabel payloads are supported by the CIPSO subsystem, all - * of which are preceeded by the nlmsghdr struct. - * - * o ACK: - * Sent by the kernel in response to an applications message, applications - * should never send this message. - * - * +----------------------+-----------------------+ - * | seq number (32 bits) | return code (32 bits) | - * +----------------------+-----------------------+ - * - * seq number: the sequence number of the original message, taken from the - * nlmsghdr structure - * return code: return value, based on errno values - * - * o ADD: - * Sent by an application to add a new DOI mapping table, after completion - * of the task the kernel should ACK this message. - * - * +---------------+--------------------+---------------------+ - * | DOI (32 bits) | map type (32 bits) | tag count (32 bits) | ... - * +---------------+--------------------+---------------------+ - * - * +-----------------+ - * | tag #X (8 bits) | ... repeated - * +-----------------+ - * - * +-------------- ---- --- -- - - * | mapping data - * +-------------- ---- --- -- - - * - * DOI: the DOI value - * map type: the mapping table type (defined in the cipso_ipv4.h header - * as CIPSO_V4_MAP_*) - * tag count: the number of tags, must be greater than zero - * tag: the CIPSO tag for the DOI, tags listed first are given - * higher priorirty when sending packets - * mapping data: specific to the map type (see below) - * - * CIPSO_V4_MAP_STD - * - * +------------------+-----------------------+----------------------+ - * | levels (32 bits) | max l level (32 bits) | max r level (8 bits) | ... - * +------------------+-----------------------+----------------------+ - * - * +----------------------+---------------------+---------------------+ - * | categories (32 bits) | max l cat (32 bits) | max r cat (16 bits) | ... - * +----------------------+---------------------+---------------------+ - * - * +--------------------------+-------------------------+ - * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated - * +--------------------------+-------------------------+ - * - * +-----------------------------+-----------------------------+ - * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated - * +-----------------------------+-----------------------------+ - * - * levels: the number of level mappings - * max l level: the highest local level - * max r level: the highest remote/CIPSO level - * categories: the number of category mappings - * max l cat: the highest local category - * max r cat: the highest remote/CIPSO category - * local level: the local part of a level mapping - * CIPSO level: the remote/CIPSO part of a level mapping - * local category: the local part of a category mapping - * CIPSO category: the remote/CIPSO part of a category mapping - * - * CIPSO_V4_MAP_PASS - * - * No mapping data is needed for this map type. - * - * o REMOVE: - * Sent by an application to remove a specific DOI mapping table from the - * CIPSO V4 system. The kernel should ACK this message. - * - * +---------------+ - * | DOI (32 bits) | - * +---------------+ - * - * DOI: the DOI value - * - * o LIST: - * Sent by an application to list the details of a DOI definition. The - * kernel should send an ACK on error or a response as indicated below. The - * application generated message format is shown below. - * - * +---------------+ - * | DOI (32 bits) | - * +---------------+ - * - * DOI: the DOI value - * - * The valid response message format depends on the type of the DOI mapping, - * the known formats are shown below. - * - * +--------------------+ - * | map type (32 bits) | ... - * +--------------------+ - * - * map type: the DOI mapping table type (defined in the cipso_ipv4.h - * header as CIPSO_V4_MAP_*) - * - * (map type == CIPSO_V4_MAP_STD) - * - * +----------------+------------------+----------------------+ - * | tags (32 bits) | levels (32 bits) | categories (32 bits) | ... - * +----------------+------------------+----------------------+ - * - * +-----------------+ - * | tag #X (8 bits) | ... repeated - * +-----------------+ - * - * +--------------------------+-------------------------+ - * | local level #X (32 bits) | CIPSO level #X (8 bits) | ... repeated - * +--------------------------+-------------------------+ - * - * +-----------------------------+-----------------------------+ - * | local category #X (32 bits) | CIPSO category #X (16 bits) | ... repeated - * +-----------------------------+-----------------------------+ - * - * tags: the number of CIPSO tag types - * levels: the number of level mappings - * categories: the number of category mappings - * tag: the tag number, tags listed first are given higher - * priority when sending packets - * local level: the local part of a level mapping - * CIPSO level: the remote/CIPSO part of a level mapping - * local category: the local part of a category mapping - * CIPSO category: the remote/CIPSO part of a category mapping - * - * (map type == CIPSO_V4_MAP_PASS) - * - * +----------------+ - * | tags (32 bits) | ... - * +----------------+ - * - * +-----------------+ - * | tag #X (8 bits) | ... repeated - * +-----------------+ - * - * tags: the number of CIPSO tag types - * tag: the tag number, tags listed first are given higher - * priority when sending packets - * - * o LISTALL: - * This message is sent by an application to list the valid DOIs on the - * system. There is no payload and the kernel should respond with an ACK - * or the following message. - * - * +---------------------+------------------+-----------------------+ - * | DOI count (32 bits) | DOI #X (32 bits) | map type #X (32 bits) | - * +---------------------+------------------+-----------------------+ - * - * +-----------------------+ - * | map type #X (32 bits) | ... - * +-----------------------+ - * - * DOI count: the number of DOIs - * DOI: the DOI value - * map type: the DOI mapping table type (defined in the cipso_ipv4.h - * header as CIPSO_V4_MAP_*) - * - */ - -/* NetLabel CIPSOv4 commands */ -enum { - NLBL_CIPSOV4_C_UNSPEC, - NLBL_CIPSOV4_C_ACK, - NLBL_CIPSOV4_C_ADD, - NLBL_CIPSOV4_C_REMOVE, - NLBL_CIPSOV4_C_LIST, - NLBL_CIPSOV4_C_LISTALL, - __NLBL_CIPSOV4_C_MAX, -}; -#define NLBL_CIPSOV4_C_MAX (__NLBL_CIPSOV4_C_MAX - 1) - -/* NetLabel protocol functions */ -int netlbl_cipsov4_genl_init(void); - -#endif diff --git a/trunk/net/netlabel/netlabel_domainhash.c b/trunk/net/netlabel/netlabel_domainhash.c deleted file mode 100644 index 0489a1378101..000000000000 --- a/trunk/net/netlabel/netlabel_domainhash.c +++ /dev/null @@ -1,513 +0,0 @@ -/* - * NetLabel Domain Hash Table - * - * This file manages the domain hash table that NetLabel uses to determine - * which network labeling protocol to use for a given domain. The NetLabel - * system manages static and dynamic label mappings for network protocols such - * as CIPSO and RIPSO. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "netlabel_mgmt.h" -#include "netlabel_domainhash.h" - -struct netlbl_domhsh_tbl { - struct list_head *tbl; - u32 size; -}; - -/* Domain hash table */ -/* XXX - updates should be so rare that having one spinlock for the entire - * hash table should be okay */ -static DEFINE_SPINLOCK(netlbl_domhsh_lock); -static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL; - -/* Default domain mapping */ -static DEFINE_SPINLOCK(netlbl_domhsh_def_lock); -static struct netlbl_dom_map *netlbl_domhsh_def = NULL; - -/* - * Domain Hash Table Helper Functions - */ - -/** - * netlbl_domhsh_free_entry - Frees a domain hash table entry - * @entry: the entry's RCU field - * - * Description: - * This function is designed to be used as a callback to the call_rcu() - * function so that the memory allocated to a hash table entry can be released - * safely. - * - */ -static void netlbl_domhsh_free_entry(struct rcu_head *entry) -{ - struct netlbl_dom_map *ptr; - - ptr = container_of(entry, struct netlbl_dom_map, rcu); - kfree(ptr->domain); - kfree(ptr); -} - -/** - * netlbl_domhsh_hash - Hashing function for the domain hash table - * @domain: the domain name to hash - * - * Description: - * This is the hashing function for the domain hash table, it returns the - * correct bucket number for the domain. The caller is responsibile for - * calling the rcu_read_[un]lock() functions. - * - */ -static u32 netlbl_domhsh_hash(const char *key) -{ - u32 iter; - u32 val; - u32 len; - - /* This is taken (with slight modification) from - * security/selinux/ss/symtab.c:symhash() */ - - for (iter = 0, val = 0, len = strlen(key); iter < len; iter++) - val = (val << 4 | (val >> (8 * sizeof(u32) - 4))) ^ key[iter]; - return val & (rcu_dereference(netlbl_domhsh)->size - 1); -} - -/** - * netlbl_domhsh_search - Search for a domain entry - * @domain: the domain - * @def: return default if no match is found - * - * Description: - * Searches the domain hash table and returns a pointer to the hash table - * entry if found, otherwise NULL is returned. If @def is non-zero and a - * match is not found in the domain hash table the default mapping is returned - * if it exists. The caller is responsibile for the rcu hash table locks - * (i.e. the caller much call rcu_read_[un]lock()). - * - */ -static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def) -{ - u32 bkt; - struct netlbl_dom_map *iter; - - if (domain != NULL) { - bkt = netlbl_domhsh_hash(domain); - list_for_each_entry_rcu(iter, &netlbl_domhsh->tbl[bkt], list) - if (iter->valid && strcmp(iter->domain, domain) == 0) - return iter; - } - - if (def != 0) { - iter = rcu_dereference(netlbl_domhsh_def); - if (iter != NULL && iter->valid) - return iter; - } - - return NULL; -} - -/* - * Domain Hash Table Functions - */ - -/** - * netlbl_domhsh_init - Init for the domain hash - * @size: the number of bits to use for the hash buckets - * - * Description: - * Initializes the domain hash table, should be called only by - * netlbl_user_init() during initialization. Returns zero on success, non-zero - * values on error. - * - */ -int netlbl_domhsh_init(u32 size) -{ - u32 iter; - struct netlbl_domhsh_tbl *hsh_tbl; - - if (size == 0) - return -EINVAL; - - hsh_tbl = kmalloc(sizeof(*hsh_tbl), GFP_KERNEL); - if (hsh_tbl == NULL) - return -ENOMEM; - hsh_tbl->size = 1 << size; - hsh_tbl->tbl = kcalloc(hsh_tbl->size, - sizeof(struct list_head), - GFP_KERNEL); - if (hsh_tbl->tbl == NULL) { - kfree(hsh_tbl); - return -ENOMEM; - } - for (iter = 0; iter < hsh_tbl->size; iter++) - INIT_LIST_HEAD(&hsh_tbl->tbl[iter]); - - rcu_read_lock(); - spin_lock(&netlbl_domhsh_lock); - rcu_assign_pointer(netlbl_domhsh, hsh_tbl); - spin_unlock(&netlbl_domhsh_lock); - rcu_read_unlock(); - - return 0; -} - -/** - * netlbl_domhsh_add - Adds a entry to the domain hash table - * @entry: the entry to add - * - * Description: - * Adds a new entry to the domain hash table and handles any updates to the - * lower level protocol handler (i.e. CIPSO). Returns zero on success, - * negative on failure. - * - */ -int netlbl_domhsh_add(struct netlbl_dom_map *entry) -{ - int ret_val; - u32 bkt; - - switch (entry->type) { - case NETLBL_NLTYPE_UNLABELED: - ret_val = 0; - break; - case NETLBL_NLTYPE_CIPSOV4: - ret_val = cipso_v4_doi_domhsh_add(entry->type_def.cipsov4, - entry->domain); - break; - default: - return -EINVAL; - } - if (ret_val != 0) - return ret_val; - - entry->valid = 1; - INIT_RCU_HEAD(&entry->rcu); - - ret_val = 0; - rcu_read_lock(); - if (entry->domain != NULL) { - bkt = netlbl_domhsh_hash(entry->domain); - spin_lock(&netlbl_domhsh_lock); - if (netlbl_domhsh_search(entry->domain, 0) == NULL) - list_add_tail_rcu(&entry->list, - &netlbl_domhsh->tbl[bkt]); - else - ret_val = -EEXIST; - spin_unlock(&netlbl_domhsh_lock); - } else if (entry->domain == NULL) { - INIT_LIST_HEAD(&entry->list); - spin_lock(&netlbl_domhsh_def_lock); - if (rcu_dereference(netlbl_domhsh_def) == NULL) - rcu_assign_pointer(netlbl_domhsh_def, entry); - else - ret_val = -EEXIST; - spin_unlock(&netlbl_domhsh_def_lock); - } else - ret_val = -EINVAL; - rcu_read_unlock(); - - if (ret_val != 0) { - switch (entry->type) { - case NETLBL_NLTYPE_CIPSOV4: - if (cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4, - entry->domain) != 0) - BUG(); - break; - } - } - - return ret_val; -} - -/** - * netlbl_domhsh_add_default - Adds the default entry to the domain hash table - * @entry: the entry to add - * - * Description: - * Adds a new default entry to the domain hash table and handles any updates - * to the lower level protocol handler (i.e. CIPSO). Returns zero on success, - * negative on failure. - * - */ -int netlbl_domhsh_add_default(struct netlbl_dom_map *entry) -{ - return netlbl_domhsh_add(entry); -} - -/** - * netlbl_domhsh_remove - Removes an entry from the domain hash table - * @domain: the domain to remove - * - * Description: - * Removes an entry from the domain hash table and handles any updates to the - * lower level protocol handler (i.e. CIPSO). Returns zero on success, - * negative on failure. - * - */ -int netlbl_domhsh_remove(const char *domain) -{ - int ret_val = -ENOENT; - struct netlbl_dom_map *entry; - - rcu_read_lock(); - if (domain != NULL) - entry = netlbl_domhsh_search(domain, 0); - else - entry = netlbl_domhsh_search(domain, 1); - if (entry == NULL) - goto remove_return; - switch (entry->type) { - case NETLBL_NLTYPE_UNLABELED: - break; - case NETLBL_NLTYPE_CIPSOV4: - ret_val = cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4, - entry->domain); - if (ret_val != 0) - goto remove_return; - break; - } - ret_val = 0; - if (entry != rcu_dereference(netlbl_domhsh_def)) { - spin_lock(&netlbl_domhsh_lock); - if (entry->valid) { - entry->valid = 0; - list_del_rcu(&entry->list); - } else - ret_val = -ENOENT; - spin_unlock(&netlbl_domhsh_lock); - } else { - spin_lock(&netlbl_domhsh_def_lock); - if (entry->valid) { - entry->valid = 0; - rcu_assign_pointer(netlbl_domhsh_def, NULL); - } else - ret_val = -ENOENT; - spin_unlock(&netlbl_domhsh_def_lock); - } - if (ret_val == 0) - call_rcu(&entry->rcu, netlbl_domhsh_free_entry); - -remove_return: - rcu_read_unlock(); - return ret_val; -} - -/** - * netlbl_domhsh_remove_default - Removes the default entry from the table - * - * Description: - * Removes/resets the default entry for the domain hash table and handles any - * updates to the lower level protocol handler (i.e. CIPSO). Returns zero on - * success, non-zero on failure. - * - */ -int netlbl_domhsh_remove_default(void) -{ - return netlbl_domhsh_remove(NULL); -} - -/** - * netlbl_domhsh_getentry - Get an entry from the domain hash table - * @domain: the domain name to search for - * - * Description: - * Look through the domain hash table searching for an entry to match @domain, - * return a pointer to a copy of the entry or NULL. The caller is responsibile - * for ensuring that rcu_read_[un]lock() is called. - * - */ -struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain) -{ - return netlbl_domhsh_search(domain, 1); -} - -/** - * netlbl_domhsh_dump - Dump the domain hash table into a sk_buff - * - * Description: - * Dump the domain hash table into a buffer suitable for returning to an - * application in response to a NetLabel management DOMAIN message. This - * function may fail if another process is growing the hash table at the same - * time. The returned sk_buff has room at the front of the sk_buff for - * @headroom bytes. See netlabel.h for the DOMAIN message format. Returns a - * pointer to a sk_buff on success, NULL on error. - * - */ -struct sk_buff *netlbl_domhsh_dump(size_t headroom) -{ - struct sk_buff *skb = NULL; - ssize_t buf_len; - u32 bkt_iter; - u32 dom_cnt = 0; - struct netlbl_domhsh_tbl *hsh_tbl; - struct netlbl_dom_map *list_iter; - ssize_t tmp_len; - - buf_len = NETLBL_LEN_U32; - rcu_read_lock(); - hsh_tbl = rcu_dereference(netlbl_domhsh); - for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++) - list_for_each_entry_rcu(list_iter, - &hsh_tbl->tbl[bkt_iter], list) { - buf_len += NETLBL_LEN_U32 + - nla_total_size(strlen(list_iter->domain) + 1); - switch (list_iter->type) { - case NETLBL_NLTYPE_UNLABELED: - break; - case NETLBL_NLTYPE_CIPSOV4: - buf_len += 2 * NETLBL_LEN_U32; - break; - } - dom_cnt++; - } - - skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); - if (skb == NULL) - goto dump_failure; - - if (nla_put_u32(skb, NLA_U32, dom_cnt) != 0) - goto dump_failure; - buf_len -= NETLBL_LEN_U32; - hsh_tbl = rcu_dereference(netlbl_domhsh); - for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++) - list_for_each_entry_rcu(list_iter, - &hsh_tbl->tbl[bkt_iter], list) { - tmp_len = nla_total_size(strlen(list_iter->domain) + - 1); - if (buf_len < NETLBL_LEN_U32 + tmp_len) - goto dump_failure; - if (nla_put_string(skb, - NLA_STRING, - list_iter->domain) != 0) - goto dump_failure; - if (nla_put_u32(skb, NLA_U32, list_iter->type) != 0) - goto dump_failure; - buf_len -= NETLBL_LEN_U32 + tmp_len; - switch (list_iter->type) { - case NETLBL_NLTYPE_UNLABELED: - break; - case NETLBL_NLTYPE_CIPSOV4: - if (buf_len < 2 * NETLBL_LEN_U32) - goto dump_failure; - if (nla_put_u32(skb, - NLA_U32, - list_iter->type_def.cipsov4->type) != 0) - goto dump_failure; - if (nla_put_u32(skb, - NLA_U32, - list_iter->type_def.cipsov4->doi) != 0) - goto dump_failure; - buf_len -= 2 * NETLBL_LEN_U32; - break; - } - } - rcu_read_unlock(); - - return skb; - -dump_failure: - rcu_read_unlock(); - kfree_skb(skb); - return NULL; -} - -/** - * netlbl_domhsh_dump_default - Dump the default domain mapping into a sk_buff - * - * Description: - * Dump the default domain mapping into a buffer suitable for returning to an - * application in response to a NetLabel management DEFDOMAIN message. This - * function may fail if another process is changing the default domain mapping - * at the same time. The returned sk_buff has room at the front of the - * skb_buff for @headroom bytes. See netlabel.h for the DEFDOMAIN message - * format. Returns a pointer to a sk_buff on success, NULL on error. - * - */ -struct sk_buff *netlbl_domhsh_dump_default(size_t headroom) -{ - struct sk_buff *skb; - ssize_t buf_len; - struct netlbl_dom_map *entry; - - buf_len = NETLBL_LEN_U32; - rcu_read_lock(); - entry = rcu_dereference(netlbl_domhsh_def); - if (entry != NULL) - switch (entry->type) { - case NETLBL_NLTYPE_UNLABELED: - break; - case NETLBL_NLTYPE_CIPSOV4: - buf_len += 2 * NETLBL_LEN_U32; - break; - } - - skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC); - if (skb == NULL) - goto dump_default_failure; - - if (entry != rcu_dereference(netlbl_domhsh_def)) - goto dump_default_failure; - if (entry != NULL) { - if (nla_put_u32(skb, NLA_U32, entry->type) != 0) - goto dump_default_failure; - buf_len -= NETLBL_LEN_U32; - switch (entry->type) { - case NETLBL_NLTYPE_UNLABELED: - break; - case NETLBL_NLTYPE_CIPSOV4: - if (buf_len < 2 * NETLBL_LEN_U32) - goto dump_default_failure; - if (nla_put_u32(skb, - NLA_U32, - entry->type_def.cipsov4->type) != 0) - goto dump_default_failure; - if (nla_put_u32(skb, - NLA_U32, - entry->type_def.cipsov4->doi) != 0) - goto dump_default_failure; - buf_len -= 2 * NETLBL_LEN_U32; - break; - } - } else - nla_put_u32(skb, NLA_U32, NETLBL_NLTYPE_NONE); - rcu_read_unlock(); - - return skb; - -dump_default_failure: - rcu_read_unlock(); - kfree_skb(skb); - return NULL; -} diff --git a/trunk/net/netlabel/netlabel_domainhash.h b/trunk/net/netlabel/netlabel_domainhash.h deleted file mode 100644 index 99a2287de246..000000000000 --- a/trunk/net/netlabel/netlabel_domainhash.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * NetLabel Domain Hash Table - * - * This file manages the domain hash table that NetLabel uses to determine - * which network labeling protocol to use for a given domain. The NetLabel - * system manages static and dynamic label mappings for network protocols such - * as CIPSO and RIPSO. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _NETLABEL_DOMAINHASH_H -#define _NETLABEL_DOMAINHASH_H - -#include -#include -#include - -/* Domain hash table size */ -/* XXX - currently this number is an uneducated guess */ -#define NETLBL_DOMHSH_BITSIZE 7 - -/* Domain mapping definition struct */ -struct netlbl_dom_map { - char *domain; - u32 type; - union { - struct cipso_v4_doi *cipsov4; - } type_def; - - u32 valid; - struct list_head list; - struct rcu_head rcu; -}; - -/* init function */ -int netlbl_domhsh_init(u32 size); - -/* Manipulate the domain hash table */ -int netlbl_domhsh_add(struct netlbl_dom_map *entry); -int netlbl_domhsh_add_default(struct netlbl_dom_map *entry); -int netlbl_domhsh_remove_default(void); -struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain); -struct sk_buff *netlbl_domhsh_dump(size_t headroom); -struct sk_buff *netlbl_domhsh_dump_default(size_t headroom); - -#endif diff --git a/trunk/net/netlabel/netlabel_kapi.c b/trunk/net/netlabel/netlabel_kapi.c deleted file mode 100644 index 0fd8aaafe23f..000000000000 --- a/trunk/net/netlabel/netlabel_kapi.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * NetLabel Kernel API - * - * This file defines the kernel API for the NetLabel system. The NetLabel - * system manages static and dynamic label mappings for network protocols such - * as CIPSO and RIPSO. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include "netlabel_domainhash.h" -#include "netlabel_unlabeled.h" -#include "netlabel_user.h" - -/* - * LSM Functions - */ - -/** - * netlbl_socket_setattr - Label a socket using the correct protocol - * @sock: the socket to label - * @secattr: the security attributes - * - * Description: - * Attach the correct label to the given socket using the security attributes - * specified in @secattr. This function requires exclusive access to - * @sock->sk, which means it either needs to be in the process of being - * created or locked via lock_sock(sock->sk). Returns zero on success, - * negative values on failure. - * - */ -int netlbl_socket_setattr(const struct socket *sock, - const struct netlbl_lsm_secattr *secattr) -{ - int ret_val = -ENOENT; - struct netlbl_dom_map *dom_entry; - - rcu_read_lock(); - dom_entry = netlbl_domhsh_getentry(secattr->domain); - if (dom_entry == NULL) - goto socket_setattr_return; - switch (dom_entry->type) { - case NETLBL_NLTYPE_CIPSOV4: - ret_val = cipso_v4_socket_setattr(sock, - dom_entry->type_def.cipsov4, - secattr); - break; - case NETLBL_NLTYPE_UNLABELED: - ret_val = 0; - break; - default: - ret_val = -ENOENT; - } - -socket_setattr_return: - rcu_read_unlock(); - return ret_val; -} - -/** - * netlbl_socket_getattr - Determine the security attributes of a socket - * @sock: the socket - * @secattr: the security attributes - * - * Description: - * Examines the given socket to see any NetLabel style labeling has been - * applied to the socket, if so it parses the socket label and returns the - * security attributes in @secattr. Returns zero on success, negative values - * on failure. - * - */ -int netlbl_socket_getattr(const struct socket *sock, - struct netlbl_lsm_secattr *secattr) -{ - int ret_val; - - ret_val = cipso_v4_socket_getattr(sock, secattr); - if (ret_val == 0) - return 0; - - return netlbl_unlabel_getattr(secattr); -} - -/** - * netlbl_skbuff_getattr - Determine the security attributes of a packet - * @skb: the packet - * @secattr: the security attributes - * - * Description: - * Examines the given packet to see if a recognized form of packet labeling - * is present, if so it parses the packet label and returns the security - * attributes in @secattr. Returns zero on success, negative values on - * failure. - * - */ -int netlbl_skbuff_getattr(const struct sk_buff *skb, - struct netlbl_lsm_secattr *secattr) -{ - int ret_val; - - ret_val = cipso_v4_skbuff_getattr(skb, secattr); - if (ret_val == 0) - return 0; - - return netlbl_unlabel_getattr(secattr); -} - -/** - * netlbl_skbuff_err - Handle a LSM error on a sk_buff - * @skb: the packet - * @error: the error code - * - * Description: - * Deal with a LSM problem when handling the packet in @skb, typically this is - * a permission denied problem (-EACCES). The correct action is determined - * according to the packet's labeling protocol. - * - */ -void netlbl_skbuff_err(struct sk_buff *skb, int error) -{ - if (CIPSO_V4_OPTEXIST(skb)) - cipso_v4_error(skb, error, 0); -} - -/** - * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches - * - * Description: - * For all of the NetLabel protocols that support some form of label mapping - * cache, invalidate the cache. Returns zero on success, negative values on - * error. - * - */ -void netlbl_cache_invalidate(void) -{ - cipso_v4_cache_invalidate(); -} - -/** - * netlbl_cache_add - Add an entry to a NetLabel protocol cache - * @skb: the packet - * @secattr: the packet's security attributes - * - * Description: - * Add the LSM security attributes for the given packet to the underlying - * NetLabel protocol's label mapping cache. Returns zero on success, negative - * values on error. - * - */ -int netlbl_cache_add(const struct sk_buff *skb, - const struct netlbl_lsm_secattr *secattr) -{ - if (secattr->cache.data == NULL) - return -ENOMSG; - - if (CIPSO_V4_OPTEXIST(skb)) - return cipso_v4_cache_add(skb, secattr); - - return -ENOMSG; -} - -/* - * Setup Functions - */ - -/** - * netlbl_init - Initialize NetLabel - * - * Description: - * Perform the required NetLabel initialization before first use. - * - */ -static int __init netlbl_init(void) -{ - int ret_val; - - printk(KERN_INFO "NetLabel: Initializing\n"); - printk(KERN_INFO "NetLabel: domain hash size = %u\n", - (1 << NETLBL_DOMHSH_BITSIZE)); - printk(KERN_INFO "NetLabel: protocols =" - " UNLABELED" - " CIPSOv4" - "\n"); - - ret_val = netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE); - if (ret_val != 0) - goto init_failure; - - ret_val = netlbl_netlink_init(); - if (ret_val != 0) - goto init_failure; - - ret_val = netlbl_unlabel_defconf(); - if (ret_val != 0) - goto init_failure; - printk(KERN_INFO "NetLabel: unlabeled traffic allowed by default\n"); - - return 0; - -init_failure: - panic("NetLabel: failed to initialize properly (%d)\n", ret_val); -} - -subsys_initcall(netlbl_init); diff --git a/trunk/net/netlabel/netlabel_mgmt.c b/trunk/net/netlabel/netlabel_mgmt.c deleted file mode 100644 index 85bc11a1fc46..000000000000 --- a/trunk/net/netlabel/netlabel_mgmt.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - * NetLabel Management Support - * - * This file defines the management functions for the NetLabel system. The - * NetLabel system manages static and dynamic label mappings for network - * protocols such as CIPSO and RIPSO. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "netlabel_domainhash.h" -#include "netlabel_user.h" -#include "netlabel_mgmt.h" - -/* NetLabel Generic NETLINK CIPSOv4 family */ -static struct genl_family netlbl_mgmt_gnl_family = { - .id = GENL_ID_GENERATE, - .hdrsize = 0, - .name = NETLBL_NLTYPE_MGMT_NAME, - .version = NETLBL_PROTO_VERSION, - .maxattr = 0, -}; - - -/* - * NetLabel Command Handlers - */ - -/** - * netlbl_mgmt_add - Handle an ADD message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Process a user generated ADD message and add the domains from the message - * to the hash table. See netlabel.h for a description of the message format. - * Returns zero on success, negative values on failure. - * - */ -static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) -{ - int ret_val = -EINVAL; - struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb); - int msg_len = netlbl_netlink_payload_len(skb); - u32 count; - struct netlbl_dom_map *entry = NULL; - u32 iter; - u32 tmp_val; - int tmp_size; - - ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); - if (ret_val != 0) - goto add_failure; - - if (msg_len < NETLBL_LEN_U32) - goto add_failure; - count = netlbl_getinc_u32(&msg_ptr, &msg_len); - - for (iter = 0; iter < count && msg_len > 0; iter++, entry = NULL) { - if (msg_len <= 0) { - ret_val = -EINVAL; - goto add_failure; - } - entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (entry == NULL) { - ret_val = -ENOMEM; - goto add_failure; - } - tmp_size = nla_len(msg_ptr); - if (tmp_size <= 0 || tmp_size > msg_len) { - ret_val = -EINVAL; - goto add_failure; - } - entry->domain = kmalloc(tmp_size, GFP_KERNEL); - if (entry->domain == NULL) { - ret_val = -ENOMEM; - goto add_failure; - } - nla_strlcpy(entry->domain, msg_ptr, tmp_size); - entry->domain[tmp_size - 1] = '\0'; - msg_ptr = nla_next(msg_ptr, &msg_len); - - if (msg_len < NETLBL_LEN_U32) { - ret_val = -EINVAL; - goto add_failure; - } - tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len); - entry->type = tmp_val; - switch (tmp_val) { - case NETLBL_NLTYPE_UNLABELED: - ret_val = netlbl_domhsh_add(entry); - break; - case NETLBL_NLTYPE_CIPSOV4: - if (msg_len < NETLBL_LEN_U32) { - ret_val = -EINVAL; - goto add_failure; - } - tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len); - /* We should be holding a rcu_read_lock() here - * while we hold the result but since the entry - * will always be deleted when the CIPSO DOI - * is deleted we aren't going to keep the lock. */ - rcu_read_lock(); - entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); - if (entry->type_def.cipsov4 == NULL) { - rcu_read_unlock(); - ret_val = -EINVAL; - goto add_failure; - } - ret_val = netlbl_domhsh_add(entry); - rcu_read_unlock(); - break; - default: - ret_val = -EINVAL; - } - if (ret_val != 0) - goto add_failure; - } - - netlbl_netlink_send_ack(info, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_ACK, - NETLBL_E_OK); - return 0; - -add_failure: - if (entry) - kfree(entry->domain); - kfree(entry); - netlbl_netlink_send_ack(info, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_ACK, - -ret_val); - return ret_val; -} - -/** - * netlbl_mgmt_remove - Handle a REMOVE message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Process a user generated REMOVE message and remove the specified domain - * mappings. Returns zero on success, negative values on failure. - * - */ -static int netlbl_mgmt_remove(struct sk_buff *skb, struct genl_info *info) -{ - int ret_val = -EINVAL; - struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb); - int msg_len = netlbl_netlink_payload_len(skb); - u32 count; - u32 iter; - int tmp_size; - unsigned char *domain; - - ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); - if (ret_val != 0) - goto remove_return; - - if (msg_len < NETLBL_LEN_U32) - goto remove_return; - count = netlbl_getinc_u32(&msg_ptr, &msg_len); - - for (iter = 0; iter < count && msg_len > 0; iter++) { - if (msg_len <= 0) { - ret_val = -EINVAL; - goto remove_return; - } - tmp_size = nla_len(msg_ptr); - domain = nla_data(msg_ptr); - if (tmp_size <= 0 || tmp_size > msg_len || - domain[tmp_size - 1] != '\0') { - ret_val = -EINVAL; - goto remove_return; - } - ret_val = netlbl_domhsh_remove(domain); - if (ret_val != 0) - goto remove_return; - msg_ptr = nla_next(msg_ptr, &msg_len); - } - - ret_val = 0; - -remove_return: - netlbl_netlink_send_ack(info, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_ACK, - -ret_val); - return ret_val; -} - -/** - * netlbl_mgmt_list - Handle a LIST message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Process a user generated LIST message and dumps the domain hash table in a - * form suitable for use in a kernel generated LIST message. Returns zero on - * success, negative values on failure. - * - */ -static int netlbl_mgmt_list(struct sk_buff *skb, struct genl_info *info) -{ - int ret_val = -ENOMEM; - struct sk_buff *ans_skb; - - ans_skb = netlbl_domhsh_dump(NLMSG_SPACE(GENL_HDRLEN)); - if (ans_skb == NULL) - goto list_failure; - netlbl_netlink_hdr_push(ans_skb, - info->snd_pid, - 0, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_LIST); - - ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); - if (ret_val != 0) - goto list_failure; - - return 0; - -list_failure: - netlbl_netlink_send_ack(info, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_ACK, - -ret_val); - return ret_val; -} - -/** - * netlbl_mgmt_adddef - Handle an ADDDEF message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Process a user generated ADDDEF message and respond accordingly. Returns - * zero on success, negative values on failure. - * - */ -static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info) -{ - int ret_val = -EINVAL; - struct nlattr *msg_ptr = netlbl_netlink_payload_data(skb); - int msg_len = netlbl_netlink_payload_len(skb); - struct netlbl_dom_map *entry = NULL; - u32 tmp_val; - - ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); - if (ret_val != 0) - goto adddef_failure; - - if (msg_len < NETLBL_LEN_U32) - goto adddef_failure; - tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len); - - entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (entry == NULL) { - ret_val = -ENOMEM; - goto adddef_failure; - } - - entry->type = tmp_val; - switch (entry->type) { - case NETLBL_NLTYPE_UNLABELED: - ret_val = netlbl_domhsh_add_default(entry); - break; - case NETLBL_NLTYPE_CIPSOV4: - if (msg_len < NETLBL_LEN_U32) { - ret_val = -EINVAL; - goto adddef_failure; - } - tmp_val = netlbl_getinc_u32(&msg_ptr, &msg_len); - /* We should be holding a rcu_read_lock here while we - * hold the result but since the entry will always be - * deleted when the CIPSO DOI is deleted we are going - * to skip the lock. */ - rcu_read_lock(); - entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); - if (entry->type_def.cipsov4 == NULL) { - rcu_read_unlock(); - ret_val = -EINVAL; - goto adddef_failure; - } - ret_val = netlbl_domhsh_add_default(entry); - rcu_read_unlock(); - break; - default: - ret_val = -EINVAL; - } - if (ret_val != 0) - goto adddef_failure; - - netlbl_netlink_send_ack(info, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_ACK, - NETLBL_E_OK); - return 0; - -adddef_failure: - kfree(entry); - netlbl_netlink_send_ack(info, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_ACK, - -ret_val); - return ret_val; -} - -/** - * netlbl_mgmt_removedef - Handle a REMOVEDEF message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Process a user generated REMOVEDEF message and remove the default domain - * mapping. Returns zero on success, negative values on failure. - * - */ -static int netlbl_mgmt_removedef(struct sk_buff *skb, struct genl_info *info) -{ - int ret_val; - - ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); - if (ret_val != 0) - goto removedef_return; - - ret_val = netlbl_domhsh_remove_default(); - -removedef_return: - netlbl_netlink_send_ack(info, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_ACK, - -ret_val); - return ret_val; -} - -/** - * netlbl_mgmt_listdef - Handle a LISTDEF message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Process a user generated LISTDEF message and dumps the default domain - * mapping in a form suitable for use in a kernel generated LISTDEF message. - * Returns zero on success, negative values on failure. - * - */ -static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) -{ - int ret_val = -ENOMEM; - struct sk_buff *ans_skb; - - ans_skb = netlbl_domhsh_dump_default(NLMSG_SPACE(GENL_HDRLEN)); - if (ans_skb == NULL) - goto listdef_failure; - netlbl_netlink_hdr_push(ans_skb, - info->snd_pid, - 0, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_LISTDEF); - - ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); - if (ret_val != 0) - goto listdef_failure; - - return 0; - -listdef_failure: - netlbl_netlink_send_ack(info, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_ACK, - -ret_val); - return ret_val; -} - -/** - * netlbl_mgmt_modules - Handle a MODULES message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Process a user generated MODULES message and respond accordingly. - * - */ -static int netlbl_mgmt_modules(struct sk_buff *skb, struct genl_info *info) -{ - int ret_val = -ENOMEM; - size_t data_size; - u32 mod_count; - struct sk_buff *ans_skb = NULL; - - /* unlabeled + cipsov4 */ - mod_count = 2; - - data_size = GENL_HDRLEN + NETLBL_LEN_U32 + mod_count * NETLBL_LEN_U32; - ans_skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL); - if (ans_skb == NULL) - goto modules_failure; - - if (netlbl_netlink_hdr_put(ans_skb, - info->snd_pid, - 0, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_MODULES) == NULL) - goto modules_failure; - - ret_val = nla_put_u32(ans_skb, NLA_U32, mod_count); - if (ret_val != 0) - goto modules_failure; - ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_UNLABELED); - if (ret_val != 0) - goto modules_failure; - ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_NLTYPE_CIPSOV4); - if (ret_val != 0) - goto modules_failure; - - ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); - if (ret_val != 0) - goto modules_failure; - - return 0; - -modules_failure: - kfree_skb(ans_skb); - netlbl_netlink_send_ack(info, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_ACK, - -ret_val); - return ret_val; -} - -/** - * netlbl_mgmt_version - Handle a VERSION message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Process a user generated VERSION message and respond accordingly. Returns - * zero on success, negative values on failure. - * - */ -static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info) -{ - int ret_val = -ENOMEM; - struct sk_buff *ans_skb = NULL; - - ans_skb = netlbl_netlink_alloc_skb(0, - GENL_HDRLEN + NETLBL_LEN_U32, - GFP_KERNEL); - if (ans_skb == NULL) - goto version_failure; - if (netlbl_netlink_hdr_put(ans_skb, - info->snd_pid, - 0, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_VERSION) == NULL) - goto version_failure; - - ret_val = nla_put_u32(ans_skb, NLA_U32, NETLBL_PROTO_VERSION); - if (ret_val != 0) - goto version_failure; - - ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); - if (ret_val != 0) - goto version_failure; - - return 0; - -version_failure: - kfree_skb(ans_skb); - netlbl_netlink_send_ack(info, - netlbl_mgmt_gnl_family.id, - NLBL_MGMT_C_ACK, - -ret_val); - return ret_val; -} - - -/* - * NetLabel Generic NETLINK Command Definitions - */ - -static struct genl_ops netlbl_mgmt_genl_c_add = { - .cmd = NLBL_MGMT_C_ADD, - .flags = 0, - .doit = netlbl_mgmt_add, - .dumpit = NULL, -}; - -static struct genl_ops netlbl_mgmt_genl_c_remove = { - .cmd = NLBL_MGMT_C_REMOVE, - .flags = 0, - .doit = netlbl_mgmt_remove, - .dumpit = NULL, -}; - -static struct genl_ops netlbl_mgmt_genl_c_list = { - .cmd = NLBL_MGMT_C_LIST, - .flags = 0, - .doit = netlbl_mgmt_list, - .dumpit = NULL, -}; - -static struct genl_ops netlbl_mgmt_genl_c_adddef = { - .cmd = NLBL_MGMT_C_ADDDEF, - .flags = 0, - .doit = netlbl_mgmt_adddef, - .dumpit = NULL, -}; - -static struct genl_ops netlbl_mgmt_genl_c_removedef = { - .cmd = NLBL_MGMT_C_REMOVEDEF, - .flags = 0, - .doit = netlbl_mgmt_removedef, - .dumpit = NULL, -}; - -static struct genl_ops netlbl_mgmt_genl_c_listdef = { - .cmd = NLBL_MGMT_C_LISTDEF, - .flags = 0, - .doit = netlbl_mgmt_listdef, - .dumpit = NULL, -}; - -static struct genl_ops netlbl_mgmt_genl_c_modules = { - .cmd = NLBL_MGMT_C_MODULES, - .flags = 0, - .doit = netlbl_mgmt_modules, - .dumpit = NULL, -}; - -static struct genl_ops netlbl_mgmt_genl_c_version = { - .cmd = NLBL_MGMT_C_VERSION, - .flags = 0, - .doit = netlbl_mgmt_version, - .dumpit = NULL, -}; - -/* - * NetLabel Generic NETLINK Protocol Functions - */ - -/** - * netlbl_mgmt_genl_init - Register the NetLabel management component - * - * Description: - * Register the NetLabel management component with the Generic NETLINK - * mechanism. Returns zero on success, negative values on failure. - * - */ -int netlbl_mgmt_genl_init(void) -{ - int ret_val; - - ret_val = genl_register_family(&netlbl_mgmt_gnl_family); - if (ret_val != 0) - return ret_val; - - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_add); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_remove); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_list); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_adddef); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_removedef); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_listdef); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_modules); - if (ret_val != 0) - return ret_val; - ret_val = genl_register_ops(&netlbl_mgmt_gnl_family, - &netlbl_mgmt_genl_c_version); - if (ret_val != 0) - return ret_val; - - return 0; -} diff --git a/trunk/net/netlabel/netlabel_mgmt.h b/trunk/net/netlabel/netlabel_mgmt.h deleted file mode 100644 index fd6c6acbfa08..000000000000 --- a/trunk/net/netlabel/netlabel_mgmt.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * NetLabel Management Support - * - * This file defines the management functions for the NetLabel system. The - * NetLabel system manages static and dynamic label mappings for network - * protocols such as CIPSO and RIPSO. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _NETLABEL_MGMT_H -#define _NETLABEL_MGMT_H - -#include - -/* - * The following NetLabel payloads are supported by the management interface, - * all of which are preceeded by the nlmsghdr struct. - * - * o ACK: - * Sent by the kernel in response to an applications message, applications - * should never send this message. - * - * +----------------------+-----------------------+ - * | seq number (32 bits) | return code (32 bits) | - * +----------------------+-----------------------+ - * - * seq number: the sequence number of the original message, taken from the - * nlmsghdr structure - * return code: return value, based on errno values - * - * o ADD: - * Sent by an application to add a domain mapping to the NetLabel system. - * The kernel should respond with an ACK. - * - * +-------------------+ - * | domains (32 bits) | ... - * +-------------------+ - * - * domains: the number of domains in the message - * - * +--------------------------+-------------------------+ - * | domain string (variable) | protocol type (32 bits) | ... - * +--------------------------+-------------------------+ - * - * +-------------- ---- --- -- - - * | mapping data ... repeated - * +-------------- ---- --- -- - - * - * domain string: the domain string, NULL terminated - * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) - * mapping data: specific to the map type (see below) - * - * NETLBL_NLTYPE_UNLABELED - * - * No mapping data for this protocol type. - * - * NETLBL_NLTYPE_CIPSOV4 - * - * +---------------+ - * | doi (32 bits) | - * +---------------+ - * - * doi: the CIPSO DOI value - * - * o REMOVE: - * Sent by an application to remove a domain mapping from the NetLabel - * system. The kernel should ACK this message. - * - * +-------------------+ - * | domains (32 bits) | ... - * +-------------------+ - * - * domains: the number of domains in the message - * - * +--------------------------+ - * | domain string (variable) | ... - * +--------------------------+ - * - * domain string: the domain string, NULL terminated - * - * o LIST: - * This message can be sent either from an application or by the kernel in - * response to an application generated LIST message. When sent by an - * application there is no payload. The kernel should respond to a LIST - * message either with a LIST message on success or an ACK message on - * failure. - * - * +-------------------+ - * | domains (32 bits) | ... - * +-------------------+ - * - * domains: the number of domains in the message - * - * +--------------------------+ - * | domain string (variable) | ... - * +--------------------------+ - * - * +-------------------------+-------------- ---- --- -- - - * | protocol type (32 bits) | mapping data ... repeated - * +-------------------------+-------------- ---- --- -- - - * - * domain string: the domain string, NULL terminated - * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) - * mapping data: specific to the map type (see below) - * - * NETLBL_NLTYPE_UNLABELED - * - * No mapping data for this protocol type. - * - * NETLBL_NLTYPE_CIPSOV4 - * - * +----------------+---------------+ - * | type (32 bits) | doi (32 bits) | - * +----------------+---------------+ - * - * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header - * as CIPSO_V4_MAP_*) - * doi: the CIPSO DOI value - * - * o ADDDEF: - * Sent by an application to set the default domain mapping for the NetLabel - * system. The kernel should respond with an ACK. - * - * +-------------------------+-------------- ---- --- -- - - * | protocol type (32 bits) | mapping data ... repeated - * +-------------------------+-------------- ---- --- -- - - * - * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) - * mapping data: specific to the map type (see below) - * - * NETLBL_NLTYPE_UNLABELED - * - * No mapping data for this protocol type. - * - * NETLBL_NLTYPE_CIPSOV4 - * - * +---------------+ - * | doi (32 bits) | - * +---------------+ - * - * doi: the CIPSO DOI value - * - * o REMOVEDEF: - * Sent by an application to remove the default domain mapping from the - * NetLabel system, there is no payload. The kernel should ACK this message. - * - * o LISTDEF: - * This message can be sent either from an application or by the kernel in - * response to an application generated LISTDEF message. When sent by an - * application there is no payload. The kernel should respond to a - * LISTDEF message either with a LISTDEF message on success or an ACK message - * on failure. - * - * +-------------------------+-------------- ---- --- -- - - * | protocol type (32 bits) | mapping data ... repeated - * +-------------------------+-------------- ---- --- -- - - * - * protocol type: the protocol type (defined by NETLBL_NLTYPE_*) - * mapping data: specific to the map type (see below) - * - * NETLBL_NLTYPE_UNLABELED - * - * No mapping data for this protocol type. - * - * NETLBL_NLTYPE_CIPSOV4 - * - * +----------------+---------------+ - * | type (32 bits) | doi (32 bits) | - * +----------------+---------------+ - * - * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header - * as CIPSO_V4_MAP_*) - * doi: the CIPSO DOI value - * - * o MODULES: - * Sent by an application to request a list of configured NetLabel modules - * in the kernel. When sent by an application there is no payload. - * - * +-------------------+ - * | modules (32 bits) | ... - * +-------------------+ - * - * modules: the number of modules in the message, if this is an application - * generated message and the value is zero then return a list of - * the configured modules - * - * +------------------+ - * | module (32 bits) | ... repeated - * +------------------+ - * - * module: the module number as defined by NETLBL_NLTYPE_* - * - * o VERSION: - * Sent by an application to request the NetLabel version string. When sent - * by an application there is no payload. This message type is also used by - * the kernel to respond to an VERSION request. - * - * +-------------------+ - * | version (32 bits) | - * +-------------------+ - * - * version: the protocol version number - * - */ - -/* NetLabel Management commands */ -enum { - NLBL_MGMT_C_UNSPEC, - NLBL_MGMT_C_ACK, - NLBL_MGMT_C_ADD, - NLBL_MGMT_C_REMOVE, - NLBL_MGMT_C_LIST, - NLBL_MGMT_C_ADDDEF, - NLBL_MGMT_C_REMOVEDEF, - NLBL_MGMT_C_LISTDEF, - NLBL_MGMT_C_MODULES, - NLBL_MGMT_C_VERSION, - __NLBL_MGMT_C_MAX, -}; -#define NLBL_MGMT_C_MAX (__NLBL_MGMT_C_MAX - 1) - -/* NetLabel protocol functions */ -int netlbl_mgmt_genl_init(void); - -#endif diff --git a/trunk/net/netlabel/netlabel_unlabeled.c b/trunk/net/netlabel/netlabel_unlabeled.c deleted file mode 100644 index 785f4960e0d3..000000000000 --- a/trunk/net/netlabel/netlabel_unlabeled.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - * NetLabel Unlabeled Support - * - * This file defines functions for dealing with unlabeled packets for the - * NetLabel system. The NetLabel system manages static and dynamic label - * mappings for network protocols such as CIPSO and RIPSO. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "netlabel_user.h" -#include "netlabel_domainhash.h" -#include "netlabel_unlabeled.h" - -/* Accept unlabeled packets flag */ -static atomic_t netlabel_unlabel_accept_flg = ATOMIC_INIT(0); - -/* NetLabel Generic NETLINK CIPSOv4 family */ -static struct genl_family netlbl_unlabel_gnl_family = { - .id = GENL_ID_GENERATE, - .hdrsize = 0, - .name = NETLBL_NLTYPE_UNLABELED_NAME, - .version = NETLBL_PROTO_VERSION, - .maxattr = 0, -}; - - -/* - * NetLabel Command Handlers - */ - -/** - * netlbl_unlabel_accept - Handle an ACCEPT message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Process a user generated ACCEPT message and set the accept flag accordingly. - * Returns zero on success, negative values on failure. - * - */ -static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info) -{ - int ret_val; - struct nlattr *data = netlbl_netlink_payload_data(skb); - u32 value; - - ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN); - if (ret_val != 0) - return ret_val; - - if (netlbl_netlink_payload_len(skb) == NETLBL_LEN_U32) { - value = nla_get_u32(data); - if (value == 1 || value == 0) { - atomic_set(&netlabel_unlabel_accept_flg, value); - netlbl_netlink_send_ack(info, - netlbl_unlabel_gnl_family.id, - NLBL_UNLABEL_C_ACK, - NETLBL_E_OK); - return 0; - } - } - - netlbl_netlink_send_ack(info, - netlbl_unlabel_gnl_family.id, - NLBL_UNLABEL_C_ACK, - EINVAL); - return -EINVAL; -} - -/** - * netlbl_unlabel_list - Handle a LIST message - * @skb: the NETLINK buffer - * @info: the Generic NETLINK info block - * - * Description: - * Process a user generated LIST message and respond with the current status. - * Returns zero on success, negative values on failure. - * - */ -static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) -{ - int ret_val = -ENOMEM; - struct sk_buff *ans_skb; - - ans_skb = netlbl_netlink_alloc_skb(0, - GENL_HDRLEN + NETLBL_LEN_U32, - GFP_KERNEL); - if (ans_skb == NULL) - goto list_failure; - - if (netlbl_netlink_hdr_put(ans_skb, - info->snd_pid, - 0, - netlbl_unlabel_gnl_family.id, - NLBL_UNLABEL_C_LIST) == NULL) - goto list_failure; - - ret_val = nla_put_u32(ans_skb, - NLA_U32, - atomic_read(&netlabel_unlabel_accept_flg)); - if (ret_val != 0) - goto list_failure; - - ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid); - if (ret_val != 0) - goto list_failure; - - return 0; - -list_failure: - netlbl_netlink_send_ack(info, - netlbl_unlabel_gnl_family.id, - NLBL_UNLABEL_C_ACK, - -ret_val); - return ret_val; -} - - -/* - * NetLabel Generic NETLINK Command Definitions - */ - -static struct genl_ops netlbl_unlabel_genl_c_accept = { - .cmd = NLBL_UNLABEL_C_ACCEPT, - .flags = 0, - .doit = netlbl_unlabel_accept, - .dumpit = NULL, -}; - -static struct genl_ops netlbl_unlabel_genl_c_list = { - .cmd = NLBL_UNLABEL_C_LIST, - .flags = 0, - .doit = netlbl_unlabel_list, - .dumpit = NULL, -}; - - -/* - * NetLabel Generic NETLINK Protocol Functions - */ - -/** - * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component - * - * Description: - * Register the unlabeled packet NetLabel component with the Generic NETLINK - * mechanism. Returns zero on success, negative values on failure. - * - */ -int netlbl_unlabel_genl_init(void) -{ - int ret_val; - - ret_val = genl_register_family(&netlbl_unlabel_gnl_family); - if (ret_val != 0) - return ret_val; - - ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, - &netlbl_unlabel_genl_c_accept); - if (ret_val != 0) - return ret_val; - - ret_val = genl_register_ops(&netlbl_unlabel_gnl_family, - &netlbl_unlabel_genl_c_list); - if (ret_val != 0) - return ret_val; - - return 0; -} - -/* - * NetLabel KAPI Hooks - */ - -/** - * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet - * @secattr: the security attributes - * - * Description: - * Determine the security attributes, if any, for an unlabled packet and return - * them in @secattr. Returns zero on success and negative values on failure. - * - */ -int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr) -{ - if (atomic_read(&netlabel_unlabel_accept_flg) == 1) { - memset(secattr, 0, sizeof(*secattr)); - return 0; - } - - return -ENOMSG; -} - -/** - * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets - * - * Description: - * Set the default NetLabel configuration to allow incoming unlabeled packets - * and to send unlabeled network traffic by default. - * - */ -int netlbl_unlabel_defconf(void) -{ - int ret_val; - struct netlbl_dom_map *entry; - - entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (entry == NULL) - return -ENOMEM; - entry->type = NETLBL_NLTYPE_UNLABELED; - ret_val = netlbl_domhsh_add_default(entry); - if (ret_val != 0) - return ret_val; - - atomic_set(&netlabel_unlabel_accept_flg, 1); - - return 0; -} diff --git a/trunk/net/netlabel/netlabel_unlabeled.h b/trunk/net/netlabel/netlabel_unlabeled.h deleted file mode 100644 index f300e54e14b6..000000000000 --- a/trunk/net/netlabel/netlabel_unlabeled.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * NetLabel Unlabeled Support - * - * This file defines functions for dealing with unlabeled packets for the - * NetLabel system. The NetLabel system manages static and dynamic label - * mappings for network protocols such as CIPSO and RIPSO. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _NETLABEL_UNLABELED_H -#define _NETLABEL_UNLABELED_H - -#include - -/* - * The following NetLabel payloads are supported by the Unlabeled subsystem. - * - * o ACK: - * Sent by the kernel in response to an applications message, applications - * should never send this message. - * - * +----------------------+-----------------------+ - * | seq number (32 bits) | return code (32 bits) | - * +----------------------+-----------------------+ - * - * seq number: the sequence number of the original message, taken from the - * nlmsghdr structure - * return code: return value, based on errno values - * - * o ACCEPT - * This message is sent from an application to specify if the kernel should - * allow unlabled packets to pass if they do not match any of the static - * mappings defined in the unlabeled module. - * - * +-----------------+ - * | allow (32 bits) | - * +-----------------+ - * - * allow: if true (1) then allow the packets to pass, if false (0) then - * reject the packets - * - * o LIST - * This message can be sent either from an application or by the kernel in - * response to an application generated LIST message. When sent by an - * application there is no payload. The kernel should respond to a LIST - * message either with a LIST message on success or an ACK message on - * failure. - * - * +-----------------------+ - * | accept flag (32 bits) | - * +-----------------------+ - * - * accept flag: if true (1) then unlabeled packets are allowed to pass, - * if false (0) then unlabeled packets are rejected - * - */ - -/* NetLabel Unlabeled commands */ -enum { - NLBL_UNLABEL_C_UNSPEC, - NLBL_UNLABEL_C_ACK, - NLBL_UNLABEL_C_ACCEPT, - NLBL_UNLABEL_C_LIST, - __NLBL_UNLABEL_C_MAX, -}; -#define NLBL_UNLABEL_C_MAX (__NLBL_UNLABEL_C_MAX - 1) - -/* NetLabel protocol functions */ -int netlbl_unlabel_genl_init(void); - -/* Process Unlabeled incoming network packets */ -int netlbl_unlabel_getattr(struct netlbl_lsm_secattr *secattr); - -/* Set the default configuration to allow Unlabeled packets */ -int netlbl_unlabel_defconf(void); - -#endif diff --git a/trunk/net/netlabel/netlabel_user.c b/trunk/net/netlabel/netlabel_user.c deleted file mode 100644 index 73cbe66e42ff..000000000000 --- a/trunk/net/netlabel/netlabel_user.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * NetLabel NETLINK Interface - * - * This file defines the NETLINK interface for the NetLabel system. The - * NetLabel system manages static and dynamic label mappings for network - * protocols such as CIPSO and RIPSO. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "netlabel_mgmt.h" -#include "netlabel_unlabeled.h" -#include "netlabel_cipso_v4.h" -#include "netlabel_user.h" - -/* - * NetLabel NETLINK Setup Functions - */ - -/** - * netlbl_netlink_init - Initialize the NETLINK communication channel - * - * Description: - * Call out to the NetLabel components so they can register their families and - * commands with the Generic NETLINK mechanism. Returns zero on success and - * non-zero on failure. - * - */ -int netlbl_netlink_init(void) -{ - int ret_val; - - ret_val = netlbl_mgmt_genl_init(); - if (ret_val != 0) - return ret_val; - - ret_val = netlbl_cipsov4_genl_init(); - if (ret_val != 0) - return ret_val; - - ret_val = netlbl_unlabel_genl_init(); - if (ret_val != 0) - return ret_val; - - return 0; -} - -/* - * NetLabel Common Protocol Functions - */ - -/** - * netlbl_netlink_send_ack - Send an ACK message - * @info: the generic NETLINK information - * @genl_family: the generic NETLINK family ID value - * @ack_cmd: the generic NETLINK family ACK command value - * @ret_code: return code to use - * - * Description: - * This function sends an ACK message to the sender of the NETLINK message - * specified by @info. - * - */ -void netlbl_netlink_send_ack(const struct genl_info *info, - u32 genl_family, - u8 ack_cmd, - u32 ret_code) -{ - size_t data_size; - struct sk_buff *skb; - - data_size = GENL_HDRLEN + 2 * NETLBL_LEN_U32; - skb = netlbl_netlink_alloc_skb(0, data_size, GFP_KERNEL); - if (skb == NULL) - return; - - if (netlbl_netlink_hdr_put(skb, - info->snd_pid, - 0, - genl_family, - ack_cmd) == NULL) - goto send_ack_failure; - - if (nla_put_u32(skb, NLA_U32, info->snd_seq) != 0) - goto send_ack_failure; - if (nla_put_u32(skb, NLA_U32, ret_code) != 0) - goto send_ack_failure; - - netlbl_netlink_snd(skb, info->snd_pid); - return; - -send_ack_failure: - kfree_skb(skb); -} - -/* - * NETLINK I/O Functions - */ - -/** - * netlbl_netlink_snd - Send a NetLabel message - * @skb: NetLabel message - * @pid: destination PID - * - * Description: - * Sends a unicast NetLabel message over the NETLINK socket. - * - */ -int netlbl_netlink_snd(struct sk_buff *skb, u32 pid) -{ - return genlmsg_unicast(skb, pid); -} - -/** - * netlbl_netlink_snd - Send a NetLabel message - * @skb: NetLabel message - * @pid: sending PID - * @group: multicast group id - * - * Description: - * Sends a multicast NetLabel message over the NETLINK socket to all members - * of @group except @pid. - * - */ -int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group) -{ - return genlmsg_multicast(skb, pid, group, GFP_KERNEL); -} diff --git a/trunk/net/netlabel/netlabel_user.h b/trunk/net/netlabel/netlabel_user.h deleted file mode 100644 index 385a6c7488c6..000000000000 --- a/trunk/net/netlabel/netlabel_user.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * NetLabel NETLINK Interface - * - * This file defines the NETLINK interface for the NetLabel system. The - * NetLabel system manages static and dynamic label mappings for network - * protocols such as CIPSO and RIPSO. - * - * Author: Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _NETLABEL_USER_H -#define _NETLABEL_USER_H - -#include -#include -#include -#include -#include -#include - -/* NetLabel NETLINK helper functions */ - -/** - * netlbl_netlink_cap_check - Check the NETLINK msg capabilities - * @skb: the NETLINK buffer - * @req_cap: the required capability - * - * Description: - * Check the NETLINK buffer's capabilities against the required capabilities. - * Returns zero on success, negative values on failure. - * - */ -static inline int netlbl_netlink_cap_check(const struct sk_buff *skb, - kernel_cap_t req_cap) -{ - if (cap_raised(NETLINK_CB(skb).eff_cap, req_cap)) - return 0; - return -EPERM; -} - -/** - * netlbl_getinc_u8 - Read a u8 value from a nlattr stream and move on - * @nla: the attribute - * @rem_len: remaining length - * - * Description: - * Return a u8 value pointed to by @nla and advance it to the next attribute. - * - */ -static inline u8 netlbl_getinc_u8(struct nlattr **nla, int *rem_len) -{ - u8 val = nla_get_u8(*nla); - *nla = nla_next(*nla, rem_len); - return val; -} - -/** - * netlbl_getinc_u16 - Read a u16 value from a nlattr stream and move on - * @nla: the attribute - * @rem_len: remaining length - * - * Description: - * Return a u16 value pointed to by @nla and advance it to the next attribute. - * - */ -static inline u16 netlbl_getinc_u16(struct nlattr **nla, int *rem_len) -{ - u16 val = nla_get_u16(*nla); - *nla = nla_next(*nla, rem_len); - return val; -} - -/** - * netlbl_getinc_u32 - Read a u32 value from a nlattr stream and move on - * @nla: the attribute - * @rem_len: remaining length - * - * Description: - * Return a u32 value pointed to by @nla and advance it to the next attribute. - * - */ -static inline u32 netlbl_getinc_u32(struct nlattr **nla, int *rem_len) -{ - u32 val = nla_get_u32(*nla); - *nla = nla_next(*nla, rem_len); - return val; -} - -/** - * netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff - * @skb: the packet - * @pid: the PID of the receipient - * @seq: the sequence number - * @type: the generic NETLINK message family type - * @cmd: command - * - * Description: - * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr - * struct to the packet. Returns a pointer to the start of the payload buffer - * on success or NULL on failure. - * - */ -static inline void *netlbl_netlink_hdr_put(struct sk_buff *skb, - u32 pid, - u32 seq, - int type, - u8 cmd) -{ - return genlmsg_put(skb, - pid, - seq, - type, - 0, - 0, - cmd, - NETLBL_PROTO_VERSION); -} - -/** - * netlbl_netlink_hdr_push - Write the NETLINK buffers into a sk_buff - * @skb: the packet - * @pid: the PID of the receipient - * @seq: the sequence number - * @type: the generic NETLINK message family type - * @cmd: command - * - * Description: - * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr - * struct to the packet. - * - */ -static inline void netlbl_netlink_hdr_push(struct sk_buff *skb, - u32 pid, - u32 seq, - int type, - u8 cmd) - -{ - struct nlmsghdr *nlh; - struct genlmsghdr *hdr; - - nlh = (struct nlmsghdr *)skb_push(skb, NLMSG_SPACE(GENL_HDRLEN)); - nlh->nlmsg_type = type; - nlh->nlmsg_len = skb->len; - nlh->nlmsg_flags = 0; - nlh->nlmsg_pid = pid; - nlh->nlmsg_seq = seq; - - hdr = nlmsg_data(nlh); - hdr->cmd = cmd; - hdr->version = NETLBL_PROTO_VERSION; - hdr->reserved = 0; -} - -/** - * netlbl_netlink_payload_len - Return the length of the payload - * @skb: the NETLINK buffer - * - * Description: - * This function returns the length of the NetLabel payload. - * - */ -static inline u32 netlbl_netlink_payload_len(const struct sk_buff *skb) -{ - return nlmsg_len((struct nlmsghdr *)skb->data) - GENL_HDRLEN; -} - -/** - * netlbl_netlink_payload_data - Returns a pointer to the start of the payload - * @skb: the NETLINK buffer - * - * Description: - * This function returns a pointer to the start of the NetLabel payload. - * - */ -static inline void *netlbl_netlink_payload_data(const struct sk_buff *skb) -{ - return (unsigned char *)nlmsg_data((struct nlmsghdr *)skb->data) + - GENL_HDRLEN; -} - -/* NetLabel common protocol functions */ - -void netlbl_netlink_send_ack(const struct genl_info *info, - u32 genl_family, - u8 ack_cmd, - u32 ret_code); - -/* NetLabel NETLINK I/O functions */ - -int netlbl_netlink_init(void); -int netlbl_netlink_snd(struct sk_buff *skb, u32 pid); -int netlbl_netlink_snd_multicast(struct sk_buff *skb, u32 pid, u32 group); - -#endif diff --git a/trunk/net/netlink/af_netlink.c b/trunk/net/netlink/af_netlink.c index d56e0d21f919..b85c1f9f1288 100644 --- a/trunk/net/netlink/af_netlink.c +++ b/trunk/net/netlink/af_netlink.c @@ -1147,7 +1147,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, if (len > sk->sk_sndbuf - 32) goto out; err = -ENOBUFS; - skb = nlmsg_new(len, GFP_KERNEL); + skb = alloc_skb(len, GFP_KERNEL); if (skb==NULL) goto out; @@ -1273,7 +1273,8 @@ netlink_kernel_create(int unit, unsigned int groups, struct netlink_sock *nlk; unsigned long *listeners = NULL; - BUG_ON(!nl_table); + if (!nl_table) + return NULL; if (unit<0 || unit>=MAX_LINKS) return NULL; @@ -1341,18 +1342,19 @@ static int netlink_dump(struct sock *sk) struct netlink_callback *cb; struct sk_buff *skb; struct nlmsghdr *nlh; - int len, err = -ENOBUFS; + int len; skb = sock_rmalloc(sk, NLMSG_GOODSIZE, 0, GFP_KERNEL); if (!skb) - goto errout; + return -ENOBUFS; spin_lock(&nlk->cb_lock); cb = nlk->cb; if (cb == NULL) { - err = -EINVAL; - goto errout_skb; + spin_unlock(&nlk->cb_lock); + kfree_skb(skb); + return -EINVAL; } len = cb->dump(skb, cb); @@ -1364,12 +1366,8 @@ static int netlink_dump(struct sock *sk) return 0; } - nlh = nlmsg_put_answer(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI); - if (!nlh) - goto errout_skb; - - memcpy(nlmsg_data(nlh), &len, sizeof(len)); - + nlh = NLMSG_NEW_ANSWER(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI); + memcpy(NLMSG_DATA(nlh), &len, sizeof(len)); skb_queue_tail(&sk->sk_receive_queue, skb); sk->sk_data_ready(sk, skb->len); @@ -1381,11 +1379,8 @@ static int netlink_dump(struct sock *sk) netlink_destroy_callback(cb); return 0; -errout_skb: - spin_unlock(&nlk->cb_lock); - kfree_skb(skb); -errout: - return err; +nlmsg_failure: + return -ENOBUFS; } int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, @@ -1437,11 +1432,11 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) int size; if (err == 0) - size = nlmsg_total_size(sizeof(*errmsg)); + size = NLMSG_SPACE(sizeof(struct nlmsgerr)); else - size = nlmsg_total_size(sizeof(*errmsg) + nlmsg_len(nlh)); + size = NLMSG_SPACE(4 + NLMSG_ALIGN(nlh->nlmsg_len)); - skb = nlmsg_new(size, GFP_KERNEL); + skb = alloc_skb(size, GFP_KERNEL); if (!skb) { struct sock *sk; @@ -1457,15 +1452,16 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) rep = __nlmsg_put(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, NLMSG_ERROR, sizeof(struct nlmsgerr), 0); - errmsg = nlmsg_data(rep); + errmsg = NLMSG_DATA(rep); errmsg->error = err; - memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(*nlh)); + memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(struct nlmsghdr)); netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); } static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, struct nlmsghdr *, int *)) { + unsigned int total_len; struct nlmsghdr *nlh; int err; @@ -1475,6 +1471,8 @@ static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, if (nlh->nlmsg_len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len) return 0; + total_len = min(NLMSG_ALIGN(nlh->nlmsg_len), skb->len); + if (cb(skb, nlh, &err) < 0) { /* Not an error, but we have to interrupt processing * here. Note: that in this case we do not pull @@ -1486,7 +1484,7 @@ static int netlink_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, } else if (nlh->nlmsg_flags & NLM_F_ACK) netlink_ack(skb, nlh, 0); - netlink_queue_skip(nlh, skb); + skb_pull(skb, total_len); } return 0; @@ -1549,38 +1547,6 @@ void netlink_queue_skip(struct nlmsghdr *nlh, struct sk_buff *skb) skb_pull(skb, msglen); } -/** - * nlmsg_notify - send a notification netlink message - * @sk: netlink socket to use - * @skb: notification message - * @pid: destination netlink pid for reports or 0 - * @group: destination multicast group or 0 - * @report: 1 to report back, 0 to disable - * @flags: allocation flags - */ -int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 pid, - unsigned int group, int report, gfp_t flags) -{ - int err = 0; - - if (group) { - int exclude_pid = 0; - - if (report) { - atomic_inc(&skb->users); - exclude_pid = pid; - } - - /* errors reported via destination sk->sk_err */ - nlmsg_multicast(sk, skb, exclude_pid, group, flags); - } - - if (report) - err = nlmsg_unicast(sk, skb, pid); - - return err; -} - #ifdef CONFIG_PROC_FS struct nl_seq_iter { int link; @@ -1762,6 +1728,8 @@ static struct net_proto_family netlink_family_ops = { .owner = THIS_MODULE, /* for consistency 8) */ }; +extern void netlink_skb_parms_too_large(void); + static int __init netlink_proto_init(void) { struct sk_buff *dummy_skb; @@ -1773,11 +1741,15 @@ static int __init netlink_proto_init(void) if (err != 0) goto out; - BUILD_BUG_ON(sizeof(struct netlink_skb_parms) > sizeof(dummy_skb->cb)); + if (sizeof(struct netlink_skb_parms) > sizeof(dummy_skb->cb)) + netlink_skb_parms_too_large(); nl_table = kcalloc(MAX_LINKS, sizeof(*nl_table), GFP_KERNEL); - if (!nl_table) - goto panic; + if (!nl_table) { +enomem: + printk(KERN_CRIT "netlink_init: Cannot allocate nl_table\n"); + return -ENOMEM; + } if (num_physpages >= (128 * 1024)) max = num_physpages >> (21 - PAGE_SHIFT); @@ -1797,7 +1769,7 @@ static int __init netlink_proto_init(void) nl_pid_hash_free(nl_table[i].hash.table, 1 * sizeof(*hash->table)); kfree(nl_table); - goto panic; + goto enomem; } memset(hash->table, 0, 1 * sizeof(*hash->table)); hash->max_shift = order; @@ -1814,8 +1786,6 @@ static int __init netlink_proto_init(void) rtnetlink_init(); out: return err; -panic: - panic("netlink_init: Cannot allocate nl_table\n"); } core_initcall(netlink_proto_init); @@ -1831,4 +1801,4 @@ EXPORT_SYMBOL(netlink_set_err); EXPORT_SYMBOL(netlink_set_nonroot); EXPORT_SYMBOL(netlink_unicast); EXPORT_SYMBOL(netlink_unregister_notifier); -EXPORT_SYMBOL(nlmsg_notify); + diff --git a/trunk/net/netlink/attr.c b/trunk/net/netlink/attr.c index 004139557e09..dddbd15135a8 100644 --- a/trunk/net/netlink/attr.c +++ b/trunk/net/netlink/attr.c @@ -20,6 +20,7 @@ static u16 nla_attr_minlen[NLA_TYPE_MAX+1] __read_mostly = { [NLA_U16] = sizeof(u16), [NLA_U32] = sizeof(u32), [NLA_U64] = sizeof(u64), + [NLA_STRING] = 1, [NLA_NESTED] = NLA_HDRLEN, }; @@ -27,7 +28,7 @@ static int validate_nla(struct nlattr *nla, int maxtype, struct nla_policy *policy) { struct nla_policy *pt; - int minlen = 0, attrlen = nla_len(nla); + int minlen = 0; if (nla->nla_type <= 0 || nla->nla_type > maxtype) return 0; @@ -36,46 +37,16 @@ static int validate_nla(struct nlattr *nla, int maxtype, BUG_ON(pt->type > NLA_TYPE_MAX); - switch (pt->type) { - case NLA_FLAG: - if (attrlen > 0) - return -ERANGE; - break; + if (pt->minlen) + minlen = pt->minlen; + else if (pt->type != NLA_UNSPEC) + minlen = nla_attr_minlen[pt->type]; - case NLA_NUL_STRING: - if (pt->len) - minlen = min_t(int, attrlen, pt->len + 1); - else - minlen = attrlen; + if (pt->type == NLA_FLAG && nla_len(nla) > 0) + return -ERANGE; - if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL) - return -EINVAL; - /* fall through */ - - case NLA_STRING: - if (attrlen < 1) - return -ERANGE; - - if (pt->len) { - char *buf = nla_data(nla); - - if (buf[attrlen - 1] == '\0') - attrlen--; - - if (attrlen > pt->len) - return -ERANGE; - } - break; - - default: - if (pt->len) - minlen = pt->len; - else if (pt->type != NLA_UNSPEC) - minlen = nla_attr_minlen[pt->type]; - - if (attrlen < minlen) - return -ERANGE; - } + if (nla_len(nla) < minlen) + return -ERANGE; return 0; } @@ -283,26 +254,6 @@ struct nlattr *__nla_reserve(struct sk_buff *skb, int attrtype, int attrlen) return nla; } -/** - * __nla_reserve_nohdr - reserve room for attribute without header - * @skb: socket buffer to reserve room on - * @attrlen: length of attribute payload - * - * Reserves room for attribute payload without a header. - * - * The caller is responsible to ensure that the skb provides enough - * tailroom for the payload. - */ -void *__nla_reserve_nohdr(struct sk_buff *skb, int attrlen) -{ - void *start; - - start = skb_put(skb, NLA_ALIGN(attrlen)); - memset(start, 0, NLA_ALIGN(attrlen)); - - return start; -} - /** * nla_reserve - reserve room for attribute on the skb * @skb: socket buffer to reserve room on @@ -323,24 +274,6 @@ struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen) return __nla_reserve(skb, attrtype, attrlen); } -/** - * nla_reserve - reserve room for attribute without header - * @skb: socket buffer to reserve room on - * @len: length of attribute payload - * - * Reserves room for attribute payload without a header. - * - * Returns NULL if the tailroom of the skb is insufficient to store - * the attribute payload. - */ -void *nla_reserve_nohdr(struct sk_buff *skb, int attrlen) -{ - if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen))) - return NULL; - - return __nla_reserve_nohdr(skb, attrlen); -} - /** * __nla_put - Add a netlink attribute to a socket buffer * @skb: socket buffer to add attribute to @@ -360,22 +293,6 @@ void __nla_put(struct sk_buff *skb, int attrtype, int attrlen, memcpy(nla_data(nla), data, attrlen); } -/** - * __nla_put_nohdr - Add a netlink attribute without header - * @skb: socket buffer to add attribute to - * @attrlen: length of attribute payload - * @data: head of attribute payload - * - * The caller is responsible to ensure that the skb provides enough - * tailroom for the attribute payload. - */ -void __nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data) -{ - void *start; - - start = __nla_reserve_nohdr(skb, attrlen); - memcpy(start, data, attrlen); -} /** * nla_put - Add a netlink attribute to a socket buffer @@ -396,36 +313,15 @@ int nla_put(struct sk_buff *skb, int attrtype, int attrlen, const void *data) return 0; } -/** - * nla_put_nohdr - Add a netlink attribute without header - * @skb: socket buffer to add attribute to - * @attrlen: length of attribute payload - * @data: head of attribute payload - * - * Returns -1 if the tailroom of the skb is insufficient to store - * the attribute payload. - */ -int nla_put_nohdr(struct sk_buff *skb, int attrlen, const void *data) -{ - if (unlikely(skb_tailroom(skb) < NLA_ALIGN(attrlen))) - return -1; - - __nla_put_nohdr(skb, attrlen, data); - return 0; -} EXPORT_SYMBOL(nla_validate); EXPORT_SYMBOL(nla_parse); EXPORT_SYMBOL(nla_find); EXPORT_SYMBOL(nla_strlcpy); EXPORT_SYMBOL(__nla_reserve); -EXPORT_SYMBOL(__nla_reserve_nohdr); EXPORT_SYMBOL(nla_reserve); -EXPORT_SYMBOL(nla_reserve_nohdr); EXPORT_SYMBOL(__nla_put); -EXPORT_SYMBOL(__nla_put_nohdr); EXPORT_SYMBOL(nla_put); -EXPORT_SYMBOL(nla_put_nohdr); EXPORT_SYMBOL(nla_memcpy); EXPORT_SYMBOL(nla_memcmp); EXPORT_SYMBOL(nla_strcmp); diff --git a/trunk/net/netlink/genetlink.c b/trunk/net/netlink/genetlink.c index 49bc2db7982b..a298f77cc3e3 100644 --- a/trunk/net/netlink/genetlink.c +++ b/trunk/net/netlink/genetlink.c @@ -387,10 +387,7 @@ static void genl_rcv(struct sock *sk, int len) static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, u32 flags, struct sk_buff *skb, u8 cmd) { - struct nlattr *nla_ops; - struct genl_ops *ops; void *hdr; - int idx = 1; hdr = genlmsg_put(skb, pid, seq, GENL_ID_CTRL, 0, flags, cmd, family->version); @@ -399,37 +396,6 @@ static int ctrl_fill_info(struct genl_family *family, u32 pid, u32 seq, NLA_PUT_STRING(skb, CTRL_ATTR_FAMILY_NAME, family->name); NLA_PUT_U16(skb, CTRL_ATTR_FAMILY_ID, family->id); - NLA_PUT_U32(skb, CTRL_ATTR_VERSION, family->version); - NLA_PUT_U32(skb, CTRL_ATTR_HDRSIZE, family->hdrsize); - NLA_PUT_U32(skb, CTRL_ATTR_MAXATTR, family->maxattr); - - nla_ops = nla_nest_start(skb, CTRL_ATTR_OPS); - if (nla_ops == NULL) - goto nla_put_failure; - - list_for_each_entry(ops, &family->ops_list, ops_list) { - struct nlattr *nest; - - nest = nla_nest_start(skb, idx++); - if (nest == NULL) - goto nla_put_failure; - - NLA_PUT_U32(skb, CTRL_ATTR_OP_ID, ops->cmd); - NLA_PUT_U32(skb, CTRL_ATTR_OP_FLAGS, ops->flags); - - if (ops->policy) - NLA_PUT_FLAG(skb, CTRL_ATTR_OP_POLICY); - - if (ops->doit) - NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DOIT); - - if (ops->dumpit) - NLA_PUT_FLAG(skb, CTRL_ATTR_OP_DUMPIT); - - nla_nest_end(skb, nest); - } - - nla_nest_end(skb, nla_ops); return genlmsg_end(skb, hdr); @@ -445,9 +411,6 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) int chains_to_skip = cb->args[0]; int fams_to_skip = cb->args[1]; - if (chains_to_skip != 0) - genl_lock(); - for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { if (i < chains_to_skip) continue; @@ -465,9 +428,6 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb) } errout: - if (chains_to_skip != 0) - genl_unlock(); - cb->args[0] = i; cb->args[1] = n; @@ -480,7 +440,7 @@ static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid, struct sk_buff *skb; int err; - skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + skb = nlmsg_new(NLMSG_GOODSIZE); if (skb == NULL) return ERR_PTR(-ENOBUFS); @@ -495,8 +455,7 @@ static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid, static struct nla_policy ctrl_policy[CTRL_ATTR_MAX+1] __read_mostly = { [CTRL_ATTR_FAMILY_ID] = { .type = NLA_U16 }, - [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_NUL_STRING, - .len = GENL_NAMSIZ - 1 }, + [CTRL_ATTR_FAMILY_NAME] = { .type = NLA_STRING }, }; static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info) @@ -511,9 +470,12 @@ static int ctrl_getfamily(struct sk_buff *skb, struct genl_info *info) } if (info->attrs[CTRL_ATTR_FAMILY_NAME]) { - char *name; + char name[GENL_NAMSIZ]; + + if (nla_strlcpy(name, info->attrs[CTRL_ATTR_FAMILY_NAME], + GENL_NAMSIZ) >= GENL_NAMSIZ) + goto errout; - name = nla_data(info->attrs[CTRL_ATTR_FAMILY_NAME]); res = genl_family_find_byname(name); } @@ -548,7 +510,7 @@ static int genl_ctrl_event(int event, void *data) if (IS_ERR(msg)) return PTR_ERR(msg); - genlmsg_multicast(msg, 0, GENL_ID_CTRL, GFP_KERNEL); + genlmsg_multicast(msg, 0, GENL_ID_CTRL); break; } diff --git a/trunk/net/packet/af_packet.c b/trunk/net/packet/af_packet.c index f4ccb90e6739..f9cef3671593 100644 --- a/trunk/net/packet/af_packet.c +++ b/trunk/net/packet/af_packet.c @@ -427,24 +427,21 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, } #endif -static inline int run_filter(struct sk_buff *skb, struct sock *sk, - unsigned *snaplen) +static inline unsigned run_filter(struct sk_buff *skb, struct sock *sk, unsigned res) { struct sk_filter *filter; - int err = 0; - rcu_read_lock_bh(); - filter = rcu_dereference(sk->sk_filter); - if (filter != NULL) { - err = sk_run_filter(skb, filter->insns, filter->len); - if (!err) - err = -EPERM; - else if (*snaplen > err) - *snaplen = err; - } - rcu_read_unlock_bh(); + bh_lock_sock(sk); + filter = sk->sk_filter; + /* + * Our caller already checked that filter != NULL but we need to + * verify that under bh_lock_sock() to be safe + */ + if (likely(filter != NULL)) + res = sk_run_filter(skb, filter->insns, filter->len); + bh_unlock_sock(sk); - return err; + return res; } /* @@ -494,8 +491,13 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, struct packet snaplen = skb->len; - if (run_filter(skb, sk, &snaplen) < 0) - goto drop_n_restore; + if (sk->sk_filter) { + unsigned res = run_filter(skb, sk, snaplen); + if (res == 0) + goto drop_n_restore; + if (snaplen > res) + snaplen = res; + } if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= (unsigned)sk->sk_rcvbuf) @@ -584,15 +586,20 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe else if (skb->pkt_type == PACKET_OUTGOING) { /* Special case: outgoing packets have ll header at head */ skb_pull(skb, skb->nh.raw - skb->data); - if (skb->ip_summed == CHECKSUM_PARTIAL) + if (skb->ip_summed == CHECKSUM_HW) status |= TP_STATUS_CSUMNOTREADY; } } snaplen = skb->len; - if (run_filter(skb, sk, &snaplen) < 0) - goto drop_n_restore; + if (sk->sk_filter) { + unsigned res = run_filter(skb, sk, snaplen); + if (res == 0) + goto drop_n_restore; + if (snaplen > res) + snaplen = res; + } if (sk->sk_type == SOCK_DGRAM) { macoff = netoff = TPACKET_ALIGN(TPACKET_HDRLEN) + 16; @@ -619,6 +626,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe if ((int)snaplen < 0) snaplen = 0; } + if (snaplen > skb->len-skb->data_len) + snaplen = skb->len-skb->data_len; spin_lock(&sk->sk_receive_queue.lock); h = (struct tpacket_hdr *)packet_lookup_frame(po, po->head); @@ -635,7 +644,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe status &= ~TP_STATUS_LOSING; spin_unlock(&sk->sk_receive_queue.lock); - skb_copy_bits(skb, 0, (u8*)h + macoff, snaplen); + memcpy((u8*)h + macoff, skb->data, snaplen); h->tp_len = skb->len; h->tp_snaplen = snaplen; diff --git a/trunk/net/sched/act_api.c b/trunk/net/sched/act_api.c index 835070e9169c..a2587b52e531 100644 --- a/trunk/net/sched/act_api.c +++ b/trunk/net/sched/act_api.c @@ -33,230 +33,16 @@ #include #include -void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo) -{ - unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); - struct tcf_common **p1p; - - for (p1p = &hinfo->htab[h]; *p1p; p1p = &(*p1p)->tcfc_next) { - if (*p1p == p) { - write_lock_bh(hinfo->lock); - *p1p = p->tcfc_next; - write_unlock_bh(hinfo->lock); -#ifdef CONFIG_NET_ESTIMATOR - gen_kill_estimator(&p->tcfc_bstats, - &p->tcfc_rate_est); +#if 0 /* control */ +#define DPRINTK(format, args...) printk(KERN_DEBUG format, ##args) +#else +#define DPRINTK(format, args...) #endif - kfree(p); - return; - } - } - BUG_TRAP(0); -} -EXPORT_SYMBOL(tcf_hash_destroy); - -int tcf_hash_release(struct tcf_common *p, int bind, - struct tcf_hashinfo *hinfo) -{ - int ret = 0; - - if (p) { - if (bind) - p->tcfc_bindcnt--; - - p->tcfc_refcnt--; - if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) { - tcf_hash_destroy(p, hinfo); - ret = 1; - } - } - return ret; -} -EXPORT_SYMBOL(tcf_hash_release); - -static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb, - struct tc_action *a, struct tcf_hashinfo *hinfo) -{ - struct tcf_common *p; - int err = 0, index = -1,i = 0, s_i = 0, n_i = 0; - struct rtattr *r ; - - read_lock(hinfo->lock); - - s_i = cb->args[0]; - - for (i = 0; i < (hinfo->hmask + 1); i++) { - p = hinfo->htab[tcf_hash(i, hinfo->hmask)]; - - for (; p; p = p->tcfc_next) { - index++; - if (index < s_i) - continue; - a->priv = p; - a->order = n_i; - r = (struct rtattr*) skb->tail; - RTA_PUT(skb, a->order, 0, NULL); - err = tcf_action_dump_1(skb, a, 0, 0); - if (err < 0) { - index--; - skb_trim(skb, (u8*)r - skb->data); - goto done; - } - r->rta_len = skb->tail - (u8*)r; - n_i++; - if (n_i >= TCA_ACT_MAX_PRIO) - goto done; - } - } -done: - read_unlock(hinfo->lock); - if (n_i) - cb->args[0] += n_i; - return n_i; - -rtattr_failure: - skb_trim(skb, (u8*)r - skb->data); - goto done; -} - -static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a, - struct tcf_hashinfo *hinfo) -{ - struct tcf_common *p, *s_p; - struct rtattr *r ; - int i= 0, n_i = 0; - - r = (struct rtattr*) skb->tail; - RTA_PUT(skb, a->order, 0, NULL); - RTA_PUT(skb, TCA_KIND, IFNAMSIZ, a->ops->kind); - for (i = 0; i < (hinfo->hmask + 1); i++) { - p = hinfo->htab[tcf_hash(i, hinfo->hmask)]; - - while (p != NULL) { - s_p = p->tcfc_next; - if (ACT_P_DELETED == tcf_hash_release(p, 0, hinfo)) - module_put(a->ops->owner); - n_i++; - p = s_p; - } - } - RTA_PUT(skb, TCA_FCNT, 4, &n_i); - r->rta_len = skb->tail - (u8*)r; - - return n_i; -rtattr_failure: - skb_trim(skb, (u8*)r - skb->data); - return -EINVAL; -} - -int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, - int type, struct tc_action *a) -{ - struct tcf_hashinfo *hinfo = a->ops->hinfo; - - if (type == RTM_DELACTION) { - return tcf_del_walker(skb, a, hinfo); - } else if (type == RTM_GETACTION) { - return tcf_dump_walker(skb, cb, a, hinfo); - } else { - printk("tcf_generic_walker: unknown action %d\n", type); - return -EINVAL; - } -} -EXPORT_SYMBOL(tcf_generic_walker); - -struct tcf_common *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo) -{ - struct tcf_common *p; - - read_lock(hinfo->lock); - for (p = hinfo->htab[tcf_hash(index, hinfo->hmask)]; p; - p = p->tcfc_next) { - if (p->tcfc_index == index) - break; - } - read_unlock(hinfo->lock); - - return p; -} -EXPORT_SYMBOL(tcf_hash_lookup); - -u32 tcf_hash_new_index(u32 *idx_gen, struct tcf_hashinfo *hinfo) -{ - u32 val = *idx_gen; - - do { - if (++val == 0) - val = 1; - } while (tcf_hash_lookup(val, hinfo)); - - return (*idx_gen = val); -} -EXPORT_SYMBOL(tcf_hash_new_index); - -int tcf_hash_search(struct tc_action *a, u32 index) -{ - struct tcf_hashinfo *hinfo = a->ops->hinfo; - struct tcf_common *p = tcf_hash_lookup(index, hinfo); - - if (p) { - a->priv = p; - return 1; - } - return 0; -} -EXPORT_SYMBOL(tcf_hash_search); - -struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, int bind, - struct tcf_hashinfo *hinfo) -{ - struct tcf_common *p = NULL; - if (index && (p = tcf_hash_lookup(index, hinfo)) != NULL) { - if (bind) { - p->tcfc_bindcnt++; - p->tcfc_refcnt++; - } - a->priv = p; - } - return p; -} -EXPORT_SYMBOL(tcf_hash_check); - -struct tcf_common *tcf_hash_create(u32 index, struct rtattr *est, struct tc_action *a, int size, int bind, u32 *idx_gen, struct tcf_hashinfo *hinfo) -{ - struct tcf_common *p = kzalloc(size, GFP_KERNEL); - - if (unlikely(!p)) - return p; - p->tcfc_refcnt = 1; - if (bind) - p->tcfc_bindcnt = 1; - - spin_lock_init(&p->tcfc_lock); - p->tcfc_stats_lock = &p->tcfc_lock; - p->tcfc_index = index ? index : tcf_hash_new_index(idx_gen, hinfo); - p->tcfc_tm.install = jiffies; - p->tcfc_tm.lastuse = jiffies; -#ifdef CONFIG_NET_ESTIMATOR - if (est) - gen_new_estimator(&p->tcfc_bstats, &p->tcfc_rate_est, - p->tcfc_stats_lock, est); +#if 0 /* data */ +#define D2PRINTK(format, args...) printk(KERN_DEBUG format, ##args) +#else +#define D2PRINTK(format, args...) #endif - a->priv = (void *) p; - return p; -} -EXPORT_SYMBOL(tcf_hash_create); - -void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo) -{ - unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); - - write_lock_bh(hinfo->lock); - p->tcfc_next = hinfo->htab[h]; - hinfo->htab[h] = p; - write_unlock_bh(hinfo->lock); -} -EXPORT_SYMBOL(tcf_hash_insert); static struct tc_action_ops *act_base = NULL; static DEFINE_RWLOCK(act_mod_lock); @@ -369,6 +155,9 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action *act, if (skb->tc_verd & TC_NCLS) { skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); + D2PRINTK("(%p)tcf_action_exec: cleared TC_NCLS in %s out %s\n", + skb, skb->input_dev ? skb->input_dev->name : "xxx", + skb->dev->name); ret = TC_ACT_OK; goto exec_done; } @@ -398,6 +187,8 @@ void tcf_action_destroy(struct tc_action *act, int bind) for (a = act; a; a = act) { if (a->ops && a->ops->cleanup) { + DPRINTK("tcf_action_destroy destroying %p next %p\n", + a, a->next); if (a->ops->cleanup(a, bind) == ACT_P_DELETED) module_put(a->ops->owner); act = act->next; @@ -540,6 +331,7 @@ struct tc_action *tcf_action_init_1(struct rtattr *rta, struct rtattr *est, if (*err != ACT_P_CREATED) module_put(a_o->owner); a->ops = a_o; + DPRINTK("tcf_action_init_1: successfull %s\n", act_name); *err = 0; return a; @@ -600,12 +392,12 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, if (compat_mode) { if (a->type == TCA_OLD_COMPAT) err = gnet_stats_start_copy_compat(skb, 0, - TCA_STATS, TCA_XSTATS, h->tcf_stats_lock, &d); + TCA_STATS, TCA_XSTATS, h->stats_lock, &d); else return 0; } else err = gnet_stats_start_copy(skb, TCA_ACT_STATS, - h->tcf_stats_lock, &d); + h->stats_lock, &d); if (err < 0) goto errout; @@ -614,11 +406,11 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, if (a->ops->get_stats(skb, a) < 0) goto errout; - if (gnet_stats_copy_basic(&d, &h->tcf_bstats) < 0 || + if (gnet_stats_copy_basic(&d, &h->bstats) < 0 || #ifdef CONFIG_NET_ESTIMATOR - gnet_stats_copy_rate_est(&d, &h->tcf_rate_est) < 0 || + gnet_stats_copy_rate_est(&d, &h->rate_est) < 0 || #endif - gnet_stats_copy_queue(&d, &h->tcf_qstats) < 0) + gnet_stats_copy_queue(&d, &h->qstats) < 0) goto errout; if (gnet_stats_finish_copy(&d) < 0) @@ -667,6 +459,7 @@ static int act_get_notify(u32 pid, struct nlmsghdr *n, struct tc_action *a, int event) { struct sk_buff *skb; + int err = 0; skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (!skb) @@ -675,8 +468,10 @@ act_get_notify(u32 pid, struct nlmsghdr *n, struct tc_action *a, int event) kfree_skb(skb); return -EINVAL; } - - return rtnl_unicast(skb, pid); + err = netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT); + if (err > 0) + err = 0; + return err; } static struct tc_action * diff --git a/trunk/net/sched/act_gact.c b/trunk/net/sched/act_gact.c index 6cff56696a81..e75a147ad60f 100644 --- a/trunk/net/sched/act_gact.c +++ b/trunk/net/sched/act_gact.c @@ -34,43 +34,48 @@ #include #include -#define GACT_TAB_MASK 15 -static struct tcf_common *tcf_gact_ht[GACT_TAB_MASK + 1]; -static u32 gact_idx_gen; +/* use generic hash table */ +#define MY_TAB_SIZE 16 +#define MY_TAB_MASK 15 + +static u32 idx_gen; +static struct tcf_gact *tcf_gact_ht[MY_TAB_SIZE]; static DEFINE_RWLOCK(gact_lock); -static struct tcf_hashinfo gact_hash_info = { - .htab = tcf_gact_ht, - .hmask = GACT_TAB_MASK, - .lock = &gact_lock, -}; +/* ovewrride the defaults */ +#define tcf_st tcf_gact +#define tc_st tc_gact +#define tcf_t_lock gact_lock +#define tcf_ht tcf_gact_ht + +#define CONFIG_NET_ACT_INIT 1 +#include #ifdef CONFIG_GACT_PROB -static int gact_net_rand(struct tcf_gact *gact) +static int gact_net_rand(struct tcf_gact *p) { - if (net_random() % gact->tcfg_pval) - return gact->tcf_action; - return gact->tcfg_paction; + if (net_random()%p->pval) + return p->action; + return p->paction; } -static int gact_determ(struct tcf_gact *gact) +static int gact_determ(struct tcf_gact *p) { - if (gact->tcf_bstats.packets % gact->tcfg_pval) - return gact->tcf_action; - return gact->tcfg_paction; + if (p->bstats.packets%p->pval) + return p->action; + return p->paction; } -typedef int (*g_rand)(struct tcf_gact *gact); +typedef int (*g_rand)(struct tcf_gact *p); static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ }; -#endif /* CONFIG_GACT_PROB */ +#endif static int tcf_gact_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, int ovr, int bind) { struct rtattr *tb[TCA_GACT_MAX]; struct tc_gact *parm; - struct tcf_gact *gact; - struct tcf_common *pc; + struct tcf_gact *p; int ret = 0; if (rta == NULL || rtattr_parse_nested(tb, TCA_GACT_MAX, rta) < 0) @@ -89,106 +94,105 @@ static int tcf_gact_init(struct rtattr *rta, struct rtattr *est, return -EOPNOTSUPP; #endif - pc = tcf_hash_check(parm->index, a, bind, &gact_hash_info); - if (!pc) { - pc = tcf_hash_create(parm->index, est, a, sizeof(*gact), - bind, &gact_idx_gen, &gact_hash_info); - if (unlikely(!pc)) + p = tcf_hash_check(parm->index, a, ovr, bind); + if (p == NULL) { + p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); + if (p == NULL) return -ENOMEM; ret = ACT_P_CREATED; } else { if (!ovr) { - tcf_hash_release(pc, bind, &gact_hash_info); + tcf_hash_release(p, bind); return -EEXIST; } } - gact = to_gact(pc); - - spin_lock_bh(&gact->tcf_lock); - gact->tcf_action = parm->action; + spin_lock_bh(&p->lock); + p->action = parm->action; #ifdef CONFIG_GACT_PROB if (tb[TCA_GACT_PROB-1] != NULL) { struct tc_gact_p *p_parm = RTA_DATA(tb[TCA_GACT_PROB-1]); - gact->tcfg_paction = p_parm->paction; - gact->tcfg_pval = p_parm->pval; - gact->tcfg_ptype = p_parm->ptype; + p->paction = p_parm->paction; + p->pval = p_parm->pval; + p->ptype = p_parm->ptype; } #endif - spin_unlock_bh(&gact->tcf_lock); + spin_unlock_bh(&p->lock); if (ret == ACT_P_CREATED) - tcf_hash_insert(pc, &gact_hash_info); + tcf_hash_insert(p); return ret; } -static int tcf_gact_cleanup(struct tc_action *a, int bind) +static int +tcf_gact_cleanup(struct tc_action *a, int bind) { - struct tcf_gact *gact = a->priv; + struct tcf_gact *p = PRIV(a, gact); - if (gact) - return tcf_hash_release(&gact->common, bind, &gact_hash_info); + if (p != NULL) + return tcf_hash_release(p, bind); return 0; } -static int tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) +static int +tcf_gact(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { - struct tcf_gact *gact = a->priv; + struct tcf_gact *p = PRIV(a, gact); int action = TC_ACT_SHOT; - spin_lock(&gact->tcf_lock); + spin_lock(&p->lock); #ifdef CONFIG_GACT_PROB - if (gact->tcfg_ptype && gact_rand[gact->tcfg_ptype] != NULL) - action = gact_rand[gact->tcfg_ptype](gact); + if (p->ptype && gact_rand[p->ptype] != NULL) + action = gact_rand[p->ptype](p); else - action = gact->tcf_action; + action = p->action; #else - action = gact->tcf_action; + action = p->action; #endif - gact->tcf_bstats.bytes += skb->len; - gact->tcf_bstats.packets++; + p->bstats.bytes += skb->len; + p->bstats.packets++; if (action == TC_ACT_SHOT) - gact->tcf_qstats.drops++; - gact->tcf_tm.lastuse = jiffies; - spin_unlock(&gact->tcf_lock); + p->qstats.drops++; + p->tm.lastuse = jiffies; + spin_unlock(&p->lock); return action; } -static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) +static int +tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) { unsigned char *b = skb->tail; struct tc_gact opt; - struct tcf_gact *gact = a->priv; + struct tcf_gact *p = PRIV(a, gact); struct tcf_t t; - opt.index = gact->tcf_index; - opt.refcnt = gact->tcf_refcnt - ref; - opt.bindcnt = gact->tcf_bindcnt - bind; - opt.action = gact->tcf_action; + opt.index = p->index; + opt.refcnt = p->refcnt - ref; + opt.bindcnt = p->bindcnt - bind; + opt.action = p->action; RTA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt); #ifdef CONFIG_GACT_PROB - if (gact->tcfg_ptype) { + if (p->ptype) { struct tc_gact_p p_opt; - p_opt.paction = gact->tcfg_paction; - p_opt.pval = gact->tcfg_pval; - p_opt.ptype = gact->tcfg_ptype; + p_opt.paction = p->paction; + p_opt.pval = p->pval; + p_opt.ptype = p->ptype; RTA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt); } #endif - t.install = jiffies_to_clock_t(jiffies - gact->tcf_tm.install); - t.lastuse = jiffies_to_clock_t(jiffies - gact->tcf_tm.lastuse); - t.expires = jiffies_to_clock_t(gact->tcf_tm.expires); + t.install = jiffies_to_clock_t(jiffies - p->tm.install); + t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); + t.expires = jiffies_to_clock_t(p->tm.expires); RTA_PUT(skb, TCA_GACT_TM, sizeof(t), &t); return skb->len; -rtattr_failure: + rtattr_failure: skb_trim(skb, b - skb->data); return -1; } static struct tc_action_ops act_gact_ops = { .kind = "gact", - .hinfo = &gact_hash_info, .type = TCA_ACT_GACT, .capab = TCA_CAP_NONE, .owner = THIS_MODULE, @@ -204,7 +208,8 @@ MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); MODULE_DESCRIPTION("Generic Classifier actions"); MODULE_LICENSE("GPL"); -static int __init gact_init_module(void) +static int __init +gact_init_module(void) { #ifdef CONFIG_GACT_PROB printk("GACT probability on\n"); @@ -214,7 +219,8 @@ static int __init gact_init_module(void) return tcf_register_action(&act_gact_ops); } -static void __exit gact_cleanup_module(void) +static void __exit +gact_cleanup_module(void) { tcf_unregister_action(&act_gact_ops); } diff --git a/trunk/net/sched/act_ipt.c b/trunk/net/sched/act_ipt.c index d8c9310da6e5..d799e01248c4 100644 --- a/trunk/net/sched/act_ipt.c +++ b/trunk/net/sched/act_ipt.c @@ -38,19 +38,25 @@ #include +/* use generic hash table */ +#define MY_TAB_SIZE 16 +#define MY_TAB_MASK 15 -#define IPT_TAB_MASK 15 -static struct tcf_common *tcf_ipt_ht[IPT_TAB_MASK + 1]; -static u32 ipt_idx_gen; +static u32 idx_gen; +static struct tcf_ipt *tcf_ipt_ht[MY_TAB_SIZE]; +/* ipt hash table lock */ static DEFINE_RWLOCK(ipt_lock); -static struct tcf_hashinfo ipt_hash_info = { - .htab = tcf_ipt_ht, - .hmask = IPT_TAB_MASK, - .lock = &ipt_lock, -}; +/* ovewrride the defaults */ +#define tcf_st tcf_ipt +#define tcf_t_lock ipt_lock +#define tcf_ht tcf_ipt_ht + +#define CONFIG_NET_ACT_INIT +#include -static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) +static int +ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) { struct ipt_target *target; int ret = 0; @@ -59,6 +65,7 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int if (!target) return -ENOENT; + DPRINTK("ipt_init_target: found %s\n", target->name); t->u.kernel.target = target; ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), @@ -69,7 +76,10 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int if (t->u.kernel.target->checkentry && !t->u.kernel.target->checkentry(table, NULL, t->u.kernel.target, t->data, + t->u.target_size - sizeof(*t), hook)) { + DPRINTK("ipt_init_target: check failed for `%s'.\n", + t->u.kernel.target->name); module_put(t->u.kernel.target->me); ret = -EINVAL; } @@ -77,37 +87,40 @@ static int ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int return ret; } -static void ipt_destroy_target(struct ipt_entry_target *t) +static void +ipt_destroy_target(struct ipt_entry_target *t) { if (t->u.kernel.target->destroy) - t->u.kernel.target->destroy(t->u.kernel.target, t->data); + t->u.kernel.target->destroy(t->u.kernel.target, t->data, + t->u.target_size - sizeof(*t)); module_put(t->u.kernel.target->me); } -static int tcf_ipt_release(struct tcf_ipt *ipt, int bind) +static int +tcf_ipt_release(struct tcf_ipt *p, int bind) { int ret = 0; - if (ipt) { + if (p) { if (bind) - ipt->tcf_bindcnt--; - ipt->tcf_refcnt--; - if (ipt->tcf_bindcnt <= 0 && ipt->tcf_refcnt <= 0) { - ipt_destroy_target(ipt->tcfi_t); - kfree(ipt->tcfi_tname); - kfree(ipt->tcfi_t); - tcf_hash_destroy(&ipt->common, &ipt_hash_info); + p->bindcnt--; + p->refcnt--; + if (p->bindcnt <= 0 && p->refcnt <= 0) { + ipt_destroy_target(p->t); + kfree(p->tname); + kfree(p->t); + tcf_hash_destroy(p); ret = ACT_P_DELETED; } } return ret; } -static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est, - struct tc_action *a, int ovr, int bind) +static int +tcf_ipt_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, + int ovr, int bind) { struct rtattr *tb[TCA_IPT_MAX]; - struct tcf_ipt *ipt; - struct tcf_common *pc; + struct tcf_ipt *p; struct ipt_entry_target *td, *t; char *tname; int ret = 0, err; @@ -131,51 +144,49 @@ static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est, RTA_PAYLOAD(tb[TCA_IPT_INDEX-1]) >= sizeof(u32)) index = *(u32 *)RTA_DATA(tb[TCA_IPT_INDEX-1]); - pc = tcf_hash_check(index, a, bind, &ipt_hash_info); - if (!pc) { - pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind, - &ipt_idx_gen, &ipt_hash_info); - if (unlikely(!pc)) + p = tcf_hash_check(index, a, ovr, bind); + if (p == NULL) { + p = tcf_hash_create(index, est, a, sizeof(*p), ovr, bind); + if (p == NULL) return -ENOMEM; ret = ACT_P_CREATED; } else { if (!ovr) { - tcf_ipt_release(to_ipt(pc), bind); + tcf_ipt_release(p, bind); return -EEXIST; } } - ipt = to_ipt(pc); hook = *(u32 *)RTA_DATA(tb[TCA_IPT_HOOK-1]); err = -ENOMEM; tname = kmalloc(IFNAMSIZ, GFP_KERNEL); - if (unlikely(!tname)) + if (tname == NULL) goto err1; if (tb[TCA_IPT_TABLE - 1] == NULL || rtattr_strlcpy(tname, tb[TCA_IPT_TABLE-1], IFNAMSIZ) >= IFNAMSIZ) strcpy(tname, "mangle"); t = kmalloc(td->u.target_size, GFP_KERNEL); - if (unlikely(!t)) + if (t == NULL) goto err2; memcpy(t, td, td->u.target_size); if ((err = ipt_init_target(t, tname, hook)) < 0) goto err3; - spin_lock_bh(&ipt->tcf_lock); + spin_lock_bh(&p->lock); if (ret != ACT_P_CREATED) { - ipt_destroy_target(ipt->tcfi_t); - kfree(ipt->tcfi_tname); - kfree(ipt->tcfi_t); + ipt_destroy_target(p->t); + kfree(p->tname); + kfree(p->t); } - ipt->tcfi_tname = tname; - ipt->tcfi_t = t; - ipt->tcfi_hook = hook; - spin_unlock_bh(&ipt->tcf_lock); + p->tname = tname; + p->t = t; + p->hook = hook; + spin_unlock_bh(&p->lock); if (ret == ACT_P_CREATED) - tcf_hash_insert(pc, &ipt_hash_info); + tcf_hash_insert(p); return ret; err3: @@ -183,32 +194,33 @@ static int tcf_ipt_init(struct rtattr *rta, struct rtattr *est, err2: kfree(tname); err1: - kfree(pc); + kfree(p); return err; } -static int tcf_ipt_cleanup(struct tc_action *a, int bind) +static int +tcf_ipt_cleanup(struct tc_action *a, int bind) { - struct tcf_ipt *ipt = a->priv; - return tcf_ipt_release(ipt, bind); + struct tcf_ipt *p = PRIV(a, ipt); + return tcf_ipt_release(p, bind); } -static int tcf_ipt(struct sk_buff *skb, struct tc_action *a, - struct tcf_result *res) +static int +tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { int ret = 0, result = 0; - struct tcf_ipt *ipt = a->priv; + struct tcf_ipt *p = PRIV(a, ipt); if (skb_cloned(skb)) { if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) return TC_ACT_UNSPEC; } - spin_lock(&ipt->tcf_lock); + spin_lock(&p->lock); - ipt->tcf_tm.lastuse = jiffies; - ipt->tcf_bstats.bytes += skb->len; - ipt->tcf_bstats.packets++; + p->tm.lastuse = jiffies; + p->bstats.bytes += skb->len; + p->bstats.packets++; /* yes, we have to worry about both in and out dev worry later - danger - this API seems to have changed @@ -217,17 +229,16 @@ static int tcf_ipt(struct sk_buff *skb, struct tc_action *a, /* iptables targets take a double skb pointer in case the skb * needs to be replaced. We don't own the skb, so this must not * happen. The pskb_expand_head above should make sure of this */ - ret = ipt->tcfi_t->u.kernel.target->target(&skb, skb->dev, NULL, - ipt->tcfi_hook, - ipt->tcfi_t->u.kernel.target, - ipt->tcfi_t->data); + ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, p->hook, + p->t->u.kernel.target, p->t->data, + NULL); switch (ret) { case NF_ACCEPT: result = TC_ACT_OK; break; case NF_DROP: result = TC_ACT_SHOT; - ipt->tcf_qstats.drops++; + p->qstats.drops++; break; case IPT_CONTINUE: result = TC_ACT_PIPE; @@ -238,46 +249,53 @@ static int tcf_ipt(struct sk_buff *skb, struct tc_action *a, result = TC_POLICE_OK; break; } - spin_unlock(&ipt->tcf_lock); + spin_unlock(&p->lock); return result; } -static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) +static int +tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) { - unsigned char *b = skb->tail; - struct tcf_ipt *ipt = a->priv; struct ipt_entry_target *t; struct tcf_t tm; struct tc_cnt c; + unsigned char *b = skb->tail; + struct tcf_ipt *p = PRIV(a, ipt); /* for simple targets kernel size == user size ** user name = target name ** for foolproof you need to not assume this */ - t = kmalloc(ipt->tcfi_t->u.user.target_size, GFP_ATOMIC); - if (unlikely(!t)) + t = kmalloc(p->t->u.user.target_size, GFP_ATOMIC); + if (t == NULL) goto rtattr_failure; - c.bindcnt = ipt->tcf_bindcnt - bind; - c.refcnt = ipt->tcf_refcnt - ref; - memcpy(t, ipt->tcfi_t, ipt->tcfi_t->u.user.target_size); - strcpy(t->u.user.name, ipt->tcfi_t->u.kernel.target->name); - - RTA_PUT(skb, TCA_IPT_TARG, ipt->tcfi_t->u.user.target_size, t); - RTA_PUT(skb, TCA_IPT_INDEX, 4, &ipt->tcf_index); - RTA_PUT(skb, TCA_IPT_HOOK, 4, &ipt->tcfi_hook); + c.bindcnt = p->bindcnt - bind; + c.refcnt = p->refcnt - ref; + memcpy(t, p->t, p->t->u.user.target_size); + strcpy(t->u.user.name, p->t->u.kernel.target->name); + + DPRINTK("\ttcf_ipt_dump tablename %s length %d\n", p->tname, + strlen(p->tname)); + DPRINTK("\tdump target name %s size %d size user %d " + "data[0] %x data[1] %x\n", p->t->u.kernel.target->name, + p->t->u.target_size, p->t->u.user.target_size, + p->t->data[0], p->t->data[1]); + RTA_PUT(skb, TCA_IPT_TARG, p->t->u.user.target_size, t); + RTA_PUT(skb, TCA_IPT_INDEX, 4, &p->index); + RTA_PUT(skb, TCA_IPT_HOOK, 4, &p->hook); RTA_PUT(skb, TCA_IPT_CNT, sizeof(struct tc_cnt), &c); - RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, ipt->tcfi_tname); - tm.install = jiffies_to_clock_t(jiffies - ipt->tcf_tm.install); - tm.lastuse = jiffies_to_clock_t(jiffies - ipt->tcf_tm.lastuse); - tm.expires = jiffies_to_clock_t(ipt->tcf_tm.expires); + RTA_PUT(skb, TCA_IPT_TABLE, IFNAMSIZ, p->tname); + tm.install = jiffies_to_clock_t(jiffies - p->tm.install); + tm.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); + tm.expires = jiffies_to_clock_t(p->tm.expires); RTA_PUT(skb, TCA_IPT_TM, sizeof (tm), &tm); kfree(t); return skb->len; -rtattr_failure: + rtattr_failure: skb_trim(skb, b - skb->data); kfree(t); return -1; @@ -285,7 +303,6 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int static struct tc_action_ops act_ipt_ops = { .kind = "ipt", - .hinfo = &ipt_hash_info, .type = TCA_ACT_IPT, .capab = TCA_CAP_NONE, .owner = THIS_MODULE, @@ -301,12 +318,14 @@ MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); MODULE_DESCRIPTION("Iptables target actions"); MODULE_LICENSE("GPL"); -static int __init ipt_init_module(void) +static int __init +ipt_init_module(void) { return tcf_register_action(&act_ipt_ops); } -static void __exit ipt_cleanup_module(void) +static void __exit +ipt_cleanup_module(void) { tcf_unregister_action(&act_ipt_ops); } diff --git a/trunk/net/sched/act_mirred.c b/trunk/net/sched/act_mirred.c index 483897271f15..fc562047ecc5 100644 --- a/trunk/net/sched/act_mirred.c +++ b/trunk/net/sched/act_mirred.c @@ -39,39 +39,46 @@ #include #include -#define MIRRED_TAB_MASK 7 -static struct tcf_common *tcf_mirred_ht[MIRRED_TAB_MASK + 1]; -static u32 mirred_idx_gen; + +/* use generic hash table */ +#define MY_TAB_SIZE 8 +#define MY_TAB_MASK (MY_TAB_SIZE - 1) +static u32 idx_gen; +static struct tcf_mirred *tcf_mirred_ht[MY_TAB_SIZE]; static DEFINE_RWLOCK(mirred_lock); -static struct tcf_hashinfo mirred_hash_info = { - .htab = tcf_mirred_ht, - .hmask = MIRRED_TAB_MASK, - .lock = &mirred_lock, -}; +/* ovewrride the defaults */ +#define tcf_st tcf_mirred +#define tc_st tc_mirred +#define tcf_t_lock mirred_lock +#define tcf_ht tcf_mirred_ht + +#define CONFIG_NET_ACT_INIT 1 +#include -static inline int tcf_mirred_release(struct tcf_mirred *m, int bind) +static inline int +tcf_mirred_release(struct tcf_mirred *p, int bind) { - if (m) { + if (p) { if (bind) - m->tcf_bindcnt--; - m->tcf_refcnt--; - if(!m->tcf_bindcnt && m->tcf_refcnt <= 0) { - dev_put(m->tcfm_dev); - tcf_hash_destroy(&m->common, &mirred_hash_info); + p->bindcnt--; + p->refcnt--; + if(!p->bindcnt && p->refcnt <= 0) { + dev_put(p->dev); + tcf_hash_destroy(p); return 1; } } return 0; } -static int tcf_mirred_init(struct rtattr *rta, struct rtattr *est, - struct tc_action *a, int ovr, int bind) +static int +tcf_mirred_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, + int ovr, int bind) { struct rtattr *tb[TCA_MIRRED_MAX]; struct tc_mirred *parm; - struct tcf_mirred *m; - struct tcf_common *pc; + struct tcf_mirred *p; struct net_device *dev = NULL; int ret = 0; int ok_push = 0; @@ -103,62 +110,64 @@ static int tcf_mirred_init(struct rtattr *rta, struct rtattr *est, } } - pc = tcf_hash_check(parm->index, a, bind, &mirred_hash_info); - if (!pc) { + p = tcf_hash_check(parm->index, a, ovr, bind); + if (p == NULL) { if (!parm->ifindex) return -EINVAL; - pc = tcf_hash_create(parm->index, est, a, sizeof(*m), bind, - &mirred_idx_gen, &mirred_hash_info); - if (unlikely(!pc)) + p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); + if (p == NULL) return -ENOMEM; ret = ACT_P_CREATED; } else { if (!ovr) { - tcf_mirred_release(to_mirred(pc), bind); + tcf_mirred_release(p, bind); return -EEXIST; } } - m = to_mirred(pc); - spin_lock_bh(&m->tcf_lock); - m->tcf_action = parm->action; - m->tcfm_eaction = parm->eaction; + spin_lock_bh(&p->lock); + p->action = parm->action; + p->eaction = parm->eaction; if (parm->ifindex) { - m->tcfm_ifindex = parm->ifindex; + p->ifindex = parm->ifindex; if (ret != ACT_P_CREATED) - dev_put(m->tcfm_dev); - m->tcfm_dev = dev; + dev_put(p->dev); + p->dev = dev; dev_hold(dev); - m->tcfm_ok_push = ok_push; + p->ok_push = ok_push; } - spin_unlock_bh(&m->tcf_lock); + spin_unlock_bh(&p->lock); if (ret == ACT_P_CREATED) - tcf_hash_insert(pc, &mirred_hash_info); + tcf_hash_insert(p); + DPRINTK("tcf_mirred_init index %d action %d eaction %d device %s " + "ifindex %d\n", parm->index, parm->action, parm->eaction, + dev->name, parm->ifindex); return ret; } -static int tcf_mirred_cleanup(struct tc_action *a, int bind) +static int +tcf_mirred_cleanup(struct tc_action *a, int bind) { - struct tcf_mirred *m = a->priv; + struct tcf_mirred *p = PRIV(a, mirred); - if (m) - return tcf_mirred_release(m, bind); + if (p != NULL) + return tcf_mirred_release(p, bind); return 0; } -static int tcf_mirred(struct sk_buff *skb, struct tc_action *a, - struct tcf_result *res) +static int +tcf_mirred(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { - struct tcf_mirred *m = a->priv; + struct tcf_mirred *p = PRIV(a, mirred); struct net_device *dev; struct sk_buff *skb2 = NULL; u32 at = G_TC_AT(skb->tc_verd); - spin_lock(&m->tcf_lock); + spin_lock(&p->lock); - dev = m->tcfm_dev; - m->tcf_tm.lastuse = jiffies; + dev = p->dev; + p->tm.lastuse = jiffies; if (!(dev->flags&IFF_UP) ) { if (net_ratelimit()) @@ -167,10 +176,10 @@ static int tcf_mirred(struct sk_buff *skb, struct tc_action *a, bad_mirred: if (skb2 != NULL) kfree_skb(skb2); - m->tcf_qstats.overlimits++; - m->tcf_bstats.bytes += skb->len; - m->tcf_bstats.packets++; - spin_unlock(&m->tcf_lock); + p->qstats.overlimits++; + p->bstats.bytes += skb->len; + p->bstats.packets++; + spin_unlock(&p->lock); /* should we be asking for packet to be dropped? * may make sense for redirect case only */ @@ -180,59 +189,59 @@ static int tcf_mirred(struct sk_buff *skb, struct tc_action *a, skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2 == NULL) goto bad_mirred; - if (m->tcfm_eaction != TCA_EGRESS_MIRROR && - m->tcfm_eaction != TCA_EGRESS_REDIR) { + if (p->eaction != TCA_EGRESS_MIRROR && p->eaction != TCA_EGRESS_REDIR) { if (net_ratelimit()) - printk("tcf_mirred unknown action %d\n", - m->tcfm_eaction); + printk("tcf_mirred unknown action %d\n", p->eaction); goto bad_mirred; } - m->tcf_bstats.bytes += skb2->len; - m->tcf_bstats.packets++; + p->bstats.bytes += skb2->len; + p->bstats.packets++; if (!(at & AT_EGRESS)) - if (m->tcfm_ok_push) + if (p->ok_push) skb_push(skb2, skb2->dev->hard_header_len); /* mirror is always swallowed */ - if (m->tcfm_eaction != TCA_EGRESS_MIRROR) + if (p->eaction != TCA_EGRESS_MIRROR) skb2->tc_verd = SET_TC_FROM(skb2->tc_verd, at); skb2->dev = dev; skb2->input_dev = skb->dev; dev_queue_xmit(skb2); - spin_unlock(&m->tcf_lock); - return m->tcf_action; + spin_unlock(&p->lock); + return p->action; } -static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) +static int +tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) { unsigned char *b = skb->tail; - struct tcf_mirred *m = a->priv; struct tc_mirred opt; + struct tcf_mirred *p = PRIV(a, mirred); struct tcf_t t; - opt.index = m->tcf_index; - opt.action = m->tcf_action; - opt.refcnt = m->tcf_refcnt - ref; - opt.bindcnt = m->tcf_bindcnt - bind; - opt.eaction = m->tcfm_eaction; - opt.ifindex = m->tcfm_ifindex; + opt.index = p->index; + opt.action = p->action; + opt.refcnt = p->refcnt - ref; + opt.bindcnt = p->bindcnt - bind; + opt.eaction = p->eaction; + opt.ifindex = p->ifindex; + DPRINTK("tcf_mirred_dump index %d action %d eaction %d ifindex %d\n", + p->index, p->action, p->eaction, p->ifindex); RTA_PUT(skb, TCA_MIRRED_PARMS, sizeof(opt), &opt); - t.install = jiffies_to_clock_t(jiffies - m->tcf_tm.install); - t.lastuse = jiffies_to_clock_t(jiffies - m->tcf_tm.lastuse); - t.expires = jiffies_to_clock_t(m->tcf_tm.expires); + t.install = jiffies_to_clock_t(jiffies - p->tm.install); + t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); + t.expires = jiffies_to_clock_t(p->tm.expires); RTA_PUT(skb, TCA_MIRRED_TM, sizeof(t), &t); return skb->len; -rtattr_failure: + rtattr_failure: skb_trim(skb, b - skb->data); return -1; } static struct tc_action_ops act_mirred_ops = { .kind = "mirred", - .hinfo = &mirred_hash_info, .type = TCA_ACT_MIRRED, .capab = TCA_CAP_NONE, .owner = THIS_MODULE, @@ -248,13 +257,15 @@ MODULE_AUTHOR("Jamal Hadi Salim(2002)"); MODULE_DESCRIPTION("Device Mirror/redirect actions"); MODULE_LICENSE("GPL"); -static int __init mirred_init_module(void) +static int __init +mirred_init_module(void) { printk("Mirror/redirect action on\n"); return tcf_register_action(&act_mirred_ops); } -static void __exit mirred_cleanup_module(void) +static void __exit +mirred_cleanup_module(void) { tcf_unregister_action(&act_mirred_ops); } diff --git a/trunk/net/sched/act_pedit.c b/trunk/net/sched/act_pedit.c index 8ac65c219b98..f257475e0e0c 100644 --- a/trunk/net/sched/act_pedit.c +++ b/trunk/net/sched/act_pedit.c @@ -33,25 +33,32 @@ #include #include -#define PEDIT_TAB_MASK 15 -static struct tcf_common *tcf_pedit_ht[PEDIT_TAB_MASK + 1]; -static u32 pedit_idx_gen; + +#define PEDIT_DEB 1 + +/* use generic hash table */ +#define MY_TAB_SIZE 16 +#define MY_TAB_MASK 15 +static u32 idx_gen; +static struct tcf_pedit *tcf_pedit_ht[MY_TAB_SIZE]; static DEFINE_RWLOCK(pedit_lock); -static struct tcf_hashinfo pedit_hash_info = { - .htab = tcf_pedit_ht, - .hmask = PEDIT_TAB_MASK, - .lock = &pedit_lock, -}; +#define tcf_st tcf_pedit +#define tc_st tc_pedit +#define tcf_t_lock pedit_lock +#define tcf_ht tcf_pedit_ht -static int tcf_pedit_init(struct rtattr *rta, struct rtattr *est, - struct tc_action *a, int ovr, int bind) +#define CONFIG_NET_ACT_INIT 1 +#include + +static int +tcf_pedit_init(struct rtattr *rta, struct rtattr *est, struct tc_action *a, + int ovr, int bind) { struct rtattr *tb[TCA_PEDIT_MAX]; struct tc_pedit *parm; int ret = 0; struct tcf_pedit *p; - struct tcf_common *pc; struct tc_pedit_key *keys = NULL; int ksize; @@ -66,56 +73,54 @@ static int tcf_pedit_init(struct rtattr *rta, struct rtattr *est, if (RTA_PAYLOAD(tb[TCA_PEDIT_PARMS-1]) < sizeof(*parm) + ksize) return -EINVAL; - pc = tcf_hash_check(parm->index, a, bind, &pedit_hash_info); - if (!pc) { + p = tcf_hash_check(parm->index, a, ovr, bind); + if (p == NULL) { if (!parm->nkeys) return -EINVAL; - pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind, - &pedit_idx_gen, &pedit_hash_info); - if (unlikely(!pc)) + p = tcf_hash_create(parm->index, est, a, sizeof(*p), ovr, bind); + if (p == NULL) return -ENOMEM; - p = to_pedit(pc); keys = kmalloc(ksize, GFP_KERNEL); if (keys == NULL) { - kfree(pc); + kfree(p); return -ENOMEM; } ret = ACT_P_CREATED; } else { - p = to_pedit(pc); if (!ovr) { - tcf_hash_release(pc, bind, &pedit_hash_info); + tcf_hash_release(p, bind); return -EEXIST; } - if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) { + if (p->nkeys && p->nkeys != parm->nkeys) { keys = kmalloc(ksize, GFP_KERNEL); if (keys == NULL) return -ENOMEM; } } - spin_lock_bh(&p->tcf_lock); - p->tcfp_flags = parm->flags; - p->tcf_action = parm->action; + spin_lock_bh(&p->lock); + p->flags = parm->flags; + p->action = parm->action; if (keys) { - kfree(p->tcfp_keys); - p->tcfp_keys = keys; - p->tcfp_nkeys = parm->nkeys; + kfree(p->keys); + p->keys = keys; + p->nkeys = parm->nkeys; } - memcpy(p->tcfp_keys, parm->keys, ksize); - spin_unlock_bh(&p->tcf_lock); + memcpy(p->keys, parm->keys, ksize); + spin_unlock_bh(&p->lock); if (ret == ACT_P_CREATED) - tcf_hash_insert(pc, &pedit_hash_info); + tcf_hash_insert(p); return ret; } -static int tcf_pedit_cleanup(struct tc_action *a, int bind) +static int +tcf_pedit_cleanup(struct tc_action *a, int bind) { - struct tcf_pedit *p = a->priv; + struct tcf_pedit *p = PRIV(a, pedit); - if (p) { - struct tc_pedit_key *keys = p->tcfp_keys; - if (tcf_hash_release(&p->common, bind, &pedit_hash_info)) { + if (p != NULL) { + struct tc_pedit_key *keys = p->keys; + if (tcf_hash_release(p, bind)) { kfree(keys); return 1; } @@ -123,30 +128,30 @@ static int tcf_pedit_cleanup(struct tc_action *a, int bind) return 0; } -static int tcf_pedit(struct sk_buff *skb, struct tc_action *a, - struct tcf_result *res) +static int +tcf_pedit(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { - struct tcf_pedit *p = a->priv; + struct tcf_pedit *p = PRIV(a, pedit); int i, munged = 0; u8 *pptr; if (!(skb->tc_verd & TC_OK2MUNGE)) { /* should we set skb->cloned? */ if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) { - return p->tcf_action; + return p->action; } } pptr = skb->nh.raw; - spin_lock(&p->tcf_lock); + spin_lock(&p->lock); - p->tcf_tm.lastuse = jiffies; + p->tm.lastuse = jiffies; - if (p->tcfp_nkeys > 0) { - struct tc_pedit_key *tkey = p->tcfp_keys; + if (p->nkeys > 0) { + struct tc_pedit_key *tkey = p->keys; - for (i = p->tcfp_nkeys; i > 0; i--, tkey++) { + for (i = p->nkeys; i > 0; i--, tkey++) { u32 *ptr; int offset = tkey->off; @@ -164,8 +169,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a, printk("offset must be on 32 bit boundaries\n"); goto bad; } - if (skb->len < 0 || - (offset > 0 && offset > skb->len)) { + if (skb->len < 0 || (offset > 0 && offset > skb->len)) { printk("offset %d cant exceed pkt length %d\n", offset, skb->len); goto bad; @@ -181,47 +185,63 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a, skb->tc_verd = SET_TC_MUNGED(skb->tc_verd); goto done; } else { - printk("pedit BUG: index %d\n", p->tcf_index); + printk("pedit BUG: index %d\n",p->index); } bad: - p->tcf_qstats.overlimits++; + p->qstats.overlimits++; done: - p->tcf_bstats.bytes += skb->len; - p->tcf_bstats.packets++; - spin_unlock(&p->tcf_lock); - return p->tcf_action; + p->bstats.bytes += skb->len; + p->bstats.packets++; + spin_unlock(&p->lock); + return p->action; } -static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a, - int bind, int ref) +static int +tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,int bind, int ref) { unsigned char *b = skb->tail; - struct tcf_pedit *p = a->priv; struct tc_pedit *opt; + struct tcf_pedit *p = PRIV(a, pedit); struct tcf_t t; int s; - s = sizeof(*opt) + p->tcfp_nkeys * sizeof(struct tc_pedit_key); + s = sizeof(*opt) + p->nkeys * sizeof(struct tc_pedit_key); /* netlink spinlocks held above us - must use ATOMIC */ opt = kzalloc(s, GFP_ATOMIC); - if (unlikely(!opt)) + if (opt == NULL) return -ENOBUFS; - memcpy(opt->keys, p->tcfp_keys, - p->tcfp_nkeys * sizeof(struct tc_pedit_key)); - opt->index = p->tcf_index; - opt->nkeys = p->tcfp_nkeys; - opt->flags = p->tcfp_flags; - opt->action = p->tcf_action; - opt->refcnt = p->tcf_refcnt - ref; - opt->bindcnt = p->tcf_bindcnt - bind; + memcpy(opt->keys, p->keys, p->nkeys * sizeof(struct tc_pedit_key)); + opt->index = p->index; + opt->nkeys = p->nkeys; + opt->flags = p->flags; + opt->action = p->action; + opt->refcnt = p->refcnt - ref; + opt->bindcnt = p->bindcnt - bind; + + +#ifdef PEDIT_DEB + { + /* Debug - get rid of later */ + int i; + struct tc_pedit_key *key = opt->keys; + + for (i=0; inkeys; i++, key++) { + printk( "\n key #%d",i); + printk( " at %d: val %08x mask %08x", + (unsigned int)key->off, + (unsigned int)key->val, + (unsigned int)key->mask); + } + } +#endif RTA_PUT(skb, TCA_PEDIT_PARMS, s, opt); - t.install = jiffies_to_clock_t(jiffies - p->tcf_tm.install); - t.lastuse = jiffies_to_clock_t(jiffies - p->tcf_tm.lastuse); - t.expires = jiffies_to_clock_t(p->tcf_tm.expires); + t.install = jiffies_to_clock_t(jiffies - p->tm.install); + t.lastuse = jiffies_to_clock_t(jiffies - p->tm.lastuse); + t.expires = jiffies_to_clock_t(p->tm.expires); RTA_PUT(skb, TCA_PEDIT_TM, sizeof(t), &t); kfree(opt); return skb->len; @@ -232,9 +252,9 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a, return -1; } -static struct tc_action_ops act_pedit_ops = { +static +struct tc_action_ops act_pedit_ops = { .kind = "pedit", - .hinfo = &pedit_hash_info, .type = TCA_ACT_PEDIT, .capab = TCA_CAP_NONE, .owner = THIS_MODULE, @@ -250,12 +270,14 @@ MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); MODULE_DESCRIPTION("Generic Packet Editor actions"); MODULE_LICENSE("GPL"); -static int __init pedit_init_module(void) +static int __init +pedit_init_module(void) { return tcf_register_action(&act_pedit_ops); } -static void __exit pedit_cleanup_module(void) +static void __exit +pedit_cleanup_module(void) { tcf_unregister_action(&act_pedit_ops); } diff --git a/trunk/net/sched/act_police.c b/trunk/net/sched/act_police.c index fed47b658837..da905d7b4b40 100644 --- a/trunk/net/sched/act_police.c +++ b/trunk/net/sched/act_police.c @@ -32,27 +32,43 @@ #include #include -#define L2T(p,L) ((p)->tcfp_R_tab->data[(L)>>(p)->tcfp_R_tab->rate.cell_log]) -#define L2T_P(p,L) ((p)->tcfp_P_tab->data[(L)>>(p)->tcfp_P_tab->rate.cell_log]) - -#define POL_TAB_MASK 15 -static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1]; -static u32 police_idx_gen; +#define L2T(p,L) ((p)->R_tab->data[(L)>>(p)->R_tab->rate.cell_log]) +#define L2T_P(p,L) ((p)->P_tab->data[(L)>>(p)->P_tab->rate.cell_log]) +#define PRIV(a) ((struct tcf_police *) (a)->priv) + +/* use generic hash table */ +#define MY_TAB_SIZE 16 +#define MY_TAB_MASK 15 +static u32 idx_gen; +static struct tcf_police *tcf_police_ht[MY_TAB_SIZE]; +/* Policer hash table lock */ static DEFINE_RWLOCK(police_lock); -static struct tcf_hashinfo police_hash_info = { - .htab = tcf_police_ht, - .hmask = POL_TAB_MASK, - .lock = &police_lock, -}; - /* Each policer is serialized by its individual spinlock */ +static __inline__ unsigned tcf_police_hash(u32 index) +{ + return index&0xF; +} + +static __inline__ struct tcf_police * tcf_police_lookup(u32 index) +{ + struct tcf_police *p; + + read_lock(&police_lock); + for (p = tcf_police_ht[tcf_police_hash(index)]; p; p = p->next) { + if (p->index == index) + break; + } + read_unlock(&police_lock); + return p; +} + #ifdef CONFIG_NET_CLS_ACT static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb, int type, struct tc_action *a) { - struct tcf_common *p; + struct tcf_police *p; int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; struct rtattr *r; @@ -60,10 +76,10 @@ static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *c s_i = cb->args[0]; - for (i = 0; i < (POL_TAB_MASK + 1); i++) { - p = tcf_police_ht[tcf_hash(i, POL_TAB_MASK)]; + for (i = 0; i < MY_TAB_SIZE; i++) { + p = tcf_police_ht[tcf_police_hash(i)]; - for (; p; p = p->tcfc_next) { + for (; p; p = p->next) { index++; if (index < s_i) continue; @@ -94,26 +110,48 @@ static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *c skb_trim(skb, (u8*)r - skb->data); goto done; } + +static inline int +tcf_act_police_hash_search(struct tc_action *a, u32 index) +{ + struct tcf_police *p = tcf_police_lookup(index); + + if (p != NULL) { + a->priv = p; + return 1; + } else { + return 0; + } +} #endif +static inline u32 tcf_police_new_index(void) +{ + do { + if (++idx_gen == 0) + idx_gen = 1; + } while (tcf_police_lookup(idx_gen)); + + return idx_gen; +} + void tcf_police_destroy(struct tcf_police *p) { - unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK); - struct tcf_common **p1p; + unsigned h = tcf_police_hash(p->index); + struct tcf_police **p1p; - for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->tcfc_next) { - if (*p1p == &p->common) { + for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->next) { + if (*p1p == p) { write_lock_bh(&police_lock); - *p1p = p->tcf_next; + *p1p = p->next; write_unlock_bh(&police_lock); #ifdef CONFIG_NET_ESTIMATOR - gen_kill_estimator(&p->tcf_bstats, - &p->tcf_rate_est); + gen_kill_estimator(&p->bstats, &p->rate_est); #endif - if (p->tcfp_R_tab) - qdisc_put_rtab(p->tcfp_R_tab); - if (p->tcfp_P_tab) - qdisc_put_rtab(p->tcfp_P_tab); + if (p->R_tab) + qdisc_put_rtab(p->R_tab); + if (p->P_tab) + qdisc_put_rtab(p->P_tab); kfree(p); return; } @@ -129,7 +167,7 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, int ret = 0, err; struct rtattr *tb[TCA_POLICE_MAX]; struct tc_police *parm; - struct tcf_police *police; + struct tcf_police *p; struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL; if (rta == NULL || rtattr_parse_nested(tb, TCA_POLICE_MAX, rta) < 0) @@ -147,32 +185,27 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) return -EINVAL; - if (parm->index) { - struct tcf_common *pc; - - pc = tcf_hash_lookup(parm->index, &police_hash_info); - if (pc != NULL) { - a->priv = pc; - police = to_police(pc); - if (bind) { - police->tcf_bindcnt += 1; - police->tcf_refcnt += 1; - } - if (ovr) - goto override; - return ret; + if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) { + a->priv = p; + if (bind) { + p->bindcnt += 1; + p->refcnt += 1; } + if (ovr) + goto override; + return ret; } - police = kzalloc(sizeof(*police), GFP_KERNEL); - if (police == NULL) + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (p == NULL) return -ENOMEM; + ret = ACT_P_CREATED; - police->tcf_refcnt = 1; - spin_lock_init(&police->tcf_lock); - police->tcf_stats_lock = &police->tcf_lock; + p->refcnt = 1; + spin_lock_init(&p->lock); + p->stats_lock = &p->lock; if (bind) - police->tcf_bindcnt = 1; + p->bindcnt = 1; override: if (parm->rate.rate) { err = -ENOMEM; @@ -182,71 +215,67 @@ static int tcf_act_police_locate(struct rtattr *rta, struct rtattr *est, if (parm->peakrate.rate) { P_tab = qdisc_get_rtab(&parm->peakrate, tb[TCA_POLICE_PEAKRATE-1]); - if (P_tab == NULL) { + if (p->P_tab == NULL) { qdisc_put_rtab(R_tab); goto failure; } } } /* No failure allowed after this point */ - spin_lock_bh(&police->tcf_lock); + spin_lock_bh(&p->lock); if (R_tab != NULL) { - qdisc_put_rtab(police->tcfp_R_tab); - police->tcfp_R_tab = R_tab; + qdisc_put_rtab(p->R_tab); + p->R_tab = R_tab; } if (P_tab != NULL) { - qdisc_put_rtab(police->tcfp_P_tab); - police->tcfp_P_tab = P_tab; + qdisc_put_rtab(p->P_tab); + p->P_tab = P_tab; } if (tb[TCA_POLICE_RESULT-1]) - police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); - police->tcfp_toks = police->tcfp_burst = parm->burst; - police->tcfp_mtu = parm->mtu; - if (police->tcfp_mtu == 0) { - police->tcfp_mtu = ~0; - if (police->tcfp_R_tab) - police->tcfp_mtu = 255<tcfp_R_tab->rate.cell_log; + p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); + p->toks = p->burst = parm->burst; + p->mtu = parm->mtu; + if (p->mtu == 0) { + p->mtu = ~0; + if (p->R_tab) + p->mtu = 255<R_tab->rate.cell_log; } - if (police->tcfp_P_tab) - police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu); - police->tcf_action = parm->action; + if (p->P_tab) + p->ptoks = L2T_P(p, p->mtu); + p->action = parm->action; #ifdef CONFIG_NET_ESTIMATOR if (tb[TCA_POLICE_AVRATE-1]) - police->tcfp_ewma_rate = - *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); + p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); if (est) - gen_replace_estimator(&police->tcf_bstats, - &police->tcf_rate_est, - police->tcf_stats_lock, est); + gen_replace_estimator(&p->bstats, &p->rate_est, p->stats_lock, est); #endif - spin_unlock_bh(&police->tcf_lock); + spin_unlock_bh(&p->lock); if (ret != ACT_P_CREATED) return ret; - PSCHED_GET_TIME(police->tcfp_t_c); - police->tcf_index = parm->index ? parm->index : - tcf_hash_new_index(&police_idx_gen, &police_hash_info); - h = tcf_hash(police->tcf_index, POL_TAB_MASK); + PSCHED_GET_TIME(p->t_c); + p->index = parm->index ? : tcf_police_new_index(); + h = tcf_police_hash(p->index); write_lock_bh(&police_lock); - police->tcf_next = tcf_police_ht[h]; - tcf_police_ht[h] = &police->common; + p->next = tcf_police_ht[h]; + tcf_police_ht[h] = p; write_unlock_bh(&police_lock); - a->priv = police; + a->priv = p; return ret; failure: if (ret == ACT_P_CREATED) - kfree(police); + kfree(p); return err; } static int tcf_act_police_cleanup(struct tc_action *a, int bind) { - struct tcf_police *p = a->priv; + struct tcf_police *p = PRIV(a); if (p != NULL) return tcf_police_release(p, bind); @@ -256,87 +285,86 @@ static int tcf_act_police_cleanup(struct tc_action *a, int bind) static int tcf_act_police(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { - struct tcf_police *police = a->priv; psched_time_t now; + struct tcf_police *p = PRIV(a); long toks; long ptoks = 0; - spin_lock(&police->tcf_lock); + spin_lock(&p->lock); - police->tcf_bstats.bytes += skb->len; - police->tcf_bstats.packets++; + p->bstats.bytes += skb->len; + p->bstats.packets++; #ifdef CONFIG_NET_ESTIMATOR - if (police->tcfp_ewma_rate && - police->tcf_rate_est.bps >= police->tcfp_ewma_rate) { - police->tcf_qstats.overlimits++; - spin_unlock(&police->tcf_lock); - return police->tcf_action; + if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) { + p->qstats.overlimits++; + spin_unlock(&p->lock); + return p->action; } #endif - if (skb->len <= police->tcfp_mtu) { - if (police->tcfp_R_tab == NULL) { - spin_unlock(&police->tcf_lock); - return police->tcfp_result; + if (skb->len <= p->mtu) { + if (p->R_tab == NULL) { + spin_unlock(&p->lock); + return p->result; } PSCHED_GET_TIME(now); - toks = PSCHED_TDIFF_SAFE(now, police->tcfp_t_c, - police->tcfp_burst); - if (police->tcfp_P_tab) { - ptoks = toks + police->tcfp_ptoks; - if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) - ptoks = (long)L2T_P(police, police->tcfp_mtu); - ptoks -= L2T_P(police, skb->len); + toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst); + + if (p->P_tab) { + ptoks = toks + p->ptoks; + if (ptoks > (long)L2T_P(p, p->mtu)) + ptoks = (long)L2T_P(p, p->mtu); + ptoks -= L2T_P(p, skb->len); } - toks += police->tcfp_toks; - if (toks > (long)police->tcfp_burst) - toks = police->tcfp_burst; - toks -= L2T(police, skb->len); + toks += p->toks; + if (toks > (long)p->burst) + toks = p->burst; + toks -= L2T(p, skb->len); + if ((toks|ptoks) >= 0) { - police->tcfp_t_c = now; - police->tcfp_toks = toks; - police->tcfp_ptoks = ptoks; - spin_unlock(&police->tcf_lock); - return police->tcfp_result; + p->t_c = now; + p->toks = toks; + p->ptoks = ptoks; + spin_unlock(&p->lock); + return p->result; } } - police->tcf_qstats.overlimits++; - spin_unlock(&police->tcf_lock); - return police->tcf_action; + p->qstats.overlimits++; + spin_unlock(&p->lock); + return p->action; } static int tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) { unsigned char *b = skb->tail; - struct tcf_police *police = a->priv; struct tc_police opt; - - opt.index = police->tcf_index; - opt.action = police->tcf_action; - opt.mtu = police->tcfp_mtu; - opt.burst = police->tcfp_burst; - opt.refcnt = police->tcf_refcnt - ref; - opt.bindcnt = police->tcf_bindcnt - bind; - if (police->tcfp_R_tab) - opt.rate = police->tcfp_R_tab->rate; + struct tcf_police *p = PRIV(a); + + opt.index = p->index; + opt.action = p->action; + opt.mtu = p->mtu; + opt.burst = p->burst; + opt.refcnt = p->refcnt - ref; + opt.bindcnt = p->bindcnt - bind; + if (p->R_tab) + opt.rate = p->R_tab->rate; else memset(&opt.rate, 0, sizeof(opt.rate)); - if (police->tcfp_P_tab) - opt.peakrate = police->tcfp_P_tab->rate; + if (p->P_tab) + opt.peakrate = p->P_tab->rate; else memset(&opt.peakrate, 0, sizeof(opt.peakrate)); RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); - if (police->tcfp_result) - RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), - &police->tcfp_result); + if (p->result) + RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result); #ifdef CONFIG_NET_ESTIMATOR - if (police->tcfp_ewma_rate) - RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate); + if (p->ewma_rate) + RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate); #endif return skb->len; @@ -351,14 +379,13 @@ MODULE_LICENSE("GPL"); static struct tc_action_ops act_police_ops = { .kind = "police", - .hinfo = &police_hash_info, .type = TCA_ID_POLICE, .capab = TCA_CAP_NONE, .owner = THIS_MODULE, .act = tcf_act_police, .dump = tcf_act_police_dump, .cleanup = tcf_act_police_cleanup, - .lookup = tcf_hash_search, + .lookup = tcf_act_police_hash_search, .init = tcf_act_police_locate, .walk = tcf_act_police_walker }; @@ -380,39 +407,10 @@ module_exit(police_cleanup_module); #else /* CONFIG_NET_CLS_ACT */ -static struct tcf_common *tcf_police_lookup(u32 index) -{ - struct tcf_hashinfo *hinfo = &police_hash_info; - struct tcf_common *p; - - read_lock(hinfo->lock); - for (p = hinfo->htab[tcf_hash(index, hinfo->hmask)]; p; - p = p->tcfc_next) { - if (p->tcfc_index == index) - break; - } - read_unlock(hinfo->lock); - - return p; -} - -static u32 tcf_police_new_index(void) -{ - u32 *idx_gen = &police_idx_gen; - u32 val = *idx_gen; - - do { - if (++val == 0) - val = 1; - } while (tcf_police_lookup(val)); - - return (*idx_gen = val); -} - -struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est) +struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est) { - unsigned int h; - struct tcf_police *police; + unsigned h; + struct tcf_police *p; struct rtattr *tb[TCA_POLICE_MAX]; struct tc_police *parm; @@ -425,158 +423,149 @@ struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est) parm = RTA_DATA(tb[TCA_POLICE_TBF-1]); - if (parm->index) { - struct tcf_common *pc; - - pc = tcf_police_lookup(parm->index); - if (pc) { - police = to_police(pc); - police->tcf_refcnt++; - return police; - } + if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) { + p->refcnt++; + return p; } - police = kzalloc(sizeof(*police), GFP_KERNEL); - if (unlikely(!police)) + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (p == NULL) return NULL; - police->tcf_refcnt = 1; - spin_lock_init(&police->tcf_lock); - police->tcf_stats_lock = &police->tcf_lock; + p->refcnt = 1; + spin_lock_init(&p->lock); + p->stats_lock = &p->lock; if (parm->rate.rate) { - police->tcfp_R_tab = - qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]); - if (police->tcfp_R_tab == NULL) + p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1]); + if (p->R_tab == NULL) goto failure; if (parm->peakrate.rate) { - police->tcfp_P_tab = - qdisc_get_rtab(&parm->peakrate, - tb[TCA_POLICE_PEAKRATE-1]); - if (police->tcfp_P_tab == NULL) + p->P_tab = qdisc_get_rtab(&parm->peakrate, + tb[TCA_POLICE_PEAKRATE-1]); + if (p->P_tab == NULL) goto failure; } } if (tb[TCA_POLICE_RESULT-1]) { if (RTA_PAYLOAD(tb[TCA_POLICE_RESULT-1]) != sizeof(u32)) goto failure; - police->tcfp_result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); + p->result = *(u32*)RTA_DATA(tb[TCA_POLICE_RESULT-1]); } #ifdef CONFIG_NET_ESTIMATOR if (tb[TCA_POLICE_AVRATE-1]) { if (RTA_PAYLOAD(tb[TCA_POLICE_AVRATE-1]) != sizeof(u32)) goto failure; - police->tcfp_ewma_rate = - *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); + p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]); } #endif - police->tcfp_toks = police->tcfp_burst = parm->burst; - police->tcfp_mtu = parm->mtu; - if (police->tcfp_mtu == 0) { - police->tcfp_mtu = ~0; - if (police->tcfp_R_tab) - police->tcfp_mtu = 255<tcfp_R_tab->rate.cell_log; + p->toks = p->burst = parm->burst; + p->mtu = parm->mtu; + if (p->mtu == 0) { + p->mtu = ~0; + if (p->R_tab) + p->mtu = 255<R_tab->rate.cell_log; } - if (police->tcfp_P_tab) - police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu); - PSCHED_GET_TIME(police->tcfp_t_c); - police->tcf_index = parm->index ? parm->index : - tcf_police_new_index(); - police->tcf_action = parm->action; + if (p->P_tab) + p->ptoks = L2T_P(p, p->mtu); + PSCHED_GET_TIME(p->t_c); + p->index = parm->index ? : tcf_police_new_index(); + p->action = parm->action; #ifdef CONFIG_NET_ESTIMATOR if (est) - gen_new_estimator(&police->tcf_bstats, &police->tcf_rate_est, - police->tcf_stats_lock, est); + gen_new_estimator(&p->bstats, &p->rate_est, p->stats_lock, est); #endif - h = tcf_hash(police->tcf_index, POL_TAB_MASK); + h = tcf_police_hash(p->index); write_lock_bh(&police_lock); - police->tcf_next = tcf_police_ht[h]; - tcf_police_ht[h] = &police->common; + p->next = tcf_police_ht[h]; + tcf_police_ht[h] = p; write_unlock_bh(&police_lock); - return police; + return p; failure: - if (police->tcfp_R_tab) - qdisc_put_rtab(police->tcfp_R_tab); - kfree(police); + if (p->R_tab) + qdisc_put_rtab(p->R_tab); + kfree(p); return NULL; } -int tcf_police(struct sk_buff *skb, struct tcf_police *police) +int tcf_police(struct sk_buff *skb, struct tcf_police *p) { psched_time_t now; long toks; long ptoks = 0; - spin_lock(&police->tcf_lock); + spin_lock(&p->lock); - police->tcf_bstats.bytes += skb->len; - police->tcf_bstats.packets++; + p->bstats.bytes += skb->len; + p->bstats.packets++; #ifdef CONFIG_NET_ESTIMATOR - if (police->tcfp_ewma_rate && - police->tcf_rate_est.bps >= police->tcfp_ewma_rate) { - police->tcf_qstats.overlimits++; - spin_unlock(&police->tcf_lock); - return police->tcf_action; + if (p->ewma_rate && p->rate_est.bps >= p->ewma_rate) { + p->qstats.overlimits++; + spin_unlock(&p->lock); + return p->action; } #endif - if (skb->len <= police->tcfp_mtu) { - if (police->tcfp_R_tab == NULL) { - spin_unlock(&police->tcf_lock); - return police->tcfp_result; + + if (skb->len <= p->mtu) { + if (p->R_tab == NULL) { + spin_unlock(&p->lock); + return p->result; } PSCHED_GET_TIME(now); - toks = PSCHED_TDIFF_SAFE(now, police->tcfp_t_c, - police->tcfp_burst); - if (police->tcfp_P_tab) { - ptoks = toks + police->tcfp_ptoks; - if (ptoks > (long)L2T_P(police, police->tcfp_mtu)) - ptoks = (long)L2T_P(police, police->tcfp_mtu); - ptoks -= L2T_P(police, skb->len); + + toks = PSCHED_TDIFF_SAFE(now, p->t_c, p->burst); + + if (p->P_tab) { + ptoks = toks + p->ptoks; + if (ptoks > (long)L2T_P(p, p->mtu)) + ptoks = (long)L2T_P(p, p->mtu); + ptoks -= L2T_P(p, skb->len); } - toks += police->tcfp_toks; - if (toks > (long)police->tcfp_burst) - toks = police->tcfp_burst; - toks -= L2T(police, skb->len); + toks += p->toks; + if (toks > (long)p->burst) + toks = p->burst; + toks -= L2T(p, skb->len); + if ((toks|ptoks) >= 0) { - police->tcfp_t_c = now; - police->tcfp_toks = toks; - police->tcfp_ptoks = ptoks; - spin_unlock(&police->tcf_lock); - return police->tcfp_result; + p->t_c = now; + p->toks = toks; + p->ptoks = ptoks; + spin_unlock(&p->lock); + return p->result; } } - police->tcf_qstats.overlimits++; - spin_unlock(&police->tcf_lock); - return police->tcf_action; + p->qstats.overlimits++; + spin_unlock(&p->lock); + return p->action; } EXPORT_SYMBOL(tcf_police); -int tcf_police_dump(struct sk_buff *skb, struct tcf_police *police) +int tcf_police_dump(struct sk_buff *skb, struct tcf_police *p) { - unsigned char *b = skb->tail; + unsigned char *b = skb->tail; struct tc_police opt; - opt.index = police->tcf_index; - opt.action = police->tcf_action; - opt.mtu = police->tcfp_mtu; - opt.burst = police->tcfp_burst; - if (police->tcfp_R_tab) - opt.rate = police->tcfp_R_tab->rate; + opt.index = p->index; + opt.action = p->action; + opt.mtu = p->mtu; + opt.burst = p->burst; + if (p->R_tab) + opt.rate = p->R_tab->rate; else memset(&opt.rate, 0, sizeof(opt.rate)); - if (police->tcfp_P_tab) - opt.peakrate = police->tcfp_P_tab->rate; + if (p->P_tab) + opt.peakrate = p->P_tab->rate; else memset(&opt.peakrate, 0, sizeof(opt.peakrate)); RTA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt); - if (police->tcfp_result) - RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), - &police->tcfp_result); + if (p->result) + RTA_PUT(skb, TCA_POLICE_RESULT, sizeof(int), &p->result); #ifdef CONFIG_NET_ESTIMATOR - if (police->tcfp_ewma_rate) - RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &police->tcfp_ewma_rate); + if (p->ewma_rate) + RTA_PUT(skb, TCA_POLICE_AVRATE, 4, &p->ewma_rate); #endif return skb->len; @@ -585,20 +574,19 @@ int tcf_police_dump(struct sk_buff *skb, struct tcf_police *police) return -1; } -int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *police) +int tcf_police_dump_stats(struct sk_buff *skb, struct tcf_police *p) { struct gnet_dump d; if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, - TCA_XSTATS, police->tcf_stats_lock, - &d) < 0) + TCA_XSTATS, p->stats_lock, &d) < 0) goto errout; - if (gnet_stats_copy_basic(&d, &police->tcf_bstats) < 0 || + if (gnet_stats_copy_basic(&d, &p->bstats) < 0 || #ifdef CONFIG_NET_ESTIMATOR - gnet_stats_copy_rate_est(&d, &police->tcf_rate_est) < 0 || + gnet_stats_copy_rate_est(&d, &p->rate_est) < 0 || #endif - gnet_stats_copy_queue(&d, &police->tcf_qstats) < 0) + gnet_stats_copy_queue(&d, &p->qstats) < 0) goto errout; if (gnet_stats_finish_copy(&d) < 0) diff --git a/trunk/net/sched/act_simple.c b/trunk/net/sched/act_simple.c index 901571a67707..17105c82537f 100644 --- a/trunk/net/sched/act_simple.c +++ b/trunk/net/sched/act_simple.c @@ -20,175 +20,54 @@ #define TCA_ACT_SIMP 22 +/* XXX: Hide all these common elements under some macro + * probably +*/ #include #include -#define SIMP_TAB_MASK 7 -static struct tcf_common *tcf_simp_ht[SIMP_TAB_MASK + 1]; -static u32 simp_idx_gen; +/* use generic hash table with 8 buckets */ +#define MY_TAB_SIZE 8 +#define MY_TAB_MASK (MY_TAB_SIZE - 1) +static u32 idx_gen; +static struct tcf_defact *tcf_simp_ht[MY_TAB_SIZE]; static DEFINE_RWLOCK(simp_lock); -static struct tcf_hashinfo simp_hash_info = { - .htab = tcf_simp_ht, - .hmask = SIMP_TAB_MASK, - .lock = &simp_lock, -}; +/* override the defaults */ +#define tcf_st tcf_defact +#define tc_st tc_defact +#define tcf_t_lock simp_lock +#define tcf_ht tcf_simp_ht + +#define CONFIG_NET_ACT_INIT 1 +#include +#include static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) { - struct tcf_defact *d = a->priv; + struct tcf_defact *p = PRIV(a, defact); - spin_lock(&d->tcf_lock); - d->tcf_tm.lastuse = jiffies; - d->tcf_bstats.bytes += skb->len; - d->tcf_bstats.packets++; + spin_lock(&p->lock); + p->tm.lastuse = jiffies; + p->bstats.bytes += skb->len; + p->bstats.packets++; /* print policy string followed by _ then packet count * Example if this was the 3rd packet and the string was "hello" * then it would look like "hello_3" (without quotes) **/ - printk("simple: %s_%d\n", - (char *)d->tcfd_defdata, d->tcf_bstats.packets); - spin_unlock(&d->tcf_lock); - return d->tcf_action; -} - -static int tcf_simp_release(struct tcf_defact *d, int bind) -{ - int ret = 0; - if (d) { - if (bind) - d->tcf_bindcnt--; - d->tcf_refcnt--; - if (d->tcf_bindcnt <= 0 && d->tcf_refcnt <= 0) { - kfree(d->tcfd_defdata); - tcf_hash_destroy(&d->common, &simp_hash_info); - ret = 1; - } - } - return ret; -} - -static int alloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata) -{ - d->tcfd_defdata = kmalloc(datalen, GFP_KERNEL); - if (unlikely(!d->tcfd_defdata)) - return -ENOMEM; - d->tcfd_datalen = datalen; - memcpy(d->tcfd_defdata, defdata, datalen); - return 0; -} - -static int realloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata) -{ - kfree(d->tcfd_defdata); - return alloc_defdata(d, datalen, defdata); -} - -static int tcf_simp_init(struct rtattr *rta, struct rtattr *est, - struct tc_action *a, int ovr, int bind) -{ - struct rtattr *tb[TCA_DEF_MAX]; - struct tc_defact *parm; - struct tcf_defact *d; - struct tcf_common *pc; - void *defdata; - u32 datalen = 0; - int ret = 0; - - if (rta == NULL || rtattr_parse_nested(tb, TCA_DEF_MAX, rta) < 0) - return -EINVAL; - - if (tb[TCA_DEF_PARMS - 1] == NULL || - RTA_PAYLOAD(tb[TCA_DEF_PARMS - 1]) < sizeof(*parm)) - return -EINVAL; - - parm = RTA_DATA(tb[TCA_DEF_PARMS - 1]); - defdata = RTA_DATA(tb[TCA_DEF_DATA - 1]); - if (defdata == NULL) - return -EINVAL; - - datalen = RTA_PAYLOAD(tb[TCA_DEF_DATA - 1]); - if (datalen <= 0) - return -EINVAL; - - pc = tcf_hash_check(parm->index, a, bind, &simp_hash_info); - if (!pc) { - pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind, - &simp_idx_gen, &simp_hash_info); - if (unlikely(!pc)) - return -ENOMEM; - - d = to_defact(pc); - ret = alloc_defdata(d, datalen, defdata); - if (ret < 0) { - kfree(pc); - return ret; - } - ret = ACT_P_CREATED; - } else { - d = to_defact(pc); - if (!ovr) { - tcf_simp_release(d, bind); - return -EEXIST; - } - realloc_defdata(d, datalen, defdata); - } - - spin_lock_bh(&d->tcf_lock); - d->tcf_action = parm->action; - spin_unlock_bh(&d->tcf_lock); - - if (ret == ACT_P_CREATED) - tcf_hash_insert(pc, &simp_hash_info); - return ret; -} - -static inline int tcf_simp_cleanup(struct tc_action *a, int bind) -{ - struct tcf_defact *d = a->priv; - - if (d) - return tcf_simp_release(d, bind); - return 0; -} - -static inline int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, - int bind, int ref) -{ - unsigned char *b = skb->tail; - struct tcf_defact *d = a->priv; - struct tc_defact opt; - struct tcf_t t; - - opt.index = d->tcf_index; - opt.refcnt = d->tcf_refcnt - ref; - opt.bindcnt = d->tcf_bindcnt - bind; - opt.action = d->tcf_action; - RTA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt); - RTA_PUT(skb, TCA_DEF_DATA, d->tcfd_datalen, d->tcfd_defdata); - t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install); - t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse); - t.expires = jiffies_to_clock_t(d->tcf_tm.expires); - RTA_PUT(skb, TCA_DEF_TM, sizeof(t), &t); - return skb->len; - -rtattr_failure: - skb_trim(skb, b - skb->data); - return -1; + printk("simple: %s_%d\n", (char *)p->defdata, p->bstats.packets); + spin_unlock(&p->lock); + return p->action; } static struct tc_action_ops act_simp_ops = { - .kind = "simple", - .hinfo = &simp_hash_info, - .type = TCA_ACT_SIMP, - .capab = TCA_CAP_NONE, - .owner = THIS_MODULE, - .act = tcf_simp, - .dump = tcf_simp_dump, - .cleanup = tcf_simp_cleanup, - .init = tcf_simp_init, - .walk = tcf_generic_walker, + .kind = "simple", + .type = TCA_ACT_SIMP, + .capab = TCA_CAP_NONE, + .owner = THIS_MODULE, + .act = tcf_simp, + tca_use_default_ops }; MODULE_AUTHOR("Jamal Hadi Salim(2005)"); diff --git a/trunk/net/sched/cls_fw.c b/trunk/net/sched/cls_fw.c index e54acc6bcccd..e6973d9b686d 100644 --- a/trunk/net/sched/cls_fw.c +++ b/trunk/net/sched/cls_fw.c @@ -50,7 +50,6 @@ struct fw_head { struct fw_filter *ht[HTSIZE]; - u32 mask; }; struct fw_filter @@ -102,7 +101,7 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp, struct fw_filter *f; int r; #ifdef CONFIG_NETFILTER - u32 id = skb->nfmark & head->mask; + u32 id = skb->nfmark; #else u32 id = 0; #endif @@ -210,9 +209,7 @@ static int fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f, struct rtattr **tb, struct rtattr **tca, unsigned long base) { - struct fw_head *head = (struct fw_head *)tp->root; struct tcf_exts e; - u32 mask; int err; err = tcf_exts_validate(tp, tb, tca[TCA_RATE-1], &e, &fw_ext_map); @@ -235,15 +232,6 @@ fw_change_attrs(struct tcf_proto *tp, struct fw_filter *f, } #endif /* CONFIG_NET_CLS_IND */ - if (tb[TCA_FW_MASK-1]) { - if (RTA_PAYLOAD(tb[TCA_FW_MASK-1]) != sizeof(u32)) - goto errout; - mask = *(u32*)RTA_DATA(tb[TCA_FW_MASK-1]); - if (mask != head->mask) - goto errout; - } else if (head->mask != 0xFFFFFFFF) - goto errout; - tcf_exts_change(tp, &f->exts, &e); return 0; @@ -279,17 +267,9 @@ static int fw_change(struct tcf_proto *tp, unsigned long base, return -EINVAL; if (head == NULL) { - u32 mask = 0xFFFFFFFF; - if (tb[TCA_FW_MASK-1]) { - if (RTA_PAYLOAD(tb[TCA_FW_MASK-1]) != sizeof(u32)) - return -EINVAL; - mask = *(u32*)RTA_DATA(tb[TCA_FW_MASK-1]); - } - head = kzalloc(sizeof(struct fw_head), GFP_KERNEL); if (head == NULL) return -ENOBUFS; - head->mask = mask; tcf_tree_lock(tp); tp->root = head; @@ -350,7 +330,6 @@ static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg) static int fw_dump(struct tcf_proto *tp, unsigned long fh, struct sk_buff *skb, struct tcmsg *t) { - struct fw_head *head = (struct fw_head *)tp->root; struct fw_filter *f = (struct fw_filter*)fh; unsigned char *b = skb->tail; struct rtattr *rta; @@ -372,8 +351,6 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh, if (strlen(f->indev)) RTA_PUT(skb, TCA_FW_INDEV, IFNAMSIZ, f->indev); #endif /* CONFIG_NET_CLS_IND */ - if (head->mask != 0xFFFFFFFF) - RTA_PUT(skb, TCA_FW_MASK, 4, &head->mask); if (tcf_exts_dump(skb, &f->exts, &fw_ext_map) < 0) goto rtattr_failure; diff --git a/trunk/net/sched/cls_u32.c b/trunk/net/sched/cls_u32.c index 0a6cfa0005be..eea366966740 100644 --- a/trunk/net/sched/cls_u32.c +++ b/trunk/net/sched/cls_u32.c @@ -796,7 +796,7 @@ static int __init init_u32(void) { printk("u32 classifier\n"); #ifdef CONFIG_CLS_U32_PERF - printk(" Performance counters on\n"); + printk(" Perfomance counters on\n"); #endif #ifdef CONFIG_NET_CLS_POLICE printk(" OLD policer on \n"); diff --git a/trunk/net/sched/sch_api.c b/trunk/net/sched/sch_api.c index a19eff12cf78..c7844bacbbcb 100644 --- a/trunk/net/sched/sch_api.c +++ b/trunk/net/sched/sch_api.c @@ -430,7 +430,7 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) } #endif - err = -ENOENT; + err = -EINVAL; if (ops == NULL) goto err_out; diff --git a/trunk/net/sched/sch_generic.c b/trunk/net/sched/sch_generic.c index 6f9151899795..0834c2ee9174 100644 --- a/trunk/net/sched/sch_generic.c +++ b/trunk/net/sched/sch_generic.c @@ -238,7 +238,9 @@ void __netdev_watchdog_up(struct net_device *dev) static void dev_watchdog_up(struct net_device *dev) { + netif_tx_lock_bh(dev); __netdev_watchdog_up(dev); + netif_tx_unlock_bh(dev); } static void dev_watchdog_down(struct net_device *dev) diff --git a/trunk/net/sched/sch_htb.c b/trunk/net/sched/sch_htb.c index bb3ddd4784b1..880a3394a51f 100644 --- a/trunk/net/sched/sch_htb.c +++ b/trunk/net/sched/sch_htb.c @@ -1,4 +1,4 @@ -/* +/* vim: ts=8 sw=8 * net/sched/sch_htb.c Hierarchical token bucket, feed tree version * * This program is free software; you can redistribute it and/or @@ -68,165 +68,218 @@ one less than their parent. */ -#define HTB_HSIZE 16 /* classid hash size */ -#define HTB_EWMAC 2 /* rate average over HTB_EWMAC*HTB_HSIZE sec */ -#define HTB_RATECM 1 /* whether to use rate computer */ -#define HTB_HYSTERESIS 1 /* whether to use mode hysteresis for speedup */ -#define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */ +#define HTB_HSIZE 16 /* classid hash size */ +#define HTB_EWMAC 2 /* rate average over HTB_EWMAC*HTB_HSIZE sec */ +#undef HTB_DEBUG /* compile debugging support (activated by tc tool) */ +#define HTB_RATECM 1 /* whether to use rate computer */ +#define HTB_HYSTERESIS 1/* whether to use mode hysteresis for speedup */ +#define HTB_QLOCK(S) spin_lock_bh(&(S)->dev->queue_lock) +#define HTB_QUNLOCK(S) spin_unlock_bh(&(S)->dev->queue_lock) +#define HTB_VER 0x30011 /* major must be matched with number suplied by TC as version */ #if HTB_VER >> 16 != TC_HTB_PROTOVER #error "Mismatched sch_htb.c and pkt_sch.h" #endif +/* debugging support; S is subsystem, these are defined: + 0 - netlink messages + 1 - enqueue + 2 - drop & requeue + 3 - dequeue main + 4 - dequeue one prio DRR part + 5 - dequeue class accounting + 6 - class overlimit status computation + 7 - hint tree + 8 - event queue + 10 - rate estimator + 11 - classifier + 12 - fast dequeue cache + + L is level; 0 = none, 1 = basic info, 2 = detailed, 3 = full + q->debug uint32 contains 16 2-bit fields one for subsystem starting + from LSB + */ +#ifdef HTB_DEBUG +#define HTB_DBG_COND(S,L) (((q->debug>>(2*S))&3) >= L) +#define HTB_DBG(S,L,FMT,ARG...) if (HTB_DBG_COND(S,L)) \ + printk(KERN_DEBUG FMT,##ARG) +#define HTB_CHCL(cl) BUG_TRAP((cl)->magic == HTB_CMAGIC) +#define HTB_PASSQ q, +#define HTB_ARGQ struct htb_sched *q, +#define static +#undef __inline__ +#define __inline__ +#undef inline +#define inline +#define HTB_CMAGIC 0xFEFAFEF1 +#define htb_safe_rb_erase(N,R) do { BUG_TRAP((N)->rb_color != -1); \ + if ((N)->rb_color == -1) break; \ + rb_erase(N,R); \ + (N)->rb_color = -1; } while (0) +#else +#define HTB_DBG_COND(S,L) (0) +#define HTB_DBG(S,L,FMT,ARG...) +#define HTB_PASSQ +#define HTB_ARGQ +#define HTB_CHCL(cl) +#define htb_safe_rb_erase(N,R) rb_erase(N,R) +#endif + + /* used internaly to keep status of single class */ enum htb_cmode { - HTB_CANT_SEND, /* class can't send and can't borrow */ - HTB_MAY_BORROW, /* class can't send but may borrow */ - HTB_CAN_SEND /* class can send */ + HTB_CANT_SEND, /* class can't send and can't borrow */ + HTB_MAY_BORROW, /* class can't send but may borrow */ + HTB_CAN_SEND /* class can send */ }; /* interior & leaf nodes; props specific to leaves are marked L: */ -struct htb_class { - /* general class parameters */ - u32 classid; - struct gnet_stats_basic bstats; - struct gnet_stats_queue qstats; - struct gnet_stats_rate_est rate_est; - struct tc_htb_xstats xstats; /* our special stats */ - int refcnt; /* usage count of this class */ +struct htb_class +{ +#ifdef HTB_DEBUG + unsigned magic; +#endif + /* general class parameters */ + u32 classid; + struct gnet_stats_basic bstats; + struct gnet_stats_queue qstats; + struct gnet_stats_rate_est rate_est; + struct tc_htb_xstats xstats;/* our special stats */ + int refcnt; /* usage count of this class */ #ifdef HTB_RATECM - /* rate measurement counters */ - unsigned long rate_bytes, sum_bytes; - unsigned long rate_packets, sum_packets; + /* rate measurement counters */ + unsigned long rate_bytes,sum_bytes; + unsigned long rate_packets,sum_packets; #endif - /* topology */ - int level; /* our level (see above) */ - struct htb_class *parent; /* parent class */ - struct hlist_node hlist; /* classid hash list item */ - struct list_head sibling; /* sibling list item */ - struct list_head children; /* children list */ - - union { - struct htb_class_leaf { - struct Qdisc *q; - int prio; - int aprio; - int quantum; - int deficit[TC_HTB_MAXDEPTH]; - struct list_head drop_list; - } leaf; - struct htb_class_inner { - struct rb_root feed[TC_HTB_NUMPRIO]; /* feed trees */ - struct rb_node *ptr[TC_HTB_NUMPRIO]; /* current class ptr */ - /* When class changes from state 1->2 and disconnects from - parent's feed then we lost ptr value and start from the - first child again. Here we store classid of the - last valid ptr (used when ptr is NULL). */ - u32 last_ptr_id[TC_HTB_NUMPRIO]; - } inner; - } un; - struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */ - struct rb_node pq_node; /* node for event queue */ - unsigned long pq_key; /* the same type as jiffies global */ - - int prio_activity; /* for which prios are we active */ - enum htb_cmode cmode; /* current mode of the class */ - - /* class attached filters */ - struct tcf_proto *filter_list; - int filter_cnt; - - int warned; /* only one warning about non work conserving .. */ - - /* token bucket parameters */ - struct qdisc_rate_table *rate; /* rate table of the class itself */ - struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */ - long buffer, cbuffer; /* token bucket depth/rate */ - psched_tdiff_t mbuffer; /* max wait time */ - long tokens, ctokens; /* current number of tokens */ - psched_time_t t_c; /* checkpoint time */ + /* topology */ + int level; /* our level (see above) */ + struct htb_class *parent; /* parent class */ + struct list_head hlist; /* classid hash list item */ + struct list_head sibling; /* sibling list item */ + struct list_head children; /* children list */ + + union { + struct htb_class_leaf { + struct Qdisc *q; + int prio; + int aprio; + int quantum; + int deficit[TC_HTB_MAXDEPTH]; + struct list_head drop_list; + } leaf; + struct htb_class_inner { + struct rb_root feed[TC_HTB_NUMPRIO]; /* feed trees */ + struct rb_node *ptr[TC_HTB_NUMPRIO]; /* current class ptr */ + /* When class changes from state 1->2 and disconnects from + parent's feed then we lost ptr value and start from the + first child again. Here we store classid of the + last valid ptr (used when ptr is NULL). */ + u32 last_ptr_id[TC_HTB_NUMPRIO]; + } inner; + } un; + struct rb_node node[TC_HTB_NUMPRIO]; /* node for self or feed tree */ + struct rb_node pq_node; /* node for event queue */ + unsigned long pq_key; /* the same type as jiffies global */ + + int prio_activity; /* for which prios are we active */ + enum htb_cmode cmode; /* current mode of the class */ + + /* class attached filters */ + struct tcf_proto *filter_list; + int filter_cnt; + + int warned; /* only one warning about non work conserving .. */ + + /* token bucket parameters */ + struct qdisc_rate_table *rate; /* rate table of the class itself */ + struct qdisc_rate_table *ceil; /* ceiling rate (limits borrows too) */ + long buffer,cbuffer; /* token bucket depth/rate */ + psched_tdiff_t mbuffer; /* max wait time */ + long tokens,ctokens; /* current number of tokens */ + psched_time_t t_c; /* checkpoint time */ }; /* TODO: maybe compute rate when size is too large .. or drop ? */ -static inline long L2T(struct htb_class *cl, struct qdisc_rate_table *rate, - int size) -{ - int slot = size >> rate->rate.cell_log; - if (slot > 255) { - cl->xstats.giants++; - slot = 255; - } - return rate->data[slot]; +static __inline__ long L2T(struct htb_class *cl,struct qdisc_rate_table *rate, + int size) +{ + int slot = size >> rate->rate.cell_log; + if (slot > 255) { + cl->xstats.giants++; + slot = 255; + } + return rate->data[slot]; } -struct htb_sched { - struct list_head root; /* root classes list */ - struct hlist_head hash[HTB_HSIZE]; /* hashed by classid */ - struct list_head drops[TC_HTB_NUMPRIO];/* active leaves (for drops) */ - - /* self list - roots of self generating tree */ - struct rb_root row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; - int row_mask[TC_HTB_MAXDEPTH]; - struct rb_node *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; - u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; - - /* self wait list - roots of wait PQs per row */ - struct rb_root wait_pq[TC_HTB_MAXDEPTH]; - - /* time of nearest event per level (row) */ - unsigned long near_ev_cache[TC_HTB_MAXDEPTH]; - - /* cached value of jiffies in dequeue */ - unsigned long jiffies; - - /* whether we hit non-work conserving class during this dequeue; we use */ - int nwc_hit; /* this to disable mindelay complaint in dequeue */ - - int defcls; /* class where unclassified flows go to */ - - /* filters for qdisc itself */ - struct tcf_proto *filter_list; - int filter_cnt; - - int rate2quantum; /* quant = rate / rate2quantum */ - psched_time_t now; /* cached dequeue time */ - struct timer_list timer; /* send delay timer */ +struct htb_sched +{ + struct list_head root; /* root classes list */ + struct list_head hash[HTB_HSIZE]; /* hashed by classid */ + struct list_head drops[TC_HTB_NUMPRIO]; /* active leaves (for drops) */ + + /* self list - roots of self generating tree */ + struct rb_root row[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; + int row_mask[TC_HTB_MAXDEPTH]; + struct rb_node *ptr[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; + u32 last_ptr_id[TC_HTB_MAXDEPTH][TC_HTB_NUMPRIO]; + + /* self wait list - roots of wait PQs per row */ + struct rb_root wait_pq[TC_HTB_MAXDEPTH]; + + /* time of nearest event per level (row) */ + unsigned long near_ev_cache[TC_HTB_MAXDEPTH]; + + /* cached value of jiffies in dequeue */ + unsigned long jiffies; + + /* whether we hit non-work conserving class during this dequeue; we use */ + int nwc_hit; /* this to disable mindelay complaint in dequeue */ + + int defcls; /* class where unclassified flows go to */ + u32 debug; /* subsystem debug levels */ + + /* filters for qdisc itself */ + struct tcf_proto *filter_list; + int filter_cnt; + + int rate2quantum; /* quant = rate / rate2quantum */ + psched_time_t now; /* cached dequeue time */ + struct timer_list timer; /* send delay timer */ #ifdef HTB_RATECM - struct timer_list rttim; /* rate computer timer */ - int recmp_bucket; /* which hash bucket to recompute next */ + struct timer_list rttim; /* rate computer timer */ + int recmp_bucket; /* which hash bucket to recompute next */ #endif + + /* non shaped skbs; let them go directly thru */ + struct sk_buff_head direct_queue; + int direct_qlen; /* max qlen of above */ - /* non shaped skbs; let them go directly thru */ - struct sk_buff_head direct_queue; - int direct_qlen; /* max qlen of above */ - - long direct_pkts; + long direct_pkts; }; /* compute hash of size HTB_HSIZE for given handle */ -static inline int htb_hash(u32 h) +static __inline__ int htb_hash(u32 h) { #if HTB_HSIZE != 16 -#error "Declare new hash for your HTB_HSIZE" + #error "Declare new hash for your HTB_HSIZE" #endif - h ^= h >> 8; /* stolen from cbq_hash */ - h ^= h >> 4; - return h & 0xf; + h ^= h>>8; /* stolen from cbq_hash */ + h ^= h>>4; + return h & 0xf; } /* find class in global hash table using given handle */ -static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch) +static __inline__ struct htb_class *htb_find(u32 handle, struct Qdisc *sch) { struct htb_sched *q = qdisc_priv(sch); - struct hlist_node *p; - struct htb_class *cl; - - if (TC_H_MAJ(handle) != sch->handle) + struct list_head *p; + if (TC_H_MAJ(handle) != sch->handle) return NULL; - - hlist_for_each_entry(cl, p, q->hash + htb_hash(handle), hlist) { + + list_for_each (p,q->hash+htb_hash(handle)) { + struct htb_class *cl = list_entry(p,struct htb_class,hlist); if (cl->classid == handle) return cl; } @@ -251,8 +304,7 @@ static inline u32 htb_classid(struct htb_class *cl) return (cl && cl != HTB_DIRECT) ? cl->classid : TC_H_UNSPEC; } -static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, - int *qerr) +static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) { struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl; @@ -264,8 +316,8 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, note that nfmark can be used too by attaching filter fw with no rules in it */ if (skb->priority == sch->handle) - return HTB_DIRECT; /* X:0 (direct flow) selected */ - if ((cl = htb_find(skb->priority, sch)) != NULL && cl->level == 0) + return HTB_DIRECT; /* X:0 (direct flow) selected */ + if ((cl = htb_find(skb->priority,sch)) != NULL && cl->level == 0) return cl; *qerr = NET_XMIT_BYPASS; @@ -274,7 +326,7 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, #ifdef CONFIG_NET_CLS_ACT switch (result) { case TC_ACT_QUEUED: - case TC_ACT_STOLEN: + case TC_ACT_STOLEN: *qerr = NET_XMIT_SUCCESS; case TC_ACT_SHOT: return NULL; @@ -283,44 +335,97 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, if (result == TC_POLICE_SHOT) return HTB_DIRECT; #endif - if ((cl = (void *)res.class) == NULL) { + if ((cl = (void*)res.class) == NULL) { if (res.classid == sch->handle) - return HTB_DIRECT; /* X:0 (direct flow) */ - if ((cl = htb_find(res.classid, sch)) == NULL) - break; /* filter selected invalid classid */ + return HTB_DIRECT; /* X:0 (direct flow) */ + if ((cl = htb_find(res.classid,sch)) == NULL) + break; /* filter selected invalid classid */ } if (!cl->level) - return cl; /* we hit leaf; return it */ + return cl; /* we hit leaf; return it */ /* we have got inner class; apply inner filter chain */ tcf = cl->filter_list; } /* classification failed; try to use default class */ - cl = htb_find(TC_H_MAKE(TC_H_MAJ(sch->handle), q->defcls), sch); + cl = htb_find(TC_H_MAKE(TC_H_MAJ(sch->handle),q->defcls),sch); if (!cl || cl->level) - return HTB_DIRECT; /* bad default .. this is safe bet */ + return HTB_DIRECT; /* bad default .. this is safe bet */ return cl; } +#ifdef HTB_DEBUG +static void htb_next_rb_node(struct rb_node **n); +#define HTB_DUMTREE(root,memb) if(root) { \ + struct rb_node *n = (root)->rb_node; \ + while (n->rb_left) n = n->rb_left; \ + while (n) { \ + struct htb_class *cl = rb_entry(n, struct htb_class, memb); \ + printk(" %x",cl->classid); htb_next_rb_node (&n); \ + } } + +static void htb_debug_dump (struct htb_sched *q) +{ + int i,p; + printk(KERN_DEBUG "htb*g j=%lu lj=%lu\n",jiffies,q->jiffies); + /* rows */ + for (i=TC_HTB_MAXDEPTH-1;i>=0;i--) { + printk(KERN_DEBUG "htb*r%d m=%x",i,q->row_mask[i]); + for (p=0;prow[i][p].rb_node) continue; + printk(" p%d:",p); + HTB_DUMTREE(q->row[i]+p,node[p]); + } + printk("\n"); + } + /* classes */ + for (i = 0; i < HTB_HSIZE; i++) { + struct list_head *l; + list_for_each (l,q->hash+i) { + struct htb_class *cl = list_entry(l,struct htb_class,hlist); + long diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32)cl->mbuffer); + printk(KERN_DEBUG "htb*c%x m=%d t=%ld c=%ld pq=%lu df=%ld ql=%d " + "pa=%x f:", + cl->classid,cl->cmode,cl->tokens,cl->ctokens, + cl->pq_node.rb_color==-1?0:cl->pq_key,diff, + cl->level?0:cl->un.leaf.q->q.qlen,cl->prio_activity); + if (cl->level) + for (p=0;pun.inner.feed[p].rb_node) continue; + printk(" p%d a=%x:",p,cl->un.inner.ptr[p]?rb_entry(cl->un.inner.ptr[p], struct htb_class,node[p])->classid:0); + HTB_DUMTREE(cl->un.inner.feed+p,node[p]); + } + printk("\n"); + } + } +} +#endif /** * htb_add_to_id_tree - adds class to the round robin list * * Routine adds class to the list (actually tree) sorted by classid. * Make sure that class is not already on such list for given prio. */ -static void htb_add_to_id_tree(struct rb_root *root, - struct htb_class *cl, int prio) +static void htb_add_to_id_tree (HTB_ARGQ struct rb_root *root, + struct htb_class *cl,int prio) { struct rb_node **p = &root->rb_node, *parent = NULL; - + HTB_DBG(7,3,"htb_add_id_tree cl=%X prio=%d\n",cl->classid,prio); +#ifdef HTB_DEBUG + if (cl->node[prio].rb_color != -1) { BUG_TRAP(0); return; } + HTB_CHCL(cl); + if (*p) { + struct htb_class *x = rb_entry(*p,struct htb_class,node[prio]); + HTB_CHCL(x); + } +#endif while (*p) { - struct htb_class *c; - parent = *p; + struct htb_class *c; parent = *p; c = rb_entry(parent, struct htb_class, node[prio]); - + HTB_CHCL(c); if (cl->classid > c->classid) p = &parent->rb_right; - else + else p = &parent->rb_left; } rb_link_node(&cl->node[prio], parent, p); @@ -334,11 +439,17 @@ static void htb_add_to_id_tree(struct rb_root *root, * change its mode in cl->pq_key microseconds. Make sure that class is not * already in the queue. */ -static void htb_add_to_wait_tree(struct htb_sched *q, - struct htb_class *cl, long delay) +static void htb_add_to_wait_tree (struct htb_sched *q, + struct htb_class *cl,long delay,int debug_hint) { struct rb_node **p = &q->wait_pq[cl->level].rb_node, *parent = NULL; - + HTB_DBG(7,3,"htb_add_wt cl=%X key=%lu\n",cl->classid,cl->pq_key); +#ifdef HTB_DEBUG + if (cl->pq_node.rb_color != -1) { BUG_TRAP(0); return; } + HTB_CHCL(cl); + if ((delay <= 0 || delay > cl->mbuffer) && net_ratelimit()) + printk(KERN_ERR "HTB: suspicious delay in wait_tree d=%ld cl=%X h=%d\n",delay,cl->classid,debug_hint); +#endif cl->pq_key = q->jiffies + PSCHED_US2JIFFIE(delay); if (cl->pq_key == q->jiffies) cl->pq_key++; @@ -346,14 +457,13 @@ static void htb_add_to_wait_tree(struct htb_sched *q, /* update the nearest event cache */ if (time_after(q->near_ev_cache[cl->level], cl->pq_key)) q->near_ev_cache[cl->level] = cl->pq_key; - + while (*p) { - struct htb_class *c; - parent = *p; + struct htb_class *c; parent = *p; c = rb_entry(parent, struct htb_class, pq_node); if (time_after_eq(cl->pq_key, c->pq_key)) p = &parent->rb_right; - else + else p = &parent->rb_left; } rb_link_node(&cl->pq_node, parent, p); @@ -366,7 +476,7 @@ static void htb_add_to_wait_tree(struct htb_sched *q, * When we are past last key we return NULL. * Average complexity is 2 steps per call. */ -static inline void htb_next_rb_node(struct rb_node **n) +static void htb_next_rb_node(struct rb_node **n) { *n = rb_next(*n); } @@ -377,51 +487,42 @@ static inline void htb_next_rb_node(struct rb_node **n) * The class is added to row at priorities marked in mask. * It does nothing if mask == 0. */ -static inline void htb_add_class_to_row(struct htb_sched *q, - struct htb_class *cl, int mask) +static inline void htb_add_class_to_row(struct htb_sched *q, + struct htb_class *cl,int mask) { + HTB_DBG(7,2,"htb_addrow cl=%X mask=%X rmask=%X\n", + cl->classid,mask,q->row_mask[cl->level]); + HTB_CHCL(cl); q->row_mask[cl->level] |= mask; while (mask) { int prio = ffz(~mask); mask &= ~(1 << prio); - htb_add_to_id_tree(q->row[cl->level] + prio, cl, prio); - } -} - -/* If this triggers, it is a bug in this code, but it need not be fatal */ -static void htb_safe_rb_erase(struct rb_node *rb, struct rb_root *root) -{ - if (RB_EMPTY_NODE(rb)) { - WARN_ON(1); - } else { - rb_erase(rb, root); - RB_CLEAR_NODE(rb); + htb_add_to_id_tree(HTB_PASSQ q->row[cl->level]+prio,cl,prio); } } - /** * htb_remove_class_from_row - removes class from its row * * The class is removed from row at priorities marked in mask. * It does nothing if mask == 0. */ -static inline void htb_remove_class_from_row(struct htb_sched *q, - struct htb_class *cl, int mask) +static __inline__ void htb_remove_class_from_row(struct htb_sched *q, + struct htb_class *cl,int mask) { int m = 0; - + HTB_CHCL(cl); while (mask) { int prio = ffz(~mask); - mask &= ~(1 << prio); - if (q->ptr[cl->level][prio] == cl->node + prio) - htb_next_rb_node(q->ptr[cl->level] + prio); - - htb_safe_rb_erase(cl->node + prio, q->row[cl->level] + prio); - if (!q->row[cl->level][prio].rb_node) + if (q->ptr[cl->level][prio] == cl->node+prio) + htb_next_rb_node(q->ptr[cl->level]+prio); + htb_safe_rb_erase(cl->node + prio,q->row[cl->level]+prio); + if (!q->row[cl->level][prio].rb_node) m |= 1 << prio; } + HTB_DBG(7,2,"htb_delrow cl=%X mask=%X rmask=%X maskdel=%X\n", + cl->classid,mask,q->row_mask[cl->level],m); q->row_mask[cl->level] &= ~m; } @@ -432,31 +533,34 @@ static inline void htb_remove_class_from_row(struct htb_sched *q, * for priorities it is participating on. cl->cmode must be new * (activated) mode. It does nothing if cl->prio_activity == 0. */ -static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl) +static void htb_activate_prios(struct htb_sched *q,struct htb_class *cl) { struct htb_class *p = cl->parent; - long m, mask = cl->prio_activity; + long m,mask = cl->prio_activity; + HTB_DBG(7,2,"htb_act_prios cl=%X mask=%lX cmode=%d\n",cl->classid,mask,cl->cmode); + HTB_CHCL(cl); while (cl->cmode == HTB_MAY_BORROW && p && mask) { - m = mask; - while (m) { + HTB_CHCL(p); + m = mask; while (m) { int prio = ffz(~m); m &= ~(1 << prio); - + if (p->un.inner.feed[prio].rb_node) /* parent already has its feed in use so that reset bit in mask as parent is already ok */ mask &= ~(1 << prio); - - htb_add_to_id_tree(p->un.inner.feed + prio, cl, prio); + + htb_add_to_id_tree(HTB_PASSQ p->un.inner.feed+prio,cl,prio); } + HTB_DBG(7,3,"htb_act_pr_aft p=%X pact=%X mask=%lX pmode=%d\n", + p->classid,p->prio_activity,mask,p->cmode); p->prio_activity |= mask; - cl = p; - p = cl->parent; - + cl = p; p = cl->parent; + HTB_CHCL(cl); } if (cl->cmode == HTB_CAN_SEND && mask) - htb_add_class_to_row(q, cl, mask); + htb_add_class_to_row(q,cl,mask); } /** @@ -469,52 +573,39 @@ static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl) static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl) { struct htb_class *p = cl->parent; - long m, mask = cl->prio_activity; + long m,mask = cl->prio_activity; + HTB_DBG(7,2,"htb_deact_prios cl=%X mask=%lX cmode=%d\n",cl->classid,mask,cl->cmode); + HTB_CHCL(cl); while (cl->cmode == HTB_MAY_BORROW && p && mask) { - m = mask; - mask = 0; + m = mask; mask = 0; while (m) { int prio = ffz(~m); m &= ~(1 << prio); - - if (p->un.inner.ptr[prio] == cl->node + prio) { + + if (p->un.inner.ptr[prio] == cl->node+prio) { /* we are removing child which is pointed to from parent feed - forget the pointer but remember classid */ p->un.inner.last_ptr_id[prio] = cl->classid; p->un.inner.ptr[prio] = NULL; } - - htb_safe_rb_erase(cl->node + prio, p->un.inner.feed + prio); - - if (!p->un.inner.feed[prio].rb_node) + + htb_safe_rb_erase(cl->node + prio,p->un.inner.feed + prio); + + if (!p->un.inner.feed[prio].rb_node) mask |= 1 << prio; } - + HTB_DBG(7,3,"htb_deact_pr_aft p=%X pact=%X mask=%lX pmode=%d\n", + p->classid,p->prio_activity,mask,p->cmode); p->prio_activity &= ~mask; - cl = p; - p = cl->parent; - + cl = p; p = cl->parent; + HTB_CHCL(cl); } - if (cl->cmode == HTB_CAN_SEND && mask) - htb_remove_class_from_row(q, cl, mask); + if (cl->cmode == HTB_CAN_SEND && mask) + htb_remove_class_from_row(q,cl,mask); } -#if HTB_HYSTERESIS -static inline long htb_lowater(const struct htb_class *cl) -{ - return cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : 0; -} -static inline long htb_hiwater(const struct htb_class *cl) -{ - return cl->cmode == HTB_CAN_SEND ? -cl->buffer : 0; -} -#else -#define htb_lowater(cl) (0) -#define htb_hiwater(cl) (0) -#endif - /** * htb_class_mode - computes and returns current class mode * @@ -526,21 +617,28 @@ static inline long htb_hiwater(const struct htb_class *cl) * 0 .. -cl->{c,}buffer range. It is meant to limit number of * mode transitions per time unit. The speed gain is about 1/6. */ -static inline enum htb_cmode -htb_class_mode(struct htb_class *cl, long *diff) +static __inline__ enum htb_cmode +htb_class_mode(struct htb_class *cl,long *diff) { - long toks; - - if ((toks = (cl->ctokens + *diff)) < htb_lowater(cl)) { - *diff = -toks; - return HTB_CANT_SEND; - } + long toks; - if ((toks = (cl->tokens + *diff)) >= htb_hiwater(cl)) - return HTB_CAN_SEND; + if ((toks = (cl->ctokens + *diff)) < ( +#if HTB_HYSTERESIS + cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : +#endif + 0)) { + *diff = -toks; + return HTB_CANT_SEND; + } + if ((toks = (cl->tokens + *diff)) >= ( +#if HTB_HYSTERESIS + cl->cmode == HTB_CAN_SEND ? -cl->buffer : +#endif + 0)) + return HTB_CAN_SEND; - *diff = -toks; - return HTB_MAY_BORROW; + *diff = -toks; + return HTB_MAY_BORROW; } /** @@ -552,21 +650,24 @@ htb_class_mode(struct htb_class *cl, long *diff) * be different from old one and cl->pq_key has to be valid if changing * to mode other than HTB_CAN_SEND (see htb_add_to_wait_tree). */ -static void +static void htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long *diff) -{ - enum htb_cmode new_mode = htb_class_mode(cl, diff); +{ + enum htb_cmode new_mode = htb_class_mode(cl,diff); + + HTB_CHCL(cl); + HTB_DBG(7,1,"htb_chging_clmode %d->%d cl=%X\n",cl->cmode,new_mode,cl->classid); if (new_mode == cl->cmode) - return; - - if (cl->prio_activity) { /* not necessary: speed optimization */ - if (cl->cmode != HTB_CANT_SEND) - htb_deactivate_prios(q, cl); + return; + + if (cl->prio_activity) { /* not necessary: speed optimization */ + if (cl->cmode != HTB_CANT_SEND) + htb_deactivate_prios(q,cl); cl->cmode = new_mode; - if (new_mode != HTB_CANT_SEND) - htb_activate_prios(q, cl); - } else + if (new_mode != HTB_CANT_SEND) + htb_activate_prios(q,cl); + } else cl->cmode = new_mode; } @@ -577,15 +678,14 @@ htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long *diff) * for the prio. It can be called on already active leaf safely. * It also adds leaf into droplist. */ -static inline void htb_activate(struct htb_sched *q, struct htb_class *cl) +static __inline__ void htb_activate(struct htb_sched *q,struct htb_class *cl) { BUG_TRAP(!cl->level && cl->un.leaf.q && cl->un.leaf.q->q.qlen); - + HTB_CHCL(cl); if (!cl->prio_activity) { cl->prio_activity = 1 << (cl->un.leaf.aprio = cl->un.leaf.prio); - htb_activate_prios(q, cl); - list_add_tail(&cl->un.leaf.drop_list, - q->drops + cl->un.leaf.aprio); + htb_activate_prios(q,cl); + list_add_tail(&cl->un.leaf.drop_list,q->drops+cl->un.leaf.aprio); } } @@ -595,120 +695,120 @@ static inline void htb_activate(struct htb_sched *q, struct htb_class *cl) * Make sure that leaf is active. In the other words it can't be called * with non-active leaf. It also removes class from the drop list. */ -static inline void htb_deactivate(struct htb_sched *q, struct htb_class *cl) +static __inline__ void +htb_deactivate(struct htb_sched *q,struct htb_class *cl) { BUG_TRAP(cl->prio_activity); - - htb_deactivate_prios(q, cl); + HTB_CHCL(cl); + htb_deactivate_prios(q,cl); cl->prio_activity = 0; list_del_init(&cl->un.leaf.drop_list); } static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) { - int ret; - struct htb_sched *q = qdisc_priv(sch); - struct htb_class *cl = htb_classify(skb, sch, &ret); - - if (cl == HTB_DIRECT) { - /* enqueue to helper queue */ - if (q->direct_queue.qlen < q->direct_qlen) { - __skb_queue_tail(&q->direct_queue, skb); - q->direct_pkts++; - } else { - kfree_skb(skb); - sch->qstats.drops++; - return NET_XMIT_DROP; - } -#ifdef CONFIG_NET_CLS_ACT - } else if (!cl) { - if (ret == NET_XMIT_BYPASS) - sch->qstats.drops++; - kfree_skb(skb); - return ret; -#endif - } else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) != - NET_XMIT_SUCCESS) { - sch->qstats.drops++; - cl->qstats.drops++; - return NET_XMIT_DROP; + int ret; + struct htb_sched *q = qdisc_priv(sch); + struct htb_class *cl = htb_classify(skb,sch,&ret); + + if (cl == HTB_DIRECT) { + /* enqueue to helper queue */ + if (q->direct_queue.qlen < q->direct_qlen) { + __skb_queue_tail(&q->direct_queue, skb); + q->direct_pkts++; } else { - cl->bstats.packets++; - cl->bstats.bytes += skb->len; - htb_activate(q, cl); + kfree_skb(skb); + sch->qstats.drops++; + return NET_XMIT_DROP; } - - sch->q.qlen++; - sch->bstats.packets++; - sch->bstats.bytes += skb->len; - return NET_XMIT_SUCCESS; +#ifdef CONFIG_NET_CLS_ACT + } else if (!cl) { + if (ret == NET_XMIT_BYPASS) + sch->qstats.drops++; + kfree_skb (skb); + return ret; +#endif + } else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) { + sch->qstats.drops++; + cl->qstats.drops++; + return NET_XMIT_DROP; + } else { + cl->bstats.packets++; cl->bstats.bytes += skb->len; + htb_activate (q,cl); + } + + sch->q.qlen++; + sch->bstats.packets++; sch->bstats.bytes += skb->len; + HTB_DBG(1,1,"htb_enq_ok cl=%X skb=%p\n",(cl && cl != HTB_DIRECT)?cl->classid:0,skb); + return NET_XMIT_SUCCESS; } /* TODO: requeuing packet charges it to policers again !! */ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) { - struct htb_sched *q = qdisc_priv(sch); - int ret = NET_XMIT_SUCCESS; - struct htb_class *cl = htb_classify(skb, sch, &ret); - struct sk_buff *tskb; - - if (cl == HTB_DIRECT || !cl) { - /* enqueue to helper queue */ - if (q->direct_queue.qlen < q->direct_qlen && cl) { - __skb_queue_head(&q->direct_queue, skb); - } else { - __skb_queue_head(&q->direct_queue, skb); - tskb = __skb_dequeue_tail(&q->direct_queue); - kfree_skb(tskb); - sch->qstats.drops++; - return NET_XMIT_CN; - } - } else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) != - NET_XMIT_SUCCESS) { - sch->qstats.drops++; - cl->qstats.drops++; - return NET_XMIT_DROP; - } else - htb_activate(q, cl); - - sch->q.qlen++; - sch->qstats.requeues++; - return NET_XMIT_SUCCESS; + struct htb_sched *q = qdisc_priv(sch); + int ret = NET_XMIT_SUCCESS; + struct htb_class *cl = htb_classify(skb,sch, &ret); + struct sk_buff *tskb; + + if (cl == HTB_DIRECT || !cl) { + /* enqueue to helper queue */ + if (q->direct_queue.qlen < q->direct_qlen && cl) { + __skb_queue_head(&q->direct_queue, skb); + } else { + __skb_queue_head(&q->direct_queue, skb); + tskb = __skb_dequeue_tail(&q->direct_queue); + kfree_skb (tskb); + sch->qstats.drops++; + return NET_XMIT_CN; + } + } else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) { + sch->qstats.drops++; + cl->qstats.drops++; + return NET_XMIT_DROP; + } else + htb_activate (q,cl); + + sch->q.qlen++; + sch->qstats.requeues++; + HTB_DBG(1,1,"htb_req_ok cl=%X skb=%p\n",(cl && cl != HTB_DIRECT)?cl->classid:0,skb); + return NET_XMIT_SUCCESS; } static void htb_timer(unsigned long arg) { - struct Qdisc *sch = (struct Qdisc *)arg; - sch->flags &= ~TCQ_F_THROTTLED; - wmb(); - netif_schedule(sch->dev); + struct Qdisc *sch = (struct Qdisc*)arg; + sch->flags &= ~TCQ_F_THROTTLED; + wmb(); + netif_schedule(sch->dev); } #ifdef HTB_RATECM #define RT_GEN(D,R) R+=D-(R/HTB_EWMAC);D=0 static void htb_rate_timer(unsigned long arg) { - struct Qdisc *sch = (struct Qdisc *)arg; + struct Qdisc *sch = (struct Qdisc*)arg; struct htb_sched *q = qdisc_priv(sch); - struct hlist_node *p; - struct htb_class *cl; - + struct list_head *p; /* lock queue so that we can muck with it */ - spin_lock_bh(&sch->dev->queue_lock); + HTB_QLOCK(sch); + HTB_DBG(10,1,"htb_rttmr j=%ld\n",jiffies); q->rttim.expires = jiffies + HZ; add_timer(&q->rttim); /* scan and recompute one bucket at time */ - if (++q->recmp_bucket >= HTB_HSIZE) + if (++q->recmp_bucket >= HTB_HSIZE) q->recmp_bucket = 0; - - hlist_for_each_entry(cl,p, q->hash + q->recmp_bucket, hlist) { - RT_GEN(cl->sum_bytes, cl->rate_bytes); - RT_GEN(cl->sum_packets, cl->rate_packets); + list_for_each (p,q->hash+q->recmp_bucket) { + struct htb_class *cl = list_entry(p,struct htb_class,hlist); + HTB_DBG(10,2,"htb_rttmr_cl cl=%X sbyte=%lu spkt=%lu\n", + cl->classid,cl->sum_bytes,cl->sum_packets); + RT_GEN (cl->sum_bytes,cl->rate_bytes); + RT_GEN (cl->sum_packets,cl->rate_packets); } - spin_unlock_bh(&sch->dev->queue_lock); + HTB_QUNLOCK(sch); } #endif @@ -723,11 +823,12 @@ static void htb_rate_timer(unsigned long arg) * CAN_SEND) because we can use more precise clock that event queue here. * In such case we remove class from event queue first. */ -static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, - int level, int bytes) -{ - long toks, diff; +static void htb_charge_class(struct htb_sched *q,struct htb_class *cl, + int level,int bytes) +{ + long toks,diff; enum htb_cmode old_mode; + HTB_DBG(5,1,"htb_chrg_cl cl=%X lev=%d len=%d\n",cl->classid,level,bytes); #define HTB_ACCNT(T,B,R) toks = diff + cl->T; \ if (toks > cl->B) toks = cl->B; \ @@ -736,31 +837,47 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, cl->T = toks while (cl) { - diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32) cl->mbuffer); + HTB_CHCL(cl); + diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32)cl->mbuffer); +#ifdef HTB_DEBUG + if (diff > cl->mbuffer || diff < 0 || PSCHED_TLESS(q->now, cl->t_c)) { + if (net_ratelimit()) + printk(KERN_ERR "HTB: bad diff in charge, cl=%X diff=%lX now=%Lu then=%Lu j=%lu\n", + cl->classid, diff, +#ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY + q->now.tv_sec * 1000000ULL + q->now.tv_usec, + cl->t_c.tv_sec * 1000000ULL + cl->t_c.tv_usec, +#else + (unsigned long long) q->now, + (unsigned long long) cl->t_c, +#endif + q->jiffies); + diff = 1000; + } +#endif if (cl->level >= level) { - if (cl->level == level) - cl->xstats.lends++; - HTB_ACCNT(tokens, buffer, rate); + if (cl->level == level) cl->xstats.lends++; + HTB_ACCNT (tokens,buffer,rate); } else { cl->xstats.borrows++; - cl->tokens += diff; /* we moved t_c; update tokens */ + cl->tokens += diff; /* we moved t_c; update tokens */ } - HTB_ACCNT(ctokens, cbuffer, ceil); + HTB_ACCNT (ctokens,cbuffer,ceil); cl->t_c = q->now; + HTB_DBG(5,2,"htb_chrg_clp cl=%X diff=%ld tok=%ld ctok=%ld\n",cl->classid,diff,cl->tokens,cl->ctokens); - old_mode = cl->cmode; - diff = 0; - htb_change_class_mode(q, cl, &diff); + old_mode = cl->cmode; diff = 0; + htb_change_class_mode(q,cl,&diff); if (old_mode != cl->cmode) { if (old_mode != HTB_CAN_SEND) - htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level); + htb_safe_rb_erase(&cl->pq_node,q->wait_pq+cl->level); if (cl->cmode != HTB_CAN_SEND) - htb_add_to_wait_tree(q, cl, diff); + htb_add_to_wait_tree (q,cl,diff,1); } + #ifdef HTB_RATECM /* update rate counters */ - cl->sum_bytes += bytes; - cl->sum_packets++; + cl->sum_bytes += bytes; cl->sum_packets++; #endif /* update byte stats except for leaves which are already updated */ @@ -779,46 +896,60 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, * next pending event (0 for no event in pq). * Note: Aplied are events whose have cl->pq_key <= jiffies. */ -static long htb_do_events(struct htb_sched *q, int level) +static long htb_do_events(struct htb_sched *q,int level) { int i; - + HTB_DBG(8,1,"htb_do_events l=%d root=%p rmask=%X\n", + level,q->wait_pq[level].rb_node,q->row_mask[level]); for (i = 0; i < 500; i++) { struct htb_class *cl; long diff; struct rb_node *p = q->wait_pq[level].rb_node; - if (!p) - return 0; - while (p->rb_left) - p = p->rb_left; + if (!p) return 0; + while (p->rb_left) p = p->rb_left; cl = rb_entry(p, struct htb_class, pq_node); if (time_after(cl->pq_key, q->jiffies)) { + HTB_DBG(8,3,"htb_do_ev_ret delay=%ld\n",cl->pq_key - q->jiffies); return cl->pq_key - q->jiffies; } - htb_safe_rb_erase(p, q->wait_pq + level); - diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32) cl->mbuffer); - htb_change_class_mode(q, cl, &diff); + htb_safe_rb_erase(p,q->wait_pq+level); + diff = PSCHED_TDIFF_SAFE(q->now, cl->t_c, (u32)cl->mbuffer); +#ifdef HTB_DEBUG + if (diff > cl->mbuffer || diff < 0 || PSCHED_TLESS(q->now, cl->t_c)) { + if (net_ratelimit()) + printk(KERN_ERR "HTB: bad diff in events, cl=%X diff=%lX now=%Lu then=%Lu j=%lu\n", + cl->classid, diff, +#ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY + q->now.tv_sec * 1000000ULL + q->now.tv_usec, + cl->t_c.tv_sec * 1000000ULL + cl->t_c.tv_usec, +#else + (unsigned long long) q->now, + (unsigned long long) cl->t_c, +#endif + q->jiffies); + diff = 1000; + } +#endif + htb_change_class_mode(q,cl,&diff); if (cl->cmode != HTB_CAN_SEND) - htb_add_to_wait_tree(q, cl, diff); + htb_add_to_wait_tree (q,cl,diff,2); } if (net_ratelimit()) printk(KERN_WARNING "htb: too many events !\n"); - return HZ / 10; + return HZ/10; } /* Returns class->node+prio from id-tree where classe's id is >= id. NULL is no such one exists. */ -static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n, - u32 id) +static struct rb_node * +htb_id_find_next_upper(int prio,struct rb_node *n,u32 id) { struct rb_node *r = NULL; while (n) { - struct htb_class *cl = - rb_entry(n, struct htb_class, node[prio]); - if (id == cl->classid) - return n; - + struct htb_class *cl = rb_entry(n,struct htb_class,node[prio]); + if (id == cl->classid) return n; + if (id > cl->classid) { n = n->rb_right; } else { @@ -834,49 +965,49 @@ static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n, * * Find leaf where current feed pointers points to. */ -static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio, - struct rb_node **pptr, u32 * pid) +static struct htb_class * +htb_lookup_leaf(HTB_ARGQ struct rb_root *tree,int prio,struct rb_node **pptr,u32 *pid) { int i; struct { struct rb_node *root; struct rb_node **pptr; u32 *pid; - } stk[TC_HTB_MAXDEPTH], *sp = stk; - + } stk[TC_HTB_MAXDEPTH],*sp = stk; + BUG_TRAP(tree->rb_node); sp->root = tree->rb_node; sp->pptr = pptr; sp->pid = pid; for (i = 0; i < 65535; i++) { - if (!*sp->pptr && *sp->pid) { + HTB_DBG(4,2,"htb_lleaf ptr=%p pid=%X\n",*sp->pptr,*sp->pid); + + if (!*sp->pptr && *sp->pid) { /* ptr was invalidated but id is valid - try to recover the original or next ptr */ - *sp->pptr = - htb_id_find_next_upper(prio, sp->root, *sp->pid); + *sp->pptr = htb_id_find_next_upper(prio,sp->root,*sp->pid); } - *sp->pid = 0; /* ptr is valid now so that remove this hint as it - can become out of date quickly */ - if (!*sp->pptr) { /* we are at right end; rewind & go up */ + *sp->pid = 0; /* ptr is valid now so that remove this hint as it + can become out of date quickly */ + if (!*sp->pptr) { /* we are at right end; rewind & go up */ *sp->pptr = sp->root; - while ((*sp->pptr)->rb_left) + while ((*sp->pptr)->rb_left) *sp->pptr = (*sp->pptr)->rb_left; if (sp > stk) { sp--; - BUG_TRAP(*sp->pptr); - if (!*sp->pptr) - return NULL; - htb_next_rb_node(sp->pptr); + BUG_TRAP(*sp->pptr); if(!*sp->pptr) return NULL; + htb_next_rb_node (sp->pptr); } } else { struct htb_class *cl; - cl = rb_entry(*sp->pptr, struct htb_class, node[prio]); - if (!cl->level) + cl = rb_entry(*sp->pptr,struct htb_class,node[prio]); + HTB_CHCL(cl); + if (!cl->level) return cl; (++sp)->root = cl->un.inner.feed[prio].rb_node; - sp->pptr = cl->un.inner.ptr + prio; - sp->pid = cl->un.inner.last_ptr_id + prio; + sp->pptr = cl->un.inner.ptr+prio; + sp->pid = cl->un.inner.last_ptr_id+prio; } } BUG_TRAP(0); @@ -885,21 +1016,21 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio, /* dequeues packet at given priority and level; call only if you are sure that there is active class at prio/level */ -static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio, - int level) +static struct sk_buff * +htb_dequeue_tree(struct htb_sched *q,int prio,int level) { struct sk_buff *skb = NULL; - struct htb_class *cl, *start; + struct htb_class *cl,*start; /* look initial class up in the row */ - start = cl = htb_lookup_leaf(q->row[level] + prio, prio, - q->ptr[level] + prio, - q->last_ptr_id[level] + prio); - + start = cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio, + q->ptr[level]+prio,q->last_ptr_id[level]+prio); + do { next: - BUG_TRAP(cl); - if (!cl) - return NULL; + BUG_TRAP(cl); + if (!cl) return NULL; + HTB_DBG(4,1,"htb_deq_tr prio=%d lev=%d cl=%X defic=%d\n", + prio,level,cl->classid,cl->un.leaf.deficit[level]); /* class can be empty - it is unlikely but can be true if leaf qdisc drops packets in enqueue routine or if someone used @@ -907,69 +1038,64 @@ static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio, simply deactivate and skip such class */ if (unlikely(cl->un.leaf.q->q.qlen == 0)) { struct htb_class *next; - htb_deactivate(q, cl); + htb_deactivate(q,cl); /* row/level might become empty */ if ((q->row_mask[level] & (1 << prio)) == 0) - return NULL; - - next = htb_lookup_leaf(q->row[level] + prio, - prio, q->ptr[level] + prio, - q->last_ptr_id[level] + prio); + return NULL; + + next = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio, + prio,q->ptr[level]+prio,q->last_ptr_id[level]+prio); - if (cl == start) /* fix start if we just deleted it */ + if (cl == start) /* fix start if we just deleted it */ start = next; cl = next; goto next; } - - skb = cl->un.leaf.q->dequeue(cl->un.leaf.q); - if (likely(skb != NULL)) + + if (likely((skb = cl->un.leaf.q->dequeue(cl->un.leaf.q)) != NULL)) break; if (!cl->warned) { - printk(KERN_WARNING - "htb: class %X isn't work conserving ?!\n", - cl->classid); + printk(KERN_WARNING "htb: class %X isn't work conserving ?!\n",cl->classid); cl->warned = 1; } q->nwc_hit++; - htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> - ptr[0]) + prio); - cl = htb_lookup_leaf(q->row[level] + prio, prio, - q->ptr[level] + prio, - q->last_ptr_id[level] + prio); + htb_next_rb_node((level?cl->parent->un.inner.ptr:q->ptr[0])+prio); + cl = htb_lookup_leaf (HTB_PASSQ q->row[level]+prio,prio,q->ptr[level]+prio, + q->last_ptr_id[level]+prio); } while (cl != start); if (likely(skb != NULL)) { if ((cl->un.leaf.deficit[level] -= skb->len) < 0) { + HTB_DBG(4,2,"htb_next_cl oldptr=%p quant_add=%d\n", + level?cl->parent->un.inner.ptr[prio]:q->ptr[0][prio],cl->un.leaf.quantum); cl->un.leaf.deficit[level] += cl->un.leaf.quantum; - htb_next_rb_node((level ? cl->parent->un.inner.ptr : q-> - ptr[0]) + prio); + htb_next_rb_node((level?cl->parent->un.inner.ptr:q->ptr[0])+prio); } /* this used to be after charge_class but this constelation gives us slightly better performance */ if (!cl->un.leaf.q->q.qlen) - htb_deactivate(q, cl); - htb_charge_class(q, cl, level, skb->len); + htb_deactivate (q,cl); + htb_charge_class (q,cl,level,skb->len); } return skb; } -static void htb_delay_by(struct Qdisc *sch, long delay) +static void htb_delay_by(struct Qdisc *sch,long delay) { struct htb_sched *q = qdisc_priv(sch); - if (delay <= 0) - delay = 1; - if (unlikely(delay > 5 * HZ)) { + if (delay <= 0) delay = 1; + if (unlikely(delay > 5*HZ)) { if (net_ratelimit()) printk(KERN_INFO "HTB delay %ld > 5sec\n", delay); - delay = 5 * HZ; + delay = 5*HZ; } /* why don't use jiffies here ? because expires can be in past */ mod_timer(&q->timer, q->jiffies + delay); sch->flags |= TCQ_F_THROTTLED; sch->qstats.overlimits++; + HTB_DBG(3,1,"htb_deq t_delay=%ld\n",delay); } static struct sk_buff *htb_dequeue(struct Qdisc *sch) @@ -978,19 +1104,22 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) struct htb_sched *q = qdisc_priv(sch); int level; long min_delay; +#ifdef HTB_DEBUG + int evs_used = 0; +#endif q->jiffies = jiffies; + HTB_DBG(3,1,"htb_deq dircnt=%d qlen=%d\n",skb_queue_len(&q->direct_queue), + sch->q.qlen); /* try to dequeue direct packets as high prio (!) to minimize cpu work */ - skb = __skb_dequeue(&q->direct_queue); - if (skb != NULL) { + if ((skb = __skb_dequeue(&q->direct_queue)) != NULL) { sch->flags &= ~TCQ_F_THROTTLED; sch->q.qlen--; return skb; } - if (!sch->q.qlen) - goto fin; + if (!sch->q.qlen) goto fin; PSCHED_GET_TIME(q->now); min_delay = LONG_MAX; @@ -1000,19 +1129,21 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) int m; long delay; if (time_after_eq(q->jiffies, q->near_ev_cache[level])) { - delay = htb_do_events(q, level); - q->near_ev_cache[level] = - q->jiffies + (delay ? delay : HZ); + delay = htb_do_events(q,level); + q->near_ev_cache[level] = q->jiffies + (delay ? delay : HZ); +#ifdef HTB_DEBUG + evs_used++; +#endif } else - delay = q->near_ev_cache[level] - q->jiffies; - - if (delay && min_delay > delay) + delay = q->near_ev_cache[level] - q->jiffies; + + if (delay && min_delay > delay) min_delay = delay; m = ~q->row_mask[level]; while (m != (int)(-1)) { - int prio = ffz(m); + int prio = ffz (m); m |= 1 << prio; - skb = htb_dequeue_tree(q, prio, level); + skb = htb_dequeue_tree(q,prio,level); if (likely(skb != NULL)) { sch->q.qlen--; sch->flags &= ~TCQ_F_THROTTLED; @@ -1020,28 +1151,40 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) } } } - htb_delay_by(sch, min_delay > 5 * HZ ? 5 * HZ : min_delay); +#ifdef HTB_DEBUG + if (!q->nwc_hit && min_delay >= 10*HZ && net_ratelimit()) { + if (min_delay == LONG_MAX) { + printk(KERN_ERR "HTB: dequeue bug (%d,%lu,%lu), report it please !\n", + evs_used,q->jiffies,jiffies); + htb_debug_dump(q); + } else + printk(KERN_WARNING "HTB: mindelay=%ld, some class has " + "too small rate\n",min_delay); + } +#endif + htb_delay_by (sch,min_delay > 5*HZ ? 5*HZ : min_delay); fin: + HTB_DBG(3,1,"htb_deq_end %s j=%lu skb=%p\n",sch->dev->name,q->jiffies,skb); return skb; } /* try to drop from each class (by prio) until one succeed */ -static unsigned int htb_drop(struct Qdisc *sch) +static unsigned int htb_drop(struct Qdisc* sch) { struct htb_sched *q = qdisc_priv(sch); int prio; for (prio = TC_HTB_NUMPRIO - 1; prio >= 0; prio--) { struct list_head *p; - list_for_each(p, q->drops + prio) { + list_for_each (p,q->drops+prio) { struct htb_class *cl = list_entry(p, struct htb_class, un.leaf.drop_list); unsigned int len; - if (cl->un.leaf.q->ops->drop && - (len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) { + if (cl->un.leaf.q->ops->drop && + (len = cl->un.leaf.q->ops->drop(cl->un.leaf.q))) { sch->q.qlen--; if (!cl->un.leaf.q->q.qlen) - htb_deactivate(q, cl); + htb_deactivate (q,cl); return len; } } @@ -1051,25 +1194,29 @@ static unsigned int htb_drop(struct Qdisc *sch) /* reset all classes */ /* always caled under BH & queue lock */ -static void htb_reset(struct Qdisc *sch) +static void htb_reset(struct Qdisc* sch) { struct htb_sched *q = qdisc_priv(sch); int i; + HTB_DBG(0,1,"htb_reset sch=%p, handle=%X\n",sch,sch->handle); for (i = 0; i < HTB_HSIZE; i++) { - struct hlist_node *p; - struct htb_class *cl; - - hlist_for_each_entry(cl, p, q->hash + i, hlist) { + struct list_head *p; + list_for_each (p,q->hash+i) { + struct htb_class *cl = list_entry(p,struct htb_class,hlist); if (cl->level) - memset(&cl->un.inner, 0, sizeof(cl->un.inner)); + memset(&cl->un.inner,0,sizeof(cl->un.inner)); else { - if (cl->un.leaf.q) + if (cl->un.leaf.q) qdisc_reset(cl->un.leaf.q); INIT_LIST_HEAD(&cl->un.leaf.drop_list); } cl->prio_activity = 0; cl->cmode = HTB_CAN_SEND; +#ifdef HTB_DEBUG + cl->pq_node.rb_color = -1; + memset(cl->node,255,sizeof(cl->node)); +#endif } } @@ -1077,12 +1224,12 @@ static void htb_reset(struct Qdisc *sch) del_timer(&q->timer); __skb_queue_purge(&q->direct_queue); sch->q.qlen = 0; - memset(q->row, 0, sizeof(q->row)); - memset(q->row_mask, 0, sizeof(q->row_mask)); - memset(q->wait_pq, 0, sizeof(q->wait_pq)); - memset(q->ptr, 0, sizeof(q->ptr)); + memset(q->row,0,sizeof(q->row)); + memset(q->row_mask,0,sizeof(q->row_mask)); + memset(q->wait_pq,0,sizeof(q->wait_pq)); + memset(q->ptr,0,sizeof(q->ptr)); for (i = 0; i < TC_HTB_NUMPRIO; i++) - INIT_LIST_HEAD(q->drops + i); + INIT_LIST_HEAD(q->drops+i); } static int htb_init(struct Qdisc *sch, struct rtattr *opt) @@ -1091,31 +1238,36 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt) struct rtattr *tb[TCA_HTB_INIT]; struct tc_htb_glob *gopt; int i; +#ifdef HTB_DEBUG + printk(KERN_INFO "HTB init, kernel part version %d.%d\n", + HTB_VER >> 16,HTB_VER & 0xffff); +#endif if (!opt || rtattr_parse_nested(tb, TCA_HTB_INIT, opt) || - tb[TCA_HTB_INIT - 1] == NULL || - RTA_PAYLOAD(tb[TCA_HTB_INIT - 1]) < sizeof(*gopt)) { + tb[TCA_HTB_INIT-1] == NULL || + RTA_PAYLOAD(tb[TCA_HTB_INIT-1]) < sizeof(*gopt)) { printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n"); return -EINVAL; } - gopt = RTA_DATA(tb[TCA_HTB_INIT - 1]); + gopt = RTA_DATA(tb[TCA_HTB_INIT-1]); if (gopt->version != HTB_VER >> 16) { - printk(KERN_ERR - "HTB: need tc/htb version %d (minor is %d), you have %d\n", - HTB_VER >> 16, HTB_VER & 0xffff, gopt->version); + printk(KERN_ERR "HTB: need tc/htb version %d (minor is %d), you have %d\n", + HTB_VER >> 16,HTB_VER & 0xffff,gopt->version); return -EINVAL; } + q->debug = gopt->debug; + HTB_DBG(0,1,"htb_init sch=%p handle=%X r2q=%d\n",sch,sch->handle,gopt->rate2quantum); INIT_LIST_HEAD(&q->root); for (i = 0; i < HTB_HSIZE; i++) - INIT_HLIST_HEAD(q->hash + i); + INIT_LIST_HEAD(q->hash+i); for (i = 0; i < TC_HTB_NUMPRIO; i++) - INIT_LIST_HEAD(q->drops + i); + INIT_LIST_HEAD(q->drops+i); init_timer(&q->timer); skb_queue_head_init(&q->direct_queue); q->direct_qlen = sch->dev->tx_queue_len; - if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */ + if (q->direct_qlen < 2) /* some devices have zero tx_queue_len */ q->direct_qlen = 2; q->timer.function = htb_timer; q->timer.data = (unsigned long)sch; @@ -1137,72 +1289,80 @@ static int htb_init(struct Qdisc *sch, struct rtattr *opt) static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) { struct htb_sched *q = qdisc_priv(sch); - unsigned char *b = skb->tail; + unsigned char *b = skb->tail; struct rtattr *rta; struct tc_htb_glob gopt; - spin_lock_bh(&sch->dev->queue_lock); + HTB_DBG(0,1,"htb_dump sch=%p, handle=%X\n",sch,sch->handle); + HTB_QLOCK(sch); gopt.direct_pkts = q->direct_pkts; +#ifdef HTB_DEBUG + if (HTB_DBG_COND(0,2)) + htb_debug_dump(q); +#endif gopt.version = HTB_VER; gopt.rate2quantum = q->rate2quantum; gopt.defcls = q->defcls; - gopt.debug = 0; - rta = (struct rtattr *)b; + gopt.debug = q->debug; + rta = (struct rtattr*)b; RTA_PUT(skb, TCA_OPTIONS, 0, NULL); RTA_PUT(skb, TCA_HTB_INIT, sizeof(gopt), &gopt); rta->rta_len = skb->tail - b; - spin_unlock_bh(&sch->dev->queue_lock); + HTB_QUNLOCK(sch); return skb->len; rtattr_failure: - spin_unlock_bh(&sch->dev->queue_lock); + HTB_QUNLOCK(sch); skb_trim(skb, skb->tail - skb->data); return -1; } static int htb_dump_class(struct Qdisc *sch, unsigned long arg, - struct sk_buff *skb, struct tcmsg *tcm) + struct sk_buff *skb, struct tcmsg *tcm) { - struct htb_class *cl = (struct htb_class *)arg; - unsigned char *b = skb->tail; +#ifdef HTB_DEBUG + struct htb_sched *q = qdisc_priv(sch); +#endif + struct htb_class *cl = (struct htb_class*)arg; + unsigned char *b = skb->tail; struct rtattr *rta; struct tc_htb_opt opt; - spin_lock_bh(&sch->dev->queue_lock); + HTB_DBG(0,1,"htb_dump_class handle=%X clid=%X\n",sch->handle,cl->classid); + + HTB_QLOCK(sch); tcm->tcm_parent = cl->parent ? cl->parent->classid : TC_H_ROOT; tcm->tcm_handle = cl->classid; if (!cl->level && cl->un.leaf.q) tcm->tcm_info = cl->un.leaf.q->handle; - rta = (struct rtattr *)b; + rta = (struct rtattr*)b; RTA_PUT(skb, TCA_OPTIONS, 0, NULL); - memset(&opt, 0, sizeof(opt)); + memset (&opt,0,sizeof(opt)); - opt.rate = cl->rate->rate; - opt.buffer = cl->buffer; - opt.ceil = cl->ceil->rate; - opt.cbuffer = cl->cbuffer; - opt.quantum = cl->un.leaf.quantum; - opt.prio = cl->un.leaf.prio; - opt.level = cl->level; + opt.rate = cl->rate->rate; opt.buffer = cl->buffer; + opt.ceil = cl->ceil->rate; opt.cbuffer = cl->cbuffer; + opt.quantum = cl->un.leaf.quantum; opt.prio = cl->un.leaf.prio; + opt.level = cl->level; RTA_PUT(skb, TCA_HTB_PARMS, sizeof(opt), &opt); rta->rta_len = skb->tail - b; - spin_unlock_bh(&sch->dev->queue_lock); + HTB_QUNLOCK(sch); return skb->len; rtattr_failure: - spin_unlock_bh(&sch->dev->queue_lock); + HTB_QUNLOCK(sch); skb_trim(skb, b - skb->data); return -1; } static int -htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d) +htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, + struct gnet_dump *d) { - struct htb_class *cl = (struct htb_class *)arg; + struct htb_class *cl = (struct htb_class*)arg; #ifdef HTB_RATECM - cl->rate_est.bps = cl->rate_bytes / (HTB_EWMAC * HTB_HSIZE); - cl->rate_est.pps = cl->rate_packets / (HTB_EWMAC * HTB_HSIZE); + cl->rate_est.bps = cl->rate_bytes/(HTB_EWMAC*HTB_HSIZE); + cl->rate_est.pps = cl->rate_packets/(HTB_EWMAC*HTB_HSIZE); #endif if (!cl->level && cl->un.leaf.q) @@ -1219,22 +1379,21 @@ htb_dump_class_stats(struct Qdisc *sch, unsigned long arg, struct gnet_dump *d) } static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, - struct Qdisc **old) + struct Qdisc **old) { - struct htb_class *cl = (struct htb_class *)arg; + struct htb_class *cl = (struct htb_class*)arg; if (cl && !cl->level) { - if (new == NULL && (new = qdisc_create_dflt(sch->dev, - &pfifo_qdisc_ops)) - == NULL) - return -ENOBUFS; + if (new == NULL && (new = qdisc_create_dflt(sch->dev, + &pfifo_qdisc_ops)) == NULL) + return -ENOBUFS; sch_tree_lock(sch); if ((*old = xchg(&cl->un.leaf.q, new)) != NULL) { if (cl->prio_activity) - htb_deactivate(qdisc_priv(sch), cl); + htb_deactivate (qdisc_priv(sch),cl); /* TODO: is it correct ? Why CBQ doesn't do it ? */ - sch->q.qlen -= (*old)->q.qlen; + sch->q.qlen -= (*old)->q.qlen; qdisc_reset(*old); } sch_tree_unlock(sch); @@ -1243,16 +1402,20 @@ static int htb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, return -ENOENT; } -static struct Qdisc *htb_leaf(struct Qdisc *sch, unsigned long arg) +static struct Qdisc * htb_leaf(struct Qdisc *sch, unsigned long arg) { - struct htb_class *cl = (struct htb_class *)arg; + struct htb_class *cl = (struct htb_class*)arg; return (cl && !cl->level) ? cl->un.leaf.q : NULL; } static unsigned long htb_get(struct Qdisc *sch, u32 classid) { - struct htb_class *cl = htb_find(classid, sch); - if (cl) +#ifdef HTB_DEBUG + struct htb_sched *q = qdisc_priv(sch); +#endif + struct htb_class *cl = htb_find(classid,sch); + HTB_DBG(0,1,"htb_get clid=%X q=%p cl=%p ref=%d\n",classid,q,cl,cl?cl->refcnt:0); + if (cl) cl->refcnt++; return (unsigned long)cl; } @@ -1267,9 +1430,10 @@ static void htb_destroy_filters(struct tcf_proto **fl) } } -static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) +static void htb_destroy_class(struct Qdisc* sch,struct htb_class *cl) { struct htb_sched *q = qdisc_priv(sch); + HTB_DBG(0,1,"htb_destrycls clid=%X ref=%d\n", cl?cl->classid:0,cl?cl->refcnt:0); if (!cl->level) { BUG_TRAP(cl->un.leaf.q); sch->q.qlen -= cl->un.leaf.q->q.qlen; @@ -1277,45 +1441,45 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl) } qdisc_put_rtab(cl->rate); qdisc_put_rtab(cl->ceil); - - htb_destroy_filters(&cl->filter_list); - - while (!list_empty(&cl->children)) - htb_destroy_class(sch, list_entry(cl->children.next, - struct htb_class, sibling)); + + htb_destroy_filters (&cl->filter_list); + + while (!list_empty(&cl->children)) + htb_destroy_class (sch,list_entry(cl->children.next, + struct htb_class,sibling)); /* note: this delete may happen twice (see htb_delete) */ - if (!hlist_unhashed(&cl->hlist)) - hlist_del(&cl->hlist); + list_del(&cl->hlist); list_del(&cl->sibling); - + if (cl->prio_activity) - htb_deactivate(q, cl); - + htb_deactivate (q,cl); + if (cl->cmode != HTB_CAN_SEND) - htb_safe_rb_erase(&cl->pq_node, q->wait_pq + cl->level); - + htb_safe_rb_erase(&cl->pq_node,q->wait_pq+cl->level); + kfree(cl); } /* always caled under BH & queue lock */ -static void htb_destroy(struct Qdisc *sch) +static void htb_destroy(struct Qdisc* sch) { struct htb_sched *q = qdisc_priv(sch); + HTB_DBG(0,1,"htb_destroy q=%p\n",q); - del_timer_sync(&q->timer); + del_timer_sync (&q->timer); #ifdef HTB_RATECM - del_timer_sync(&q->rttim); + del_timer_sync (&q->rttim); #endif /* This line used to be after htb_destroy_class call below and surprisingly it worked in 2.4. But it must precede it because filter need its target class alive to be able to call unbind_filter on it (without Oops). */ htb_destroy_filters(&q->filter_list); - - while (!list_empty(&q->root)) - htb_destroy_class(sch, list_entry(q->root.next, - struct htb_class, sibling)); + + while (!list_empty(&q->root)) + htb_destroy_class (sch,list_entry(q->root.next, + struct htb_class,sibling)); __skb_queue_purge(&q->direct_queue); } @@ -1323,25 +1487,24 @@ static void htb_destroy(struct Qdisc *sch) static int htb_delete(struct Qdisc *sch, unsigned long arg) { struct htb_sched *q = qdisc_priv(sch); - struct htb_class *cl = (struct htb_class *)arg; + struct htb_class *cl = (struct htb_class*)arg; + HTB_DBG(0,1,"htb_delete q=%p cl=%X ref=%d\n",q,cl?cl->classid:0,cl?cl->refcnt:0); // TODO: why don't allow to delete subtree ? references ? does // tc subsys quarantee us that in htb_destroy it holds no class // refs so that we can remove children safely there ? if (!list_empty(&cl->children) || cl->filter_cnt) return -EBUSY; - + sch_tree_lock(sch); - + /* delete from hash and active; remainder in destroy_class */ - if (!hlist_unhashed(&cl->hlist)) - hlist_del(&cl->hlist); - + list_del_init(&cl->hlist); if (cl->prio_activity) - htb_deactivate(q, cl); + htb_deactivate (q,cl); if (--cl->refcnt == 0) - htb_destroy_class(sch, cl); + htb_destroy_class(sch,cl); sch_tree_unlock(sch); return 0; @@ -1349,46 +1512,45 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg) static void htb_put(struct Qdisc *sch, unsigned long arg) { - struct htb_class *cl = (struct htb_class *)arg; +#ifdef HTB_DEBUG + struct htb_sched *q = qdisc_priv(sch); +#endif + struct htb_class *cl = (struct htb_class*)arg; + HTB_DBG(0,1,"htb_put q=%p cl=%X ref=%d\n",q,cl?cl->classid:0,cl?cl->refcnt:0); if (--cl->refcnt == 0) - htb_destroy_class(sch, cl); + htb_destroy_class(sch,cl); } -static int htb_change_class(struct Qdisc *sch, u32 classid, - u32 parentid, struct rtattr **tca, - unsigned long *arg) +static int htb_change_class(struct Qdisc *sch, u32 classid, + u32 parentid, struct rtattr **tca, unsigned long *arg) { int err = -EINVAL; struct htb_sched *q = qdisc_priv(sch); - struct htb_class *cl = (struct htb_class *)*arg, *parent; - struct rtattr *opt = tca[TCA_OPTIONS - 1]; + struct htb_class *cl = (struct htb_class*)*arg,*parent; + struct rtattr *opt = tca[TCA_OPTIONS-1]; struct qdisc_rate_table *rtab = NULL, *ctab = NULL; struct rtattr *tb[TCA_HTB_RTAB]; struct tc_htb_opt *hopt; /* extract all subattrs from opt attr */ if (!opt || rtattr_parse_nested(tb, TCA_HTB_RTAB, opt) || - tb[TCA_HTB_PARMS - 1] == NULL || - RTA_PAYLOAD(tb[TCA_HTB_PARMS - 1]) < sizeof(*hopt)) + tb[TCA_HTB_PARMS-1] == NULL || + RTA_PAYLOAD(tb[TCA_HTB_PARMS-1]) < sizeof(*hopt)) goto failure; + + parent = parentid == TC_H_ROOT ? NULL : htb_find (parentid,sch); - parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch); - - hopt = RTA_DATA(tb[TCA_HTB_PARMS - 1]); - - rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB - 1]); - ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB - 1]); - if (!rtab || !ctab) - goto failure; + hopt = RTA_DATA(tb[TCA_HTB_PARMS-1]); + HTB_DBG(0,1,"htb_chg cl=%p(%X), clid=%X, parid=%X, opt/prio=%d, rate=%u, buff=%d, quant=%d\n", cl,cl?cl->classid:0,classid,parentid,(int)hopt->prio,hopt->rate.rate,hopt->buffer,hopt->quantum); + rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB-1]); + ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB-1]); + if (!rtab || !ctab) goto failure; - if (!cl) { /* new class */ + if (!cl) { /* new class */ struct Qdisc *new_q; - int prio; - /* check for valid classid */ - if (!classid || TC_H_MAJ(classid ^ sch->handle) - || htb_find(classid, sch)) + if (!classid || TC_H_MAJ(classid^sch->handle) || htb_find(classid,sch)) goto failure; /* check maximal depth */ @@ -1399,16 +1561,15 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, err = -ENOBUFS; if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL) goto failure; - + cl->refcnt = 1; INIT_LIST_HEAD(&cl->sibling); - INIT_HLIST_NODE(&cl->hlist); + INIT_LIST_HEAD(&cl->hlist); INIT_LIST_HEAD(&cl->children); INIT_LIST_HEAD(&cl->un.leaf.drop_list); - RB_CLEAR_NODE(&cl->pq_node); - - for (prio = 0; prio < TC_HTB_NUMPRIO; prio++) - RB_CLEAR_NODE(&cl->node[prio]); +#ifdef HTB_DEBUG + cl->magic = HTB_CMAGIC; +#endif /* create leaf qdisc early because it uses kmalloc(GFP_KERNEL) so that can't be used inside of sch_tree_lock @@ -1418,53 +1579,53 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, if (parent && !parent->level) { /* turn parent into inner node */ sch->q.qlen -= parent->un.leaf.q->q.qlen; - qdisc_destroy(parent->un.leaf.q); - if (parent->prio_activity) - htb_deactivate(q, parent); + qdisc_destroy (parent->un.leaf.q); + if (parent->prio_activity) + htb_deactivate (q,parent); /* remove from evt list because of level change */ if (parent->cmode != HTB_CAN_SEND) { - htb_safe_rb_erase(&parent->pq_node, q->wait_pq); + htb_safe_rb_erase(&parent->pq_node,q->wait_pq /*+0*/); parent->cmode = HTB_CAN_SEND; } parent->level = (parent->parent ? parent->parent->level - : TC_HTB_MAXDEPTH) - 1; - memset(&parent->un.inner, 0, sizeof(parent->un.inner)); + : TC_HTB_MAXDEPTH) - 1; + memset (&parent->un.inner,0,sizeof(parent->un.inner)); } /* leaf (we) needs elementary qdisc */ cl->un.leaf.q = new_q ? new_q : &noop_qdisc; - cl->classid = classid; - cl->parent = parent; + cl->classid = classid; cl->parent = parent; /* set class to be in HTB_CAN_SEND state */ cl->tokens = hopt->buffer; cl->ctokens = hopt->cbuffer; - cl->mbuffer = PSCHED_JIFFIE2US(HZ * 60); /* 1min */ + cl->mbuffer = PSCHED_JIFFIE2US(HZ*60); /* 1min */ PSCHED_GET_TIME(cl->t_c); cl->cmode = HTB_CAN_SEND; /* attach to the hash list and parent's family */ - hlist_add_head(&cl->hlist, q->hash + htb_hash(classid)); - list_add_tail(&cl->sibling, - parent ? &parent->children : &q->root); - } else - sch_tree_lock(sch); + list_add_tail(&cl->hlist, q->hash+htb_hash(classid)); + list_add_tail(&cl->sibling, parent ? &parent->children : &q->root); +#ifdef HTB_DEBUG + { + int i; + for (i = 0; i < TC_HTB_NUMPRIO; i++) cl->node[i].rb_color = -1; + cl->pq_node.rb_color = -1; + } +#endif + } else sch_tree_lock(sch); /* it used to be a nasty bug here, we have to check that node - is really leaf before changing cl->un.leaf ! */ + is really leaf before changing cl->un.leaf ! */ if (!cl->level) { cl->un.leaf.quantum = rtab->rate.rate / q->rate2quantum; if (!hopt->quantum && cl->un.leaf.quantum < 1000) { - printk(KERN_WARNING - "HTB: quantum of class %X is small. Consider r2q change.\n", - cl->classid); + printk(KERN_WARNING "HTB: quantum of class %X is small. Consider r2q change.\n", cl->classid); cl->un.leaf.quantum = 1000; } if (!hopt->quantum && cl->un.leaf.quantum > 200000) { - printk(KERN_WARNING - "HTB: quantum of class %X is big. Consider r2q change.\n", - cl->classid); + printk(KERN_WARNING "HTB: quantum of class %X is big. Consider r2q change.\n", cl->classid); cl->un.leaf.quantum = 200000; } if (hopt->quantum) @@ -1475,22 +1636,16 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, cl->buffer = hopt->buffer; cl->cbuffer = hopt->cbuffer; - if (cl->rate) - qdisc_put_rtab(cl->rate); - cl->rate = rtab; - if (cl->ceil) - qdisc_put_rtab(cl->ceil); - cl->ceil = ctab; + if (cl->rate) qdisc_put_rtab(cl->rate); cl->rate = rtab; + if (cl->ceil) qdisc_put_rtab(cl->ceil); cl->ceil = ctab; sch_tree_unlock(sch); *arg = (unsigned long)cl; return 0; failure: - if (rtab) - qdisc_put_rtab(rtab); - if (ctab) - qdisc_put_rtab(ctab); + if (rtab) qdisc_put_rtab(rtab); + if (ctab) qdisc_put_rtab(ctab); return err; } @@ -1499,28 +1654,28 @@ static struct tcf_proto **htb_find_tcf(struct Qdisc *sch, unsigned long arg) struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl = (struct htb_class *)arg; struct tcf_proto **fl = cl ? &cl->filter_list : &q->filter_list; - + HTB_DBG(0,2,"htb_tcf q=%p clid=%X fref=%d fl=%p\n",q,cl?cl->classid:0,cl?cl->filter_cnt:q->filter_cnt,*fl); return fl; } static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent, - u32 classid) + u32 classid) { struct htb_sched *q = qdisc_priv(sch); - struct htb_class *cl = htb_find(classid, sch); - + struct htb_class *cl = htb_find (classid,sch); + HTB_DBG(0,2,"htb_bind q=%p clid=%X cl=%p fref=%d\n",q,classid,cl,cl?cl->filter_cnt:q->filter_cnt); /*if (cl && !cl->level) return 0; - The line above used to be there to prevent attaching filters to - leaves. But at least tc_index filter uses this just to get class - for other reasons so that we have to allow for it. - ---- - 19.6.2002 As Werner explained it is ok - bind filter is just - another way to "lock" the class - unlike "get" this lock can - be broken by class during destroy IIUC. + The line above used to be there to prevent attaching filters to + leaves. But at least tc_index filter uses this just to get class + for other reasons so that we have to allow for it. + ---- + 19.6.2002 As Werner explained it is ok - bind filter is just + another way to "lock" the class - unlike "get" this lock can + be broken by class during destroy IIUC. */ - if (cl) - cl->filter_cnt++; - else + if (cl) + cl->filter_cnt++; + else q->filter_cnt++; return (unsigned long)cl; } @@ -1529,10 +1684,10 @@ static void htb_unbind_filter(struct Qdisc *sch, unsigned long arg) { struct htb_sched *q = qdisc_priv(sch); struct htb_class *cl = (struct htb_class *)arg; - - if (cl) - cl->filter_cnt--; - else + HTB_DBG(0,2,"htb_unbind q=%p cl=%p fref=%d\n",q,cl,cl?cl->filter_cnt:q->filter_cnt); + if (cl) + cl->filter_cnt--; + else q->filter_cnt--; } @@ -1545,10 +1700,9 @@ static void htb_walk(struct Qdisc *sch, struct qdisc_walker *arg) return; for (i = 0; i < HTB_HSIZE; i++) { - struct hlist_node *p; - struct htb_class *cl; - - hlist_for_each_entry(cl, p, q->hash + i, hlist) { + struct list_head *p; + list_for_each (p,q->hash+i) { + struct htb_class *cl = list_entry(p,struct htb_class,hlist); if (arg->count < arg->skip) { arg->count++; continue; @@ -1596,13 +1750,12 @@ static struct Qdisc_ops htb_qdisc_ops = { static int __init htb_module_init(void) { - return register_qdisc(&htb_qdisc_ops); + return register_qdisc(&htb_qdisc_ops); } -static void __exit htb_module_exit(void) +static void __exit htb_module_exit(void) { - unregister_qdisc(&htb_qdisc_ops); + unregister_qdisc(&htb_qdisc_ops); } - module_init(htb_module_init) module_exit(htb_module_exit) MODULE_LICENSE("GPL"); diff --git a/trunk/net/sched/sch_netem.c b/trunk/net/sched/sch_netem.c index 45939bafbdf8..a08ec4c7c55d 100644 --- a/trunk/net/sched/sch_netem.c +++ b/trunk/net/sched/sch_netem.c @@ -192,8 +192,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) */ if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) { if (!(skb = skb_unshare(skb, GFP_ATOMIC)) - || (skb->ip_summed == CHECKSUM_PARTIAL - && skb_checksum_help(skb))) { + || (skb->ip_summed == CHECKSUM_HW + && skb_checksum_help(skb, 0))) { sch->qstats.drops++; return NET_XMIT_DROP; } diff --git a/trunk/net/sctp/endpointola.c b/trunk/net/sctp/endpointola.c index 35c49ff2d062..ffda1d680529 100644 --- a/trunk/net/sctp/endpointola.c +++ b/trunk/net/sctp/endpointola.c @@ -173,7 +173,7 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return); /* Free up the HMAC transform. */ - crypto_free_hash(sctp_sk(ep->base.sk)->hmac); + sctp_crypto_free_tfm(sctp_sk(ep->base.sk)->hmac); /* Cleanup. */ sctp_inq_free(&ep->base.inqueue); diff --git a/trunk/net/sctp/input.c b/trunk/net/sctp/input.c index 03f65de75d88..42b66e74bbb5 100644 --- a/trunk/net/sctp/input.c +++ b/trunk/net/sctp/input.c @@ -228,7 +228,7 @@ int sctp_rcv(struct sk_buff *skb) goto discard_release; nf_reset(skb); - if (sk_filter(sk, skb)) + if (sk_filter(sk, skb, 1)) goto discard_release; /* Create an SCTP packet structure. */ @@ -255,13 +255,10 @@ int sctp_rcv(struct sk_buff *skb) */ sctp_bh_lock_sock(sk); - if (sock_owned_by_user(sk)) { - SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG); + if (sock_owned_by_user(sk)) sctp_add_backlog(sk, skb); - } else { - SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_SOFTIRQ); + else sctp_inq_push(&chunk->rcvr->inqueue, chunk); - } sctp_bh_unlock_sock(sk); @@ -274,7 +271,6 @@ int sctp_rcv(struct sk_buff *skb) return 0; discard_it: - SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_DISCARDS); kfree_skb(skb); return 0; diff --git a/trunk/net/sctp/inqueue.c b/trunk/net/sctp/inqueue.c index cf6deed7e849..cf0c767d43ae 100644 --- a/trunk/net/sctp/inqueue.c +++ b/trunk/net/sctp/inqueue.c @@ -87,7 +87,7 @@ void sctp_inq_free(struct sctp_inq *queue) /* Put a new packet in an SCTP inqueue. * We assume that packet->sctp_hdr is set and in host byte order. */ -void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk) +void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *packet) { /* Directly call the packet handling routine. */ @@ -96,7 +96,7 @@ void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk) * Eventually, we should clean up inqueue to not rely * on the BH related data structures. */ - list_add_tail(&chunk->list, &q->in_chunk_list); + list_add_tail(&packet->list, &q->in_chunk_list); q->immediate.func(q->immediate.data); } diff --git a/trunk/net/sctp/ipv6.c b/trunk/net/sctp/ipv6.c index 249e5033c1a8..99c0cefc04e0 100644 --- a/trunk/net/sctp/ipv6.c +++ b/trunk/net/sctp/ipv6.c @@ -78,6 +78,7 @@ #include +extern int sctp_inetaddr_event(struct notifier_block *, unsigned long, void *); static struct notifier_block sctp_inet6addr_notifier = { .notifier_call = sctp_inetaddr_event, }; @@ -321,9 +322,9 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, struct inet6_ifaddr *ifp; struct sctp_sockaddr_entry *addr; - rcu_read_lock(); + read_lock(&addrconf_lock); if ((in6_dev = __in6_dev_get(dev)) == NULL) { - rcu_read_unlock(); + read_unlock(&addrconf_lock); return; } @@ -342,7 +343,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, } read_unlock(&in6_dev->lock); - rcu_read_unlock(); + read_unlock(&addrconf_lock); } /* Initialize a sockaddr_storage from in incoming skb. */ diff --git a/trunk/net/sctp/outqueue.c b/trunk/net/sctp/outqueue.c index 37074a39ecbb..30b710c54e64 100644 --- a/trunk/net/sctp/outqueue.c +++ b/trunk/net/sctp/outqueue.c @@ -467,7 +467,6 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, switch(reason) { case SCTP_RTXR_T3_RTX: - SCTP_INC_STATS(SCTP_MIB_T3_RETRANSMITS); sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX); /* Update the retran path if the T3-rtx timer has expired for * the current retran path. @@ -476,15 +475,12 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, sctp_assoc_update_retran_path(transport->asoc); break; case SCTP_RTXR_FAST_RTX: - SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS); sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX); fast_retransmit = 1; break; case SCTP_RTXR_PMTUD: - SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS); - break; default: - BUG(); + break; } sctp_retransmit_mark(q, transport, fast_retransmit); diff --git a/trunk/net/sctp/proc.c b/trunk/net/sctp/proc.c index a356d8d310a9..5b3b0e0ae7e5 100644 --- a/trunk/net/sctp/proc.c +++ b/trunk/net/sctp/proc.c @@ -57,21 +57,6 @@ static struct snmp_mib sctp_snmp_list[] = { SNMP_MIB_ITEM("SctpReasmUsrMsgs", SCTP_MIB_REASMUSRMSGS), SNMP_MIB_ITEM("SctpOutSCTPPacks", SCTP_MIB_OUTSCTPPACKS), SNMP_MIB_ITEM("SctpInSCTPPacks", SCTP_MIB_INSCTPPACKS), - SNMP_MIB_ITEM("SctpT1InitExpireds", SCTP_MIB_T1_INIT_EXPIREDS), - SNMP_MIB_ITEM("SctpT1CookieExpireds", SCTP_MIB_T1_COOKIE_EXPIREDS), - SNMP_MIB_ITEM("SctpT2ShutdownExpireds", SCTP_MIB_T2_SHUTDOWN_EXPIREDS), - SNMP_MIB_ITEM("SctpT3RtxExpireds", SCTP_MIB_T3_RTX_EXPIREDS), - SNMP_MIB_ITEM("SctpT4RtoExpireds", SCTP_MIB_T4_RTO_EXPIREDS), - SNMP_MIB_ITEM("SctpT5ShutdownGuardExpireds", SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS), - SNMP_MIB_ITEM("SctpDelaySackExpireds", SCTP_MIB_DELAY_SACK_EXPIREDS), - SNMP_MIB_ITEM("SctpAutocloseExpireds", SCTP_MIB_AUTOCLOSE_EXPIREDS), - SNMP_MIB_ITEM("SctpT3Retransmits", SCTP_MIB_T3_RETRANSMITS), - SNMP_MIB_ITEM("SctpPmtudRetransmits", SCTP_MIB_PMTUD_RETRANSMITS), - SNMP_MIB_ITEM("SctpFastRetransmits", SCTP_MIB_FAST_RETRANSMITS), - SNMP_MIB_ITEM("SctpInPktSoftirq", SCTP_MIB_IN_PKT_SOFTIRQ), - SNMP_MIB_ITEM("SctpInPktBacklog", SCTP_MIB_IN_PKT_BACKLOG), - SNMP_MIB_ITEM("SctpInPktDiscards", SCTP_MIB_IN_PKT_DISCARDS), - SNMP_MIB_ITEM("SctpInDataChunkDiscards", SCTP_MIB_IN_DATA_CHUNK_DISCARDS), SNMP_MIB_SENTINEL }; @@ -343,8 +328,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ", assoc, sk, sctp_sk(sk)->type, sk->sk_state, assoc->state, hash, assoc->assoc_id, - assoc->sndbuf_used, (sk->sk_rcvbuf - assoc->rwnd), + assoc->sndbuf_used, sock_i_uid(sk), sock_i_ino(sk), epb->bind_addr.port, assoc->peer.port); diff --git a/trunk/net/sctp/protocol.c b/trunk/net/sctp/protocol.c index fac7674438a4..1ab03a27a76e 100644 --- a/trunk/net/sctp/protocol.c +++ b/trunk/net/sctp/protocol.c @@ -61,7 +61,7 @@ #include /* Global data structures. */ -struct sctp_globals sctp_globals __read_mostly; +struct sctp_globals sctp_globals; struct proc_dir_entry *proc_net_sctp; DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly; @@ -82,6 +82,13 @@ static struct sctp_af *sctp_af_v6_specific; kmem_cache_t *sctp_chunk_cachep __read_mostly; kmem_cache_t *sctp_bucket_cachep __read_mostly; +extern int sctp_snmp_proc_init(void); +extern int sctp_snmp_proc_exit(void); +extern int sctp_eps_proc_init(void); +extern int sctp_eps_proc_exit(void); +extern int sctp_assocs_proc_init(void); +extern int sctp_assocs_proc_exit(void); + /* Return the address of the control sock. */ struct sock *sctp_get_ctl_sock(void) { @@ -1042,7 +1049,7 @@ SCTP_STATIC __init int sctp_init(void) sctp_rto_beta = SCTP_RTO_BETA; /* Valid.Cookie.Life - 60 seconds */ - sctp_valid_cookie_life = SCTP_DEFAULT_COOKIE_LIFE; + sctp_valid_cookie_life = 60 * HZ; /* Whether Cookie Preservative is enabled(1) or not(0) */ sctp_cookie_preserve_enable = 1; diff --git a/trunk/net/sctp/sm_make_chunk.c b/trunk/net/sctp/sm_make_chunk.c index 7745bdea7817..4f11f5858209 100644 --- a/trunk/net/sctp/sm_make_chunk.c +++ b/trunk/net/sctp/sm_make_chunk.c @@ -806,26 +806,38 @@ struct sctp_chunk *sctp_make_abort_no_data( /* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */ struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc, - const struct msghdr *msg, - size_t paylen) + const struct sctp_chunk *chunk, + const struct msghdr *msg) { struct sctp_chunk *retval; - void *payload = NULL; - int err; + void *payload = NULL, *payoff; + size_t paylen = 0; + struct iovec *iov = NULL; + int iovlen = 0; + + if (msg) { + iov = msg->msg_iov; + iovlen = msg->msg_iovlen; + paylen = get_user_iov_size(iov, iovlen); + } - retval = sctp_make_abort(asoc, NULL, sizeof(sctp_errhdr_t) + paylen); + retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen); if (!retval) goto err_chunk; if (paylen) { /* Put the msg_iov together into payload. */ - payload = kmalloc(paylen, GFP_KERNEL); + payload = kmalloc(paylen, GFP_ATOMIC); if (!payload) goto err_payload; + payoff = payload; - err = memcpy_fromiovec(payload, msg->msg_iov, paylen); - if (err < 0) - goto err_copy; + for (; iovlen > 0; --iovlen) { + if (copy_from_user(payoff, iov->iov_base,iov->iov_len)) + goto err_copy; + payoff += iov->iov_len; + iov++; + } } sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen); @@ -1282,8 +1294,10 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, retval = kmalloc(*cookie_len, GFP_ATOMIC); - if (!retval) + if (!retval) { + *cookie_len = 0; goto nodata; + } /* Clear this memory since we are sending this data structure * out on the network. @@ -1319,29 +1333,19 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len); if (sctp_sk(ep->base.sk)->hmac) { - struct hash_desc desc; - /* Sign the message. */ sg.page = virt_to_page(&cookie->c); sg.offset = (unsigned long)(&cookie->c) % PAGE_SIZE; sg.length = bodysize; keylen = SCTP_SECRET_SIZE; key = (char *)ep->secret_key[ep->current_key]; - desc.tfm = sctp_sk(ep->base.sk)->hmac; - desc.flags = 0; - if (crypto_hash_setkey(desc.tfm, key, keylen) || - crypto_hash_digest(&desc, &sg, bodysize, cookie->signature)) - goto free_cookie; + sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, + &sg, 1, cookie->signature); } - return retval; - -free_cookie: - kfree(retval); nodata: - *cookie_len = 0; - return NULL; + return retval; } /* Unpack the cookie from COOKIE ECHO chunk, recreating the association. */ @@ -1362,7 +1366,6 @@ struct sctp_association *sctp_unpack_cookie( sctp_scope_t scope; struct sk_buff *skb = chunk->skb; struct timeval tv; - struct hash_desc desc; /* Header size is static data prior to the actual cookie, including * any padding. @@ -1398,25 +1401,17 @@ struct sctp_association *sctp_unpack_cookie( sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE; sg.length = bodysize; key = (char *)ep->secret_key[ep->current_key]; - desc.tfm = sctp_sk(ep->base.sk)->hmac; - desc.flags = 0; memset(digest, 0x00, SCTP_SIGNATURE_SIZE); - if (crypto_hash_setkey(desc.tfm, key, keylen) || - crypto_hash_digest(&desc, &sg, bodysize, digest)) { - *error = -SCTP_IERROR_NOMEM; - goto fail; - } + sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg, + 1, digest); if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) { /* Try the previous key. */ key = (char *)ep->secret_key[ep->last_key]; memset(digest, 0x00, SCTP_SIGNATURE_SIZE); - if (crypto_hash_setkey(desc.tfm, key, keylen) || - crypto_hash_digest(&desc, &sg, bodysize, digest)) { - *error = -SCTP_IERROR_NOMEM; - goto fail; - } + sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, + &sg, 1, digest); if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) { /* Yikes! Still bad signature! */ diff --git a/trunk/net/sctp/sm_statefuns.c b/trunk/net/sctp/sm_statefuns.c index 1c42fe983a5b..ead3f1b0ea3d 100644 --- a/trunk/net/sctp/sm_statefuns.c +++ b/trunk/net/sctp/sm_statefuns.c @@ -187,9 +187,10 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep, */ ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP, 0, 0, 0, GFP_ATOMIC); - if (ev) - sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, - SCTP_ULPEVENT(ev)); + if (!ev) + goto nomem; + + sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); /* Upon reception of the SHUTDOWN COMPLETE chunk the endpoint * will verify that it is in SHUTDOWN-ACK-SENT state, if it is @@ -214,6 +215,9 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep, sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); return SCTP_DISPOSITION_DELETE_TCB; + +nomem: + return SCTP_DISPOSITION_NOMEM; } /* @@ -343,6 +347,8 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, GFP_ATOMIC)) goto nomem_init; + sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); + /* B) "Z" shall respond immediately with an INIT ACK chunk. */ /* If there are errors need to be reported for unknown parameters, @@ -354,11 +360,11 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, sizeof(sctp_chunkhdr_t); if (sctp_assoc_set_bind_addr_from_ep(new_asoc, GFP_ATOMIC) < 0) - goto nomem_init; + goto nomem_ack; repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len); if (!repl) - goto nomem_init; + goto nomem_ack; /* If there are errors need to be reported for unknown parameters, * include them in the outgoing INIT ACK as "Unrecognized parameter" @@ -382,8 +388,6 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, sctp_chunk_free(err_chunk); } - sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); /* @@ -396,11 +400,12 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, return SCTP_DISPOSITION_DELETE_TCB; +nomem_ack: + if (err_chunk) + sctp_chunk_free(err_chunk); nomem_init: sctp_association_free(new_asoc); nomem: - if (err_chunk) - sctp_chunk_free(err_chunk); return SCTP_DISPOSITION_NOMEM; } @@ -595,7 +600,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, struct sctp_association *new_asoc; sctp_init_chunk_t *peer_init; struct sctp_chunk *repl; - struct sctp_ulpevent *ev, *ai_ev = NULL; + struct sctp_ulpevent *ev; int error = 0; struct sctp_chunk *err_chk_p; @@ -654,10 +659,20 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, }; } + sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); + sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, + SCTP_STATE(SCTP_STATE_ESTABLISHED)); + SCTP_INC_STATS(SCTP_MIB_CURRESTAB); + SCTP_INC_STATS(SCTP_MIB_PASSIVEESTABS); + sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); - /* Delay state machine commands until later. - * - * Re-build the bind address for the association is done in + if (new_asoc->autoclose) + sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, + SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); + + sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); + + /* Re-build the bind address for the association is done in * the sctp_unpack_cookie() already. */ /* This is a brand-new association, so these are not yet side @@ -672,7 +687,9 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, repl = sctp_make_cookie_ack(new_asoc, chunk); if (!repl) - goto nomem_init; + goto nomem_repl; + + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); /* RFC 2960 5.1 Normal Establishment of an Association * @@ -687,53 +704,28 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, if (!ev) goto nomem_ev; + sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); + /* Sockets API Draft Section 5.3.1.6 * When a peer sends a Adaption Layer Indication parameter , SCTP * delivers this notification to inform the application that of the * peers requested adaption layer. */ if (new_asoc->peer.adaption_ind) { - ai_ev = sctp_ulpevent_make_adaption_indication(new_asoc, + ev = sctp_ulpevent_make_adaption_indication(new_asoc, GFP_ATOMIC); - if (!ai_ev) - goto nomem_aiev; - } - - /* Add all the state machine commands now since we've created - * everything. This way we don't introduce memory corruptions - * during side-effect processing and correclty count established - * associations. - */ - sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); - sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, - SCTP_STATE(SCTP_STATE_ESTABLISHED)); - SCTP_INC_STATS(SCTP_MIB_CURRESTAB); - SCTP_INC_STATS(SCTP_MIB_PASSIVEESTABS); - sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); - - if (new_asoc->autoclose) - sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, - SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE)); - - sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); - - /* This will send the COOKIE ACK */ - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); - - /* Queue the ASSOC_CHANGE event */ - sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); + if (!ev) + goto nomem_ev; - /* Send up the Adaptation Layer Indication event */ - if (ai_ev) sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, - SCTP_ULPEVENT(ai_ev)); + SCTP_ULPEVENT(ev)); + } return SCTP_DISPOSITION_CONSUME; -nomem_aiev: - sctp_ulpevent_free(ev); nomem_ev: sctp_chunk_free(repl); +nomem_repl: nomem_init: sctp_association_free(new_asoc); nomem: @@ -1368,8 +1360,10 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, sctp_source(chunk), (sctp_init_chunk_t *)chunk->chunk_hdr, - GFP_ATOMIC)) - goto nomem; + GFP_ATOMIC)) { + retval = SCTP_DISPOSITION_NOMEM; + goto nomem_init; + } /* Make sure no new addresses are being added during the * restart. Do not do this check for COOKIE-WAIT state, @@ -1380,7 +1374,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) { retval = SCTP_DISPOSITION_CONSUME; - goto nomem_retval; + goto cleanup_asoc; } } @@ -1436,17 +1430,17 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); retval = SCTP_DISPOSITION_CONSUME; - return retval; - -nomem: - retval = SCTP_DISPOSITION_NOMEM; -nomem_retval: - if (new_asoc) - sctp_association_free(new_asoc); cleanup: if (err_chunk) sctp_chunk_free(err_chunk); return retval; +nomem: + retval = SCTP_DISPOSITION_NOMEM; + goto cleanup; +nomem_init: +cleanup_asoc: + sctp_association_free(new_asoc); + goto cleanup; } /* @@ -1617,10 +1611,15 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, */ sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL()); + /* Update the content of current association. */ + sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); + repl = sctp_make_cookie_ack(new_asoc, chunk); if (!repl) goto nomem; + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); + /* Report association restart to upper layer. */ ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0, new_asoc->c.sinit_num_ostreams, @@ -1629,9 +1628,6 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, if (!ev) goto nomem_ev; - /* Update the content of current association. */ - sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); return SCTP_DISPOSITION_CONSUME; @@ -1755,7 +1751,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, sctp_cmd_seq_t *commands, struct sctp_association *new_asoc) { - struct sctp_ulpevent *ev = NULL, *ai_ev = NULL; + struct sctp_ulpevent *ev = NULL; struct sctp_chunk *repl; /* Clarification from Implementor's Guide: @@ -1782,25 +1778,29 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, * SCTP user upon reception of a valid COOKIE * ECHO chunk. */ - ev = sctp_ulpevent_make_assoc_change(asoc, 0, + ev = sctp_ulpevent_make_assoc_change(new_asoc, 0, SCTP_COMM_UP, 0, - asoc->c.sinit_num_ostreams, - asoc->c.sinit_max_instreams, + new_asoc->c.sinit_num_ostreams, + new_asoc->c.sinit_max_instreams, GFP_ATOMIC); if (!ev) goto nomem; + sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, + SCTP_ULPEVENT(ev)); /* Sockets API Draft Section 5.3.1.6 * When a peer sends a Adaption Layer Indication parameter, * SCTP delivers this notification to inform the application * that of the peers requested adaption layer. */ - if (asoc->peer.adaption_ind) { - ai_ev = sctp_ulpevent_make_adaption_indication(asoc, + if (new_asoc->peer.adaption_ind) { + ev = sctp_ulpevent_make_adaption_indication(new_asoc, GFP_ATOMIC); - if (!ai_ev) + if (!ev) goto nomem; + sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, + SCTP_ULPEVENT(ev)); } } sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); @@ -1809,21 +1809,12 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, if (!repl) goto nomem; - if (ev) - sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, - SCTP_ULPEVENT(ev)); - if (ai_ev) - sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, - SCTP_ULPEVENT(ai_ev)); - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl)); sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL()); return SCTP_DISPOSITION_CONSUME; nomem: - if (ai_ev) - sctp_ulpevent_free(ai_ev); if (ev) sctp_ulpevent_free(ev); return SCTP_DISPOSITION_NOMEM; @@ -2672,11 +2663,9 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep, break; case SCTP_IERROR_HIGH_TSN: case SCTP_IERROR_BAD_STREAM: - SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS); goto discard_noforce; case SCTP_IERROR_DUP_TSN: case SCTP_IERROR_IGNORE_TSN: - SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS); goto discard_force; case SCTP_IERROR_NO_DATA: goto consume; @@ -3028,6 +3017,7 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) return sctp_sf_violation_chunklen(ep, asoc, type, arg, commands); + /* 10.2 H) SHUTDOWN COMPLETE notification * * When SCTP completes the shutdown procedures (section 9.2) this @@ -3038,14 +3028,6 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, if (!ev) goto nomem; - /* ...send a SHUTDOWN COMPLETE chunk to its peer, */ - reply = sctp_make_shutdown_complete(asoc, chunk); - if (!reply) - goto nomem_chunk; - - /* Do all the commands now (after allocation), so that we - * have consistent state if memory allocation failes - */ sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); /* Upon the receipt of the SHUTDOWN ACK, the SHUTDOWN sender shall @@ -3057,6 +3039,11 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); + /* ...send a SHUTDOWN COMPLETE chunk to its peer, */ + reply = sctp_make_shutdown_complete(asoc, chunk); + if (!reply) + goto nomem; + sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, SCTP_STATE(SCTP_STATE_CLOSED)); SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS); @@ -3067,8 +3054,6 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); return SCTP_DISPOSITION_DELETE_TCB; -nomem_chunk: - sctp_ulpevent_free(ev); nomem: return SCTP_DISPOSITION_NOMEM; } @@ -3667,7 +3652,6 @@ sctp_disposition_t sctp_sf_pdiscard(const struct sctp_endpoint *ep, void *arg, sctp_cmd_seq_t *commands) { - SCTP_INC_STATS(SCTP_MIB_IN_PKT_DISCARDS); sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); return SCTP_DISPOSITION_CONSUME; @@ -4047,12 +4031,18 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort( * from its upper layer, but retransmits data to the far end * if necessary to fill gaps. */ - struct sctp_chunk *abort = arg; + struct msghdr *msg = arg; + struct sctp_chunk *abort; sctp_disposition_t retval; retval = SCTP_DISPOSITION_CONSUME; - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); + /* Generate ABORT chunk to send the peer. */ + abort = sctp_make_abort_user(asoc, NULL, msg); + if (!abort) + retval = SCTP_DISPOSITION_NOMEM; + else + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); /* Even if we can't send the ABORT due to low memory delete the * TCB. This is a departure from our typical NOMEM handling. @@ -4176,7 +4166,8 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( void *arg, sctp_cmd_seq_t *commands) { - struct sctp_chunk *abort = arg; + struct msghdr *msg = arg; + struct sctp_chunk *abort; sctp_disposition_t retval; /* Stop T1-init timer */ @@ -4184,7 +4175,12 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); retval = SCTP_DISPOSITION_CONSUME; - sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); + /* Generate ABORT chunk to send the peer */ + abort = sctp_make_abort_user(asoc, NULL, msg); + if (!abort) + retval = SCTP_DISPOSITION_NOMEM; + else + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, SCTP_STATE(SCTP_STATE_CLOSED)); @@ -4564,8 +4560,6 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep, { struct sctp_transport *transport = arg; - SCTP_INC_STATS(SCTP_MIB_T3_RTX_EXPIREDS); - if (asoc->overall_error_count >= asoc->max_retrans) { sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ETIMEDOUT)); @@ -4634,7 +4628,6 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, void *arg, sctp_cmd_seq_t *commands) { - SCTP_INC_STATS(SCTP_MIB_DELAY_SACK_EXPIREDS); sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); return SCTP_DISPOSITION_CONSUME; } @@ -4669,7 +4662,6 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, int attempts = asoc->init_err_counter + 1; SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n"); - SCTP_INC_STATS(SCTP_MIB_T1_INIT_EXPIREDS); if (attempts <= asoc->max_init_attempts) { bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; @@ -4729,7 +4721,6 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep int attempts = asoc->init_err_counter + 1; SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n"); - SCTP_INC_STATS(SCTP_MIB_T1_COOKIE_EXPIREDS); if (attempts <= asoc->max_init_attempts) { repl = sctp_make_cookie_echo(asoc, NULL); @@ -4774,8 +4765,6 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, struct sctp_chunk *reply = NULL; SCTP_DEBUG_PRINTK("Timer T2 expired.\n"); - SCTP_INC_STATS(SCTP_MIB_T2_SHUTDOWN_EXPIREDS); - if (asoc->overall_error_count >= asoc->max_retrans) { sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ETIMEDOUT)); @@ -4837,8 +4826,6 @@ sctp_disposition_t sctp_sf_t4_timer_expire( struct sctp_chunk *chunk = asoc->addip_last_asconf; struct sctp_transport *transport = chunk->transport; - SCTP_INC_STATS(SCTP_MIB_T4_RTO_EXPIREDS); - /* ADDIP 4.1 B1) Increment the error counters and perform path failure * detection on the appropriate destination address as defined in * RFC2960 [5] section 8.1 and 8.2. @@ -4905,7 +4892,6 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep, struct sctp_chunk *reply = NULL; SCTP_DEBUG_PRINTK("Timer T5 expired.\n"); - SCTP_INC_STATS(SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS); reply = sctp_make_abort(asoc, NULL, 0); if (!reply) @@ -4936,8 +4922,6 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire( { int disposition; - SCTP_INC_STATS(SCTP_MIB_AUTOCLOSE_EXPIREDS); - /* From 9.2 Shutdown of an Association * Upon receipt of the SHUTDOWN primitive from its upper * layer, the endpoint enters SHUTDOWN-PENDING state and diff --git a/trunk/net/sctp/socket.c b/trunk/net/sctp/socket.c index 79c3e072cf28..54722e622e6d 100644 --- a/trunk/net/sctp/socket.c +++ b/trunk/net/sctp/socket.c @@ -1289,13 +1289,9 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) } } - if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) { - struct sctp_chunk *chunk; - - chunk = sctp_make_abort_user(asoc, NULL, 0); - if (chunk) - sctp_primitive_ABORT(asoc, chunk); - } else + if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) + sctp_primitive_ABORT(asoc, NULL); + else sctp_primitive_SHUTDOWN(asoc, NULL); } @@ -1524,16 +1520,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, goto out_unlock; } if (sinfo_flags & SCTP_ABORT) { - struct sctp_chunk *chunk; - - chunk = sctp_make_abort_user(asoc, msg, msg_len); - if (!chunk) { - err = -ENOMEM; - goto out_unlock; - } - SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc); - sctp_primitive_ABORT(asoc, chunk); + sctp_primitive_ABORT(asoc, msg); err = 0; goto out_unlock; } @@ -2081,13 +2069,13 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval, * SPP_SACKDELAY_ENABLE, setting both will have undefined * results. */ -static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, - struct sctp_transport *trans, - struct sctp_association *asoc, - struct sctp_sock *sp, - int hb_change, - int pmtud_change, - int sackdelay_change) +int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, + struct sctp_transport *trans, + struct sctp_association *asoc, + struct sctp_sock *sp, + int hb_change, + int pmtud_change, + int sackdelay_change) { int error; @@ -2970,7 +2958,7 @@ SCTP_STATIC struct sock *sctp_accept(struct sock *sk, int flags, int *err) goto out; } - timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); + timeo = sock_rcvtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK); error = sctp_wait_for_accept(sk, timeo); if (error) @@ -3045,14 +3033,14 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) sp->initmsg.sinit_num_ostreams = sctp_max_outstreams; sp->initmsg.sinit_max_instreams = sctp_max_instreams; sp->initmsg.sinit_max_attempts = sctp_max_retrans_init; - sp->initmsg.sinit_max_init_timeo = sctp_rto_max; + sp->initmsg.sinit_max_init_timeo = jiffies_to_msecs(sctp_rto_max); /* Initialize default RTO related parameters. These parameters can * be modified for with the SCTP_RTOINFO socket option. */ - sp->rtoinfo.srto_initial = sctp_rto_initial; - sp->rtoinfo.srto_max = sctp_rto_max; - sp->rtoinfo.srto_min = sctp_rto_min; + sp->rtoinfo.srto_initial = jiffies_to_msecs(sctp_rto_initial); + sp->rtoinfo.srto_max = jiffies_to_msecs(sctp_rto_max); + sp->rtoinfo.srto_min = jiffies_to_msecs(sctp_rto_min); /* Initialize default association related parameters. These parameters * can be modified with the SCTP_ASSOCINFO socket option. @@ -3061,7 +3049,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) sp->assocparams.sasoc_number_peer_destinations = 0; sp->assocparams.sasoc_peer_rwnd = 0; sp->assocparams.sasoc_local_rwnd = 0; - sp->assocparams.sasoc_cookie_life = sctp_valid_cookie_life; + sp->assocparams.sasoc_cookie_life = + jiffies_to_msecs(sctp_valid_cookie_life); /* Initialize default event subscriptions. By default, all the * options are off. @@ -3071,10 +3060,10 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) /* Default Peer Address Parameters. These defaults can * be modified via SCTP_PEER_ADDR_PARAMS */ - sp->hbinterval = sctp_hb_interval; + sp->hbinterval = jiffies_to_msecs(sctp_hb_interval); sp->pathmaxrxt = sctp_max_retrans_path; sp->pathmtu = 0; // allow default discovery - sp->sackdelay = sctp_sack_timeout; + sp->sackdelay = jiffies_to_msecs(sctp_sack_timeout); sp->param_flags = SPP_HB_ENABLE | SPP_PMTUD_ENABLE | SPP_SACKDELAY_ENABLE; @@ -4897,7 +4886,7 @@ SCTP_STATIC int sctp_stream_listen(struct sock *sk, int backlog) int sctp_inet_listen(struct socket *sock, int backlog) { struct sock *sk = sock->sk; - struct crypto_hash *tfm = NULL; + struct crypto_tfm *tfm=NULL; int err = -EINVAL; if (unlikely(backlog < 0)) @@ -4910,7 +4899,7 @@ int sctp_inet_listen(struct socket *sock, int backlog) /* Allocate HMAC for generating cookie. */ if (sctp_hmac_alg) { - tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC); + tfm = sctp_crypto_alloc_tfm(sctp_hmac_alg, 0); if (!tfm) { err = -ENOSYS; goto out; @@ -4936,7 +4925,7 @@ int sctp_inet_listen(struct socket *sock, int backlog) sctp_release_sock(sk); return err; cleanup: - crypto_free_hash(tfm); + sctp_crypto_free_tfm(tfm); goto out; } @@ -5618,8 +5607,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, /* Copy the bind_addr list from the original endpoint to the new * endpoint so that we can handle restarts properly */ - if (PF_INET6 == assoc->base.sk->sk_family) - flags = SCTP_ADDR6_ALLOWED; if (assoc->peer.ipv4_address) flags |= SCTP_ADDR4_PEERSUPP; if (assoc->peer.ipv6_address) diff --git a/trunk/net/sctp/sysctl.c b/trunk/net/sctp/sysctl.c index 633cd178654b..dc6f3ff32358 100644 --- a/trunk/net/sctp/sysctl.c +++ b/trunk/net/sctp/sysctl.c @@ -45,10 +45,9 @@ #include #include -static int zero = 0; -static int one = 1; -static int timer_max = 86400000; /* ms in one day */ -static int int_max = INT_MAX; +static ctl_handler sctp_sysctl_jiffies_ms; +static long rto_timer_min = 1; +static long rto_timer_max = 86400000; /* One day */ static long sack_timer_min = 1; static long sack_timer_max = 500; @@ -57,45 +56,45 @@ static ctl_table sctp_table[] = { .ctl_name = NET_SCTP_RTO_INITIAL, .procname = "rto_initial", .data = &sctp_rto_initial, - .maxlen = sizeof(unsigned int), + .maxlen = sizeof(long), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &one, - .extra2 = &timer_max + .proc_handler = &proc_doulongvec_ms_jiffies_minmax, + .strategy = &sctp_sysctl_jiffies_ms, + .extra1 = &rto_timer_min, + .extra2 = &rto_timer_max }, { .ctl_name = NET_SCTP_RTO_MIN, .procname = "rto_min", .data = &sctp_rto_min, - .maxlen = sizeof(unsigned int), + .maxlen = sizeof(long), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &one, - .extra2 = &timer_max + .proc_handler = &proc_doulongvec_ms_jiffies_minmax, + .strategy = &sctp_sysctl_jiffies_ms, + .extra1 = &rto_timer_min, + .extra2 = &rto_timer_max }, { .ctl_name = NET_SCTP_RTO_MAX, .procname = "rto_max", .data = &sctp_rto_max, - .maxlen = sizeof(unsigned int), + .maxlen = sizeof(long), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &one, - .extra2 = &timer_max + .proc_handler = &proc_doulongvec_ms_jiffies_minmax, + .strategy = &sctp_sysctl_jiffies_ms, + .extra1 = &rto_timer_min, + .extra2 = &rto_timer_max }, { .ctl_name = NET_SCTP_VALID_COOKIE_LIFE, .procname = "valid_cookie_life", .data = &sctp_valid_cookie_life, - .maxlen = sizeof(unsigned int), + .maxlen = sizeof(long), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &one, - .extra2 = &timer_max + .proc_handler = &proc_doulongvec_ms_jiffies_minmax, + .strategy = &sctp_sysctl_jiffies_ms, + .extra1 = &rto_timer_min, + .extra2 = &rto_timer_max }, { .ctl_name = NET_SCTP_MAX_BURST, @@ -103,10 +102,7 @@ static ctl_table sctp_table[] = { .data = &sctp_max_burst, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &zero, - .extra2 = &int_max + .proc_handler = &proc_dointvec }, { .ctl_name = NET_SCTP_ASSOCIATION_MAX_RETRANS, @@ -114,10 +110,7 @@ static ctl_table sctp_table[] = { .data = &sctp_max_retrans_association, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &one, - .extra2 = &int_max + .proc_handler = &proc_dointvec }, { .ctl_name = NET_SCTP_SNDBUF_POLICY, @@ -125,8 +118,7 @@ static ctl_table sctp_table[] = { .data = &sctp_sndbuf_policy, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec + .proc_handler = &proc_dointvec }, { .ctl_name = NET_SCTP_RCVBUF_POLICY, @@ -134,8 +126,7 @@ static ctl_table sctp_table[] = { .data = &sctp_rcvbuf_policy, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec + .proc_handler = &proc_dointvec }, { .ctl_name = NET_SCTP_PATH_MAX_RETRANS, @@ -143,10 +134,7 @@ static ctl_table sctp_table[] = { .data = &sctp_max_retrans_path, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &one, - .extra2 = &int_max + .proc_handler = &proc_dointvec }, { .ctl_name = NET_SCTP_MAX_INIT_RETRANSMITS, @@ -154,21 +142,18 @@ static ctl_table sctp_table[] = { .data = &sctp_max_retrans_init, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &one, - .extra2 = &int_max + .proc_handler = &proc_dointvec }, { .ctl_name = NET_SCTP_HB_INTERVAL, .procname = "hb_interval", .data = &sctp_hb_interval, - .maxlen = sizeof(unsigned int), + .maxlen = sizeof(long), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &one, - .extra2 = &timer_max + .proc_handler = &proc_doulongvec_ms_jiffies_minmax, + .strategy = &sctp_sysctl_jiffies_ms, + .extra1 = &rto_timer_min, + .extra2 = &rto_timer_max }, { .ctl_name = NET_SCTP_PRESERVE_ENABLE, @@ -176,26 +161,23 @@ static ctl_table sctp_table[] = { .data = &sctp_cookie_preserve_enable, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec + .proc_handler = &proc_dointvec }, { .ctl_name = NET_SCTP_RTO_ALPHA, .procname = "rto_alpha_exp_divisor", .data = &sctp_rto_alpha, .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec + .mode = 0644, + .proc_handler = &proc_dointvec }, { .ctl_name = NET_SCTP_RTO_BETA, .procname = "rto_beta_exp_divisor", .data = &sctp_rto_beta, .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec + .mode = 0644, + .proc_handler = &proc_dointvec }, { .ctl_name = NET_SCTP_ADDIP_ENABLE, @@ -203,8 +185,7 @@ static ctl_table sctp_table[] = { .data = &sctp_addip_enable, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec + .proc_handler = &proc_dointvec }, { .ctl_name = NET_SCTP_PRSCTP_ENABLE, @@ -212,8 +193,7 @@ static ctl_table sctp_table[] = { .data = &sctp_prsctp_enable, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = &proc_dointvec, - .strategy = &sysctl_intvec + .proc_handler = &proc_dointvec }, { .ctl_name = NET_SCTP_SACK_TIMEOUT, @@ -221,8 +201,8 @@ static ctl_table sctp_table[] = { .data = &sctp_sack_timeout, .maxlen = sizeof(long), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, + .proc_handler = &proc_doulongvec_ms_jiffies_minmax, + .strategy = &sctp_sysctl_jiffies_ms, .extra1 = &sack_timer_min, .extra2 = &sack_timer_max, }, @@ -262,3 +242,37 @@ void sctp_sysctl_unregister(void) { unregister_sysctl_table(sctp_sysctl_header); } + +/* Strategy function to convert jiffies to milliseconds. */ +static int sctp_sysctl_jiffies_ms(ctl_table *table, int __user *name, int nlen, + void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen, void **context) { + + if (oldval) { + size_t olen; + + if (oldlenp) { + if (get_user(olen, oldlenp)) + return -EFAULT; + + if (olen != sizeof (int)) + return -EINVAL; + } + if (put_user((*(int *)(table->data) * 1000) / HZ, + (int __user *)oldval) || + (oldlenp && put_user(sizeof (int), oldlenp))) + return -EFAULT; + } + if (newval && newlen) { + int new; + + if (newlen != sizeof (int)) + return -EINVAL; + + if (get_user(new, (int __user *)newval)) + return -EFAULT; + + *(int *)(table->data) = (new * HZ) / 1000; + } + return 1; +} diff --git a/trunk/net/sctp/transport.c b/trunk/net/sctp/transport.c index 3e5936a5f671..2763aa93de1a 100644 --- a/trunk/net/sctp/transport.c +++ b/trunk/net/sctp/transport.c @@ -75,7 +75,7 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, * parameter 'RTO.Initial'. */ peer->rtt = 0; - peer->rto = msecs_to_jiffies(sctp_rto_initial); + peer->rto = sctp_rto_initial; peer->rttvar = 0; peer->srtt = 0; peer->rto_pending = 0; diff --git a/trunk/net/socket.c b/trunk/net/socket.c index 1bc4167e0da8..b4848ce0d6ac 100644 --- a/trunk/net/socket.c +++ b/trunk/net/socket.c @@ -42,7 +42,7 @@ * Andi Kleen : Some small cleanups, optimizations, * and fixed a copy_from_user() bug. * Tigran Aivazian : sys_send(args) calls sys_sendto(args, NULL, 0) - * Tigran Aivazian : Made listen(2) backlog sanity checks + * Tigran Aivazian : Made listen(2) backlog sanity checks * protocol-independent * * @@ -53,17 +53,17 @@ * * * This module is effectively the top level interface to the BSD socket - * paradigm. + * paradigm. * * Based upon Swansea University Computer Society NET3.039 */ #include +#include #include #include #include #include -#include #include #include #include @@ -96,24 +96,25 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare); static ssize_t sock_aio_read(struct kiocb *iocb, char __user *buf, - size_t size, loff_t pos); + size_t size, loff_t pos); static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *buf, - size_t size, loff_t pos); -static int sock_mmap(struct file *file, struct vm_area_struct *vma); + size_t size, loff_t pos); +static int sock_mmap(struct file *file, struct vm_area_struct * vma); static int sock_close(struct inode *inode, struct file *file); static unsigned int sock_poll(struct file *file, struct poll_table_struct *wait); -static long sock_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +static long sock_ioctl(struct file *file, + unsigned int cmd, unsigned long arg); #ifdef CONFIG_COMPAT static long compat_sock_ioctl(struct file *file, - unsigned int cmd, unsigned long arg); + unsigned int cmd, unsigned long arg); #endif static int sock_fasync(int fd, struct file *filp, int on); static ssize_t sock_readv(struct file *file, const struct iovec *vector, unsigned long count, loff_t *ppos); static ssize_t sock_writev(struct file *file, const struct iovec *vector, - unsigned long count, loff_t *ppos); + unsigned long count, loff_t *ppos); static ssize_t sock_sendpage(struct file *file, struct page *page, int offset, size_t size, loff_t *ppos, int more); @@ -146,8 +147,52 @@ static struct file_operations socket_file_ops = { * The protocol list. Each protocol is registered in here. */ +static struct net_proto_family *net_families[NPROTO]; + +#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) +static atomic_t net_family_lockct = ATOMIC_INIT(0); static DEFINE_SPINLOCK(net_family_lock); -static const struct net_proto_family *net_families[NPROTO] __read_mostly; + +/* The strategy is: modifications net_family vector are short, do not + sleep and veeery rare, but read access should be free of any exclusive + locks. + */ + +static void net_family_write_lock(void) +{ + spin_lock(&net_family_lock); + while (atomic_read(&net_family_lockct) != 0) { + spin_unlock(&net_family_lock); + + yield(); + + spin_lock(&net_family_lock); + } +} + +static __inline__ void net_family_write_unlock(void) +{ + spin_unlock(&net_family_lock); +} + +static __inline__ void net_family_read_lock(void) +{ + atomic_inc(&net_family_lockct); + spin_unlock_wait(&net_family_lock); +} + +static __inline__ void net_family_read_unlock(void) +{ + atomic_dec(&net_family_lockct); +} + +#else +#define net_family_write_lock() do { } while(0) +#define net_family_write_unlock() do { } while(0) +#define net_family_read_lock() do { } while(0) +#define net_family_read_unlock() do { } while(0) +#endif + /* * Statistics counters of the socket lists @@ -156,20 +201,19 @@ static const struct net_proto_family *net_families[NPROTO] __read_mostly; static DEFINE_PER_CPU(int, sockets_in_use) = 0; /* - * Support routines. - * Move socket addresses back and forth across the kernel/user - * divide and look after the messy bits. + * Support routines. Move socket addresses back and forth across the kernel/user + * divide and look after the messy bits. */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - +#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - 16 for IP, 16 for IPX, 24 for IPv6, - about 80 for AX.25 + about 80 for AX.25 must be at least one bigger than the AF_UNIX size (see net/unix/af_unix.c - :unix_mkname()). + :unix_mkname()). */ - + /** * move_addr_to_kernel - copy a socket address into kernel space * @uaddr: Address in user space @@ -183,11 +227,11 @@ static DEFINE_PER_CPU(int, sockets_in_use) = 0; int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr) { - if (ulen < 0 || ulen > MAX_SOCK_ADDR) + if(ulen<0||ulen>MAX_SOCK_ADDR) return -EINVAL; - if (ulen == 0) + if(ulen==0) return 0; - if (copy_from_user(kaddr, uaddr, ulen)) + if(copy_from_user(kaddr,uaddr,ulen)) return -EFAULT; return audit_sockaddr(ulen, kaddr); } @@ -208,52 +252,51 @@ int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr) * length of the data is written over the length limit the user * specified. Zero is returned for a success. */ - -int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, - int __user *ulen) + +int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ulen) { int err; int len; - err = get_user(len, ulen); - if (err) + if((err=get_user(len, ulen))) return err; - if (len > klen) - len = klen; - if (len < 0 || len > MAX_SOCK_ADDR) + if(len>klen) + len=klen; + if(len<0 || len> MAX_SOCK_ADDR) return -EINVAL; - if (len) { + if(len) + { if (audit_sockaddr(klen, kaddr)) return -ENOMEM; - if (copy_to_user(uaddr, kaddr, len)) + if(copy_to_user(uaddr,kaddr,len)) return -EFAULT; } /* - * "fromlen shall refer to the value before truncation.." - * 1003.1g + * "fromlen shall refer to the value before truncation.." + * 1003.1g */ return __put_user(klen, ulen); } #define SOCKFS_MAGIC 0x534F434B -static kmem_cache_t *sock_inode_cachep __read_mostly; +static kmem_cache_t * sock_inode_cachep __read_mostly; static struct inode *sock_alloc_inode(struct super_block *sb) { struct socket_alloc *ei; - - ei = kmem_cache_alloc(sock_inode_cachep, SLAB_KERNEL); + ei = (struct socket_alloc *)kmem_cache_alloc(sock_inode_cachep, SLAB_KERNEL); if (!ei) return NULL; init_waitqueue_head(&ei->socket.wait); - + ei->socket.fasync_list = NULL; ei->socket.state = SS_UNCONNECTED; ei->socket.flags = 0; ei->socket.ops = NULL; ei->socket.sk = NULL; ei->socket.file = NULL; + ei->socket.flags = 0; return &ei->vfs_inode; } @@ -264,25 +307,22 @@ static void sock_destroy_inode(struct inode *inode) container_of(inode, struct socket_alloc, vfs_inode)); } -static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) +static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) { - struct socket_alloc *ei = (struct socket_alloc *)foo; + struct socket_alloc *ei = (struct socket_alloc *) foo; - if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) - == SLAB_CTOR_CONSTRUCTOR) + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) inode_init_once(&ei->vfs_inode); } - + static int init_inodecache(void) { sock_inode_cachep = kmem_cache_create("sock_inode_cache", - sizeof(struct socket_alloc), - 0, - (SLAB_HWCACHE_ALIGN | - SLAB_RECLAIM_ACCOUNT | - SLAB_MEM_SPREAD), - init_once, - NULL); + sizeof(struct socket_alloc), + 0, (SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT| + SLAB_MEM_SPREAD), + init_once, NULL); if (sock_inode_cachep == NULL) return -ENOMEM; return 0; @@ -295,8 +335,7 @@ static struct super_operations sockfs_ops = { }; static int sockfs_get_sb(struct file_system_type *fs_type, - int flags, const char *dev_name, void *data, - struct vfsmount *mnt) + int flags, const char *dev_name, void *data, struct vfsmount *mnt) { return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC, mnt); @@ -309,13 +348,12 @@ static struct file_system_type sock_fs_type = { .get_sb = sockfs_get_sb, .kill_sb = kill_anon_super, }; - static int sockfs_delete_dentry(struct dentry *dentry) { return 1; } static struct dentry_operations sockfs_dentry_operations = { - .d_delete = sockfs_delete_dentry, + .d_delete = sockfs_delete_dentry, }; /* @@ -439,12 +477,10 @@ struct socket *sockfd_lookup(int fd, int *err) struct file *file; struct socket *sock; - file = fget(fd); - if (!file) { + if (!(file = fget(fd))) { *err = -EBADF; return NULL; } - sock = sock_from_file(file, err); if (!sock) fput(file); @@ -469,7 +505,7 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) /** * sock_alloc - allocate a socket - * + * * Allocate a new inode and socket object. The two are bound together * and initialised. The socket is then returned. If we are out of inodes * NULL is returned. @@ -477,8 +513,8 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) static struct socket *sock_alloc(void) { - struct inode *inode; - struct socket *sock; + struct inode * inode; + struct socket * sock; inode = new_inode(sock_mnt->mnt_sb); if (!inode) @@ -486,7 +522,7 @@ static struct socket *sock_alloc(void) sock = SOCKET_I(inode); - inode->i_mode = S_IFSOCK | S_IRWXUGO; + inode->i_mode = S_IFSOCK|S_IRWXUGO; inode->i_uid = current->fsuid; inode->i_gid = current->fsgid; @@ -500,7 +536,7 @@ static struct socket *sock_alloc(void) * a back door. Remember to keep it shut otherwise you'll let the * creepy crawlies in. */ - + static int sock_no_open(struct inode *irrelevant, struct file *dontcare) { return -ENXIO; @@ -517,9 +553,9 @@ const struct file_operations bad_sock_fops = { * * The socket is released from the protocol stack if it has a release * callback, and the inode is then released if the socket is bound to - * an inode not a file. + * an inode not a file. */ - + void sock_release(struct socket *sock) { if (sock->ops) { @@ -539,10 +575,10 @@ void sock_release(struct socket *sock) iput(SOCK_INODE(sock)); return; } - sock->file = NULL; + sock->file=NULL; } -static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, +static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size) { struct sock_iocb *si = kiocb_to_siocb(iocb); @@ -585,14 +621,14 @@ int kernel_sendmsg(struct socket *sock, struct msghdr *msg, * the following is safe, since for compiler definitions of kvec and * iovec are identical, yielding the same in-core layout and alignment */ - msg->msg_iov = (struct iovec *)vec; + msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num; result = sock_sendmsg(sock, msg, size); set_fs(oldfs); return result; } -static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, +static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size, int flags) { int err; @@ -611,14 +647,14 @@ static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock, return sock->ops->recvmsg(iocb, sock, msg, size, flags); } -int sock_recvmsg(struct socket *sock, struct msghdr *msg, +int sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, int flags) { struct kiocb iocb; struct sock_iocb siocb; int ret; - init_sync_kiocb(&iocb, NULL); + init_sync_kiocb(&iocb, NULL); iocb.private = &siocb; ret = __sock_recvmsg(&iocb, sock, msg, size, flags); if (-EIOCBQUEUED == ret) @@ -626,8 +662,9 @@ int sock_recvmsg(struct socket *sock, struct msghdr *msg, return ret; } -int kernel_recvmsg(struct socket *sock, struct msghdr *msg, - struct kvec *vec, size_t num, size_t size, int flags) +int kernel_recvmsg(struct socket *sock, struct msghdr *msg, + struct kvec *vec, size_t num, + size_t size, int flags) { mm_segment_t oldfs = get_fs(); int result; @@ -637,7 +674,8 @@ int kernel_recvmsg(struct socket *sock, struct msghdr *msg, * the following is safe, since for compiler definitions of kvec and * iovec are identical, yielding the same in-core layout and alignment */ - msg->msg_iov = (struct iovec *)vec, msg->msg_iovlen = num; + msg->msg_iov = (struct iovec *)vec, + msg->msg_iovlen = num; result = sock_recvmsg(sock, msg, size, flags); set_fs(oldfs); return result; @@ -664,8 +702,7 @@ static ssize_t sock_sendpage(struct file *file, struct page *page, } static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, - char __user *ubuf, size_t size, - struct sock_iocb *siocb) + char __user *ubuf, size_t size, struct sock_iocb *siocb) { if (!is_sync_kiocb(iocb)) { siocb = kmalloc(sizeof(*siocb), GFP_KERNEL); @@ -683,21 +720,20 @@ static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb, } static ssize_t do_sock_read(struct msghdr *msg, struct kiocb *iocb, - struct file *file, struct iovec *iov, - unsigned long nr_segs) + struct file *file, struct iovec *iov, unsigned long nr_segs) { struct socket *sock = file->private_data; size_t size = 0; int i; - for (i = 0; i < nr_segs; i++) - size += iov[i].iov_len; + for (i = 0 ; i < nr_segs ; i++) + size += iov[i].iov_len; msg->msg_name = NULL; msg->msg_namelen = 0; msg->msg_control = NULL; msg->msg_controllen = 0; - msg->msg_iov = (struct iovec *)iov; + msg->msg_iov = (struct iovec *) iov; msg->msg_iovlen = nr_segs; msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; @@ -712,7 +748,7 @@ static ssize_t sock_readv(struct file *file, const struct iovec *iov, struct msghdr msg; int ret; - init_sync_kiocb(&iocb, NULL); + init_sync_kiocb(&iocb, NULL); iocb.private = &siocb; ret = do_sock_read(&msg, &iocb, file, (struct iovec *)iov, nr_segs); @@ -722,7 +758,7 @@ static ssize_t sock_readv(struct file *file, const struct iovec *iov, } static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf, - size_t count, loff_t pos) + size_t count, loff_t pos) { struct sock_iocb siocb, *x; @@ -735,25 +771,24 @@ static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf, if (!x) return -ENOMEM; return do_sock_read(&x->async_msg, iocb, iocb->ki_filp, - &x->async_iov, 1); + &x->async_iov, 1); } static ssize_t do_sock_write(struct msghdr *msg, struct kiocb *iocb, - struct file *file, struct iovec *iov, - unsigned long nr_segs) + struct file *file, struct iovec *iov, unsigned long nr_segs) { struct socket *sock = file->private_data; size_t size = 0; int i; - for (i = 0; i < nr_segs; i++) - size += iov[i].iov_len; + for (i = 0 ; i < nr_segs ; i++) + size += iov[i].iov_len; msg->msg_name = NULL; msg->msg_namelen = 0; msg->msg_control = NULL; msg->msg_controllen = 0; - msg->msg_iov = (struct iovec *)iov; + msg->msg_iov = (struct iovec *) iov; msg->msg_iovlen = nr_segs; msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0; if (sock->type == SOCK_SEQPACKET) @@ -780,7 +815,7 @@ static ssize_t sock_writev(struct file *file, const struct iovec *iov, } static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf, - size_t count, loff_t pos) + size_t count, loff_t pos) { struct sock_iocb siocb, *x; @@ -794,48 +829,46 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf, return -ENOMEM; return do_sock_write(&x->async_msg, iocb, iocb->ki_filp, - &x->async_iov, 1); + &x->async_iov, 1); } + /* * Atomic setting of ioctl hooks to avoid race * with module unload. */ static DEFINE_MUTEX(br_ioctl_mutex); -static int (*br_ioctl_hook) (unsigned int cmd, void __user *arg) = NULL; +static int (*br_ioctl_hook)(unsigned int cmd, void __user *arg) = NULL; -void brioctl_set(int (*hook) (unsigned int, void __user *)) +void brioctl_set(int (*hook)(unsigned int, void __user *)) { mutex_lock(&br_ioctl_mutex); br_ioctl_hook = hook; mutex_unlock(&br_ioctl_mutex); } - EXPORT_SYMBOL(brioctl_set); static DEFINE_MUTEX(vlan_ioctl_mutex); -static int (*vlan_ioctl_hook) (void __user *arg); +static int (*vlan_ioctl_hook)(void __user *arg); -void vlan_ioctl_set(int (*hook) (void __user *)) +void vlan_ioctl_set(int (*hook)(void __user *)) { mutex_lock(&vlan_ioctl_mutex); vlan_ioctl_hook = hook; mutex_unlock(&vlan_ioctl_mutex); } - EXPORT_SYMBOL(vlan_ioctl_set); static DEFINE_MUTEX(dlci_ioctl_mutex); -static int (*dlci_ioctl_hook) (unsigned int, void __user *); +static int (*dlci_ioctl_hook)(unsigned int, void __user *); -void dlci_ioctl_set(int (*hook) (unsigned int, void __user *)) +void dlci_ioctl_set(int (*hook)(unsigned int, void __user *)) { mutex_lock(&dlci_ioctl_mutex); dlci_ioctl_hook = hook; mutex_unlock(&dlci_ioctl_mutex); } - EXPORT_SYMBOL(dlci_ioctl_set); /* @@ -857,8 +890,8 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { err = dev_ioctl(cmd, argp); } else -#endif /* CONFIG_WIRELESS_EXT */ - switch (cmd) { +#endif /* CONFIG_WIRELESS_EXT */ + switch (cmd) { case FIOSETOWN: case SIOCSPGRP: err = -EFAULT; @@ -868,8 +901,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) break; case FIOGETOWN: case SIOCGPGRP: - err = put_user(sock->file->f_owner.pid, - (int __user *)argp); + err = put_user(sock->file->f_owner.pid, (int __user *)argp); break; case SIOCGIFBR: case SIOCSIFBR: @@ -880,7 +912,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) request_module("bridge"); mutex_lock(&br_ioctl_mutex); - if (br_ioctl_hook) + if (br_ioctl_hook) err = br_ioctl_hook(cmd, argp); mutex_unlock(&br_ioctl_mutex); break; @@ -897,7 +929,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) break; case SIOCGIFDIVERT: case SIOCSIFDIVERT: - /* Convert this to call through a hook */ + /* Convert this to call through a hook */ err = divert_ioctl(cmd, argp); break; case SIOCADDDLCI: @@ -922,7 +954,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) if (err == -ENOIOCTLCMD) err = dev_ioctl(cmd, argp); break; - } + } return err; } @@ -930,7 +962,7 @@ int sock_create_lite(int family, int type, int protocol, struct socket **res) { int err; struct socket *sock = NULL; - + err = security_socket_create(family, type, protocol, 1); if (err) goto out; @@ -941,33 +973,26 @@ int sock_create_lite(int family, int type, int protocol, struct socket **res) goto out; } + security_socket_post_create(sock, family, type, protocol, 1); sock->type = type; - err = security_socket_post_create(sock, family, type, protocol, 1); - if (err) - goto out_release; - out: *res = sock; return err; -out_release: - sock_release(sock); - sock = NULL; - goto out; } /* No kernel lock held - perfect */ -static unsigned int sock_poll(struct file *file, poll_table *wait) +static unsigned int sock_poll(struct file *file, poll_table * wait) { struct socket *sock; /* - * We can't return errors to poll, so it's either yes or no. + * We can't return errors to poll, so it's either yes or no. */ sock = file->private_data; return sock->ops->poll(file, sock, wait); } -static int sock_mmap(struct file *file, struct vm_area_struct *vma) +static int sock_mmap(struct file * file, struct vm_area_struct * vma) { struct socket *sock = file->private_data; @@ -977,11 +1002,12 @@ static int sock_mmap(struct file *file, struct vm_area_struct *vma) static int sock_close(struct inode *inode, struct file *filp) { /* - * It was possible the inode is NULL we were - * closing an unfinished socket. + * It was possible the inode is NULL we were + * closing an unfinished socket. */ - if (!inode) { + if (!inode) + { printk(KERN_DEBUG "sock_close: NULL inode\n"); return 0; } @@ -1007,52 +1033,57 @@ static int sock_close(struct inode *inode, struct file *filp) static int sock_fasync(int fd, struct file *filp, int on) { - struct fasync_struct *fa, *fna = NULL, **prev; + struct fasync_struct *fa, *fna=NULL, **prev; struct socket *sock; struct sock *sk; - if (on) { + if (on) + { fna = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL); - if (fna == NULL) + if(fna==NULL) return -ENOMEM; } sock = filp->private_data; - sk = sock->sk; - if (sk == NULL) { + if ((sk=sock->sk) == NULL) { kfree(fna); return -EINVAL; } lock_sock(sk); - prev = &(sock->fasync_list); + prev=&(sock->fasync_list); - for (fa = *prev; fa != NULL; prev = &fa->fa_next, fa = *prev) - if (fa->fa_file == filp) + for (fa=*prev; fa!=NULL; prev=&fa->fa_next,fa=*prev) + if (fa->fa_file==filp) break; - if (on) { - if (fa != NULL) { + if(on) + { + if(fa!=NULL) + { write_lock_bh(&sk->sk_callback_lock); - fa->fa_fd = fd; + fa->fa_fd=fd; write_unlock_bh(&sk->sk_callback_lock); kfree(fna); goto out; } - fna->fa_file = filp; - fna->fa_fd = fd; - fna->magic = FASYNC_MAGIC; - fna->fa_next = sock->fasync_list; + fna->fa_file=filp; + fna->fa_fd=fd; + fna->magic=FASYNC_MAGIC; + fna->fa_next=sock->fasync_list; write_lock_bh(&sk->sk_callback_lock); - sock->fasync_list = fna; + sock->fasync_list=fna; write_unlock_bh(&sk->sk_callback_lock); - } else { - if (fa != NULL) { + } + else + { + if (fa!=NULL) + { write_lock_bh(&sk->sk_callback_lock); - *prev = fa->fa_next; + *prev=fa->fa_next; write_unlock_bh(&sk->sk_callback_lock); kfree(fa); } @@ -1069,9 +1100,10 @@ int sock_wake_async(struct socket *sock, int how, int band) { if (!sock || !sock->fasync_list) return -1; - switch (how) { + switch (how) + { case 1: - + if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) break; goto call_kill; @@ -1080,7 +1112,7 @@ int sock_wake_async(struct socket *sock, int how, int band) break; /* fall through */ case 0: -call_kill: + call_kill: __kill_fasync(sock->fasync_list, SIGIO, band); break; case 3: @@ -1089,15 +1121,13 @@ int sock_wake_async(struct socket *sock, int how, int band) return 0; } -static int __sock_create(int family, int type, int protocol, - struct socket **res, int kern) +static int __sock_create(int family, int type, int protocol, struct socket **res, int kern) { int err; struct socket *sock; - const struct net_proto_family *pf; /* - * Check protocol is in range + * Check protocol is in range */ if (family < 0 || family >= NPROTO) return -EAFNOSUPPORT; @@ -1110,11 +1140,10 @@ static int __sock_create(int family, int type, int protocol, deadlock in module load. */ if (family == PF_INET && type == SOCK_PACKET) { - static int warned; + static int warned; if (!warned) { warned = 1; - printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", - current->comm); + printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", current->comm); } family = PF_PACKET; } @@ -1122,84 +1151,78 @@ static int __sock_create(int family, int type, int protocol, err = security_socket_create(family, type, protocol, kern); if (err) return err; - - /* - * Allocate the socket and allow the family to set things up. if - * the protocol is 0, the family is instructed to select an appropriate - * default. - */ - sock = sock_alloc(); - if (!sock) { - if (net_ratelimit()) - printk(KERN_WARNING "socket: no more sockets\n"); - return -ENFILE; /* Not exactly a match, but its the - closest posix thing */ - } - - sock->type = type; - + #if defined(CONFIG_KMOD) - /* Attempt to load a protocol module if the find failed. - * - * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user + /* Attempt to load a protocol module if the find failed. + * + * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user * requested real, full-featured networking support upon configuration. * Otherwise module support will break! */ - if (net_families[family] == NULL) - request_module("net-pf-%d", family); + if (net_families[family]==NULL) + { + request_module("net-pf-%d",family); + } #endif - rcu_read_lock(); - pf = rcu_dereference(net_families[family]); - err = -EAFNOSUPPORT; - if (!pf) - goto out_release; + net_family_read_lock(); + if (net_families[family] == NULL) { + err = -EAFNOSUPPORT; + goto out; + } + +/* + * Allocate the socket and allow the family to set things up. if + * the protocol is 0, the family is instructed to select an appropriate + * default. + */ + + if (!(sock = sock_alloc())) { + printk(KERN_WARNING "socket: no more sockets\n"); + err = -ENFILE; /* Not exactly a match, but its the + closest posix thing */ + goto out; + } + + sock->type = type; /* * We will call the ->create function, that possibly is in a loadable * module, so we have to bump that loadable module refcnt first. */ - if (!try_module_get(pf->owner)) + err = -EAFNOSUPPORT; + if (!try_module_get(net_families[family]->owner)) goto out_release; - /* Now protected by module ref count */ - rcu_read_unlock(); - - err = pf->create(sock, protocol); - if (err < 0) + if ((err = net_families[family]->create(sock, protocol)) < 0) { + sock->ops = NULL; goto out_module_put; + } /* * Now to bump the refcnt of the [loadable] module that owns this * socket at sock_release time we decrement its refcnt. */ - if (!try_module_get(sock->ops->owner)) - goto out_module_busy; - + if (!try_module_get(sock->ops->owner)) { + sock->ops = NULL; + goto out_module_put; + } /* * Now that we're done with the ->create function, the [loadable] * module can have its refcnt decremented */ - module_put(pf->owner); - err = security_socket_post_create(sock, family, type, protocol, kern); - if (err) - goto out_release; + module_put(net_families[family]->owner); *res = sock; + security_socket_post_create(sock, family, type, protocol, kern); - return 0; - -out_module_busy: - err = -EAFNOSUPPORT; -out_module_put: - sock->ops = NULL; - module_put(pf->owner); -out_sock_release: - sock_release(sock); +out: + net_family_read_unlock(); return err; - +out_module_put: + module_put(net_families[family]->owner); out_release: - rcu_read_unlock(); - goto out_sock_release; + sock_release(sock); + goto out; } int sock_create(int family, int type, int protocol, struct socket **res) @@ -1238,8 +1261,7 @@ asmlinkage long sys_socket(int family, int type, int protocol) * Create a pair of connected sockets. */ -asmlinkage long sys_socketpair(int family, int type, int protocol, - int __user *usockvec) +asmlinkage long sys_socketpair(int family, int type, int protocol, int __user *usockvec) { struct socket *sock1, *sock2; int fd1, fd2, err; @@ -1258,7 +1280,7 @@ asmlinkage long sys_socketpair(int family, int type, int protocol, goto out_release_1; err = sock1->ops->socketpair(sock1, sock2); - if (err < 0) + if (err < 0) goto out_release_both; fd1 = fd2 = -1; @@ -1277,7 +1299,7 @@ asmlinkage long sys_socketpair(int family, int type, int protocol, * Not kernel problem. */ - err = put_user(fd1, &usockvec[0]); + err = put_user(fd1, &usockvec[0]); if (!err) err = put_user(fd2, &usockvec[1]); if (!err) @@ -1288,18 +1310,19 @@ asmlinkage long sys_socketpair(int family, int type, int protocol, return err; out_close_1: - sock_release(sock2); + sock_release(sock2); sys_close(fd1); return err; out_release_both: - sock_release(sock2); + sock_release(sock2); out_release_1: - sock_release(sock1); + sock_release(sock1); out: return err; } + /* * Bind a name to a socket. Nothing much to do here since it's * the protocol's responsibility to handle the local address. @@ -1314,39 +1337,35 @@ asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) char address[MAX_SOCK_ADDR]; int err, fput_needed; - sock = sockfd_lookup_light(fd, &err, &fput_needed); - if(sock) { - err = move_addr_to_kernel(umyaddr, addrlen, address); - if (err >= 0) { - err = security_socket_bind(sock, - (struct sockaddr *)address, - addrlen); + if((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL) + { + if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) { + err = security_socket_bind(sock, (struct sockaddr *)address, addrlen); if (!err) err = sock->ops->bind(sock, - (struct sockaddr *) - address, addrlen); + (struct sockaddr *)address, addrlen); } fput_light(sock->file, fput_needed); - } + } return err; } + /* * Perform a listen. Basically, we allow the protocol to do anything * necessary for a listen, and if that works, we mark the socket as * ready for listening. */ -int sysctl_somaxconn __read_mostly = SOMAXCONN; +int sysctl_somaxconn = SOMAXCONN; asmlinkage long sys_listen(int fd, int backlog) { struct socket *sock; int err, fput_needed; - - sock = sockfd_lookup_light(fd, &err, &fput_needed); - if (sock) { - if ((unsigned)backlog > sysctl_somaxconn) + + if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) { + if ((unsigned) backlog > sysctl_somaxconn) backlog = sysctl_somaxconn; err = security_socket_listen(sock, backlog); @@ -1358,6 +1377,7 @@ asmlinkage long sys_listen(int fd, int backlog) return err; } + /* * For accept, we attempt to create a new socket, set up the link * with the client, wake up the client, then return the new @@ -1370,8 +1390,7 @@ asmlinkage long sys_listen(int fd, int backlog) * clean when we restucture accept also. */ -asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, - int __user *upeer_addrlen) +asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen) { struct socket *sock, *newsock; struct file *newfile; @@ -1383,7 +1402,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, goto out; err = -ENFILE; - if (!(newsock = sock_alloc())) + if (!(newsock = sock_alloc())) goto out_put; newsock->type = sock->type; @@ -1415,13 +1434,11 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, goto out_fd; if (upeer_sockaddr) { - if (newsock->ops->getname(newsock, (struct sockaddr *)address, - &len, 2) < 0) { + if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) { err = -ECONNABORTED; goto out_fd; } - err = move_addr_to_user(address, len, upeer_sockaddr, - upeer_addrlen); + err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen); if (err < 0) goto out_fd; } @@ -1443,6 +1460,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, goto out_put; } + /* * Attempt to connect to a socket with the server address. The address * is in user space so we verify it is OK and move it to kernel space. @@ -1455,8 +1473,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, * include the -EINPROGRESS status for such sockets. */ -asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, - int addrlen) +asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen) { struct socket *sock; char address[MAX_SOCK_ADDR]; @@ -1469,12 +1486,11 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, if (err < 0) goto out_put; - err = - security_socket_connect(sock, (struct sockaddr *)address, addrlen); + err = security_socket_connect(sock, (struct sockaddr *)address, addrlen); if (err) goto out_put; - err = sock->ops->connect(sock, (struct sockaddr *)address, addrlen, + err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen, sock->file->f_flags); out_put: fput_light(sock->file, fput_needed); @@ -1487,13 +1503,12 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, * name to user space. */ -asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, - int __user *usockaddr_len) +asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len) { struct socket *sock; char address[MAX_SOCK_ADDR]; int len, err, fput_needed; - + sock = sockfd_lookup_light(fd, &err, &fput_needed); if (!sock) goto out; @@ -1518,27 +1533,22 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, * name to user space. */ -asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, - int __user *usockaddr_len) +asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int __user *usockaddr_len) { struct socket *sock; char address[MAX_SOCK_ADDR]; int len, err, fput_needed; - sock = sockfd_lookup_light(fd, &err, &fput_needed); - if (sock != NULL) { + if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) { err = security_socket_getpeername(sock); if (err) { fput_light(sock->file, fput_needed); return err; } - err = - sock->ops->getname(sock, (struct sockaddr *)address, &len, - 1); + err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1); if (!err) - err = move_addr_to_user(address, len, usockaddr, - usockaddr_len); + err=move_addr_to_user(address,len, usockaddr, usockaddr_len); fput_light(sock->file, fput_needed); } return err; @@ -1550,9 +1560,8 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, * the protocol. */ -asmlinkage long sys_sendto(int fd, void __user *buff, size_t len, - unsigned flags, struct sockaddr __user *addr, - int addr_len) +asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flags, + struct sockaddr __user *addr, int addr_len) { struct socket *sock; char address[MAX_SOCK_ADDR]; @@ -1569,55 +1578,54 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len, sock = sock_from_file(sock_file, &err); if (!sock) goto out_put; - iov.iov_base = buff; - iov.iov_len = len; - msg.msg_name = NULL; - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_namelen = 0; + iov.iov_base=buff; + iov.iov_len=len; + msg.msg_name=NULL; + msg.msg_iov=&iov; + msg.msg_iovlen=1; + msg.msg_control=NULL; + msg.msg_controllen=0; + msg.msg_namelen=0; if (addr) { err = move_addr_to_kernel(addr, addr_len, address); if (err < 0) goto out_put; - msg.msg_name = address; - msg.msg_namelen = addr_len; + msg.msg_name=address; + msg.msg_namelen=addr_len; } if (sock->file->f_flags & O_NONBLOCK) flags |= MSG_DONTWAIT; msg.msg_flags = flags; err = sock_sendmsg(sock, &msg, len); -out_put: +out_put: fput_light(sock_file, fput_needed); return err; } /* - * Send a datagram down a socket. + * Send a datagram down a socket. */ -asmlinkage long sys_send(int fd, void __user *buff, size_t len, unsigned flags) +asmlinkage long sys_send(int fd, void __user * buff, size_t len, unsigned flags) { return sys_sendto(fd, buff, len, flags, NULL, 0); } /* - * Receive a frame from the socket and optionally record the address of the + * Receive a frame from the socket and optionally record the address of the * sender. We verify the buffers are writable and if needed move the * sender address from kernel to user space. */ -asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size, - unsigned flags, struct sockaddr __user *addr, - int __user *addr_len) +asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned flags, + struct sockaddr __user *addr, int __user *addr_len) { struct socket *sock; struct iovec iov; struct msghdr msg; char address[MAX_SOCK_ADDR]; - int err, err2; + int err,err2; struct file *sock_file; int fput_needed; @@ -1629,22 +1637,23 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size, if (!sock) goto out; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_iovlen = 1; - msg.msg_iov = &iov; - iov.iov_len = size; - iov.iov_base = ubuf; - msg.msg_name = address; - msg.msg_namelen = MAX_SOCK_ADDR; + msg.msg_control=NULL; + msg.msg_controllen=0; + msg.msg_iovlen=1; + msg.msg_iov=&iov; + iov.iov_len=size; + iov.iov_base=ubuf; + msg.msg_name=address; + msg.msg_namelen=MAX_SOCK_ADDR; if (sock->file->f_flags & O_NONBLOCK) flags |= MSG_DONTWAIT; - err = sock_recvmsg(sock, &msg, size, flags); + err=sock_recvmsg(sock, &msg, size, flags); - if (err >= 0 && addr != NULL) { - err2 = move_addr_to_user(address, msg.msg_namelen, addr, addr_len); - if (err2 < 0) - err = err2; + if(err >= 0 && addr != NULL) + { + err2=move_addr_to_user(address, msg.msg_namelen, addr, addr_len); + if(err2<0) + err=err2; } out: fput_light(sock_file, fput_needed); @@ -1652,11 +1661,10 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size, } /* - * Receive a datagram from a socket. + * Receive a datagram from a socket. */ -asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size, - unsigned flags) +asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags) { return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); } @@ -1666,29 +1674,24 @@ asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size, * to pass the user mode parameter for the protocols to sort out. */ -asmlinkage long sys_setsockopt(int fd, int level, int optname, - char __user *optval, int optlen) +asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen) { int err, fput_needed; struct socket *sock; if (optlen < 0) return -EINVAL; - - sock = sockfd_lookup_light(fd, &err, &fput_needed); - if (sock != NULL) { - err = security_socket_setsockopt(sock, level, optname); + + if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) + { + err = security_socket_setsockopt(sock,level,optname); if (err) goto out_put; if (level == SOL_SOCKET) - err = - sock_setsockopt(sock, level, optname, optval, - optlen); + err=sock_setsockopt(sock,level,optname,optval,optlen); else - err = - sock->ops->setsockopt(sock, level, optname, optval, - optlen); + err=sock->ops->setsockopt(sock, level, optname, optval, optlen); out_put: fput_light(sock->file, fput_needed); } @@ -1700,32 +1703,27 @@ asmlinkage long sys_setsockopt(int fd, int level, int optname, * to pass a user mode parameter for the protocols to sort out. */ -asmlinkage long sys_getsockopt(int fd, int level, int optname, - char __user *optval, int __user *optlen) +asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen) { int err, fput_needed; struct socket *sock; - sock = sockfd_lookup_light(fd, &err, &fput_needed); - if (sock != NULL) { + if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) { err = security_socket_getsockopt(sock, level, optname); if (err) goto out_put; if (level == SOL_SOCKET) - err = - sock_getsockopt(sock, level, optname, optval, - optlen); + err=sock_getsockopt(sock,level,optname,optval,optlen); else - err = - sock->ops->getsockopt(sock, level, optname, optval, - optlen); + err=sock->ops->getsockopt(sock, level, optname, optval, optlen); out_put: fput_light(sock->file, fput_needed); } return err; } + /* * Shutdown a socket. */ @@ -1735,8 +1733,8 @@ asmlinkage long sys_shutdown(int fd, int how) int err, fput_needed; struct socket *sock; - sock = sockfd_lookup_light(fd, &err, &fput_needed); - if (sock != NULL) { + if ((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL) + { err = security_socket_shutdown(sock, how); if (!err) err = sock->ops->shutdown(sock, how); @@ -1745,42 +1743,41 @@ asmlinkage long sys_shutdown(int fd, int how) return err; } -/* A couple of helpful macros for getting the address of the 32/64 bit +/* A couple of helpful macros for getting the address of the 32/64 bit * fields which are the same type (int / unsigned) on our platforms. */ #define COMPAT_MSG(msg, member) ((MSG_CMSG_COMPAT & flags) ? &msg##_compat->member : &msg->member) #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) + /* * BSD sendmsg interface */ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) { - struct compat_msghdr __user *msg_compat = - (struct compat_msghdr __user *)msg; + struct compat_msghdr __user *msg_compat = (struct compat_msghdr __user *)msg; struct socket *sock; char address[MAX_SOCK_ADDR]; struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; unsigned char ctl[sizeof(struct cmsghdr) + 20] - __attribute__ ((aligned(sizeof(__kernel_size_t)))); - /* 20 is size of ipv6_pktinfo */ + __attribute__ ((aligned (sizeof(__kernel_size_t)))); + /* 20 is size of ipv6_pktinfo */ unsigned char *ctl_buf = ctl; struct msghdr msg_sys; int err, ctl_len, iov_size, total_len; int fput_needed; - + err = -EFAULT; if (MSG_CMSG_COMPAT & flags) { if (get_compat_msghdr(&msg_sys, msg_compat)) return -EFAULT; - } - else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr))) + } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr))) return -EFAULT; sock = sockfd_lookup_light(fd, &err, &fput_needed); - if (!sock) + if (!sock) goto out; /* do not move before msg_sys is valid */ @@ -1788,7 +1785,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) if (msg_sys.msg_iovlen > UIO_MAXIOV) goto out_put; - /* Check whether to allocate the iovec area */ + /* Check whether to allocate the iovec area*/ err = -ENOMEM; iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); if (msg_sys.msg_iovlen > UIO_FASTIOV) { @@ -1802,7 +1799,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ); } else err = verify_iovec(&msg_sys, iov, address, VERIFY_READ); - if (err < 0) + if (err < 0) goto out_freeiov; total_len = err; @@ -1810,19 +1807,18 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) if (msg_sys.msg_controllen > INT_MAX) goto out_freeiov; - ctl_len = msg_sys.msg_controllen; + ctl_len = msg_sys.msg_controllen; if ((MSG_CMSG_COMPAT & flags) && ctl_len) { - err = - cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl, - sizeof(ctl)); + err = cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl, sizeof(ctl)); if (err) goto out_freeiov; ctl_buf = msg_sys.msg_control; ctl_len = msg_sys.msg_controllen; } else if (ctl_len) { - if (ctl_len > sizeof(ctl)) { + if (ctl_len > sizeof(ctl)) + { ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); - if (ctl_buf == NULL) + if (ctl_buf == NULL) goto out_freeiov; } err = -EFAULT; @@ -1831,8 +1827,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) * Afterwards, it will be a kernel pointer. Thus the compiler-assisted * checking falls down on this. */ - if (copy_from_user(ctl_buf, (void __user *)msg_sys.msg_control, - ctl_len)) + if (copy_from_user(ctl_buf, (void __user *) msg_sys.msg_control, ctl_len)) goto out_freectl; msg_sys.msg_control = ctl_buf; } @@ -1843,14 +1838,14 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) err = sock_sendmsg(sock, &msg_sys, total_len); out_freectl: - if (ctl_buf != ctl) + if (ctl_buf != ctl) sock_kfree_s(sock->sk, ctl_buf, ctl_len); out_freeiov: if (iov != iovstack) sock_kfree_s(sock->sk, iov, iov_size); out_put: fput_light(sock->file, fput_needed); -out: +out: return err; } @@ -1858,14 +1853,12 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) * BSD recvmsg interface */ -asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, - unsigned int flags) +asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flags) { - struct compat_msghdr __user *msg_compat = - (struct compat_msghdr __user *)msg; + struct compat_msghdr __user *msg_compat = (struct compat_msghdr __user *)msg; struct socket *sock; struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov = iovstack; + struct iovec *iov=iovstack; struct msghdr msg_sys; unsigned long cmsg_ptr; int err, iov_size, total_len, len; @@ -1877,13 +1870,13 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, /* user mode address pointers */ struct sockaddr __user *uaddr; int __user *uaddr_len; - + if (MSG_CMSG_COMPAT & flags) { if (get_compat_msghdr(&msg_sys, msg_compat)) return -EFAULT; - } - else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr))) - return -EFAULT; + } else + if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr))) + return -EFAULT; sock = sockfd_lookup_light(fd, &err, &fput_needed); if (!sock) @@ -1892,8 +1885,8 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, err = -EMSGSIZE; if (msg_sys.msg_iovlen > UIO_MAXIOV) goto out_put; - - /* Check whether to allocate the iovec area */ + + /* Check whether to allocate the iovec area*/ err = -ENOMEM; iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); if (msg_sys.msg_iovlen > UIO_FASTIOV) { @@ -1903,11 +1896,11 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, } /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) + * Save the user-mode address (verify_iovec will change the + * kernel msghdr to use the kernel address space) */ - - uaddr = (void __user *)msg_sys.msg_name; + + uaddr = (void __user *) msg_sys.msg_name; uaddr_len = COMPAT_NAMELEN(msg); if (MSG_CMSG_COMPAT & flags) { err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE); @@ -1915,13 +1908,13 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, err = verify_iovec(&msg_sys, iov, addr, VERIFY_WRITE); if (err < 0) goto out_freeiov; - total_len = err; + total_len=err; cmsg_ptr = (unsigned long)msg_sys.msg_control; msg_sys.msg_flags = 0; if (MSG_CMSG_COMPAT & flags) msg_sys.msg_flags = MSG_CMSG_COMPAT; - + if (sock->file->f_flags & O_NONBLOCK) flags |= MSG_DONTWAIT; err = sock_recvmsg(sock, &msg_sys, total_len, flags); @@ -1930,8 +1923,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, len = err; if (uaddr != NULL) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, - uaddr_len); + err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); if (err < 0) goto out_freeiov; } @@ -1940,10 +1932,10 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, if (err) goto out_freeiov; if (MSG_CMSG_COMPAT & flags) - err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr, + err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, &msg_compat->msg_controllen); else - err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr, + err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, &msg->msg_controllen); if (err) goto out_freeiov; @@ -1962,187 +1954,163 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, /* Argument list sizes for sys_socketcall */ #define AL(x) ((x) * sizeof(unsigned long)) -static const unsigned char nargs[18]={ - AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), - AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), - AL(6),AL(2),AL(5),AL(5),AL(3),AL(3) -}; - +static unsigned char nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), + AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), + AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; #undef AL /* - * System call vectors. + * System call vectors. * * Argument checking cleaned up. Saved 20% in size. * This function doesn't need to set the kernel lock because - * it is set by the callees. + * it is set by the callees. */ asmlinkage long sys_socketcall(int call, unsigned long __user *args) { unsigned long a[6]; - unsigned long a0, a1; + unsigned long a0,a1; int err; - if (call < 1 || call > SYS_RECVMSG) + if(call<1||call>SYS_RECVMSG) return -EINVAL; /* copy_from_user should be SMP safe. */ if (copy_from_user(a, args, nargs[call])) return -EFAULT; - err = audit_socketcall(nargs[call] / sizeof(unsigned long), a); + err = audit_socketcall(nargs[call]/sizeof(unsigned long), a); if (err) return err; - a0 = a[0]; - a1 = a[1]; - - switch (call) { - case SYS_SOCKET: - err = sys_socket(a0, a1, a[2]); - break; - case SYS_BIND: - err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]); - break; - case SYS_CONNECT: - err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]); - break; - case SYS_LISTEN: - err = sys_listen(a0, a1); - break; - case SYS_ACCEPT: - err = - sys_accept(a0, (struct sockaddr __user *)a1, - (int __user *)a[2]); - break; - case SYS_GETSOCKNAME: - err = - sys_getsockname(a0, (struct sockaddr __user *)a1, - (int __user *)a[2]); - break; - case SYS_GETPEERNAME: - err = - sys_getpeername(a0, (struct sockaddr __user *)a1, - (int __user *)a[2]); - break; - case SYS_SOCKETPAIR: - err = sys_socketpair(a0, a1, a[2], (int __user *)a[3]); - break; - case SYS_SEND: - err = sys_send(a0, (void __user *)a1, a[2], a[3]); - break; - case SYS_SENDTO: - err = sys_sendto(a0, (void __user *)a1, a[2], a[3], - (struct sockaddr __user *)a[4], a[5]); - break; - case SYS_RECV: - err = sys_recv(a0, (void __user *)a1, a[2], a[3]); - break; - case SYS_RECVFROM: - err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3], - (struct sockaddr __user *)a[4], - (int __user *)a[5]); - break; - case SYS_SHUTDOWN: - err = sys_shutdown(a0, a1); - break; - case SYS_SETSOCKOPT: - err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]); - break; - case SYS_GETSOCKOPT: - err = - sys_getsockopt(a0, a1, a[2], (char __user *)a[3], - (int __user *)a[4]); - break; - case SYS_SENDMSG: - err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); - break; - case SYS_RECVMSG: - err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); - break; - default: - err = -EINVAL; - break; + a0=a[0]; + a1=a[1]; + + switch(call) + { + case SYS_SOCKET: + err = sys_socket(a0,a1,a[2]); + break; + case SYS_BIND: + err = sys_bind(a0,(struct sockaddr __user *)a1, a[2]); + break; + case SYS_CONNECT: + err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]); + break; + case SYS_LISTEN: + err = sys_listen(a0,a1); + break; + case SYS_ACCEPT: + err = sys_accept(a0,(struct sockaddr __user *)a1, (int __user *)a[2]); + break; + case SYS_GETSOCKNAME: + err = sys_getsockname(a0,(struct sockaddr __user *)a1, (int __user *)a[2]); + break; + case SYS_GETPEERNAME: + err = sys_getpeername(a0, (struct sockaddr __user *)a1, (int __user *)a[2]); + break; + case SYS_SOCKETPAIR: + err = sys_socketpair(a0,a1, a[2], (int __user *)a[3]); + break; + case SYS_SEND: + err = sys_send(a0, (void __user *)a1, a[2], a[3]); + break; + case SYS_SENDTO: + err = sys_sendto(a0,(void __user *)a1, a[2], a[3], + (struct sockaddr __user *)a[4], a[5]); + break; + case SYS_RECV: + err = sys_recv(a0, (void __user *)a1, a[2], a[3]); + break; + case SYS_RECVFROM: + err = sys_recvfrom(a0, (void __user *)a1, a[2], a[3], + (struct sockaddr __user *)a[4], (int __user *)a[5]); + break; + case SYS_SHUTDOWN: + err = sys_shutdown(a0,a1); + break; + case SYS_SETSOCKOPT: + err = sys_setsockopt(a0, a1, a[2], (char __user *)a[3], a[4]); + break; + case SYS_GETSOCKOPT: + err = sys_getsockopt(a0, a1, a[2], (char __user *)a[3], (int __user *)a[4]); + break; + case SYS_SENDMSG: + err = sys_sendmsg(a0, (struct msghdr __user *) a1, a[2]); + break; + case SYS_RECVMSG: + err = sys_recvmsg(a0, (struct msghdr __user *) a1, a[2]); + break; + default: + err = -EINVAL; + break; } return err; } -#endif /* __ARCH_WANT_SYS_SOCKETCALL */ +#endif /* __ARCH_WANT_SYS_SOCKETCALL */ -/** - * sock_register - add a socket protocol handler - * @ops: description of protocol - * +/* * This function is called by a protocol handler that wants to * advertise its address family, and have it linked into the - * socket interface. The value ops->family coresponds to the - * socket system call protocol family. + * SOCKET module. */ -int sock_register(const struct net_proto_family *ops) + +int sock_register(struct net_proto_family *ops) { int err; if (ops->family >= NPROTO) { - printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family, - NPROTO); + printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family, NPROTO); return -ENOBUFS; } - - spin_lock(&net_family_lock); - if (net_families[ops->family]) - err = -EEXIST; - else { - net_families[ops->family] = ops; + net_family_write_lock(); + err = -EEXIST; + if (net_families[ops->family] == NULL) { + net_families[ops->family]=ops; err = 0; } - spin_unlock(&net_family_lock); - - printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family); + net_family_write_unlock(); + printk(KERN_INFO "NET: Registered protocol family %d\n", + ops->family); return err; } -/** - * sock_unregister - remove a protocol handler - * @family: protocol family to remove - * +/* * This function is called by a protocol handler that wants to * remove its address family, and have it unlinked from the - * new socket creation. - * - * If protocol handler is a module, then it can use module reference - * counts to protect against new references. If protocol handler is not - * a module then it needs to provide its own protection in - * the ops->create routine. + * SOCKET module. */ -void sock_unregister(int family) -{ - BUG_ON(family < 0 || family >= NPROTO); - spin_lock(&net_family_lock); - net_families[family] = NULL; - spin_unlock(&net_family_lock); - - synchronize_rcu(); +int sock_unregister(int family) +{ + if (family < 0 || family >= NPROTO) + return -1; - printk(KERN_INFO "NET: Unregistered protocol family %d\n", family); + net_family_write_lock(); + net_families[family]=NULL; + net_family_write_unlock(); + printk(KERN_INFO "NET: Unregistered protocol family %d\n", + family); + return 0; } static int __init sock_init(void) { /* - * Initialize sock SLAB cache. + * Initialize sock SLAB cache. */ - + sk_init(); /* - * Initialize skbuff SLAB cache + * Initialize skbuff SLAB cache */ skb_init(); /* - * Initialize the protocols module. + * Initialize the protocols module. */ init_inodecache(); @@ -2168,7 +2136,7 @@ void socket_seq_show(struct seq_file *seq) int counter = 0; for_each_possible_cpu(cpu) - counter += per_cpu(sockets_in_use, cpu); + counter += per_cpu(sockets_in_use, cpu); /* It can be negative, by the way. 8) */ if (counter < 0) @@ -2176,11 +2144,11 @@ void socket_seq_show(struct seq_file *seq) seq_printf(seq, "sockets: used %d\n", counter); } -#endif /* CONFIG_PROC_FS */ +#endif /* CONFIG_PROC_FS */ #ifdef CONFIG_COMPAT static long compat_sock_ioctl(struct file *file, unsigned cmd, - unsigned long arg) + unsigned long arg) { struct socket *sock = file->private_data; int ret = -ENOIOCTLCMD; @@ -2192,109 +2160,6 @@ static long compat_sock_ioctl(struct file *file, unsigned cmd, } #endif -int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen) -{ - return sock->ops->bind(sock, addr, addrlen); -} - -int kernel_listen(struct socket *sock, int backlog) -{ - return sock->ops->listen(sock, backlog); -} - -int kernel_accept(struct socket *sock, struct socket **newsock, int flags) -{ - struct sock *sk = sock->sk; - int err; - - err = sock_create_lite(sk->sk_family, sk->sk_type, sk->sk_protocol, - newsock); - if (err < 0) - goto done; - - err = sock->ops->accept(sock, *newsock, flags); - if (err < 0) { - sock_release(*newsock); - goto done; - } - - (*newsock)->ops = sock->ops; - -done: - return err; -} - -int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen, - int flags) -{ - return sock->ops->connect(sock, addr, addrlen, flags); -} - -int kernel_getsockname(struct socket *sock, struct sockaddr *addr, - int *addrlen) -{ - return sock->ops->getname(sock, addr, addrlen, 0); -} - -int kernel_getpeername(struct socket *sock, struct sockaddr *addr, - int *addrlen) -{ - return sock->ops->getname(sock, addr, addrlen, 1); -} - -int kernel_getsockopt(struct socket *sock, int level, int optname, - char *optval, int *optlen) -{ - mm_segment_t oldfs = get_fs(); - int err; - - set_fs(KERNEL_DS); - if (level == SOL_SOCKET) - err = sock_getsockopt(sock, level, optname, optval, optlen); - else - err = sock->ops->getsockopt(sock, level, optname, optval, - optlen); - set_fs(oldfs); - return err; -} - -int kernel_setsockopt(struct socket *sock, int level, int optname, - char *optval, int optlen) -{ - mm_segment_t oldfs = get_fs(); - int err; - - set_fs(KERNEL_DS); - if (level == SOL_SOCKET) - err = sock_setsockopt(sock, level, optname, optval, optlen); - else - err = sock->ops->setsockopt(sock, level, optname, optval, - optlen); - set_fs(oldfs); - return err; -} - -int kernel_sendpage(struct socket *sock, struct page *page, int offset, - size_t size, int flags) -{ - if (sock->ops->sendpage) - return sock->ops->sendpage(sock, page, offset, size, flags); - - return sock_no_sendpage(sock, page, offset, size, flags); -} - -int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg) -{ - mm_segment_t oldfs = get_fs(); - int err; - - set_fs(KERNEL_DS); - err = sock->ops->ioctl(sock, cmd, arg); - set_fs(oldfs); - - return err; -} - /* ABI emulation layers need these two */ EXPORT_SYMBOL(move_addr_to_kernel); EXPORT_SYMBOL(move_addr_to_user); @@ -2311,13 +2176,3 @@ EXPORT_SYMBOL(sock_wake_async); EXPORT_SYMBOL(sockfd_lookup); EXPORT_SYMBOL(kernel_sendmsg); EXPORT_SYMBOL(kernel_recvmsg); -EXPORT_SYMBOL(kernel_bind); -EXPORT_SYMBOL(kernel_listen); -EXPORT_SYMBOL(kernel_accept); -EXPORT_SYMBOL(kernel_connect); -EXPORT_SYMBOL(kernel_getsockname); -EXPORT_SYMBOL(kernel_getpeername); -EXPORT_SYMBOL(kernel_getsockopt); -EXPORT_SYMBOL(kernel_setsockopt); -EXPORT_SYMBOL(kernel_sendpage); -EXPORT_SYMBOL(kernel_sock_ioctl); diff --git a/trunk/net/sunrpc/auth_gss/auth_gss.c b/trunk/net/sunrpc/auth_gss/auth_gss.c index 6eed3e166ba3..4a9aa9393b97 100644 --- a/trunk/net/sunrpc/auth_gss/auth_gss.c +++ b/trunk/net/sunrpc/auth_gss/auth_gss.c @@ -88,6 +88,7 @@ struct gss_auth { struct list_head upcalls; struct rpc_clnt *client; struct dentry *dentry; + char path[48]; spinlock_t lock; }; @@ -689,8 +690,10 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) if (err) goto err_put_mech; - gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name, - clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); + snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s", + clnt->cl_pathname, + gss_auth->mech->gm_name); + gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); if (IS_ERR(gss_auth->dentry)) { err = PTR_ERR(gss_auth->dentry); goto err_put_mech; @@ -715,7 +718,8 @@ gss_destroy(struct rpc_auth *auth) auth, auth->au_flavor); gss_auth = container_of(auth, struct gss_auth, rpc_auth); - rpc_unlink(gss_auth->dentry); + rpc_unlink(gss_auth->path); + dput(gss_auth->dentry); gss_auth->dentry = NULL; gss_mech_put(gss_auth->mech); diff --git a/trunk/net/sunrpc/auth_gss/gss_krb5_crypto.c b/trunk/net/sunrpc/auth_gss/gss_krb5_crypto.c index e11a40b25cce..76b969e6904f 100644 --- a/trunk/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/trunk/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -34,7 +34,6 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#include #include #include #include @@ -50,7 +49,7 @@ u32 krb5_encrypt( - struct crypto_blkcipher *tfm, + struct crypto_tfm *tfm, void * iv, void * in, void * out, @@ -59,27 +58,26 @@ krb5_encrypt( u32 ret = -EINVAL; struct scatterlist sg[1]; u8 local_iv[16] = {0}; - struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv }; dprintk("RPC: krb5_encrypt: input data:\n"); print_hexl((u32 *)in, length, 0); - if (length % crypto_blkcipher_blocksize(tfm) != 0) + if (length % crypto_tfm_alg_blocksize(tfm) != 0) goto out; - if (crypto_blkcipher_ivsize(tfm) > 16) { + if (crypto_tfm_alg_ivsize(tfm) > 16) { dprintk("RPC: gss_k5encrypt: tfm iv size to large %d\n", - crypto_blkcipher_ivsize(tfm)); + crypto_tfm_alg_ivsize(tfm)); goto out; } if (iv) - memcpy(local_iv, iv, crypto_blkcipher_ivsize(tfm)); + memcpy(local_iv, iv, crypto_tfm_alg_ivsize(tfm)); memcpy(out, in, length); sg_set_buf(sg, out, length); - ret = crypto_blkcipher_encrypt_iv(&desc, sg, sg, length); + ret = crypto_cipher_encrypt_iv(tfm, sg, sg, length, local_iv); dprintk("RPC: krb5_encrypt: output data:\n"); print_hexl((u32 *)out, length, 0); @@ -92,7 +90,7 @@ EXPORT_SYMBOL(krb5_encrypt); u32 krb5_decrypt( - struct crypto_blkcipher *tfm, + struct crypto_tfm *tfm, void * iv, void * in, void * out, @@ -101,26 +99,25 @@ krb5_decrypt( u32 ret = -EINVAL; struct scatterlist sg[1]; u8 local_iv[16] = {0}; - struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv }; dprintk("RPC: krb5_decrypt: input data:\n"); print_hexl((u32 *)in, length, 0); - if (length % crypto_blkcipher_blocksize(tfm) != 0) + if (length % crypto_tfm_alg_blocksize(tfm) != 0) goto out; - if (crypto_blkcipher_ivsize(tfm) > 16) { + if (crypto_tfm_alg_ivsize(tfm) > 16) { dprintk("RPC: gss_k5decrypt: tfm iv size to large %d\n", - crypto_blkcipher_ivsize(tfm)); + crypto_tfm_alg_ivsize(tfm)); goto out; } if (iv) - memcpy(local_iv,iv, crypto_blkcipher_ivsize(tfm)); + memcpy(local_iv,iv, crypto_tfm_alg_ivsize(tfm)); memcpy(out, in, length); sg_set_buf(sg, out, length); - ret = crypto_blkcipher_decrypt_iv(&desc, sg, sg, length); + ret = crypto_cipher_decrypt_iv(tfm, sg, sg, length, local_iv); dprintk("RPC: krb5_decrypt: output_data:\n"); print_hexl((u32 *)out, length, 0); @@ -200,9 +197,11 @@ process_xdr_buf(struct xdr_buf *buf, int offset, int len, static int checksummer(struct scatterlist *sg, void *data) { - struct hash_desc *desc = data; + struct crypto_tfm *tfm = (struct crypto_tfm *)data; - return crypto_hash_update(desc, sg, sg->length); + crypto_digest_update(tfm, sg, 1); + + return 0; } /* checksum the plaintext data and hdrlen bytes of the token header */ @@ -211,9 +210,8 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body, int body_offset, struct xdr_netobj *cksum) { char *cksumname; - struct hash_desc desc; /* XXX add to ctx? */ + struct crypto_tfm *tfm = NULL; /* XXX add to ctx? */ struct scatterlist sg[1]; - int err; switch (cksumtype) { case CKSUMTYPE_RSA_MD5: @@ -224,35 +222,25 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body, " unsupported checksum %d", cksumtype); return GSS_S_FAILURE; } - desc.tfm = crypto_alloc_hash(cksumname, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(desc.tfm)) + if (!(tfm = crypto_alloc_tfm(cksumname, CRYPTO_TFM_REQ_MAY_SLEEP))) return GSS_S_FAILURE; - cksum->len = crypto_hash_digestsize(desc.tfm); - desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; + cksum->len = crypto_tfm_alg_digestsize(tfm); - err = crypto_hash_init(&desc); - if (err) - goto out; + crypto_digest_init(tfm); sg_set_buf(sg, header, hdrlen); - err = crypto_hash_update(&desc, sg, hdrlen); - if (err) - goto out; - err = process_xdr_buf(body, body_offset, body->len - body_offset, - checksummer, &desc); - if (err) - goto out; - err = crypto_hash_final(&desc, cksum->data); - -out: - crypto_free_hash(desc.tfm); - return err ? GSS_S_FAILURE : 0; + crypto_digest_update(tfm, sg, 1); + process_xdr_buf(body, body_offset, body->len - body_offset, + checksummer, tfm); + crypto_digest_final(tfm, cksum->data); + crypto_free_tfm(tfm); + return 0; } EXPORT_SYMBOL(make_checksum); struct encryptor_desc { u8 iv[8]; /* XXX hard-coded blocksize */ - struct blkcipher_desc desc; + struct crypto_tfm *tfm; int pos; struct xdr_buf *outbuf; struct page **pages; @@ -297,8 +285,8 @@ encryptor(struct scatterlist *sg, void *data) if (thislen == 0) return 0; - ret = crypto_blkcipher_encrypt_iv(&desc->desc, desc->outfrags, - desc->infrags, thislen); + ret = crypto_cipher_encrypt_iv(desc->tfm, desc->outfrags, desc->infrags, + thislen, desc->iv); if (ret) return ret; if (fraglen) { @@ -317,18 +305,16 @@ encryptor(struct scatterlist *sg, void *data) } int -gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf, - int offset, struct page **pages) +gss_encrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *buf, int offset, + struct page **pages) { int ret; struct encryptor_desc desc; - BUG_ON((buf->len - offset) % crypto_blkcipher_blocksize(tfm) != 0); + BUG_ON((buf->len - offset) % crypto_tfm_alg_blocksize(tfm) != 0); memset(desc.iv, 0, sizeof(desc.iv)); - desc.desc.tfm = tfm; - desc.desc.info = desc.iv; - desc.desc.flags = 0; + desc.tfm = tfm; desc.pos = offset; desc.outbuf = buf; desc.pages = pages; @@ -343,7 +329,7 @@ EXPORT_SYMBOL(gss_encrypt_xdr_buf); struct decryptor_desc { u8 iv[8]; /* XXX hard-coded blocksize */ - struct blkcipher_desc desc; + struct crypto_tfm *tfm; struct scatterlist frags[4]; int fragno; int fraglen; @@ -369,8 +355,8 @@ decryptor(struct scatterlist *sg, void *data) if (thislen == 0) return 0; - ret = crypto_blkcipher_decrypt_iv(&desc->desc, desc->frags, - desc->frags, thislen); + ret = crypto_cipher_decrypt_iv(desc->tfm, desc->frags, desc->frags, + thislen, desc->iv); if (ret) return ret; if (fraglen) { @@ -387,18 +373,15 @@ decryptor(struct scatterlist *sg, void *data) } int -gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf, - int offset) +gss_decrypt_xdr_buf(struct crypto_tfm *tfm, struct xdr_buf *buf, int offset) { struct decryptor_desc desc; /* XXXJBF: */ - BUG_ON((buf->len - offset) % crypto_blkcipher_blocksize(tfm) != 0); + BUG_ON((buf->len - offset) % crypto_tfm_alg_blocksize(tfm) != 0); memset(desc.iv, 0, sizeof(desc.iv)); - desc.desc.tfm = tfm; - desc.desc.info = desc.iv; - desc.desc.flags = 0; + desc.tfm = tfm; desc.fragno = 0; desc.fraglen = 0; return process_xdr_buf(buf, offset, buf->len - offset, decryptor, &desc); diff --git a/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c b/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c index 325e72e4fd31..70e1e53a632b 100644 --- a/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/trunk/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -34,7 +34,6 @@ * */ -#include #include #include #include @@ -79,10 +78,10 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res) } static inline const void * -get_key(const void *p, const void *end, struct crypto_blkcipher **res) +get_key(const void *p, const void *end, struct crypto_tfm **res) { struct xdr_netobj key; - int alg; + int alg, alg_mode; char *alg_name; p = simple_get_bytes(p, end, &alg, sizeof(alg)); @@ -94,19 +93,18 @@ get_key(const void *p, const void *end, struct crypto_blkcipher **res) switch (alg) { case ENCTYPE_DES_CBC_RAW: - alg_name = "cbc(des)"; + alg_name = "des"; + alg_mode = CRYPTO_TFM_MODE_CBC; break; default: printk("gss_kerberos_mech: unsupported algorithm %d\n", alg); goto out_err_free_key; } - *res = crypto_alloc_blkcipher(alg_name, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(*res)) { + if (!(*res = crypto_alloc_tfm(alg_name, alg_mode))) { printk("gss_kerberos_mech: unable to initialize crypto algorithm %s\n", alg_name); - *res = NULL; goto out_err_free_key; } - if (crypto_blkcipher_setkey(*res, key.data, key.len)) { + if (crypto_cipher_setkey(*res, key.data, key.len)) { printk("gss_kerberos_mech: error setting key for crypto algorithm %s\n", alg_name); goto out_err_free_tfm; } @@ -115,7 +113,7 @@ get_key(const void *p, const void *end, struct crypto_blkcipher **res) return p; out_err_free_tfm: - crypto_free_blkcipher(*res); + crypto_free_tfm(*res); out_err_free_key: kfree(key.data); p = ERR_PTR(-EINVAL); @@ -174,9 +172,9 @@ gss_import_sec_context_kerberos(const void *p, return 0; out_err_free_key2: - crypto_free_blkcipher(ctx->seq); + crypto_free_tfm(ctx->seq); out_err_free_key1: - crypto_free_blkcipher(ctx->enc); + crypto_free_tfm(ctx->enc); out_err_free_mech: kfree(ctx->mech_used.data); out_err_free_ctx: @@ -189,8 +187,8 @@ static void gss_delete_sec_context_kerberos(void *internal_ctx) { struct krb5_ctx *kctx = internal_ctx; - crypto_free_blkcipher(kctx->seq); - crypto_free_blkcipher(kctx->enc); + crypto_free_tfm(kctx->seq); + crypto_free_tfm(kctx->enc); kfree(kctx->mech_used.data); kfree(kctx); } diff --git a/trunk/net/sunrpc/auth_gss/gss_krb5_seqnum.c b/trunk/net/sunrpc/auth_gss/gss_krb5_seqnum.c index c604baf3a5f6..c53ead39118d 100644 --- a/trunk/net/sunrpc/auth_gss/gss_krb5_seqnum.c +++ b/trunk/net/sunrpc/auth_gss/gss_krb5_seqnum.c @@ -41,7 +41,7 @@ #endif s32 -krb5_make_seq_num(struct crypto_blkcipher *key, +krb5_make_seq_num(struct crypto_tfm *key, int direction, s32 seqnum, unsigned char *cksum, unsigned char *buf) @@ -62,7 +62,7 @@ krb5_make_seq_num(struct crypto_blkcipher *key, } s32 -krb5_get_seq_num(struct crypto_blkcipher *key, +krb5_get_seq_num(struct crypto_tfm *key, unsigned char *cksum, unsigned char *buf, int *direction, s32 * seqnum) diff --git a/trunk/net/sunrpc/auth_gss/gss_krb5_wrap.c b/trunk/net/sunrpc/auth_gss/gss_krb5_wrap.c index f179415d0c38..89d1f3e14128 100644 --- a/trunk/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/trunk/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -149,7 +149,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset, goto out_err; } - blocksize = crypto_blkcipher_blocksize(kctx->enc); + blocksize = crypto_tfm_alg_blocksize(kctx->enc); gss_krb5_add_padding(buf, offset, blocksize); BUG_ON((buf->len - offset) % blocksize); plainlen = blocksize + buf->len - offset; @@ -346,7 +346,7 @@ gss_unwrap_kerberos(struct gss_ctx *ctx, int offset, struct xdr_buf *buf) /* Copy the data back to the right position. XXX: Would probably be * better to copy and encrypt at the same time. */ - blocksize = crypto_blkcipher_blocksize(kctx->enc); + blocksize = crypto_tfm_alg_blocksize(kctx->enc); data_start = ptr + 22 + blocksize; orig_start = buf->head[0].iov_base + offset; data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start; diff --git a/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c b/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c index bdedf456bc17..88dcb52d171b 100644 --- a/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/trunk/net/sunrpc/auth_gss/gss_spkm3_mech.c @@ -34,7 +34,6 @@ * */ -#include #include #include #include @@ -84,11 +83,10 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res) } static inline const void * -get_key(const void *p, const void *end, struct crypto_blkcipher **res, - int *resalg) +get_key(const void *p, const void *end, struct crypto_tfm **res, int *resalg) { struct xdr_netobj key = { 0 }; - int setkey = 0; + int alg_mode,setkey = 0; char *alg_name; p = simple_get_bytes(p, end, resalg, sizeof(*resalg)); @@ -100,12 +98,14 @@ get_key(const void *p, const void *end, struct crypto_blkcipher **res, switch (*resalg) { case NID_des_cbc: - alg_name = "cbc(des)"; + alg_name = "des"; + alg_mode = CRYPTO_TFM_MODE_CBC; setkey = 1; break; case NID_cast5_cbc: /* XXXX here in name only, not used */ - alg_name = "cbc(cast5)"; + alg_name = "cast5"; + alg_mode = CRYPTO_TFM_MODE_CBC; setkey = 0; /* XXX will need to set to 1 */ break; case NID_md5: @@ -113,20 +113,19 @@ get_key(const void *p, const void *end, struct crypto_blkcipher **res, dprintk("RPC: SPKM3 get_key: NID_md5 zero Key length\n"); } alg_name = "md5"; + alg_mode = 0; setkey = 0; break; default: dprintk("gss_spkm3_mech: unsupported algorithm %d\n", *resalg); goto out_err_free_key; } - *res = crypto_alloc_blkcipher(alg_name, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(*res)) { + if (!(*res = crypto_alloc_tfm(alg_name, alg_mode))) { printk("gss_spkm3_mech: unable to initialize crypto algorthm %s\n", alg_name); - *res = NULL; goto out_err_free_key; } if (setkey) { - if (crypto_blkcipher_setkey(*res, key.data, key.len)) { + if (crypto_cipher_setkey(*res, key.data, key.len)) { printk("gss_spkm3_mech: error setting key for crypto algorthm %s\n", alg_name); goto out_err_free_tfm; } @@ -137,7 +136,7 @@ get_key(const void *p, const void *end, struct crypto_blkcipher **res, return p; out_err_free_tfm: - crypto_free_blkcipher(*res); + crypto_free_tfm(*res); out_err_free_key: if(key.len > 0) kfree(key.data); @@ -205,9 +204,9 @@ gss_import_sec_context_spkm3(const void *p, size_t len, return 0; out_err_free_key2: - crypto_free_blkcipher(ctx->derived_integ_key); + crypto_free_tfm(ctx->derived_integ_key); out_err_free_key1: - crypto_free_blkcipher(ctx->derived_conf_key); + crypto_free_tfm(ctx->derived_conf_key); out_err_free_s_key: kfree(ctx->share_key.data); out_err_free_mech: @@ -224,8 +223,8 @@ static void gss_delete_sec_context_spkm3(void *internal_ctx) { struct spkm3_ctx *sctx = internal_ctx; - crypto_free_blkcipher(sctx->derived_integ_key); - crypto_free_blkcipher(sctx->derived_conf_key); + crypto_free_tfm(sctx->derived_integ_key); + crypto_free_tfm(sctx->derived_conf_key); kfree(sctx->share_key.data); kfree(sctx->mech_used.data); kfree(sctx); diff --git a/trunk/net/sunrpc/cache.c b/trunk/net/sunrpc/cache.c index 00cb388ece03..7026b0866b7b 100644 --- a/trunk/net/sunrpc/cache.c +++ b/trunk/net/sunrpc/cache.c @@ -71,12 +71,7 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, new = detail->alloc(); if (!new) return NULL; - /* must fully initialise 'new', else - * we might get lose if we need to - * cache_put it soon. - */ cache_init(new); - detail->init(new, key); write_lock(&detail->hash_lock); @@ -90,6 +85,7 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, return tmp; } } + detail->init(new, key); new->next = *head; *head = new; detail->entries++; diff --git a/trunk/net/sunrpc/clnt.c b/trunk/net/sunrpc/clnt.c index 084a0ad5c64e..4ba271f892c8 100644 --- a/trunk/net/sunrpc/clnt.c +++ b/trunk/net/sunrpc/clnt.c @@ -97,7 +97,17 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) } } -static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, struct rpc_program *program, u32 vers, rpc_authflavor_t flavor) +/* + * Create an RPC client + * FIXME: This should also take a flags argument (as in task->tk_flags). + * It's called (among others) from pmap_create_client, which may in + * turn be called by an async task. In this case, rpciod should not be + * made to sleep too long. + */ +struct rpc_clnt * +rpc_new_client(struct rpc_xprt *xprt, char *servname, + struct rpc_program *program, u32 vers, + rpc_authflavor_t flavor) { struct rpc_version *version; struct rpc_clnt *clnt = NULL; @@ -137,12 +147,16 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s clnt->cl_procinfo = version->procs; clnt->cl_maxproc = version->nrprocs; clnt->cl_protname = program->name; + clnt->cl_pmap = &clnt->cl_pmap_default; + clnt->cl_port = xprt->addr.sin_port; clnt->cl_prog = program->number; clnt->cl_vers = version->number; + clnt->cl_prot = xprt->prot; clnt->cl_stats = program->stats; clnt->cl_metrics = rpc_alloc_iostats(clnt); + rpc_init_wait_queue(&clnt->cl_pmap_default.pm_bindwait, "bindwait"); - if (!xprt_bound(clnt->cl_xprt)) + if (!clnt->cl_port) clnt->cl_autobind = 1; clnt->cl_rtt = &clnt->cl_rtt_default; @@ -169,7 +183,8 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s out_no_auth: if (!IS_ERR(clnt->cl_dentry)) { - rpc_rmdir(clnt->cl_dentry); + rpc_rmdir(clnt->cl_pathname); + dput(clnt->cl_dentry); rpc_put_mount(); } out_no_path: @@ -177,71 +192,40 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s kfree(clnt->cl_server); kfree(clnt); out_err: - xprt_put(xprt); + xprt_destroy(xprt); out_no_xprt: return ERR_PTR(err); } -/* - * rpc_create - create an RPC client and transport with one call - * @args: rpc_clnt create argument structure +/** + * Create an RPC client + * @xprt - pointer to xprt struct + * @servname - name of server + * @info - rpc_program + * @version - rpc_program version + * @authflavor - rpc_auth flavour to use * - * Creates and initializes an RPC transport and an RPC client. + * Creates an RPC client structure, then pings the server in order to + * determine if it is up, and if it supports this program and version. * - * It can ping the server in order to determine if it is up, and to see if - * it supports this program and version. RPC_CLNT_CREATE_NOPING disables - * this behavior so asynchronous tasks can also use rpc_create. + * This function should never be called by asynchronous tasks such as + * the portmapper. */ -struct rpc_clnt *rpc_create(struct rpc_create_args *args) +struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname, + struct rpc_program *info, u32 version, rpc_authflavor_t authflavor) { - struct rpc_xprt *xprt; struct rpc_clnt *clnt; - - xprt = xprt_create_transport(args->protocol, args->address, - args->addrsize, args->timeout); - if (IS_ERR(xprt)) - return (struct rpc_clnt *)xprt; - - /* - * By default, kernel RPC client connects from a reserved port. - * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters, - * but it is always enabled for rpciod, which handles the connect - * operation. - */ - xprt->resvport = 1; - if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) - xprt->resvport = 0; - - dprintk("RPC: creating %s client for %s (xprt %p)\n", - args->program->name, args->servername, xprt); - - clnt = rpc_new_client(xprt, args->servername, args->program, - args->version, args->authflavor); + int err; + + clnt = rpc_new_client(xprt, servname, info, version, authflavor); if (IS_ERR(clnt)) return clnt; - - if (!(args->flags & RPC_CLNT_CREATE_NOPING)) { - int err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR); - if (err != 0) { - rpc_shutdown_client(clnt); - return ERR_PTR(err); - } - } - - clnt->cl_softrtry = 1; - if (args->flags & RPC_CLNT_CREATE_HARDRTRY) - clnt->cl_softrtry = 0; - - if (args->flags & RPC_CLNT_CREATE_INTR) - clnt->cl_intr = 1; - if (args->flags & RPC_CLNT_CREATE_AUTOBIND) - clnt->cl_autobind = 1; - if (args->flags & RPC_CLNT_CREATE_ONESHOT) - clnt->cl_oneshot = 1; - - return clnt; + err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR); + if (err == 0) + return clnt; + rpc_shutdown_client(clnt); + return ERR_PTR(err); } -EXPORT_SYMBOL_GPL(rpc_create); /* * This function clones the RPC client structure. It allows us to share the @@ -261,17 +245,21 @@ rpc_clone_client(struct rpc_clnt *clnt) atomic_set(&new->cl_users, 0); new->cl_parent = clnt; atomic_inc(&clnt->cl_count); - new->cl_xprt = xprt_get(clnt->cl_xprt); + /* Duplicate portmapper */ + rpc_init_wait_queue(&new->cl_pmap_default.pm_bindwait, "bindwait"); /* Turn off autobind on clones */ new->cl_autobind = 0; new->cl_oneshot = 0; new->cl_dead = 0; - if (!IS_ERR(new->cl_dentry)) + if (!IS_ERR(new->cl_dentry)) { dget(new->cl_dentry); + rpc_get_mount(); + } rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); if (new->cl_auth) atomic_inc(&new->cl_auth->au_count); - new->cl_metrics = rpc_alloc_iostats(clnt); + new->cl_pmap = &new->cl_pmap_default; + new->cl_metrics = rpc_alloc_iostats(clnt); return new; out_no_clnt: printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__); @@ -329,21 +317,24 @@ rpc_destroy_client(struct rpc_clnt *clnt) clnt->cl_auth = NULL; } if (clnt->cl_parent != clnt) { - if (!IS_ERR(clnt->cl_dentry)) - dput(clnt->cl_dentry); rpc_destroy_client(clnt->cl_parent); goto out_free; } - if (!IS_ERR(clnt->cl_dentry)) { - rpc_rmdir(clnt->cl_dentry); - rpc_put_mount(); + if (clnt->cl_pathname[0]) + rpc_rmdir(clnt->cl_pathname); + if (clnt->cl_xprt) { + xprt_destroy(clnt->cl_xprt); + clnt->cl_xprt = NULL; } if (clnt->cl_server != clnt->cl_inline_name) kfree(clnt->cl_server); out_free: rpc_free_iostats(clnt->cl_metrics); clnt->cl_metrics = NULL; - xprt_put(clnt->cl_xprt); + if (!IS_ERR(clnt->cl_dentry)) { + dput(clnt->cl_dentry); + rpc_put_mount(); + } kfree(clnt); return 0; } @@ -552,40 +543,6 @@ rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags) task->tk_action = rpc_exit_task; } -/** - * rpc_peeraddr - extract remote peer address from clnt's xprt - * @clnt: RPC client structure - * @buf: target buffer - * @size: length of target buffer - * - * Returns the number of bytes that are actually in the stored address. - */ -size_t rpc_peeraddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t bufsize) -{ - size_t bytes; - struct rpc_xprt *xprt = clnt->cl_xprt; - - bytes = sizeof(xprt->addr); - if (bytes > bufsize) - bytes = bufsize; - memcpy(buf, &clnt->cl_xprt->addr, bytes); - return xprt->addrlen; -} -EXPORT_SYMBOL_GPL(rpc_peeraddr); - -/** - * rpc_peeraddr2str - return remote peer address in printable format - * @clnt: RPC client structure - * @format: address format - * - */ -char *rpc_peeraddr2str(struct rpc_clnt *clnt, enum rpc_display_format_t format) -{ - struct rpc_xprt *xprt = clnt->cl_xprt; - return xprt->ops->print_addr(xprt, format); -} -EXPORT_SYMBOL_GPL(rpc_peeraddr2str); - void rpc_setbufsize(struct rpc_clnt *clnt, unsigned int sndsize, unsigned int rcvsize) { @@ -606,7 +563,7 @@ size_t rpc_max_payload(struct rpc_clnt *clnt) { return clnt->cl_xprt->max_payload; } -EXPORT_SYMBOL_GPL(rpc_max_payload); +EXPORT_SYMBOL(rpc_max_payload); /** * rpc_force_rebind - force transport to check that remote port is unchanged @@ -616,9 +573,9 @@ EXPORT_SYMBOL_GPL(rpc_max_payload); void rpc_force_rebind(struct rpc_clnt *clnt) { if (clnt->cl_autobind) - xprt_clear_bound(clnt->cl_xprt); + clnt->cl_port = 0; } -EXPORT_SYMBOL_GPL(rpc_force_rebind); +EXPORT_SYMBOL(rpc_force_rebind); /* * Restart an (async) RPC call. Usually called from within the @@ -827,16 +784,16 @@ call_encode(struct rpc_task *task) static void call_bind(struct rpc_task *task) { - struct rpc_xprt *xprt = task->tk_xprt; + struct rpc_clnt *clnt = task->tk_client; dprintk("RPC: %4d call_bind (status %d)\n", task->tk_pid, task->tk_status); task->tk_action = call_connect; - if (!xprt_bound(xprt)) { + if (!clnt->cl_port) { task->tk_action = call_bind_status; - task->tk_timeout = xprt->bind_timeout; - xprt->ops->rpcbind(task); + task->tk_timeout = task->tk_xprt->bind_timeout; + rpc_getport(task, clnt); } } @@ -861,11 +818,15 @@ call_bind_status(struct rpc_task *task) dprintk("RPC: %4d remote rpcbind: RPC program/version unavailable\n", task->tk_pid); rpc_delay(task, 3*HZ); - goto retry_timeout; + goto retry_bind; case -ETIMEDOUT: dprintk("RPC: %4d rpcbind request timed out\n", task->tk_pid); - goto retry_timeout; + if (RPC_IS_SOFT(task)) { + status = -EIO; + break; + } + goto retry_bind; case -EPFNOSUPPORT: dprintk("RPC: %4d remote rpcbind service unavailable\n", task->tk_pid); @@ -878,13 +839,16 @@ call_bind_status(struct rpc_task *task) dprintk("RPC: %4d unrecognized rpcbind error (%d)\n", task->tk_pid, -task->tk_status); status = -EIO; + break; } rpc_exit(task, status); return; -retry_timeout: - task->tk_action = call_timeout; +retry_bind: + task->tk_status = 0; + task->tk_action = call_bind; + return; } /* @@ -932,16 +896,14 @@ call_connect_status(struct rpc_task *task) switch (status) { case -ENOTCONN: + case -ETIMEDOUT: case -EAGAIN: task->tk_action = call_bind; - if (!RPC_IS_SOFT(task)) - return; - /* if soft mounted, test if we've timed out */ - case -ETIMEDOUT: - task->tk_action = call_timeout; - return; + break; + default: + rpc_exit(task, -EIO); + break; } - rpc_exit(task, -EIO); } /* @@ -959,43 +921,26 @@ call_transmit(struct rpc_task *task) task->tk_status = xprt_prepare_transmit(task); if (task->tk_status != 0) return; - task->tk_action = call_transmit_status; /* Encode here so that rpcsec_gss can use correct sequence number. */ if (rpc_task_need_encode(task)) { - BUG_ON(task->tk_rqstp->rq_bytes_sent != 0); + task->tk_rqstp->rq_bytes_sent = 0; call_encode(task); /* Did the encode result in an error condition? */ if (task->tk_status != 0) - return; + goto out_nosend; } + task->tk_action = call_transmit_status; xprt_transmit(task); if (task->tk_status < 0) return; - /* - * On success, ensure that we call xprt_end_transmit() before sleeping - * in order to allow access to the socket to other RPC requests. - */ - call_transmit_status(task); - if (task->tk_msg.rpc_proc->p_decode != NULL) - return; - task->tk_action = rpc_exit_task; - rpc_wake_up_task(task); -} - -/* - * 5a. Handle cleanup after a transmission - */ -static void -call_transmit_status(struct rpc_task *task) -{ - task->tk_action = call_status; - /* - * Special case: if we've been waiting on the socket's write_space() - * callback, then don't call xprt_end_transmit(). - */ - if (task->tk_status == -EAGAIN) - return; - xprt_end_transmit(task); + if (!task->tk_msg.rpc_proc->p_decode) { + task->tk_action = rpc_exit_task; + rpc_wake_up_task(task); + } + return; +out_nosend: + /* release socket write lock before attempting to handle error */ + xprt_abort_transmit(task); rpc_task_force_reencode(task); } @@ -1023,14 +968,6 @@ call_status(struct rpc_task *task) task->tk_status = 0; switch(status) { - case -EHOSTDOWN: - case -EHOSTUNREACH: - case -ENETUNREACH: - /* - * Delay any retries for 3 seconds, then handle as if it - * were a timeout. - */ - rpc_delay(task, 3*HZ); case -ETIMEDOUT: task->tk_action = call_timeout; break; @@ -1050,11 +987,23 @@ call_status(struct rpc_task *task) printk("%s: RPC call returned error %d\n", clnt->cl_protname, -status); rpc_exit(task, status); + break; } } /* - * 6a. Handle RPC timeout + * 6a. Handle transmission errors. + */ +static void +call_transmit_status(struct rpc_task *task) +{ + if (task->tk_status != -EAGAIN) + rpc_task_force_reencode(task); + call_status(task); +} + +/* + * 6b. Handle RPC timeout * We do not release the request slot, so we keep using the * same XID for all retransmits. */ @@ -1117,10 +1066,10 @@ call_decode(struct rpc_task *task) clnt->cl_stats->rpcretrans++; goto out_retry; } - dprintk("%s: too small RPC reply size (%d bytes)\n", + printk(KERN_WARNING "%s: too small RPC reply size (%d bytes)\n", clnt->cl_protname, task->tk_status); - task->tk_action = call_timeout; - goto out_retry; + rpc_exit(task, -EIO); + return; } /* @@ -1229,17 +1178,6 @@ call_verify(struct rpc_task *task) u32 *p = iov->iov_base, n; int error = -EACCES; - if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) { - /* RFC-1014 says that the representation of XDR data must be a - * multiple of four bytes - * - if it isn't pointer subtraction in the NFS client may give - * undefined results - */ - printk(KERN_WARNING - "call_verify: XDR representation not a multiple of" - " 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len); - goto out_eio; - } if ((len -= 3) < 0) goto out_overflow; p += 1; /* skip XID */ diff --git a/trunk/net/sunrpc/pmap_clnt.c b/trunk/net/sunrpc/pmap_clnt.c index c04609d3476a..623180f224c9 100644 --- a/trunk/net/sunrpc/pmap_clnt.c +++ b/trunk/net/sunrpc/pmap_clnt.c @@ -1,9 +1,7 @@ /* - * linux/net/sunrpc/pmap_clnt.c + * linux/net/sunrpc/pmap.c * - * In-kernel RPC portmapper client. - * - * Portmapper supports version 2 of the rpcbind protocol (RFC 1833). + * Portmapper client. * * Copyright (C) 1996, Olaf Kirch */ @@ -15,6 +13,7 @@ #include #include #include +#include #include #ifdef RPC_DEBUG @@ -25,141 +24,80 @@ #define PMAP_UNSET 2 #define PMAP_GETPORT 3 -struct portmap_args { - u32 pm_prog; - u32 pm_vers; - u32 pm_prot; - unsigned short pm_port; - struct rpc_xprt * pm_xprt; -}; - static struct rpc_procinfo pmap_procedures[]; static struct rpc_clnt * pmap_create(char *, struct sockaddr_in *, int, int); -static void pmap_getport_done(struct rpc_task *, void *); +static void pmap_getport_done(struct rpc_task *); static struct rpc_program pmap_program; +static DEFINE_SPINLOCK(pmap_lock); -static void pmap_getport_prepare(struct rpc_task *task, void *calldata) +/* + * Obtain the port for a given RPC service on a given host. This one can + * be called for an ongoing RPC request. + */ +void +rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt) { - struct portmap_args *map = calldata; + struct rpc_portmap *map = clnt->cl_pmap; + struct sockaddr_in *sap = &clnt->cl_xprt->addr; struct rpc_message msg = { .rpc_proc = &pmap_procedures[PMAP_GETPORT], .rpc_argp = map, - .rpc_resp = &map->pm_port, + .rpc_resp = &clnt->cl_port, + .rpc_cred = NULL }; - - rpc_call_setup(task, &msg, 0); -} - -static inline struct portmap_args *pmap_map_alloc(void) -{ - return kmalloc(sizeof(struct portmap_args), GFP_NOFS); -} - -static inline void pmap_map_free(struct portmap_args *map) -{ - kfree(map); -} - -static void pmap_map_release(void *data) -{ - pmap_map_free(data); -} - -static const struct rpc_call_ops pmap_getport_ops = { - .rpc_call_prepare = pmap_getport_prepare, - .rpc_call_done = pmap_getport_done, - .rpc_release = pmap_map_release, -}; - -static inline void pmap_wake_portmap_waiters(struct rpc_xprt *xprt, int status) -{ - xprt_clear_binding(xprt); - rpc_wake_up_status(&xprt->binding, status); -} - -/** - * rpc_getport - obtain the port for a given RPC service on a given host - * @task: task that is waiting for portmapper request - * - * This one can be called for an ongoing RPC request, and can be used in - * an async (rpciod) context. - */ -void rpc_getport(struct rpc_task *task) -{ - struct rpc_clnt *clnt = task->tk_client; - struct rpc_xprt *xprt = task->tk_xprt; - struct sockaddr_in addr; - struct portmap_args *map; struct rpc_clnt *pmap_clnt; - struct rpc_task *child; - int status; + struct rpc_task *child; - dprintk("RPC: %4d rpc_getport(%s, %u, %u, %d)\n", + dprintk("RPC: %4d rpc_getport(%s, %d, %d, %d)\n", task->tk_pid, clnt->cl_server, - clnt->cl_prog, clnt->cl_vers, xprt->prot); + map->pm_prog, map->pm_vers, map->pm_prot); /* Autobind on cloned rpc clients is discouraged */ BUG_ON(clnt->cl_parent != clnt); - if (xprt_test_and_set_binding(xprt)) { - task->tk_status = -EACCES; /* tell caller to check again */ - rpc_sleep_on(&xprt->binding, task, NULL, NULL); + spin_lock(&pmap_lock); + if (map->pm_binding) { + rpc_sleep_on(&map->pm_bindwait, task, NULL, NULL); + spin_unlock(&pmap_lock); return; } + map->pm_binding = 1; + spin_unlock(&pmap_lock); - /* Someone else may have bound if we slept */ - status = 0; - if (xprt_bound(xprt)) - goto bailout_nofree; - - status = -ENOMEM; - map = pmap_map_alloc(); - if (!map) - goto bailout_nofree; - map->pm_prog = clnt->cl_prog; - map->pm_vers = clnt->cl_vers; - map->pm_prot = xprt->prot; - map->pm_port = 0; - map->pm_xprt = xprt_get(xprt); - - rpc_peeraddr(clnt, (struct sockaddr *) &addr, sizeof(addr)); - pmap_clnt = pmap_create(clnt->cl_server, &addr, map->pm_prot, 0); - status = PTR_ERR(pmap_clnt); - if (IS_ERR(pmap_clnt)) + pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot, 0); + if (IS_ERR(pmap_clnt)) { + task->tk_status = PTR_ERR(pmap_clnt); goto bailout; + } + task->tk_status = 0; - status = -EIO; - child = rpc_run_task(pmap_clnt, RPC_TASK_ASYNC, &pmap_getport_ops, map); - if (IS_ERR(child)) + /* + * Note: rpc_new_child will release client after a failure. + */ + if (!(child = rpc_new_child(pmap_clnt, task))) goto bailout; - rpc_release_task(child); - rpc_sleep_on(&xprt->binding, task, NULL, NULL); + /* Setup the call info struct */ + rpc_call_setup(child, &msg, 0); + /* ... and run the child task */ task->tk_xprt->stat.bind_count++; + rpc_run_child(task, child, pmap_getport_done); return; bailout: - pmap_map_free(map); - xprt_put(xprt); -bailout_nofree: - task->tk_status = status; - pmap_wake_portmap_waiters(xprt, status); + spin_lock(&pmap_lock); + map->pm_binding = 0; + rpc_wake_up(&map->pm_bindwait); + spin_unlock(&pmap_lock); + rpc_exit(task, -EIO); } #ifdef CONFIG_ROOT_NFS -/** - * rpc_getport_external - obtain the port for a given RPC service on a given host - * @sin: address of remote peer - * @prog: RPC program number to bind - * @vers: RPC version number to bind - * @prot: transport protocol to use to make this request - * - * This one is called from outside the RPC client in a synchronous task context. - */ -int rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot) +int +rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot) { - struct portmap_args map = { + struct rpc_portmap map = { .pm_prog = prog, .pm_vers = vers, .pm_prot = prot, @@ -174,7 +112,7 @@ int rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int pr char hostname[32]; int status; - dprintk("RPC: rpc_getport_external(%u.%u.%u.%u, %u, %u, %d)\n", + dprintk("RPC: rpc_getport_external(%u.%u.%u.%u, %d, %d, %d)\n", NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(sin->sin_addr.s_addr)); @@ -194,53 +132,45 @@ int rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int pr } #endif -/* - * Portmapper child task invokes this callback via tk_exit. - */ -static void pmap_getport_done(struct rpc_task *child, void *data) +static void +pmap_getport_done(struct rpc_task *task) { - struct portmap_args *map = data; - struct rpc_xprt *xprt = map->pm_xprt; - int status = child->tk_status; - - if (status < 0) { - /* Portmapper not available */ - xprt->ops->set_port(xprt, 0); - } else if (map->pm_port == 0) { - /* Requested RPC service wasn't registered */ - xprt->ops->set_port(xprt, 0); - status = -EACCES; + struct rpc_clnt *clnt = task->tk_client; + struct rpc_xprt *xprt = task->tk_xprt; + struct rpc_portmap *map = clnt->cl_pmap; + + dprintk("RPC: %4d pmap_getport_done(status %d, port %d)\n", + task->tk_pid, task->tk_status, clnt->cl_port); + + xprt->ops->set_port(xprt, 0); + if (task->tk_status < 0) { + /* Make the calling task exit with an error */ + task->tk_action = rpc_exit_task; + } else if (clnt->cl_port == 0) { + /* Program not registered */ + rpc_exit(task, -EACCES); } else { - /* Succeeded */ - xprt->ops->set_port(xprt, map->pm_port); - xprt_set_bound(xprt); - status = 0; + xprt->ops->set_port(xprt, clnt->cl_port); + clnt->cl_port = htons(clnt->cl_port); } - - dprintk("RPC: %4d pmap_getport_done(status %d, port %u)\n", - child->tk_pid, status, map->pm_port); - - pmap_wake_portmap_waiters(xprt, status); - xprt_put(xprt); + spin_lock(&pmap_lock); + map->pm_binding = 0; + rpc_wake_up(&map->pm_bindwait); + spin_unlock(&pmap_lock); } -/** - * rpc_register - set or unset a port registration with the local portmapper - * @prog: RPC program number to bind - * @vers: RPC version number to bind - * @prot: transport protocol to use to make this request - * @port: port value to register - * @okay: result code - * +/* + * Set or unset a port registration with the local portmapper. * port == 0 means unregister, port != 0 means register. */ -int rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) +int +rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) { struct sockaddr_in sin = { .sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK), }; - struct portmap_args map = { + struct rpc_portmap map = { .pm_prog = prog, .pm_vers = vers, .pm_prot = prot, @@ -254,7 +184,7 @@ int rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) struct rpc_clnt *pmap_clnt; int error = 0; - dprintk("RPC: registering (%u, %u, %d, %u) with portmapper.\n", + dprintk("RPC: registering (%d, %d, %d, %d) with portmapper.\n", prog, vers, prot, port); pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP, 1); @@ -277,32 +207,38 @@ int rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) return error; } -static struct rpc_clnt *pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileged) +static struct rpc_clnt * +pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto, int privileged) { - struct rpc_create_args args = { - .protocol = proto, - .address = (struct sockaddr *)srvaddr, - .addrsize = sizeof(*srvaddr), - .servername = hostname, - .program = &pmap_program, - .version = RPC_PMAP_VERSION, - .authflavor = RPC_AUTH_UNIX, - .flags = (RPC_CLNT_CREATE_ONESHOT | - RPC_CLNT_CREATE_NOPING), - }; - - srvaddr->sin_port = htons(RPC_PMAP_PORT); + struct rpc_xprt *xprt; + struct rpc_clnt *clnt; + + /* printk("pmap: create xprt\n"); */ + xprt = xprt_create_proto(proto, srvaddr, NULL); + if (IS_ERR(xprt)) + return (struct rpc_clnt *)xprt; + xprt->ops->set_port(xprt, RPC_PMAP_PORT); if (!privileged) - args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; - return rpc_create(&args); + xprt->resvport = 0; + + /* printk("pmap: create clnt\n"); */ + clnt = rpc_new_client(xprt, hostname, + &pmap_program, RPC_PMAP_VERSION, + RPC_AUTH_UNIX); + if (!IS_ERR(clnt)) { + clnt->cl_softrtry = 1; + clnt->cl_oneshot = 1; + } + return clnt; } /* * XDR encode/decode functions for PMAP */ -static int xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct portmap_args *map) +static int +xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct rpc_portmap *map) { - dprintk("RPC: xdr_encode_mapping(%u, %u, %u, %u)\n", + dprintk("RPC: xdr_encode_mapping(%d, %d, %d, %d)\n", map->pm_prog, map->pm_vers, map->pm_prot, map->pm_port); *p++ = htonl(map->pm_prog); *p++ = htonl(map->pm_vers); @@ -313,13 +249,15 @@ static int xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct portmap_args return 0; } -static int xdr_decode_port(struct rpc_rqst *req, u32 *p, unsigned short *portp) +static int +xdr_decode_port(struct rpc_rqst *req, u32 *p, unsigned short *portp) { *portp = (unsigned short) ntohl(*p++); return 0; } -static int xdr_decode_bool(struct rpc_rqst *req, u32 *p, unsigned int *boolp) +static int +xdr_decode_bool(struct rpc_rqst *req, u32 *p, unsigned int *boolp) { *boolp = (unsigned int) ntohl(*p++); return 0; diff --git a/trunk/net/sunrpc/rpc_pipe.c b/trunk/net/sunrpc/rpc_pipe.c index dfa504fe383f..dc6cb93c8830 100644 --- a/trunk/net/sunrpc/rpc_pipe.c +++ b/trunk/net/sunrpc/rpc_pipe.c @@ -327,8 +327,10 @@ rpc_show_info(struct seq_file *m, void *v) seq_printf(m, "RPC server: %s\n", clnt->cl_server); seq_printf(m, "service: %s (%d) version %d\n", clnt->cl_protname, clnt->cl_prog, clnt->cl_vers); - seq_printf(m, "address: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_ADDR)); - seq_printf(m, "protocol: %s\n", rpc_peeraddr2str(clnt, RPC_DISPLAY_PROTO)); + seq_printf(m, "address: %u.%u.%u.%u\n", + NIPQUAD(clnt->cl_xprt->addr.sin_addr.s_addr)); + seq_printf(m, "protocol: %s\n", + clnt->cl_xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); return 0; } @@ -537,7 +539,6 @@ rpc_depopulate(struct dentry *parent) rpc_close_pipes(dentry->d_inode); simple_unlink(dir, dentry); } - inode_dir_notify(dir, DN_DELETE); dput(dentry); } while (n); goto repeat; @@ -609,8 +610,8 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry) int error; shrink_dcache_parent(dentry); - if (d_unhashed(dentry)) - return 0; + if (dentry->d_inode) + rpc_close_pipes(dentry->d_inode); if ((error = simple_rmdir(dir, dentry)) != 0) return error; if (!error) { @@ -621,13 +622,17 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry) } static struct dentry * -rpc_lookup_create(struct dentry *parent, const char *name, int len) +rpc_lookup_negative(char *path, struct nameidata *nd) { - struct inode *dir = parent->d_inode; struct dentry *dentry; + struct inode *dir; + int error; + if ((error = rpc_lookup_parent(path, nd)) != 0) + return ERR_PTR(error); + dir = nd->dentry->d_inode; mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); - dentry = lookup_one_len(name, parent, len); + dentry = lookup_one_len(nd->last.name, nd->dentry, nd->last.len); if (IS_ERR(dentry)) goto out_err; if (dentry->d_inode) { @@ -638,20 +643,7 @@ rpc_lookup_create(struct dentry *parent, const char *name, int len) return dentry; out_err: mutex_unlock(&dir->i_mutex); - return dentry; -} - -static struct dentry * -rpc_lookup_negative(char *path, struct nameidata *nd) -{ - struct dentry *dentry; - int error; - - if ((error = rpc_lookup_parent(path, nd)) != 0) - return ERR_PTR(error); - dentry = rpc_lookup_create(nd->dentry, nd->last.name, nd->last.len); - if (IS_ERR(dentry)) - rpc_release_path(nd); + rpc_release_path(nd); return dentry; } @@ -675,11 +667,10 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client) RPCAUTH_info, RPCAUTH_EOF); if (error) goto err_depopulate; - dget(dentry); out: mutex_unlock(&dir->i_mutex); rpc_release_path(&nd); - return dentry; + return dget(dentry); err_depopulate: rpc_depopulate(dentry); __rpc_rmdir(dir, dentry); @@ -692,35 +683,44 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client) } int -rpc_rmdir(struct dentry *dentry) +rpc_rmdir(char *path) { - struct dentry *parent; + struct nameidata nd; + struct dentry *dentry; struct inode *dir; int error; - parent = dget_parent(dentry); - dir = parent->d_inode; + if ((error = rpc_lookup_parent(path, &nd)) != 0) + return error; + dir = nd.dentry->d_inode; mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); + dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); + if (IS_ERR(dentry)) { + error = PTR_ERR(dentry); + goto out_release; + } rpc_depopulate(dentry); error = __rpc_rmdir(dir, dentry); dput(dentry); +out_release: mutex_unlock(&dir->i_mutex); - dput(parent); + rpc_release_path(&nd); return error; } struct dentry * -rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pipe_ops *ops, int flags) +rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags) { + struct nameidata nd; struct dentry *dentry; struct inode *dir, *inode; struct rpc_inode *rpci; - dentry = rpc_lookup_create(parent, name, strlen(name)); + dentry = rpc_lookup_negative(path, &nd); if (IS_ERR(dentry)) return dentry; - dir = parent->d_inode; - inode = rpc_get_inode(dir->i_sb, S_IFIFO | S_IRUSR | S_IWUSR); + dir = nd.dentry->d_inode; + inode = rpc_get_inode(dir->i_sb, S_IFSOCK | S_IRUSR | S_IWUSR); if (!inode) goto err_dput; inode->i_ino = iunique(dir->i_sb, 100); @@ -731,40 +731,45 @@ rpc_mkpipe(struct dentry *parent, const char *name, void *private, struct rpc_pi rpci->flags = flags; rpci->ops = ops; inode_dir_notify(dir, DN_CREATE); - dget(dentry); out: mutex_unlock(&dir->i_mutex); - return dentry; + rpc_release_path(&nd); + return dget(dentry); err_dput: dput(dentry); dentry = ERR_PTR(-ENOMEM); - printk(KERN_WARNING "%s: %s() failed to create pipe %s/%s (errno = %d)\n", - __FILE__, __FUNCTION__, parent->d_name.name, name, - -ENOMEM); + printk(KERN_WARNING "%s: %s() failed to create pipe %s (errno = %d)\n", + __FILE__, __FUNCTION__, path, -ENOMEM); goto out; } int -rpc_unlink(struct dentry *dentry) +rpc_unlink(char *path) { - struct dentry *parent; + struct nameidata nd; + struct dentry *dentry; struct inode *dir; - int error = 0; + int error; - parent = dget_parent(dentry); - dir = parent->d_inode; + if ((error = rpc_lookup_parent(path, &nd)) != 0) + return error; + dir = nd.dentry->d_inode; mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); - if (!d_unhashed(dentry)) { - d_drop(dentry); - if (dentry->d_inode) { - rpc_close_pipes(dentry->d_inode); - error = simple_unlink(dir, dentry); - } - inode_dir_notify(dir, DN_DELETE); + dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); + if (IS_ERR(dentry)) { + error = PTR_ERR(dentry); + goto out_release; + } + d_drop(dentry); + if (dentry->d_inode) { + rpc_close_pipes(dentry->d_inode); + error = simple_unlink(dir, dentry); } dput(dentry); + inode_dir_notify(dir, DN_DELETE); +out_release: mutex_unlock(&dir->i_mutex); - dput(parent); + rpc_release_path(&nd); return error; } diff --git a/trunk/net/sunrpc/sched.c b/trunk/net/sunrpc/sched.c index 6390461a9756..5c3eee768504 100644 --- a/trunk/net/sunrpc/sched.c +++ b/trunk/net/sunrpc/sched.c @@ -21,6 +21,7 @@ #include #include +#include #ifdef RPC_DEBUG #define RPCDBG_FACILITY RPCDBG_SCHED @@ -43,6 +44,12 @@ static void __rpc_default_timer(struct rpc_task *task); static void rpciod_killall(void); static void rpc_async_schedule(void *); +/* + * RPC tasks that create another task (e.g. for contacting the portmapper) + * will wait on this queue for their child's completion + */ +static RPC_WAITQ(childq, "childq"); + /* * RPC tasks sit here while waiting for conditions to improve. */ @@ -316,6 +323,16 @@ static void rpc_make_runnable(struct rpc_task *task) wake_up_bit(&task->tk_runstate, RPC_TASK_QUEUED); } +/* + * Place a newly initialized task on the workqueue. + */ +static inline void +rpc_schedule_run(struct rpc_task *task) +{ + rpc_set_active(task); + rpc_make_runnable(task); +} + /* * Prepare for sleeping on a wait queue. * By always appending tasks to the list we ensure FIFO behavior. @@ -542,20 +559,24 @@ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status) spin_unlock_bh(&queue->lock); } -static void __rpc_atrun(struct rpc_task *task) -{ - rpc_wake_up_task(task); -} - /* * Run a task at a later time */ -void rpc_delay(struct rpc_task *task, unsigned long delay) +static void __rpc_atrun(struct rpc_task *); +void +rpc_delay(struct rpc_task *task, unsigned long delay) { task->tk_timeout = delay; rpc_sleep_on(&delay_queue, task, NULL, __rpc_atrun); } +static void +__rpc_atrun(struct rpc_task *task) +{ + task->tk_status = 0; + rpc_wake_up_task(task); +} + /* * Helper to call task->tk_ops->rpc_call_prepare */ @@ -912,6 +933,72 @@ struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, } EXPORT_SYMBOL(rpc_run_task); +/** + * rpc_find_parent - find the parent of a child task. + * @child: child task + * @parent: parent task + * + * Checks that the parent task is still sleeping on the + * queue 'childq'. If so returns a pointer to the parent. + * Upon failure returns NULL. + * + * Caller must hold childq.lock + */ +static inline struct rpc_task *rpc_find_parent(struct rpc_task *child, struct rpc_task *parent) +{ + struct rpc_task *task; + struct list_head *le; + + task_for_each(task, le, &childq.tasks[0]) + if (task == parent) + return parent; + + return NULL; +} + +static void rpc_child_exit(struct rpc_task *child, void *calldata) +{ + struct rpc_task *parent; + + spin_lock_bh(&childq.lock); + if ((parent = rpc_find_parent(child, calldata)) != NULL) { + parent->tk_status = child->tk_status; + __rpc_wake_up_task(parent); + } + spin_unlock_bh(&childq.lock); +} + +static const struct rpc_call_ops rpc_child_ops = { + .rpc_call_done = rpc_child_exit, +}; + +/* + * Note: rpc_new_task releases the client after a failure. + */ +struct rpc_task * +rpc_new_child(struct rpc_clnt *clnt, struct rpc_task *parent) +{ + struct rpc_task *task; + + task = rpc_new_task(clnt, RPC_TASK_ASYNC | RPC_TASK_CHILD, &rpc_child_ops, parent); + if (!task) + goto fail; + return task; + +fail: + parent->tk_status = -ENOMEM; + return NULL; +} + +void rpc_run_child(struct rpc_task *task, struct rpc_task *child, rpc_action func) +{ + spin_lock_bh(&childq.lock); + /* N.B. Is it possible for the child to have already finished? */ + __rpc_sleep_on(&childq, task, func, NULL); + rpc_schedule_run(child); + spin_unlock_bh(&childq.lock); +} + /* * Kill all tasks for the given client. * XXX: kill their descendants as well? diff --git a/trunk/net/sunrpc/socklib.c b/trunk/net/sunrpc/socklib.c index 6f17527b9e69..eb330d4f66d6 100644 --- a/trunk/net/sunrpc/socklib.c +++ b/trunk/net/sunrpc/socklib.c @@ -168,7 +168,7 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) return -1; if ((unsigned short)csum_fold(desc.csum)) return -1; - if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE)) + if (unlikely(skb->ip_summed == CHECKSUM_HW)) netdev_rx_csum_fault(skb->dev); return 0; no_checksum: diff --git a/trunk/net/sunrpc/sunrpc_syms.c b/trunk/net/sunrpc/sunrpc_syms.c index 26c0531d7e25..f38f939ce95f 100644 --- a/trunk/net/sunrpc/sunrpc_syms.c +++ b/trunk/net/sunrpc/sunrpc_syms.c @@ -36,6 +36,8 @@ EXPORT_SYMBOL(rpc_wake_up_status); EXPORT_SYMBOL(rpc_release_task); /* RPC client functions */ +EXPORT_SYMBOL(rpc_create_client); +EXPORT_SYMBOL(rpc_new_client); EXPORT_SYMBOL(rpc_clone_client); EXPORT_SYMBOL(rpc_bind_new_program); EXPORT_SYMBOL(rpc_destroy_client); @@ -55,6 +57,7 @@ EXPORT_SYMBOL(rpc_queue_upcall); EXPORT_SYMBOL(rpc_mkpipe); /* Client transport */ +EXPORT_SYMBOL(xprt_create_proto); EXPORT_SYMBOL(xprt_set_timeout); /* Client credential cache */ diff --git a/trunk/net/sunrpc/svcsock.c b/trunk/net/sunrpc/svcsock.c index 953aff89bcac..d9a95732df46 100644 --- a/trunk/net/sunrpc/svcsock.c +++ b/trunk/net/sunrpc/svcsock.c @@ -388,7 +388,7 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) /* send head */ if (slen == xdr->head[0].iov_len) flags = 0; - len = kernel_sendpage(sock, rqstp->rq_respages[0], 0, xdr->head[0].iov_len, flags); + len = sock->ops->sendpage(sock, rqstp->rq_respages[0], 0, xdr->head[0].iov_len, flags); if (len != xdr->head[0].iov_len) goto out; slen -= xdr->head[0].iov_len; @@ -400,7 +400,7 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) while (pglen > 0) { if (slen == size) flags = 0; - result = kernel_sendpage(sock, *ppage, base, size, flags); + result = sock->ops->sendpage(sock, *ppage, base, size, flags); if (result > 0) len += result; if (result != size) @@ -413,7 +413,7 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) } /* send tail */ if (xdr->tail[0].iov_len) { - result = kernel_sendpage(sock, rqstp->rq_respages[rqstp->rq_restailpage], + result = sock->ops->sendpage(sock, rqstp->rq_respages[rqstp->rq_restailpage], ((unsigned long)xdr->tail[0].iov_base)& (PAGE_SIZE-1), xdr->tail[0].iov_len, 0); @@ -434,10 +434,13 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) static int svc_recv_available(struct svc_sock *svsk) { + mm_segment_t oldfs; struct socket *sock = svsk->sk_sock; int avail, err; - err = kernel_sock_ioctl(sock, TIOCINQ, (unsigned long) &avail); + oldfs = get_fs(); set_fs(KERNEL_DS); + err = sock->ops->ioctl(sock, TIOCINQ, (unsigned long) &avail); + set_fs(oldfs); return (err >= 0)? avail : err; } @@ -469,7 +472,7 @@ svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen) * at accept time. FIXME */ alen = sizeof(rqstp->rq_addr); - kernel_getpeername(sock, (struct sockaddr *)&rqstp->rq_addr, &alen); + sock->ops->getname(sock, (struct sockaddr *)&rqstp->rq_addr, &alen, 1); dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n", rqstp->rq_sock, iov[0].iov_base, iov[0].iov_len, len); @@ -755,6 +758,7 @@ svc_tcp_accept(struct svc_sock *svsk) struct svc_serv *serv = svsk->sk_server; struct socket *sock = svsk->sk_sock; struct socket *newsock; + const struct proto_ops *ops; struct svc_sock *newsvsk; int err, slen; @@ -762,23 +766,29 @@ svc_tcp_accept(struct svc_sock *svsk) if (!sock) return; - clear_bit(SK_CONN, &svsk->sk_flags); - err = kernel_accept(sock, &newsock, O_NONBLOCK); - if (err < 0) { + err = sock_create_lite(PF_INET, SOCK_STREAM, IPPROTO_TCP, &newsock); + if (err) { if (err == -ENOMEM) printk(KERN_WARNING "%s: no more sockets!\n", serv->sv_name); - else if (err != -EAGAIN && net_ratelimit()) - printk(KERN_WARNING "%s: accept failed (err %d)!\n", - serv->sv_name, -err); return; } + dprintk("svc: tcp_accept %p allocated\n", newsock); + newsock->ops = ops = sock->ops; + + clear_bit(SK_CONN, &svsk->sk_flags); + if ((err = ops->accept(sock, newsock, O_NONBLOCK)) < 0) { + if (err != -EAGAIN && net_ratelimit()) + printk(KERN_WARNING "%s: accept failed (err %d)!\n", + serv->sv_name, -err); + goto failed; /* aborted connection or whatever */ + } set_bit(SK_CONN, &svsk->sk_flags); svc_sock_enqueue(svsk); slen = sizeof(sin); - err = kernel_getpeername(newsock, (struct sockaddr *) &sin, &slen); + err = ops->getname(newsock, (struct sockaddr *) &sin, &slen, 1); if (err < 0) { if (net_ratelimit()) printk(KERN_WARNING "%s: peername failed (err %d)!\n", @@ -1396,14 +1406,14 @@ svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin) if (sin != NULL) { if (type == SOCK_STREAM) sock->sk->sk_reuse = 1; /* allow address reuse */ - error = kernel_bind(sock, (struct sockaddr *) sin, + error = sock->ops->bind(sock, (struct sockaddr *) sin, sizeof(*sin)); if (error < 0) goto bummer; } if (protocol == IPPROTO_TCP) { - if ((error = kernel_listen(sock, 64)) < 0) + if ((error = sock->ops->listen(sock, 64)) < 0) goto bummer; } diff --git a/trunk/net/sunrpc/timer.c b/trunk/net/sunrpc/timer.c index 8142fdb8a930..bcbdf6430d5c 100644 --- a/trunk/net/sunrpc/timer.c +++ b/trunk/net/sunrpc/timer.c @@ -19,6 +19,8 @@ #include #include +#include +#include #define RPC_RTO_MAX (60*HZ) #define RPC_RTO_INIT (HZ/5) diff --git a/trunk/net/sunrpc/xprt.c b/trunk/net/sunrpc/xprt.c index 1f786f68729d..313b68d892c6 100644 --- a/trunk/net/sunrpc/xprt.c +++ b/trunk/net/sunrpc/xprt.c @@ -534,7 +534,7 @@ void xprt_connect(struct rpc_task *task) dprintk("RPC: %4d xprt_connect xprt %p %s connected\n", task->tk_pid, xprt, (xprt_connected(xprt) ? "is" : "is not")); - if (!xprt_bound(xprt)) { + if (!xprt->addr.sin_port) { task->tk_status = -EIO; return; } @@ -585,6 +585,13 @@ static void xprt_connect_status(struct rpc_task *task) task->tk_pid, -task->tk_status, task->tk_client->cl_server); xprt_release_write(xprt, task); task->tk_status = -EIO; + return; + } + + /* if soft mounted, just cause this RPC to fail */ + if (RPC_IS_SOFT(task)) { + xprt_release_write(xprt, task); + task->tk_status = -EIO; } } @@ -700,9 +707,12 @@ int xprt_prepare_transmit(struct rpc_task *task) return err; } -void xprt_end_transmit(struct rpc_task *task) +void +xprt_abort_transmit(struct rpc_task *task) { - xprt_release_write(task->tk_xprt, task); + struct rpc_xprt *xprt = task->tk_xprt; + + xprt_release_write(xprt, task); } /** @@ -751,6 +761,8 @@ void xprt_transmit(struct rpc_task *task) task->tk_status = -ENOTCONN; else if (!req->rq_received) rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); + + xprt->ops->release_xprt(xprt, task); spin_unlock_bh(&xprt->transport_lock); return; } @@ -760,8 +772,18 @@ void xprt_transmit(struct rpc_task *task) * schedq, and being picked up by a parallel run of rpciod(). */ task->tk_status = status; - if (status == -ECONNREFUSED) + + switch (status) { + case -ECONNREFUSED: rpc_sleep_on(&xprt->sending, task, NULL, NULL); + case -EAGAIN: + case -ENOTCONN: + return; + default: + break; + } + xprt_release_write(xprt, task); + return; } static inline void do_xprt_reserve(struct rpc_task *task) @@ -822,7 +844,6 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) req->rq_bufsize = 0; req->rq_xid = xprt_alloc_xid(xprt); req->rq_release_snd_buf = NULL; - xprt_reset_majortimeo(req); dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid, req, ntohl(req->rq_xid)); } @@ -881,32 +902,16 @@ void xprt_set_timeout(struct rpc_timeout *to, unsigned int retr, unsigned long i to->to_exponential = 0; } -/** - * xprt_create_transport - create an RPC transport - * @proto: requested transport protocol - * @ap: remote peer address - * @size: length of address - * @to: timeout parameters - * - */ -struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t size, struct rpc_timeout *to) +static struct rpc_xprt *xprt_setup(int proto, struct sockaddr_in *ap, struct rpc_timeout *to) { int result; struct rpc_xprt *xprt; struct rpc_rqst *req; - if ((xprt = kzalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL) { - dprintk("RPC: xprt_create_transport: no memory\n"); + if ((xprt = kzalloc(sizeof(struct rpc_xprt), GFP_KERNEL)) == NULL) return ERR_PTR(-ENOMEM); - } - if (size <= sizeof(xprt->addr)) { - memcpy(&xprt->addr, ap, size); - xprt->addrlen = size; - } else { - kfree(xprt); - dprintk("RPC: xprt_create_transport: address too large\n"); - return ERR_PTR(-EBADF); - } + + xprt->addr = *ap; switch (proto) { case IPPROTO_UDP: @@ -918,15 +923,14 @@ struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t si default: printk(KERN_ERR "RPC: unrecognized transport protocol: %d\n", proto); - return ERR_PTR(-EIO); + result = -EIO; + break; } if (result) { kfree(xprt); - dprintk("RPC: xprt_create_transport: failed, %d\n", result); return ERR_PTR(result); } - kref_init(&xprt->kref); spin_lock_init(&xprt->transport_lock); spin_lock_init(&xprt->reserve_lock); @@ -939,7 +943,6 @@ struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t si xprt->last_used = jiffies; xprt->cwnd = RPC_INITCWND; - rpc_init_wait_queue(&xprt->binding, "xprt_binding"); rpc_init_wait_queue(&xprt->pending, "xprt_pending"); rpc_init_wait_queue(&xprt->sending, "xprt_sending"); rpc_init_wait_queue(&xprt->resend, "xprt_resend"); @@ -953,43 +956,41 @@ struct rpc_xprt *xprt_create_transport(int proto, struct sockaddr *ap, size_t si dprintk("RPC: created transport %p with %u slots\n", xprt, xprt->max_reqs); - + return xprt; } /** - * xprt_destroy - destroy an RPC transport, killing off all requests. - * @kref: kref for the transport to destroy + * xprt_create_proto - create an RPC client transport + * @proto: requested transport protocol + * @sap: remote peer's address + * @to: timeout parameters for new transport * */ -static void xprt_destroy(struct kref *kref) +struct rpc_xprt *xprt_create_proto(int proto, struct sockaddr_in *sap, struct rpc_timeout *to) { - struct rpc_xprt *xprt = container_of(kref, struct rpc_xprt, kref); + struct rpc_xprt *xprt; - dprintk("RPC: destroying transport %p\n", xprt); - xprt->shutdown = 1; - del_timer_sync(&xprt->timer); - xprt->ops->destroy(xprt); - kfree(xprt); + xprt = xprt_setup(proto, sap, to); + if (IS_ERR(xprt)) + dprintk("RPC: xprt_create_proto failed\n"); + else + dprintk("RPC: xprt_create_proto created xprt %p\n", xprt); + return xprt; } /** - * xprt_put - release a reference to an RPC transport. - * @xprt: pointer to the transport + * xprt_destroy - destroy an RPC transport, killing off all requests. + * @xprt: transport to destroy * */ -void xprt_put(struct rpc_xprt *xprt) +int xprt_destroy(struct rpc_xprt *xprt) { - kref_put(&xprt->kref, xprt_destroy); -} + dprintk("RPC: destroying transport %p\n", xprt); + xprt->shutdown = 1; + del_timer_sync(&xprt->timer); + xprt->ops->destroy(xprt); + kfree(xprt); -/** - * xprt_get - return a reference to an RPC transport. - * @xprt: pointer to the transport - * - */ -struct rpc_xprt *xprt_get(struct rpc_xprt *xprt) -{ - kref_get(&xprt->kref); - return xprt; + return 0; } diff --git a/trunk/net/sunrpc/xprtsock.c b/trunk/net/sunrpc/xprtsock.c index 9b62923a9c06..ee678ed13b6f 100644 --- a/trunk/net/sunrpc/xprtsock.c +++ b/trunk/net/sunrpc/xprtsock.c @@ -125,47 +125,6 @@ static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count) } #endif -static void xs_format_peer_addresses(struct rpc_xprt *xprt) -{ - struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr; - char *buf; - - buf = kzalloc(20, GFP_KERNEL); - if (buf) { - snprintf(buf, 20, "%u.%u.%u.%u", - NIPQUAD(addr->sin_addr.s_addr)); - } - xprt->address_strings[RPC_DISPLAY_ADDR] = buf; - - buf = kzalloc(8, GFP_KERNEL); - if (buf) { - snprintf(buf, 8, "%u", - ntohs(addr->sin_port)); - } - xprt->address_strings[RPC_DISPLAY_PORT] = buf; - - if (xprt->prot == IPPROTO_UDP) - xprt->address_strings[RPC_DISPLAY_PROTO] = "udp"; - else - xprt->address_strings[RPC_DISPLAY_PROTO] = "tcp"; - - buf = kzalloc(48, GFP_KERNEL); - if (buf) { - snprintf(buf, 48, "addr=%u.%u.%u.%u port=%u proto=%s", - NIPQUAD(addr->sin_addr.s_addr), - ntohs(addr->sin_port), - xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); - } - xprt->address_strings[RPC_DISPLAY_ALL] = buf; -} - -static void xs_free_peer_addresses(struct rpc_xprt *xprt) -{ - kfree(xprt->address_strings[RPC_DISPLAY_ADDR]); - kfree(xprt->address_strings[RPC_DISPLAY_PORT]); - kfree(xprt->address_strings[RPC_DISPLAY_ALL]); -} - #define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL) static inline int xs_send_head(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, unsigned int len) @@ -215,6 +174,7 @@ static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int a struct page **ppage = xdr->pages; unsigned int len, pglen = xdr->page_len; int err, ret = 0; + ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); if (unlikely(!sock)) return -ENOTCONN; @@ -247,6 +207,7 @@ static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int a base &= ~PAGE_CACHE_MASK; } + sendpage = sock->ops->sendpage ? : sock_no_sendpage; do { int flags = XS_SENDMSG_FLAGS; @@ -259,7 +220,10 @@ static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int a if (pglen != len || xdr->tail[0].iov_len != 0) flags |= MSG_MORE; - err = kernel_sendpage(sock, *ppage, base, len, flags); + /* Hmm... We might be dealing with highmem pages */ + if (PageHighMem(*ppage)) + sendpage = sock_no_sendpage; + err = sendpage(sock, *ppage, base, len, flags); if (ret == 0) ret = err; else if (err > 0) @@ -336,7 +300,7 @@ static int xs_udp_send_request(struct rpc_task *task) req->rq_xtime = jiffies; status = xs_sendpages(xprt->sock, (struct sockaddr *) &xprt->addr, - xprt->addrlen, xdr, req->rq_bytes_sent); + sizeof(xprt->addr), xdr, req->rq_bytes_sent); dprintk("RPC: xs_udp_send_request(%u) = %d\n", xdr->len - req->rq_bytes_sent, status); @@ -449,33 +413,6 @@ static int xs_tcp_send_request(struct rpc_task *task) return status; } -/** - * xs_tcp_release_xprt - clean up after a tcp transmission - * @xprt: transport - * @task: rpc task - * - * This cleans up if an error causes us to abort the transmission of a request. - * In this case, the socket may need to be reset in order to avoid confusing - * the server. - */ -static void xs_tcp_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) -{ - struct rpc_rqst *req; - - if (task != xprt->snd_task) - return; - if (task == NULL) - goto out_release; - req = task->tk_rqstp; - if (req->rq_bytes_sent == 0) - goto out_release; - if (req->rq_bytes_sent == req->rq_snd_buf.len) - goto out_release; - set_bit(XPRT_CLOSE_WAIT, &task->tk_xprt->state); -out_release: - xprt_release_xprt(xprt, task); -} - /** * xs_close - close a socket * @xprt: transport @@ -526,7 +463,6 @@ static void xs_destroy(struct rpc_xprt *xprt) xprt_disconnect(xprt); xs_close(xprt); - xs_free_peer_addresses(xprt); kfree(xprt->slot); } @@ -1001,19 +937,6 @@ static unsigned short xs_get_random_port(void) return rand + xprt_min_resvport; } -/** - * xs_print_peer_address - format an IPv4 address for printing - * @xprt: generic transport - * @format: flags field indicating which parts of the address to render - */ -static char *xs_print_peer_address(struct rpc_xprt *xprt, enum rpc_display_format_t format) -{ - if (xprt->address_strings[format] != NULL) - return xprt->address_strings[format]; - else - return "unprintable"; -} - /** * xs_set_port - reset the port number in the remote endpoint address * @xprt: generic transport @@ -1022,11 +945,8 @@ static char *xs_print_peer_address(struct rpc_xprt *xprt, enum rpc_display_forma */ static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) { - struct sockaddr_in *sap = (struct sockaddr_in *) &xprt->addr; - dprintk("RPC: setting port for xprt %p to %u\n", xprt, port); - - sap->sin_port = htons(port); + xprt->addr.sin_port = htons(port); } static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock) @@ -1039,7 +959,7 @@ static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock) do { myaddr.sin_port = htons(port); - err = kernel_bind(sock, (struct sockaddr *) &myaddr, + err = sock->ops->bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)); if (err == 0) { xprt->port = port; @@ -1069,9 +989,11 @@ static void xs_udp_connect_worker(void *args) struct socket *sock = xprt->sock; int err, status = -EIO; - if (xprt->shutdown || !xprt_bound(xprt)) + if (xprt->shutdown || xprt->addr.sin_port == 0) goto out; + dprintk("RPC: xs_udp_connect_worker for xprt %p\n", xprt); + /* Start by resetting any existing state */ xs_close(xprt); @@ -1085,9 +1007,6 @@ static void xs_udp_connect_worker(void *args) goto out; } - dprintk("RPC: worker connecting xprt %p to address: %s\n", - xprt, xs_print_peer_address(xprt, RPC_DISPLAY_ALL)); - if (!xprt->inet) { struct sock *sk = sock->sk; @@ -1135,7 +1054,7 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt) */ memset(&any, 0, sizeof(any)); any.sa_family = AF_UNSPEC; - result = kernel_connect(sock, &any, sizeof(any), 0); + result = sock->ops->connect(sock, &any, sizeof(any), 0); if (result) dprintk("RPC: AF_UNSPEC connect return code %d\n", result); @@ -1153,9 +1072,11 @@ static void xs_tcp_connect_worker(void *args) struct socket *sock = xprt->sock; int err, status = -EIO; - if (xprt->shutdown || !xprt_bound(xprt)) + if (xprt->shutdown || xprt->addr.sin_port == 0) goto out; + dprintk("RPC: xs_tcp_connect_worker for xprt %p\n", xprt); + if (!xprt->sock) { /* start from scratch */ if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { @@ -1171,9 +1092,6 @@ static void xs_tcp_connect_worker(void *args) /* "close" the socket, preserving the local port */ xs_tcp_reuse_connection(xprt); - dprintk("RPC: worker connecting xprt %p to address: %s\n", - xprt, xs_print_peer_address(xprt, RPC_DISPLAY_ALL)); - if (!xprt->inet) { struct sock *sk = sock->sk; @@ -1206,8 +1124,8 @@ static void xs_tcp_connect_worker(void *args) /* Tell the socket layer to start connecting... */ xprt->stat.connect_count++; xprt->stat.connect_start = jiffies; - status = kernel_connect(sock, (struct sockaddr *) &xprt->addr, - xprt->addrlen, O_NONBLOCK); + status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr, + sizeof(xprt->addr), O_NONBLOCK); dprintk("RPC: %p connect status %d connected %d sock state %d\n", xprt, -status, xprt_connected(xprt), sock->sk->sk_state); if (status < 0) { @@ -1315,10 +1233,8 @@ static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) static struct rpc_xprt_ops xs_udp_ops = { .set_buffer_size = xs_udp_set_buffer_size, - .print_addr = xs_print_peer_address, .reserve_xprt = xprt_reserve_xprt_cong, .release_xprt = xprt_release_xprt_cong, - .rpcbind = rpc_getport, .set_port = xs_set_port, .connect = xs_connect, .buf_alloc = rpc_malloc, @@ -1333,10 +1249,8 @@ static struct rpc_xprt_ops xs_udp_ops = { }; static struct rpc_xprt_ops xs_tcp_ops = { - .print_addr = xs_print_peer_address, .reserve_xprt = xprt_reserve_xprt, - .release_xprt = xs_tcp_release_xprt, - .rpcbind = rpc_getport, + .release_xprt = xprt_release_xprt, .set_port = xs_set_port, .connect = xs_connect, .buf_alloc = rpc_malloc, @@ -1357,7 +1271,8 @@ static struct rpc_xprt_ops xs_tcp_ops = { int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) { size_t slot_table_size; - struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr; + + dprintk("RPC: setting up udp-ipv4 transport...\n"); xprt->max_reqs = xprt_udp_slot_table_entries; slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]); @@ -1365,12 +1280,10 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) if (xprt->slot == NULL) return -ENOMEM; - if (ntohs(addr->sin_port != 0)) - xprt_set_bound(xprt); - xprt->port = xs_get_random_port(); - xprt->prot = IPPROTO_UDP; + xprt->port = xs_get_random_port(); xprt->tsh_size = 0; + xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; /* XXX: header size can vary due to auth type, IPv6, etc. */ xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); @@ -1387,10 +1300,6 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) else xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); - xs_format_peer_addresses(xprt); - dprintk("RPC: set up transport to address %s\n", - xs_print_peer_address(xprt, RPC_DISPLAY_ALL)); - return 0; } @@ -1403,7 +1312,8 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to) { size_t slot_table_size; - struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr; + + dprintk("RPC: setting up tcp-ipv4 transport...\n"); xprt->max_reqs = xprt_tcp_slot_table_entries; slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]); @@ -1411,12 +1321,10 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to) if (xprt->slot == NULL) return -ENOMEM; - if (ntohs(addr->sin_port) != 0) - xprt_set_bound(xprt); - xprt->port = xs_get_random_port(); - xprt->prot = IPPROTO_TCP; + xprt->port = xs_get_random_port(); xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); + xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt); @@ -1432,9 +1340,5 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to) else xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); - xs_format_peer_addresses(xprt); - dprintk("RPC: set up transport to address %s\n", - xs_print_peer_address(xprt, RPC_DISPLAY_ALL)); - return 0; } diff --git a/trunk/net/unix/af_unix.c b/trunk/net/unix/af_unix.c index b43a27828df5..6f2909279268 100644 --- a/trunk/net/unix/af_unix.c +++ b/trunk/net/unix/af_unix.c @@ -117,7 +117,7 @@ #include #include -int sysctl_unix_max_dgram_qlen __read_mostly = 10; +int sysctl_unix_max_dgram_qlen = 10; struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; DEFINE_SPINLOCK(unix_table_lock); @@ -128,17 +128,23 @@ static atomic_t unix_nr_socks = ATOMIC_INIT(0); #define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE) #ifdef CONFIG_SECURITY_NETWORK -static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) +static void unix_get_peersec_dgram(struct sk_buff *skb) { - memcpy(UNIXSID(skb), &scm->secid, sizeof(u32)); + int err; + + err = security_socket_getpeersec_dgram(skb, UNIXSECDATA(skb), + UNIXSECLEN(skb)); + if (err) + *(UNIXSECDATA(skb)) = NULL; } static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) { - scm->secid = *UNIXSID(skb); + scm->secdata = *UNIXSECDATA(skb); + scm->seclen = *UNIXSECLEN(skb); } #else -static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) +static inline void unix_get_peersec_dgram(struct sk_buff *skb) { } static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) @@ -1316,7 +1322,8 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); if (siocb->scm->fp) unix_attach_fds(siocb->scm, skb); - unix_get_secdata(siocb->scm, skb); + + unix_get_peersec_dgram(skb); skb->h.raw = skb->data; err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len); @@ -2060,7 +2067,10 @@ static int __init af_unix_init(void) int rc = -1; struct sk_buff *dummy_skb; - BUILD_BUG_ON(sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb)); + if (sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb)) { + printk(KERN_CRIT "%s: panic\n", __FUNCTION__); + goto out; + } rc = proto_register(&unix_proto, 1); if (rc != 0) { diff --git a/trunk/net/xfrm/Kconfig b/trunk/net/xfrm/Kconfig index 0faab6332586..0c1c04322baf 100644 --- a/trunk/net/xfrm/Kconfig +++ b/trunk/net/xfrm/Kconfig @@ -6,24 +6,14 @@ config XFRM depends on NET config XFRM_USER - tristate "Transformation user configuration interface" + tristate "IPsec user configuration interface" depends on INET && XFRM ---help--- - Support for Transformation(XFRM) user configuration interface - like IPsec used by native Linux tools. + Support for IPsec user configuration interface used + by native Linux tools. If unsure, say Y. -config XFRM_SUB_POLICY - bool "Transformation sub policy support (EXPERIMENTAL)" - depends on XFRM && EXPERIMENTAL - ---help--- - Support sub policy for developers. By using sub policy with main - one, two policies can be applied to the same packet at once. - Policy which lives shorter time in kernel should be a sub. - - If unsure, say N. - config NET_KEY tristate "PF_KEY sockets" select XFRM diff --git a/trunk/net/xfrm/Makefile b/trunk/net/xfrm/Makefile index de3c1a625a46..693aac1aa833 100644 --- a/trunk/net/xfrm/Makefile +++ b/trunk/net/xfrm/Makefile @@ -2,7 +2,6 @@ # Makefile for the XFRM subsystem. # -obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \ - xfrm_input.o xfrm_algo.o +obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_input.o xfrm_algo.o obj-$(CONFIG_XFRM_USER) += xfrm_user.o diff --git a/trunk/net/xfrm/xfrm_algo.c b/trunk/net/xfrm/xfrm_algo.c index 5a0dbeb6bbe8..04e1aea58bc9 100644 --- a/trunk/net/xfrm/xfrm_algo.c +++ b/trunk/net/xfrm/xfrm_algo.c @@ -30,8 +30,7 @@ */ static struct xfrm_algo_desc aalg_list[] = { { - .name = "hmac(digest_null)", - .compat = "digest_null", + .name = "digest_null", .uinfo = { .auth = { @@ -48,8 +47,7 @@ static struct xfrm_algo_desc aalg_list[] = { } }, { - .name = "hmac(md5)", - .compat = "md5", + .name = "md5", .uinfo = { .auth = { @@ -66,8 +64,7 @@ static struct xfrm_algo_desc aalg_list[] = { } }, { - .name = "hmac(sha1)", - .compat = "sha1", + .name = "sha1", .uinfo = { .auth = { @@ -84,8 +81,7 @@ static struct xfrm_algo_desc aalg_list[] = { } }, { - .name = "hmac(sha256)", - .compat = "sha256", + .name = "sha256", .uinfo = { .auth = { @@ -102,8 +98,7 @@ static struct xfrm_algo_desc aalg_list[] = { } }, { - .name = "hmac(ripemd160)", - .compat = "ripemd160", + .name = "ripemd160", .uinfo = { .auth = { @@ -123,8 +118,7 @@ static struct xfrm_algo_desc aalg_list[] = { static struct xfrm_algo_desc ealg_list[] = { { - .name = "ecb(cipher_null)", - .compat = "cipher_null", + .name = "cipher_null", .uinfo = { .encr = { @@ -141,8 +135,7 @@ static struct xfrm_algo_desc ealg_list[] = { } }, { - .name = "cbc(des)", - .compat = "des", + .name = "des", .uinfo = { .encr = { @@ -159,8 +152,7 @@ static struct xfrm_algo_desc ealg_list[] = { } }, { - .name = "cbc(des3_ede)", - .compat = "des3_ede", + .name = "des3_ede", .uinfo = { .encr = { @@ -177,8 +169,7 @@ static struct xfrm_algo_desc ealg_list[] = { } }, { - .name = "cbc(cast128)", - .compat = "cast128", + .name = "cast128", .uinfo = { .encr = { @@ -195,8 +186,7 @@ static struct xfrm_algo_desc ealg_list[] = { } }, { - .name = "cbc(blowfish)", - .compat = "blowfish", + .name = "blowfish", .uinfo = { .encr = { @@ -213,8 +203,7 @@ static struct xfrm_algo_desc ealg_list[] = { } }, { - .name = "cbc(aes)", - .compat = "aes", + .name = "aes", .uinfo = { .encr = { @@ -231,8 +220,7 @@ static struct xfrm_algo_desc ealg_list[] = { } }, { - .name = "cbc(serpent)", - .compat = "serpent", + .name = "serpent", .uinfo = { .encr = { @@ -249,8 +237,7 @@ static struct xfrm_algo_desc ealg_list[] = { } }, { - .name = "cbc(twofish)", - .compat = "twofish", + .name = "twofish", .uinfo = { .encr = { @@ -363,8 +350,8 @@ struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id) EXPORT_SYMBOL_GPL(xfrm_calg_get_byid); static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list, - int entries, u32 type, u32 mask, - char *name, int probe) + int entries, char *name, + int probe) { int i, status; @@ -372,8 +359,7 @@ static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list, return NULL; for (i = 0; i < entries; i++) { - if (strcmp(name, list[i].name) && - (!list[i].compat || strcmp(name, list[i].compat))) + if (strcmp(name, list[i].name)) continue; if (list[i].available) @@ -382,7 +368,7 @@ static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list, if (!probe) break; - status = crypto_has_alg(name, type, mask | CRYPTO_ALG_ASYNC); + status = crypto_alg_available(name, 0); if (!status) break; @@ -394,25 +380,19 @@ static struct xfrm_algo_desc *xfrm_get_byname(struct xfrm_algo_desc *list, struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe) { - return xfrm_get_byname(aalg_list, aalg_entries(), - CRYPTO_ALG_TYPE_HASH, CRYPTO_ALG_TYPE_HASH_MASK, - name, probe); + return xfrm_get_byname(aalg_list, aalg_entries(), name, probe); } EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname); struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe) { - return xfrm_get_byname(ealg_list, ealg_entries(), - CRYPTO_ALG_TYPE_BLKCIPHER, CRYPTO_ALG_TYPE_MASK, - name, probe); + return xfrm_get_byname(ealg_list, ealg_entries(), name, probe); } EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname); struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe) { - return xfrm_get_byname(calg_list, calg_entries(), - CRYPTO_ALG_TYPE_COMPRESS, CRYPTO_ALG_TYPE_MASK, - name, probe); + return xfrm_get_byname(calg_list, calg_entries(), name, probe); } EXPORT_SYMBOL_GPL(xfrm_calg_get_byname); @@ -447,22 +427,19 @@ void xfrm_probe_algs(void) BUG_ON(in_softirq()); for (i = 0; i < aalg_entries(); i++) { - status = crypto_has_hash(aalg_list[i].name, 0, - CRYPTO_ALG_ASYNC); + status = crypto_alg_available(aalg_list[i].name, 0); if (aalg_list[i].available != status) aalg_list[i].available = status; } for (i = 0; i < ealg_entries(); i++) { - status = crypto_has_blkcipher(ealg_list[i].name, 0, - CRYPTO_ALG_ASYNC); + status = crypto_alg_available(ealg_list[i].name, 0); if (ealg_list[i].available != status) ealg_list[i].available = status; } for (i = 0; i < calg_entries(); i++) { - status = crypto_has_comp(calg_list[i].name, 0, - CRYPTO_ALG_ASYNC); + status = crypto_alg_available(calg_list[i].name, 0); if (calg_list[i].available != status) calg_list[i].available = status; } @@ -494,12 +471,11 @@ EXPORT_SYMBOL_GPL(xfrm_count_enc_supported); /* Move to common area: it is shared with AH. */ -int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, - int offset, int len, icv_update_fn_t icv_update) +void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, + int offset, int len, icv_update_fn_t icv_update) { int start = skb_headlen(skb); int i, copy = start - offset; - int err; struct scatterlist sg; /* Checksum header. */ @@ -511,12 +487,10 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; sg.length = copy; - err = icv_update(desc, &sg, copy); - if (unlikely(err)) - return err; + icv_update(tfm, &sg, 1); if ((len -= copy) == 0) - return 0; + return; offset += copy; } @@ -536,12 +510,10 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, sg.offset = frag->page_offset + offset-start; sg.length = copy; - err = icv_update(desc, &sg, copy); - if (unlikely(err)) - return err; + icv_update(tfm, &sg, 1); if (!(len -= copy)) - return 0; + return; offset += copy; } start = end; @@ -559,19 +531,15 @@ int skb_icv_walk(const struct sk_buff *skb, struct hash_desc *desc, if ((copy = end - offset) > 0) { if (copy > len) copy = len; - err = skb_icv_walk(list, desc, offset-start, - copy, icv_update); - if (unlikely(err)) - return err; + skb_icv_walk(list, tfm, offset-start, copy, icv_update); if ((len -= copy) == 0) - return 0; + return; offset += copy; } start = end; } } BUG_ON(len); - return 0; } EXPORT_SYMBOL_GPL(skb_icv_walk); diff --git a/trunk/net/xfrm/xfrm_hash.c b/trunk/net/xfrm/xfrm_hash.c deleted file mode 100644 index 37643bb8768a..000000000000 --- a/trunk/net/xfrm/xfrm_hash.c +++ /dev/null @@ -1,41 +0,0 @@ -/* xfrm_hash.c: Common hash table code. - * - * Copyright (C) 2006 David S. Miller (davem@davemloft.net) - */ - -#include -#include -#include -#include -#include -#include - -#include "xfrm_hash.h" - -struct hlist_head *xfrm_hash_alloc(unsigned int sz) -{ - struct hlist_head *n; - - if (sz <= PAGE_SIZE) - n = kmalloc(sz, GFP_KERNEL); - else if (hashdist) - n = __vmalloc(sz, GFP_KERNEL, PAGE_KERNEL); - else - n = (struct hlist_head *) - __get_free_pages(GFP_KERNEL, get_order(sz)); - - if (n) - memset(n, 0, sz); - - return n; -} - -void xfrm_hash_free(struct hlist_head *n, unsigned int sz) -{ - if (sz <= PAGE_SIZE) - kfree(n); - else if (hashdist) - vfree(n); - else - free_pages((unsigned long)n, get_order(sz)); -} diff --git a/trunk/net/xfrm/xfrm_hash.h b/trunk/net/xfrm/xfrm_hash.h deleted file mode 100644 index d3abb0b7dc62..000000000000 --- a/trunk/net/xfrm/xfrm_hash.h +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef _XFRM_HASH_H -#define _XFRM_HASH_H - -#include -#include - -static inline unsigned int __xfrm4_addr_hash(xfrm_address_t *addr) -{ - return ntohl(addr->a4); -} - -static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr) -{ - return ntohl(addr->a6[2] ^ addr->a6[3]); -} - -static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) -{ - return ntohl(daddr->a4 ^ saddr->a4); -} - -static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) -{ - return ntohl(daddr->a6[2] ^ daddr->a6[3] ^ - saddr->a6[2] ^ saddr->a6[3]); -} - -static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, - u32 reqid, unsigned short family, - unsigned int hmask) -{ - unsigned int h = family ^ reqid; - switch (family) { - case AF_INET: - h ^= __xfrm4_daddr_saddr_hash(daddr, saddr); - break; - case AF_INET6: - h ^= __xfrm6_daddr_saddr_hash(daddr, saddr); - break; - } - return (h ^ (h >> 16)) & hmask; -} - -static inline unsigned __xfrm_src_hash(xfrm_address_t *saddr, - unsigned short family, - unsigned int hmask) -{ - unsigned int h = family; - switch (family) { - case AF_INET: - h ^= __xfrm4_addr_hash(saddr); - break; - case AF_INET6: - h ^= __xfrm6_addr_hash(saddr); - break; - }; - return (h ^ (h >> 16)) & hmask; -} - -static inline unsigned int -__xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family, - unsigned int hmask) -{ - unsigned int h = spi ^ proto; - switch (family) { - case AF_INET: - h ^= __xfrm4_addr_hash(daddr); - break; - case AF_INET6: - h ^= __xfrm6_addr_hash(daddr); - break; - } - return (h ^ (h >> 10) ^ (h >> 20)) & hmask; -} - -static inline unsigned int __idx_hash(u32 index, unsigned int hmask) -{ - return (index ^ (index >> 8)) & hmask; -} - -static inline unsigned int __sel_hash(struct xfrm_selector *sel, unsigned short family, unsigned int hmask) -{ - xfrm_address_t *daddr = &sel->daddr; - xfrm_address_t *saddr = &sel->saddr; - unsigned int h = 0; - - switch (family) { - case AF_INET: - if (sel->prefixlen_d != 32 || - sel->prefixlen_s != 32) - return hmask + 1; - - h = __xfrm4_daddr_saddr_hash(daddr, saddr); - break; - - case AF_INET6: - if (sel->prefixlen_d != 128 || - sel->prefixlen_s != 128) - return hmask + 1; - - h = __xfrm6_daddr_saddr_hash(daddr, saddr); - break; - }; - h ^= (h >> 16); - return h & hmask; -} - -static inline unsigned int __addr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, unsigned int hmask) -{ - unsigned int h = 0; - - switch (family) { - case AF_INET: - h = __xfrm4_daddr_saddr_hash(daddr, saddr); - break; - - case AF_INET6: - h = __xfrm6_daddr_saddr_hash(daddr, saddr); - break; - }; - h ^= (h >> 16); - return h & hmask; -} - -extern struct hlist_head *xfrm_hash_alloc(unsigned int sz); -extern void xfrm_hash_free(struct hlist_head *n, unsigned int sz); - -#endif /* _XFRM_HASH_H */ diff --git a/trunk/net/xfrm/xfrm_input.c b/trunk/net/xfrm/xfrm_input.c index dfc90bb1cf1f..891a6090cc09 100644 --- a/trunk/net/xfrm/xfrm_input.c +++ b/trunk/net/xfrm/xfrm_input.c @@ -82,6 +82,8 @@ void __init xfrm_input_init(void) { secpath_cachep = kmem_cache_create("secpath_cache", sizeof(struct sec_path), - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); + if (!secpath_cachep) + panic("XFRM: failed to allocate secpath_cache\n"); } diff --git a/trunk/net/xfrm/xfrm_policy.c b/trunk/net/xfrm/xfrm_policy.c index b6e2e79d7261..f35bc676128c 100644 --- a/trunk/net/xfrm/xfrm_policy.c +++ b/trunk/net/xfrm/xfrm_policy.c @@ -22,19 +22,16 @@ #include #include #include -#include #include #include -#include "xfrm_hash.h" - DEFINE_MUTEX(xfrm_cfg_mutex); EXPORT_SYMBOL(xfrm_cfg_mutex); static DEFINE_RWLOCK(xfrm_policy_lock); -unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2]; -EXPORT_SYMBOL(xfrm_policy_count); +struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2]; +EXPORT_SYMBOL(xfrm_policy_list); static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; @@ -42,7 +39,8 @@ static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; static kmem_cache_t *xfrm_dst_cache __read_mostly; static struct work_struct xfrm_policy_gc_work; -static HLIST_HEAD(xfrm_policy_gc_list); +static struct list_head xfrm_policy_gc_list = + LIST_HEAD_INIT(xfrm_policy_gc_list); static DEFINE_SPINLOCK(xfrm_policy_gc_lock); static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); @@ -312,10 +310,8 @@ struct xfrm_policy *xfrm_policy_alloc(gfp_t gfp) policy = kzalloc(sizeof(struct xfrm_policy), gfp); if (policy) { - INIT_HLIST_NODE(&policy->bydst); - INIT_HLIST_NODE(&policy->byidx); - rwlock_init(&policy->lock); atomic_set(&policy->refcnt, 1); + rwlock_init(&policy->lock); init_timer(&policy->timer); policy->timer.data = (unsigned long)policy; policy->timer.function = xfrm_policy_timer; @@ -361,16 +357,17 @@ static void xfrm_policy_gc_kill(struct xfrm_policy *policy) static void xfrm_policy_gc_task(void *data) { struct xfrm_policy *policy; - struct hlist_node *entry, *tmp; - struct hlist_head gc_list; + struct list_head *entry, *tmp; + struct list_head gc_list = LIST_HEAD_INIT(gc_list); spin_lock_bh(&xfrm_policy_gc_lock); - gc_list.first = xfrm_policy_gc_list.first; - INIT_HLIST_HEAD(&xfrm_policy_gc_list); + list_splice_init(&xfrm_policy_gc_list, &gc_list); spin_unlock_bh(&xfrm_policy_gc_lock); - hlist_for_each_entry_safe(policy, entry, tmp, &gc_list, bydst) + list_for_each_safe(entry, tmp, &gc_list) { + policy = list_entry(entry, struct xfrm_policy, list); xfrm_policy_gc_kill(policy); + } } /* Rule must be locked. Release descentant resources, announce @@ -392,275 +389,70 @@ static void xfrm_policy_kill(struct xfrm_policy *policy) } spin_lock(&xfrm_policy_gc_lock); - hlist_add_head(&policy->bydst, &xfrm_policy_gc_list); + list_add(&policy->list, &xfrm_policy_gc_list); spin_unlock(&xfrm_policy_gc_lock); schedule_work(&xfrm_policy_gc_work); } -struct xfrm_policy_hash { - struct hlist_head *table; - unsigned int hmask; -}; - -static struct hlist_head xfrm_policy_inexact[XFRM_POLICY_MAX*2]; -static struct xfrm_policy_hash xfrm_policy_bydst[XFRM_POLICY_MAX*2] __read_mostly; -static struct hlist_head *xfrm_policy_byidx __read_mostly; -static unsigned int xfrm_idx_hmask __read_mostly; -static unsigned int xfrm_policy_hashmax __read_mostly = 1 * 1024 * 1024; - -static inline unsigned int idx_hash(u32 index) -{ - return __idx_hash(index, xfrm_idx_hmask); -} - -static struct hlist_head *policy_hash_bysel(struct xfrm_selector *sel, unsigned short family, int dir) -{ - unsigned int hmask = xfrm_policy_bydst[dir].hmask; - unsigned int hash = __sel_hash(sel, family, hmask); - - return (hash == hmask + 1 ? - &xfrm_policy_inexact[dir] : - xfrm_policy_bydst[dir].table + hash); -} - -static struct hlist_head *policy_hash_direct(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, int dir) -{ - unsigned int hmask = xfrm_policy_bydst[dir].hmask; - unsigned int hash = __addr_hash(daddr, saddr, family, hmask); - - return xfrm_policy_bydst[dir].table + hash; -} - -static void xfrm_dst_hash_transfer(struct hlist_head *list, - struct hlist_head *ndsttable, - unsigned int nhashmask) -{ - struct hlist_node *entry, *tmp; - struct xfrm_policy *pol; - - hlist_for_each_entry_safe(pol, entry, tmp, list, bydst) { - unsigned int h; - - h = __addr_hash(&pol->selector.daddr, &pol->selector.saddr, - pol->family, nhashmask); - hlist_add_head(&pol->bydst, ndsttable+h); - } -} - -static void xfrm_idx_hash_transfer(struct hlist_head *list, - struct hlist_head *nidxtable, - unsigned int nhashmask) -{ - struct hlist_node *entry, *tmp; - struct xfrm_policy *pol; - - hlist_for_each_entry_safe(pol, entry, tmp, list, byidx) { - unsigned int h; - - h = __idx_hash(pol->index, nhashmask); - hlist_add_head(&pol->byidx, nidxtable+h); - } -} - -static unsigned long xfrm_new_hash_mask(unsigned int old_hmask) -{ - return ((old_hmask + 1) << 1) - 1; -} - -static void xfrm_bydst_resize(int dir) -{ - unsigned int hmask = xfrm_policy_bydst[dir].hmask; - unsigned int nhashmask = xfrm_new_hash_mask(hmask); - unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); - struct hlist_head *odst = xfrm_policy_bydst[dir].table; - struct hlist_head *ndst = xfrm_hash_alloc(nsize); - int i; - - if (!ndst) - return; - - write_lock_bh(&xfrm_policy_lock); - - for (i = hmask; i >= 0; i--) - xfrm_dst_hash_transfer(odst + i, ndst, nhashmask); - - xfrm_policy_bydst[dir].table = ndst; - xfrm_policy_bydst[dir].hmask = nhashmask; - - write_unlock_bh(&xfrm_policy_lock); - - xfrm_hash_free(odst, (hmask + 1) * sizeof(struct hlist_head)); -} - -static void xfrm_byidx_resize(int total) -{ - unsigned int hmask = xfrm_idx_hmask; - unsigned int nhashmask = xfrm_new_hash_mask(hmask); - unsigned int nsize = (nhashmask + 1) * sizeof(struct hlist_head); - struct hlist_head *oidx = xfrm_policy_byidx; - struct hlist_head *nidx = xfrm_hash_alloc(nsize); - int i; - - if (!nidx) - return; - - write_lock_bh(&xfrm_policy_lock); - - for (i = hmask; i >= 0; i--) - xfrm_idx_hash_transfer(oidx + i, nidx, nhashmask); - - xfrm_policy_byidx = nidx; - xfrm_idx_hmask = nhashmask; - - write_unlock_bh(&xfrm_policy_lock); - - xfrm_hash_free(oidx, (hmask + 1) * sizeof(struct hlist_head)); -} - -static inline int xfrm_bydst_should_resize(int dir, int *total) -{ - unsigned int cnt = xfrm_policy_count[dir]; - unsigned int hmask = xfrm_policy_bydst[dir].hmask; - - if (total) - *total += cnt; - - if ((hmask + 1) < xfrm_policy_hashmax && - cnt > hmask) - return 1; - - return 0; -} - -static inline int xfrm_byidx_should_resize(int total) -{ - unsigned int hmask = xfrm_idx_hmask; - - if ((hmask + 1) < xfrm_policy_hashmax && - total > hmask) - return 1; - - return 0; -} - -static DEFINE_MUTEX(hash_resize_mutex); - -static void xfrm_hash_resize(void *__unused) -{ - int dir, total; - - mutex_lock(&hash_resize_mutex); - - total = 0; - for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { - if (xfrm_bydst_should_resize(dir, &total)) - xfrm_bydst_resize(dir); - } - if (xfrm_byidx_should_resize(total)) - xfrm_byidx_resize(total); - - mutex_unlock(&hash_resize_mutex); -} - -static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize, NULL); - /* Generate new index... KAME seems to generate them ordered by cost * of an absolute inpredictability of ordering of rules. This will not pass. */ -static u32 xfrm_gen_index(u8 type, int dir) +static u32 xfrm_gen_index(int dir) { + u32 idx; + struct xfrm_policy *p; static u32 idx_generator; for (;;) { - struct hlist_node *entry; - struct hlist_head *list; - struct xfrm_policy *p; - u32 idx; - int found; - idx = (idx_generator | dir); idx_generator += 8; if (idx == 0) idx = 8; - list = xfrm_policy_byidx + idx_hash(idx); - found = 0; - hlist_for_each_entry(p, entry, list, byidx) { - if (p->index == idx) { - found = 1; + for (p = xfrm_policy_list[dir]; p; p = p->next) { + if (p->index == idx) break; - } } - if (!found) + if (!p) return idx; } } -static inline int selector_cmp(struct xfrm_selector *s1, struct xfrm_selector *s2) -{ - u32 *p1 = (u32 *) s1; - u32 *p2 = (u32 *) s2; - int len = sizeof(struct xfrm_selector) / sizeof(u32); - int i; - - for (i = 0; i < len; i++) { - if (p1[i] != p2[i]) - return 1; - } - - return 0; -} - int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) { - struct xfrm_policy *pol; - struct xfrm_policy *delpol; - struct hlist_head *chain; - struct hlist_node *entry, *newpos, *last; + struct xfrm_policy *pol, **p; + struct xfrm_policy *delpol = NULL; + struct xfrm_policy **newpos = NULL; struct dst_entry *gc_list; write_lock_bh(&xfrm_policy_lock); - chain = policy_hash_bysel(&policy->selector, policy->family, dir); - delpol = NULL; - newpos = NULL; - last = NULL; - hlist_for_each_entry(pol, entry, chain, bydst) { - if (!delpol && - pol->type == policy->type && - !selector_cmp(&pol->selector, &policy->selector) && + for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL;) { + if (!delpol && memcmp(&policy->selector, &pol->selector, sizeof(pol->selector)) == 0 && xfrm_sec_ctx_match(pol->security, policy->security)) { if (excl) { write_unlock_bh(&xfrm_policy_lock); return -EEXIST; } + *p = pol->next; delpol = pol; if (policy->priority > pol->priority) continue; } else if (policy->priority >= pol->priority) { - last = &pol->bydst; + p = &pol->next; continue; } if (!newpos) - newpos = &pol->bydst; + newpos = p; if (delpol) break; - last = &pol->bydst; + p = &pol->next; } - if (!newpos) - newpos = last; if (newpos) - hlist_add_after(newpos, &policy->bydst); - else - hlist_add_head(&policy->bydst, chain); + p = newpos; xfrm_pol_hold(policy); - xfrm_policy_count[dir]++; + policy->next = *p; + *p = policy; atomic_inc(&flow_cache_genid); - if (delpol) { - hlist_del(&delpol->bydst); - hlist_del(&delpol->byidx); - xfrm_policy_count[dir]--; - } - policy->index = delpol ? delpol->index : xfrm_gen_index(policy->type, dir); - hlist_add_head(&policy->byidx, xfrm_policy_byidx+idx_hash(policy->index)); + policy->index = delpol ? delpol->index : xfrm_gen_index(dir); policy->curlft.add_time = (unsigned long)xtime.tv_sec; policy->curlft.use_time = 0; if (!mod_timer(&policy->timer, jiffies + HZ)) @@ -669,13 +461,10 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) if (delpol) xfrm_policy_kill(delpol); - else if (xfrm_bydst_should_resize(dir, NULL)) - schedule_work(&xfrm_hash_work); read_lock_bh(&xfrm_policy_lock); gc_list = NULL; - entry = &policy->bydst; - hlist_for_each_entry_continue(policy, entry, bydst) { + for (policy = policy->next; policy; policy = policy->next) { struct dst_entry *dst; write_lock(&policy->lock); @@ -704,146 +493,87 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) } EXPORT_SYMBOL(xfrm_policy_insert); -struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, - struct xfrm_selector *sel, +struct xfrm_policy *xfrm_policy_bysel_ctx(int dir, struct xfrm_selector *sel, struct xfrm_sec_ctx *ctx, int delete) { - struct xfrm_policy *pol, *ret; - struct hlist_head *chain; - struct hlist_node *entry; + struct xfrm_policy *pol, **p; write_lock_bh(&xfrm_policy_lock); - chain = policy_hash_bysel(sel, sel->family, dir); - ret = NULL; - hlist_for_each_entry(pol, entry, chain, bydst) { - if (pol->type == type && - !selector_cmp(sel, &pol->selector) && - xfrm_sec_ctx_match(ctx, pol->security)) { + for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) { + if ((memcmp(sel, &pol->selector, sizeof(*sel)) == 0) && + (xfrm_sec_ctx_match(ctx, pol->security))) { xfrm_pol_hold(pol); - if (delete) { - hlist_del(&pol->bydst); - hlist_del(&pol->byidx); - xfrm_policy_count[dir]--; - } - ret = pol; + if (delete) + *p = pol->next; break; } } write_unlock_bh(&xfrm_policy_lock); - if (ret && delete) { + if (pol && delete) { atomic_inc(&flow_cache_genid); - xfrm_policy_kill(ret); + xfrm_policy_kill(pol); } - return ret; + return pol; } EXPORT_SYMBOL(xfrm_policy_bysel_ctx); -struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete) +struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete) { - struct xfrm_policy *pol, *ret; - struct hlist_head *chain; - struct hlist_node *entry; + struct xfrm_policy *pol, **p; write_lock_bh(&xfrm_policy_lock); - chain = xfrm_policy_byidx + idx_hash(id); - ret = NULL; - hlist_for_each_entry(pol, entry, chain, byidx) { - if (pol->type == type && pol->index == id) { + for (p = &xfrm_policy_list[dir]; (pol=*p)!=NULL; p = &pol->next) { + if (pol->index == id) { xfrm_pol_hold(pol); - if (delete) { - hlist_del(&pol->bydst); - hlist_del(&pol->byidx); - xfrm_policy_count[dir]--; - } - ret = pol; + if (delete) + *p = pol->next; break; } } write_unlock_bh(&xfrm_policy_lock); - if (ret && delete) { + if (pol && delete) { atomic_inc(&flow_cache_genid); - xfrm_policy_kill(ret); + xfrm_policy_kill(pol); } - return ret; + return pol; } EXPORT_SYMBOL(xfrm_policy_byid); -void xfrm_policy_flush(u8 type) +void xfrm_policy_flush(void) { + struct xfrm_policy *xp; int dir; write_lock_bh(&xfrm_policy_lock); for (dir = 0; dir < XFRM_POLICY_MAX; dir++) { - struct xfrm_policy *pol; - struct hlist_node *entry; - int i; - - again1: - hlist_for_each_entry(pol, entry, - &xfrm_policy_inexact[dir], bydst) { - if (pol->type != type) - continue; - hlist_del(&pol->bydst); - hlist_del(&pol->byidx); + while ((xp = xfrm_policy_list[dir]) != NULL) { + xfrm_policy_list[dir] = xp->next; write_unlock_bh(&xfrm_policy_lock); - xfrm_policy_kill(pol); + xfrm_policy_kill(xp); write_lock_bh(&xfrm_policy_lock); - goto again1; - } - - for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) { - again2: - hlist_for_each_entry(pol, entry, - xfrm_policy_bydst[dir].table + i, - bydst) { - if (pol->type != type) - continue; - hlist_del(&pol->bydst); - hlist_del(&pol->byidx); - write_unlock_bh(&xfrm_policy_lock); - - xfrm_policy_kill(pol); - - write_lock_bh(&xfrm_policy_lock); - goto again2; - } } - - xfrm_policy_count[dir] = 0; } atomic_inc(&flow_cache_genid); write_unlock_bh(&xfrm_policy_lock); } EXPORT_SYMBOL(xfrm_policy_flush); -int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*), +int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *data) { - struct xfrm_policy *pol; - struct hlist_node *entry; - int dir, count, error; + struct xfrm_policy *xp; + int dir; + int count = 0; + int error = 0; read_lock_bh(&xfrm_policy_lock); - count = 0; for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) { - struct hlist_head *table = xfrm_policy_bydst[dir].table; - int i; - - hlist_for_each_entry(pol, entry, - &xfrm_policy_inexact[dir], bydst) { - if (pol->type == type) - count++; - } - for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) { - hlist_for_each_entry(pol, entry, table + i, bydst) { - if (pol->type == type) - count++; - } - } + for (xp = xfrm_policy_list[dir]; xp; xp = xp->next) + count++; } if (count == 0) { @@ -852,28 +582,13 @@ int xfrm_policy_walk(u8 type, int (*func)(struct xfrm_policy *, int, int, void*) } for (dir = 0; dir < 2*XFRM_POLICY_MAX; dir++) { - struct hlist_head *table = xfrm_policy_bydst[dir].table; - int i; - - hlist_for_each_entry(pol, entry, - &xfrm_policy_inexact[dir], bydst) { - if (pol->type != type) - continue; - error = func(pol, dir % XFRM_POLICY_MAX, --count, data); + for (xp = xfrm_policy_list[dir]; xp; xp = xp->next) { + error = func(xp, dir%XFRM_POLICY_MAX, --count, data); if (error) goto out; } - for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) { - hlist_for_each_entry(pol, entry, table + i, bydst) { - if (pol->type != type) - continue; - error = func(pol, dir % XFRM_POLICY_MAX, --count, data); - if (error) - goto out; - } - } } - error = 0; + out: read_unlock_bh(&xfrm_policy_lock); return error; @@ -882,79 +597,29 @@ EXPORT_SYMBOL(xfrm_policy_walk); /* Find policy to apply to this flow. */ -static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl, - u8 type, u16 family, int dir) +static void xfrm_policy_lookup(struct flowi *fl, u32 sk_sid, u16 family, u8 dir, + void **objp, atomic_t **obj_refp) { - struct xfrm_selector *sel = &pol->selector; - int match; - - if (pol->family != family || - pol->type != type) - return 0; + struct xfrm_policy *pol; - match = xfrm_selector_match(sel, fl, family); - if (match) { - if (!security_xfrm_policy_lookup(pol, fl->secid, dir)) - return 1; - } + read_lock_bh(&xfrm_policy_lock); + for (pol = xfrm_policy_list[dir]; pol; pol = pol->next) { + struct xfrm_selector *sel = &pol->selector; + int match; - return 0; -} + if (pol->family != family) + continue; -static struct xfrm_policy *xfrm_policy_lookup_bytype(u8 type, struct flowi *fl, - u16 family, u8 dir) -{ - struct xfrm_policy *pol, *ret; - xfrm_address_t *daddr, *saddr; - struct hlist_node *entry; - struct hlist_head *chain; - u32 priority = ~0U; - - daddr = xfrm_flowi_daddr(fl, family); - saddr = xfrm_flowi_saddr(fl, family); - if (unlikely(!daddr || !saddr)) - return NULL; + match = xfrm_selector_match(sel, fl, family); - read_lock_bh(&xfrm_policy_lock); - chain = policy_hash_direct(daddr, saddr, family, dir); - ret = NULL; - hlist_for_each_entry(pol, entry, chain, bydst) { - if (xfrm_policy_match(pol, fl, type, family, dir)) { - ret = pol; - priority = ret->priority; - break; - } - } - chain = &xfrm_policy_inexact[dir]; - hlist_for_each_entry(pol, entry, chain, bydst) { - if (xfrm_policy_match(pol, fl, type, family, dir) && - pol->priority < priority) { - ret = pol; - break; + if (match) { + if (!security_xfrm_policy_lookup(pol, sk_sid, dir)) { + xfrm_pol_hold(pol); + break; + } } } - if (ret) - xfrm_pol_hold(ret); read_unlock_bh(&xfrm_policy_lock); - - return ret; -} - -static void xfrm_policy_lookup(struct flowi *fl, u16 family, u8 dir, - void **objp, atomic_t **obj_refp) -{ - struct xfrm_policy *pol; - -#ifdef CONFIG_XFRM_SUB_POLICY - pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_SUB, fl, family, dir); - if (pol) - goto end; -#endif - pol = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, fl, family, dir); - -#ifdef CONFIG_XFRM_SUB_POLICY -end: -#endif if ((*objp = (void *) pol) != NULL) *obj_refp = &pol->refcnt; } @@ -976,7 +641,7 @@ static inline int policy_to_flow_dir(int dir) }; } -static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl) +static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl, u32 sk_sid) { struct xfrm_policy *pol; @@ -987,7 +652,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc int err = 0; if (match) - err = security_xfrm_policy_lookup(pol, fl->secid, policy_to_flow_dir(dir)); + err = security_xfrm_policy_lookup(pol, sk_sid, policy_to_flow_dir(dir)); if (match && !err) xfrm_pol_hold(pol); @@ -1000,29 +665,24 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc static void __xfrm_policy_link(struct xfrm_policy *pol, int dir) { - struct hlist_head *chain = policy_hash_bysel(&pol->selector, - pol->family, dir); - - hlist_add_head(&pol->bydst, chain); - hlist_add_head(&pol->byidx, xfrm_policy_byidx+idx_hash(pol->index)); - xfrm_policy_count[dir]++; + pol->next = xfrm_policy_list[dir]; + xfrm_policy_list[dir] = pol; xfrm_pol_hold(pol); - - if (xfrm_bydst_should_resize(dir, NULL)) - schedule_work(&xfrm_hash_work); } static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol, int dir) { - if (hlist_unhashed(&pol->bydst)) - return NULL; - - hlist_del(&pol->bydst); - hlist_del(&pol->byidx); - xfrm_policy_count[dir]--; + struct xfrm_policy **polp; - return pol; + for (polp = &xfrm_policy_list[dir]; + *polp != NULL; polp = &(*polp)->next) { + if (*polp == pol) { + *polp = pol->next; + return pol; + } + } + return NULL; } int xfrm_policy_delete(struct xfrm_policy *pol, int dir) @@ -1044,17 +704,12 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) { struct xfrm_policy *old_pol; -#ifdef CONFIG_XFRM_SUB_POLICY - if (pol && pol->type != XFRM_POLICY_TYPE_MAIN) - return -EINVAL; -#endif - write_lock_bh(&xfrm_policy_lock); old_pol = sk->sk_policy[dir]; sk->sk_policy[dir] = pol; if (pol) { pol->curlft.add_time = (unsigned long)xtime.tv_sec; - pol->index = xfrm_gen_index(pol->type, XFRM_POLICY_MAX+dir); + pol->index = xfrm_gen_index(XFRM_POLICY_MAX+dir); __xfrm_policy_link(pol, XFRM_POLICY_MAX+dir); } if (old_pol) @@ -1083,7 +738,6 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir) newp->flags = old->flags; newp->xfrm_nr = old->xfrm_nr; newp->index = old->index; - newp->type = old->type; memcpy(newp->xfrm_vec, old->xfrm_vec, newp->xfrm_nr*sizeof(struct xfrm_tmpl)); write_lock_bh(&xfrm_policy_lock); @@ -1107,32 +761,17 @@ int __xfrm_sk_clone_policy(struct sock *sk) return 0; } -static int -xfrm_get_saddr(xfrm_address_t *local, xfrm_address_t *remote, - unsigned short family) -{ - int err; - struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); - - if (unlikely(afinfo == NULL)) - return -EINVAL; - err = afinfo->get_saddr(local, remote); - xfrm_policy_put_afinfo(afinfo); - return err; -} - /* Resolve list of templates for the flow, given policy. */ static int -xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl, - struct xfrm_state **xfrm, - unsigned short family) +xfrm_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl, + struct xfrm_state **xfrm, + unsigned short family) { int nx; int i, error; xfrm_address_t *daddr = xfrm_flowi_daddr(fl, family); xfrm_address_t *saddr = xfrm_flowi_saddr(fl, family); - xfrm_address_t tmp; for (nx=0, i = 0; i < policy->xfrm_nr; i++) { struct xfrm_state *x; @@ -1140,15 +779,9 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl, xfrm_address_t *local = saddr; struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i]; - if (tmpl->mode == XFRM_MODE_TUNNEL) { + if (tmpl->mode) { remote = &tmpl->id.daddr; local = &tmpl->saddr; - if (xfrm_addr_any(local, family)) { - error = xfrm_get_saddr(&tmp, remote, family); - if (error) - goto fail; - local = &tmp; - } } x = xfrm_state_find(remote, local, fl, tmpl, policy, &error, family); @@ -1176,45 +809,6 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl, return error; } -static int -xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl, - struct xfrm_state **xfrm, - unsigned short family) -{ - struct xfrm_state *tp[XFRM_MAX_DEPTH]; - struct xfrm_state **tpp = (npols > 1) ? tp : xfrm; - int cnx = 0; - int error; - int ret; - int i; - - for (i = 0; i < npols; i++) { - if (cnx + pols[i]->xfrm_nr >= XFRM_MAX_DEPTH) { - error = -ENOBUFS; - goto fail; - } - - ret = xfrm_tmpl_resolve_one(pols[i], fl, &tpp[cnx], family); - if (ret < 0) { - error = ret; - goto fail; - } else - cnx += ret; - } - - /* found states are sorted for outbound processing */ - if (npols > 1) - xfrm_state_sort(xfrm, tpp, cnx, family); - - return cnx; - - fail: - for (cnx--; cnx>=0; cnx--) - xfrm_state_put(tpp[cnx]); - return error; - -} - /* Check that the bundle accepts the flow and its components are * still valid. */ @@ -1261,11 +855,6 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, struct sock *sk, int flags) { struct xfrm_policy *policy; - struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; - int npols; - int pol_dead; - int xfrm_nr; - int pi; struct xfrm_state *xfrm[XFRM_MAX_DEPTH]; struct dst_entry *dst, *dst_orig = *dst_p; int nx = 0; @@ -1273,26 +862,19 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, u32 genid; u16 family; u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT); - + u32 sk_sid = security_sk_sid(sk, fl, dir); restart: genid = atomic_read(&flow_cache_genid); policy = NULL; - for (pi = 0; pi < ARRAY_SIZE(pols); pi++) - pols[pi] = NULL; - npols = 0; - pol_dead = 0; - xfrm_nr = 0; - if (sk && sk->sk_policy[1]) - policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl); + policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, sk_sid); if (!policy) { /* To accelerate a bit... */ - if ((dst_orig->flags & DST_NOXFRM) || - !xfrm_policy_count[XFRM_POLICY_OUT]) + if ((dst_orig->flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT]) return 0; - policy = flow_cache_lookup(fl, dst_orig->ops->family, + policy = flow_cache_lookup(fl, sk_sid, dst_orig->ops->family, dir, xfrm_policy_lookup); } @@ -1301,9 +883,6 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, family = dst_orig->ops->family; policy->curlft.use_time = (unsigned long)xtime.tv_sec; - pols[0] = policy; - npols ++; - xfrm_nr += pols[0]->xfrm_nr; switch (policy->action) { case XFRM_POLICY_BLOCK: @@ -1312,13 +891,11 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, goto error; case XFRM_POLICY_ALLOW: -#ifndef CONFIG_XFRM_SUB_POLICY if (policy->xfrm_nr == 0) { /* Flow passes not transformed. */ xfrm_pol_put(policy); return 0; } -#endif /* Try to find matching bundle. * @@ -1334,36 +911,7 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, if (dst) break; -#ifdef CONFIG_XFRM_SUB_POLICY - if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) { - pols[1] = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, - fl, family, - XFRM_POLICY_OUT); - if (pols[1]) { - if (pols[1]->action == XFRM_POLICY_BLOCK) { - err = -EPERM; - goto error; - } - npols ++; - xfrm_nr += pols[1]->xfrm_nr; - } - } - - /* - * Because neither flowi nor bundle information knows about - * transformation template size. On more than one policy usage - * we can realize whether all of them is bypass or not after - * they are searched. See above not-transformed bypass - * is surrounded by non-sub policy configuration, too. - */ - if (xfrm_nr == 0) { - /* Flow passes not transformed. */ - xfrm_pols_put(pols, npols); - return 0; - } - -#endif - nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); + nx = xfrm_tmpl_resolve(policy, fl, xfrm, family); if (unlikely(nx<0)) { err = nx; @@ -1376,7 +924,7 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, set_current_state(TASK_RUNNING); remove_wait_queue(&km_waitq, &wait); - nx = xfrm_tmpl_resolve(pols, npols, fl, xfrm, family); + nx = xfrm_tmpl_resolve(policy, fl, xfrm, family); if (nx == -EAGAIN && signal_pending(current)) { err = -ERESTART; @@ -1384,7 +932,7 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, } if (nx == -EAGAIN || genid != atomic_read(&flow_cache_genid)) { - xfrm_pols_put(pols, npols); + xfrm_pol_put(policy); goto restart; } err = nx; @@ -1394,7 +942,7 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, } if (nx == 0) { /* Flow passes not transformed. */ - xfrm_pols_put(pols, npols); + xfrm_pol_put(policy); return 0; } @@ -1408,14 +956,8 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, goto error; } - for (pi = 0; pi < npols; pi++) { - read_lock_bh(&pols[pi]->lock); - pol_dead |= pols[pi]->dead; - read_unlock_bh(&pols[pi]->lock); - } - write_lock_bh(&policy->lock); - if (unlikely(pol_dead || stale_bundle(dst))) { + if (unlikely(policy->dead || stale_bundle(dst))) { /* Wow! While we worked on resolving, this * policy has gone. Retry. It is not paranoia, * we just cannot enlist new bundle to dead object. @@ -1435,34 +977,17 @@ int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, } *dst_p = dst; dst_release(dst_orig); - xfrm_pols_put(pols, npols); + xfrm_pol_put(policy); return 0; error: dst_release(dst_orig); - xfrm_pols_put(pols, npols); + xfrm_pol_put(policy); *dst_p = NULL; return err; } EXPORT_SYMBOL(xfrm_lookup); -static inline int -xfrm_secpath_reject(int idx, struct sk_buff *skb, struct flowi *fl) -{ - struct xfrm_state *x; - int err; - - if (!skb->sp || idx < 0 || idx >= skb->sp->len) - return 0; - x = skb->sp->xvec[idx]; - if (!x->type->reject) - return 0; - xfrm_state_hold(x); - err = x->type->reject(x, skb, fl); - xfrm_state_put(x); - return err; -} - /* When skb is transformed back to its "native" form, we have to * check policy restrictions. At the moment we make this in maximally * stupid way. Shame on me. :-) Of course, connected sockets must @@ -1479,19 +1004,10 @@ xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x, (x->id.spi == tmpl->id.spi || !tmpl->id.spi) && (x->props.reqid == tmpl->reqid || !tmpl->reqid) && x->props.mode == tmpl->mode && - ((tmpl->aalgos & (1<props.aalgo)) || - !(xfrm_id_proto_match(tmpl->id.proto, IPSEC_PROTO_ANY))) && - !(x->props.mode != XFRM_MODE_TRANSPORT && - xfrm_state_addr_cmp(tmpl, x, family)); + (tmpl->aalgos & (1<props.aalgo)) && + !(x->props.mode && xfrm_state_addr_cmp(tmpl, x, family)); } -/* - * 0 or more than 0 is returned when validation is succeeded (either bypass - * because of optional transport mode, or next index of the mathced secpath - * state with the template. - * -1 is returned when no matching template is found. - * Otherwise "-2 - errored_index" is returned. - */ static inline int xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start, unsigned short family) @@ -1499,18 +1015,15 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start, int idx = start; if (tmpl->optional) { - if (tmpl->mode == XFRM_MODE_TRANSPORT) + if (!tmpl->mode) return start; } else start = -1; for (; idx < sp->len; idx++) { if (xfrm_state_ok(tmpl, sp->xvec[idx], family)) return ++idx; - if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) { - if (start == -1) - start = -2-idx; + if (sp->xvec[idx]->props.mode) break; - } } return start; } @@ -1519,25 +1032,21 @@ int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family) { struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); - int err; if (unlikely(afinfo == NULL)) return -EAFNOSUPPORT; afinfo->decode_session(skb, fl); - err = security_xfrm_decode_session(skb, &fl->secid); xfrm_policy_put_afinfo(afinfo); - return err; + return 0; } EXPORT_SYMBOL(xfrm_decode_session); -static inline int secpath_has_nontransport(struct sec_path *sp, int k, int *idxp) +static inline int secpath_has_tunnel(struct sec_path *sp, int k) { for (; k < sp->len; k++) { - if (sp->xvec[k]->props.mode != XFRM_MODE_TRANSPORT) { - *idxp = k; + if (sp->xvec[k]->props.mode) return 1; - } } return 0; @@ -1547,18 +1056,16 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family) { struct xfrm_policy *pol; - struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; - int npols = 0; - int xfrm_nr; - int pi; struct flowi fl; u8 fl_dir = policy_to_flow_dir(dir); - int xerr_idx = -1; + u32 sk_sid; if (xfrm_decode_session(skb, &fl, family) < 0) return 0; nf_nat_decode_session(skb, &fl, family); + sk_sid = security_sk_sid(sk, &fl, fl_dir); + /* First, check used SA against their selectors. */ if (skb->sp) { int i; @@ -1572,90 +1079,46 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, pol = NULL; if (sk && sk->sk_policy[dir]) - pol = xfrm_sk_policy_lookup(sk, dir, &fl); + pol = xfrm_sk_policy_lookup(sk, dir, &fl, sk_sid); if (!pol) - pol = flow_cache_lookup(&fl, family, fl_dir, + pol = flow_cache_lookup(&fl, sk_sid, family, fl_dir, xfrm_policy_lookup); - if (!pol) { - if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) { - xfrm_secpath_reject(xerr_idx, skb, &fl); - return 0; - } - return 1; - } + if (!pol) + return !skb->sp || !secpath_has_tunnel(skb->sp, 0); pol->curlft.use_time = (unsigned long)xtime.tv_sec; - pols[0] = pol; - npols ++; -#ifdef CONFIG_XFRM_SUB_POLICY - if (pols[0]->type != XFRM_POLICY_TYPE_MAIN) { - pols[1] = xfrm_policy_lookup_bytype(XFRM_POLICY_TYPE_MAIN, - &fl, family, - XFRM_POLICY_IN); - if (pols[1]) { - pols[1]->curlft.use_time = (unsigned long)xtime.tv_sec; - npols ++; - } - } -#endif - if (pol->action == XFRM_POLICY_ALLOW) { struct sec_path *sp; static struct sec_path dummy; - struct xfrm_tmpl *tp[XFRM_MAX_DEPTH]; - struct xfrm_tmpl *stp[XFRM_MAX_DEPTH]; - struct xfrm_tmpl **tpp = tp; - int ti = 0; int i, k; if ((sp = skb->sp) == NULL) sp = &dummy; - for (pi = 0; pi < npols; pi++) { - if (pols[pi] != pol && - pols[pi]->action != XFRM_POLICY_ALLOW) - goto reject; - if (ti + pols[pi]->xfrm_nr >= XFRM_MAX_DEPTH) - goto reject_error; - for (i = 0; i < pols[pi]->xfrm_nr; i++) - tpp[ti++] = &pols[pi]->xfrm_vec[i]; - } - xfrm_nr = ti; - if (npols > 1) { - xfrm_tmpl_sort(stp, tpp, xfrm_nr, family); - tpp = stp; - } - /* For each tunnel xfrm, find the first matching tmpl. * For each tmpl before that, find corresponding xfrm. * Order is _important_. Later we will implement * some barriers, but at the moment barriers * are implied between each two transformations. */ - for (i = xfrm_nr-1, k = 0; i >= 0; i--) { - k = xfrm_policy_ok(tpp[i], sp, k, family); - if (k < 0) { - if (k < -1) - /* "-2 - errored_index" returned */ - xerr_idx = -(2+k); + for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) { + k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k, family); + if (k < 0) goto reject; - } } - if (secpath_has_nontransport(sp, k, &xerr_idx)) + if (secpath_has_tunnel(sp, k)) goto reject; - xfrm_pols_put(pols, npols); + xfrm_pol_put(pol); return 1; } reject: - xfrm_secpath_reject(xerr_idx, skb, &fl); -reject_error: - xfrm_pols_put(pols, npols); + xfrm_pol_put(pol); return 0; } EXPORT_SYMBOL(__xfrm_policy_check); @@ -1671,39 +1134,18 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) } EXPORT_SYMBOL(__xfrm_route_forward); -/* Optimize later using cookies and generation ids. */ - static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) { - /* Code (such as __xfrm4_bundle_create()) sets dst->obsolete - * to "-1" to force all XFRM destinations to get validated by - * dst_ops->check on every use. We do this because when a - * normal route referenced by an XFRM dst is obsoleted we do - * not go looking around for all parent referencing XFRM dsts - * so that we can invalidate them. It is just too much work. - * Instead we make the checks here on every use. For example: - * - * XFRM dst A --> IPv4 dst X - * - * X is the "xdst->route" of A (X is also the "dst->path" of A - * in this example). If X is marked obsolete, "A" will not - * notice. That's what we are validating here via the - * stale_bundle() check. - * - * When a policy's bundle is pruned, we dst_free() the XFRM - * dst which causes it's ->obsolete field to be set to a - * positive non-zero integer. If an XFRM dst has been pruned - * like this, we want to force a new route lookup. + /* If it is marked obsolete, which is how we even get here, + * then we have purged it from the policy bundle list and we + * did that for a good reason. */ - if (dst->obsolete < 0 && !stale_bundle(dst)) - return dst; - return NULL; } static int stale_bundle(struct dst_entry *dst) { - return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0); + return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC); } void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev) @@ -1733,50 +1175,33 @@ static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst) return dst; } -static void prune_one_bundle(struct xfrm_policy *pol, int (*func)(struct dst_entry *), struct dst_entry **gc_list_p) -{ - struct dst_entry *dst, **dstp; - - write_lock(&pol->lock); - dstp = &pol->bundles; - while ((dst=*dstp) != NULL) { - if (func(dst)) { - *dstp = dst->next; - dst->next = *gc_list_p; - *gc_list_p = dst; - } else { - dstp = &dst->next; - } - } - write_unlock(&pol->lock); -} - static void xfrm_prune_bundles(int (*func)(struct dst_entry *)) { - struct dst_entry *gc_list = NULL; - int dir; + int i; + struct xfrm_policy *pol; + struct dst_entry *dst, **dstp, *gc_list = NULL; read_lock_bh(&xfrm_policy_lock); - for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { - struct xfrm_policy *pol; - struct hlist_node *entry; - struct hlist_head *table; - int i; - - hlist_for_each_entry(pol, entry, - &xfrm_policy_inexact[dir], bydst) - prune_one_bundle(pol, func, &gc_list); - - table = xfrm_policy_bydst[dir].table; - for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) { - hlist_for_each_entry(pol, entry, table + i, bydst) - prune_one_bundle(pol, func, &gc_list); + for (i=0; i<2*XFRM_POLICY_MAX; i++) { + for (pol = xfrm_policy_list[i]; pol; pol = pol->next) { + write_lock(&pol->lock); + dstp = &pol->bundles; + while ((dst=*dstp) != NULL) { + if (func(dst)) { + *dstp = dst->next; + dst->next = gc_list; + gc_list = dst; + } else { + dstp = &dst->next; + } + } + write_unlock(&pol->lock); } } read_unlock_bh(&xfrm_policy_lock); while (gc_list) { - struct dst_entry *dst = gc_list; + dst = gc_list; gc_list = dst->next; dst_free(dst); } @@ -1792,12 +1217,22 @@ static void __xfrm_garbage_collect(void) xfrm_prune_bundles(unused_bundle); } -static int xfrm_flush_bundles(void) +int xfrm_flush_bundles(void) { xfrm_prune_bundles(stale_bundle); return 0; } +static int always_true(struct dst_entry *dst) +{ + return 1; +} + +void xfrm_flush_all_bundles(void) +{ + xfrm_prune_bundles(always_true); +} + void xfrm_init_pmtu(struct dst_entry *dst) { do { @@ -1825,7 +1260,7 @@ EXPORT_SYMBOL(xfrm_init_pmtu); * still valid. */ -int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int strict) +int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family) { struct dst_entry *dst = &first->u.dst; struct xfrm_dst *last; @@ -1842,16 +1277,8 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family, int str if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family)) return 0; - if (fl && !security_xfrm_flow_state_match(fl, dst->xfrm)) - return 0; if (dst->xfrm->km.state != XFRM_STATE_VALID) return 0; - if (xdst->genid != dst->xfrm->genid) - return 0; - - if (strict && fl && dst->xfrm->props.mode != XFRM_MODE_TUNNEL && - !xfrm_state_addr_flow_check(dst->xfrm, fl, family)) - return 0; mtu = dst_mtu(dst->child); if (xdst->child_mtu_cached != mtu) { @@ -2000,33 +1427,12 @@ static struct notifier_block xfrm_dev_notifier = { static void __init xfrm_policy_init(void) { - unsigned int hmask, sz; - int dir; - xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache", sizeof(struct xfrm_dst), - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, + 0, SLAB_HWCACHE_ALIGN, NULL, NULL); - - hmask = 8 - 1; - sz = (hmask+1) * sizeof(struct hlist_head); - - xfrm_policy_byidx = xfrm_hash_alloc(sz); - xfrm_idx_hmask = hmask; - if (!xfrm_policy_byidx) - panic("XFRM: failed to allocate byidx hash\n"); - - for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) { - struct xfrm_policy_hash *htab; - - INIT_HLIST_HEAD(&xfrm_policy_inexact[dir]); - - htab = &xfrm_policy_bydst[dir]; - htab->table = xfrm_hash_alloc(sz); - htab->hmask = hmask; - if (!htab->table) - panic("XFRM: failed to allocate bydst hash\n"); - } + if (!xfrm_dst_cache) + panic("XFRM: failed to allocate xfrm_dst_cache\n"); INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task, NULL); register_netdevice_notifier(&xfrm_dev_notifier); diff --git a/trunk/net/xfrm/xfrm_state.c b/trunk/net/xfrm/xfrm_state.c index 9f63edd39346..0021aad5db43 100644 --- a/trunk/net/xfrm/xfrm_state.c +++ b/trunk/net/xfrm/xfrm_state.c @@ -18,11 +18,8 @@ #include #include #include -#include #include -#include "xfrm_hash.h" - struct sock *xfrm_nl; EXPORT_SYMBOL(xfrm_nl); @@ -35,7 +32,7 @@ EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth); /* Each xfrm_state may be linked to two tables: 1. Hash table by (spi,daddr,ah/esp) to find SA by SPI. (input,ctl) - 2. Hash table by (daddr,family,reqid) to find what SAs exist for given + 2. Hash table by daddr to find what SAs exist for given destination/tunnel endpoint. (output) */ @@ -47,123 +44,8 @@ static DEFINE_SPINLOCK(xfrm_state_lock); * Main use is finding SA after policy selected tunnel or transport mode. * Also, it can be used by ah/esp icmp error handler to find offending SA. */ -static struct hlist_head *xfrm_state_bydst __read_mostly; -static struct hlist_head *xfrm_state_bysrc __read_mostly; -static struct hlist_head *xfrm_state_byspi __read_mostly; -static unsigned int xfrm_state_hmask __read_mostly; -static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; -static unsigned int xfrm_state_num; -static unsigned int xfrm_state_genid; - -static inline unsigned int xfrm_dst_hash(xfrm_address_t *daddr, - xfrm_address_t *saddr, - u32 reqid, - unsigned short family) -{ - return __xfrm_dst_hash(daddr, saddr, reqid, family, xfrm_state_hmask); -} - -static inline unsigned int xfrm_src_hash(xfrm_address_t *addr, - unsigned short family) -{ - return __xfrm_src_hash(addr, family, xfrm_state_hmask); -} - -static inline unsigned int -xfrm_spi_hash(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family) -{ - return __xfrm_spi_hash(daddr, spi, proto, family, xfrm_state_hmask); -} - -static void xfrm_hash_transfer(struct hlist_head *list, - struct hlist_head *ndsttable, - struct hlist_head *nsrctable, - struct hlist_head *nspitable, - unsigned int nhashmask) -{ - struct hlist_node *entry, *tmp; - struct xfrm_state *x; - - hlist_for_each_entry_safe(x, entry, tmp, list, bydst) { - unsigned int h; - - h = __xfrm_dst_hash(&x->id.daddr, &x->props.saddr, - x->props.reqid, x->props.family, - nhashmask); - hlist_add_head(&x->bydst, ndsttable+h); - - h = __xfrm_src_hash(&x->props.saddr, x->props.family, - nhashmask); - hlist_add_head(&x->bysrc, nsrctable+h); - - h = __xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, - x->props.family, nhashmask); - hlist_add_head(&x->byspi, nspitable+h); - } -} - -static unsigned long xfrm_hash_new_size(void) -{ - return ((xfrm_state_hmask + 1) << 1) * - sizeof(struct hlist_head); -} - -static DEFINE_MUTEX(hash_resize_mutex); - -static void xfrm_hash_resize(void *__unused) -{ - struct hlist_head *ndst, *nsrc, *nspi, *odst, *osrc, *ospi; - unsigned long nsize, osize; - unsigned int nhashmask, ohashmask; - int i; - - mutex_lock(&hash_resize_mutex); - - nsize = xfrm_hash_new_size(); - ndst = xfrm_hash_alloc(nsize); - if (!ndst) - goto out_unlock; - nsrc = xfrm_hash_alloc(nsize); - if (!nsrc) { - xfrm_hash_free(ndst, nsize); - goto out_unlock; - } - nspi = xfrm_hash_alloc(nsize); - if (!nspi) { - xfrm_hash_free(ndst, nsize); - xfrm_hash_free(nsrc, nsize); - goto out_unlock; - } - - spin_lock_bh(&xfrm_state_lock); - - nhashmask = (nsize / sizeof(struct hlist_head)) - 1U; - for (i = xfrm_state_hmask; i >= 0; i--) - xfrm_hash_transfer(xfrm_state_bydst+i, ndst, nsrc, nspi, - nhashmask); - - odst = xfrm_state_bydst; - osrc = xfrm_state_bysrc; - ospi = xfrm_state_byspi; - ohashmask = xfrm_state_hmask; - - xfrm_state_bydst = ndst; - xfrm_state_bysrc = nsrc; - xfrm_state_byspi = nspi; - xfrm_state_hmask = nhashmask; - - spin_unlock_bh(&xfrm_state_lock); - - osize = (ohashmask + 1) * sizeof(struct hlist_head); - xfrm_hash_free(odst, osize); - xfrm_hash_free(osrc, osize); - xfrm_hash_free(ospi, osize); - -out_unlock: - mutex_unlock(&hash_resize_mutex); -} - -static DECLARE_WORK(xfrm_hash_work, xfrm_hash_resize, NULL); +static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE]; +static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; DECLARE_WAIT_QUEUE_HEAD(km_waitq); EXPORT_SYMBOL(km_waitq); @@ -172,9 +54,11 @@ static DEFINE_RWLOCK(xfrm_state_afinfo_lock); static struct xfrm_state_afinfo *xfrm_state_afinfo[NPROTO]; static struct work_struct xfrm_state_gc_work; -static HLIST_HEAD(xfrm_state_gc_list); +static struct list_head xfrm_state_gc_list = LIST_HEAD_INIT(xfrm_state_gc_list); static DEFINE_SPINLOCK(xfrm_state_gc_lock); +static int xfrm_state_gc_flush_bundles; + int __xfrm_state_delete(struct xfrm_state *x); static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family); @@ -185,13 +69,14 @@ void km_state_expired(struct xfrm_state *x, int hard, u32 pid); static void xfrm_state_gc_destroy(struct xfrm_state *x) { - del_timer_sync(&x->timer); - del_timer_sync(&x->rtimer); + if (del_timer(&x->timer)) + BUG(); + if (del_timer(&x->rtimer)) + BUG(); kfree(x->aalg); kfree(x->ealg); kfree(x->calg); kfree(x->encap); - kfree(x->coaddr); if (x->mode) xfrm_put_mode(x->mode); if (x->type) { @@ -205,17 +90,22 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x) static void xfrm_state_gc_task(void *data) { struct xfrm_state *x; - struct hlist_node *entry, *tmp; - struct hlist_head gc_list; + struct list_head *entry, *tmp; + struct list_head gc_list = LIST_HEAD_INIT(gc_list); + + if (xfrm_state_gc_flush_bundles) { + xfrm_state_gc_flush_bundles = 0; + xfrm_flush_bundles(); + } spin_lock_bh(&xfrm_state_gc_lock); - gc_list.first = xfrm_state_gc_list.first; - INIT_HLIST_HEAD(&xfrm_state_gc_list); + list_splice_init(&xfrm_state_gc_list, &gc_list); spin_unlock_bh(&xfrm_state_gc_lock); - hlist_for_each_entry_safe(x, entry, tmp, &gc_list, bydst) + list_for_each_safe(entry, tmp, &gc_list) { + x = list_entry(entry, struct xfrm_state, bydst); xfrm_state_gc_destroy(x); - + } wake_up(&km_waitq); } @@ -278,9 +168,9 @@ static void xfrm_timer_handler(unsigned long data) if (warn) km_state_expired(x, 0, 0); resched: - if (next != LONG_MAX) - mod_timer(&x->timer, jiffies + make_jiffies(next)); - + if (next != LONG_MAX && + !mod_timer(&x->timer, jiffies + make_jiffies(next))) + xfrm_state_hold(x); goto out; expired: @@ -295,6 +185,7 @@ static void xfrm_timer_handler(unsigned long data) out: spin_unlock(&x->lock); + xfrm_state_put(x); } static void xfrm_replay_timer_handler(unsigned long data); @@ -308,9 +199,8 @@ struct xfrm_state *xfrm_state_alloc(void) if (x) { atomic_set(&x->refcnt, 1); atomic_set(&x->tunnel_users, 0); - INIT_HLIST_NODE(&x->bydst); - INIT_HLIST_NODE(&x->bysrc); - INIT_HLIST_NODE(&x->byspi); + INIT_LIST_HEAD(&x->bydst); + INIT_LIST_HEAD(&x->byspi); init_timer(&x->timer); x->timer.function = xfrm_timer_handler; x->timer.data = (unsigned long)x; @@ -335,7 +225,7 @@ void __xfrm_state_destroy(struct xfrm_state *x) BUG_TRAP(x->km.state == XFRM_STATE_DEAD); spin_lock_bh(&xfrm_state_gc_lock); - hlist_add_head(&x->bydst, &xfrm_state_gc_list); + list_add(&x->bydst, &xfrm_state_gc_list); spin_unlock_bh(&xfrm_state_gc_lock); schedule_work(&xfrm_state_gc_work); } @@ -348,12 +238,27 @@ int __xfrm_state_delete(struct xfrm_state *x) if (x->km.state != XFRM_STATE_DEAD) { x->km.state = XFRM_STATE_DEAD; spin_lock(&xfrm_state_lock); - hlist_del(&x->bydst); - hlist_del(&x->bysrc); - if (x->id.spi) - hlist_del(&x->byspi); - xfrm_state_num--; + list_del(&x->bydst); + __xfrm_state_put(x); + if (x->id.spi) { + list_del(&x->byspi); + __xfrm_state_put(x); + } spin_unlock(&xfrm_state_lock); + if (del_timer(&x->timer)) + __xfrm_state_put(x); + if (del_timer(&x->rtimer)) + __xfrm_state_put(x); + + /* The number two in this test is the reference + * mentioned in the comment below plus the reference + * our caller holds. A larger value means that + * there are DSTs attached to this xfrm_state. + */ + if (atomic_read(&x->refcnt) > 2) { + xfrm_state_gc_flush_bundles = 1; + schedule_work(&xfrm_state_gc_work); + } /* All xfrm_state objects are created by xfrm_state_alloc. * The xfrm_state_alloc call gives a reference, and that @@ -382,15 +287,14 @@ EXPORT_SYMBOL(xfrm_state_delete); void xfrm_state_flush(u8 proto) { int i; + struct xfrm_state *x; spin_lock_bh(&xfrm_state_lock); - for (i = 0; i <= xfrm_state_hmask; i++) { - struct hlist_node *entry; - struct xfrm_state *x; + for (i = 0; i < XFRM_DST_HSIZE; i++) { restart: - hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) { + list_for_each_entry(x, xfrm_state_bydst+i, bydst) { if (!xfrm_state_kern(x) && - xfrm_id_proto_match(x->id.proto, proto)) { + (proto == IPSEC_PROTO_ANY || x->id.proto == proto)) { xfrm_state_hold(x); spin_unlock_bh(&xfrm_state_lock); @@ -421,103 +325,29 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, return 0; } -static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family) -{ - unsigned int h = xfrm_spi_hash(daddr, spi, proto, family); - struct xfrm_state *x; - struct hlist_node *entry; - - hlist_for_each_entry(x, entry, xfrm_state_byspi+h, byspi) { - if (x->props.family != family || - x->id.spi != spi || - x->id.proto != proto) - continue; - - switch (family) { - case AF_INET: - if (x->id.daddr.a4 != daddr->a4) - continue; - break; - case AF_INET6: - if (!ipv6_addr_equal((struct in6_addr *)daddr, - (struct in6_addr *) - x->id.daddr.a6)) - continue; - break; - }; - - xfrm_state_hold(x); - return x; - } - - return NULL; -} - -static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) -{ - unsigned int h = xfrm_src_hash(saddr, family); - struct xfrm_state *x; - struct hlist_node *entry; - - hlist_for_each_entry(x, entry, xfrm_state_bysrc+h, bysrc) { - if (x->props.family != family || - x->id.proto != proto) - continue; - - switch (family) { - case AF_INET: - if (x->id.daddr.a4 != daddr->a4 || - x->props.saddr.a4 != saddr->a4) - continue; - break; - case AF_INET6: - if (!ipv6_addr_equal((struct in6_addr *)daddr, - (struct in6_addr *) - x->id.daddr.a6) || - !ipv6_addr_equal((struct in6_addr *)saddr, - (struct in6_addr *) - x->props.saddr.a6)) - continue; - break; - }; - - xfrm_state_hold(x); - return x; - } - - return NULL; -} - -static inline struct xfrm_state * -__xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) -{ - if (use_spi) - return __xfrm_state_lookup(&x->id.daddr, x->id.spi, - x->id.proto, family); - else - return __xfrm_state_lookup_byaddr(&x->id.daddr, - &x->props.saddr, - x->id.proto, family); -} - struct xfrm_state * xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, struct flowi *fl, struct xfrm_tmpl *tmpl, struct xfrm_policy *pol, int *err, unsigned short family) { - unsigned int h = xfrm_dst_hash(daddr, saddr, tmpl->reqid, family); - struct hlist_node *entry; + unsigned h = xfrm_dst_hash(daddr, family); struct xfrm_state *x, *x0; int acquire_in_progress = 0; int error = 0; struct xfrm_state *best = NULL; + struct xfrm_state_afinfo *afinfo; + afinfo = xfrm_state_get_afinfo(family); + if (afinfo == NULL) { + *err = -EAFNOSUPPORT; + return NULL; + } + spin_lock_bh(&xfrm_state_lock); - hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { + list_for_each_entry(x, xfrm_state_bydst+h, bydst) { if (x->props.family == family && x->props.reqid == tmpl->reqid && - !(x->props.flags & XFRM_STATE_WILDRECV) && xfrm_state_addr_check(x, daddr, saddr, family) && tmpl->mode == x->props.mode && tmpl->id.proto == x->id.proto && @@ -537,7 +367,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, */ if (x->km.state == XFRM_STATE_VALID) { if (!xfrm_selector_match(&x->sel, fl, family) || - !security_xfrm_state_pol_flow_match(x, pol, fl)) + !xfrm_sec_ctx_match(pol->security, x->security)) continue; if (!best || best->km.dying > x->km.dying || @@ -549,7 +379,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, } else if (x->km.state == XFRM_STATE_ERROR || x->km.state == XFRM_STATE_EXPIRED) { if (xfrm_selector_match(&x->sel, fl, family) && - security_xfrm_state_pol_flow_match(x, pol, fl)) + xfrm_sec_ctx_match(pol->security, x->security)) error = -ESRCH; } } @@ -558,8 +388,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, x = best; if (!x && !error && !acquire_in_progress) { if (tmpl->id.spi && - (x0 = __xfrm_state_lookup(daddr, tmpl->id.spi, - tmpl->id.proto, family)) != NULL) { + (x0 = afinfo->state_lookup(daddr, tmpl->id.spi, + tmpl->id.proto)) != NULL) { xfrm_state_put(x0); error = -EEXIST; goto out; @@ -573,24 +403,17 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, * to current session. */ xfrm_init_tempsel(x, fl, tmpl, daddr, saddr, family); - error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid); - if (error) { - x->km.state = XFRM_STATE_DEAD; - xfrm_state_put(x); - x = NULL; - goto out; - } - if (km_query(x, tmpl, pol) == 0) { x->km.state = XFRM_STATE_ACQ; - hlist_add_head(&x->bydst, xfrm_state_bydst+h); - h = xfrm_src_hash(saddr, family); - hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); + list_add_tail(&x->bydst, xfrm_state_bydst+h); + xfrm_state_hold(x); if (x->id.spi) { h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); - hlist_add_head(&x->byspi, xfrm_state_byspi+h); + list_add(&x->byspi, xfrm_state_byspi+h); + xfrm_state_hold(x); } x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES; + xfrm_state_hold(x); x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; add_timer(&x->timer); } else { @@ -606,167 +429,59 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, else *err = acquire_in_progress ? -EAGAIN : error; spin_unlock_bh(&xfrm_state_lock); + xfrm_state_put_afinfo(afinfo); return x; } static void __xfrm_state_insert(struct xfrm_state *x) { - unsigned int h; + unsigned h = xfrm_dst_hash(&x->id.daddr, x->props.family); - x->genid = ++xfrm_state_genid; + list_add(&x->bydst, xfrm_state_bydst+h); + xfrm_state_hold(x); - h = xfrm_dst_hash(&x->id.daddr, &x->props.saddr, - x->props.reqid, x->props.family); - hlist_add_head(&x->bydst, xfrm_state_bydst+h); + h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family); - h = xfrm_src_hash(&x->props.saddr, x->props.family); - hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); + list_add(&x->byspi, xfrm_state_byspi+h); + xfrm_state_hold(x); - if (xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY)) { - h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, - x->props.family); - - hlist_add_head(&x->byspi, xfrm_state_byspi+h); - } + if (!mod_timer(&x->timer, jiffies + HZ)) + xfrm_state_hold(x); - mod_timer(&x->timer, jiffies + HZ); - if (x->replay_maxage) - mod_timer(&x->rtimer, jiffies + x->replay_maxage); + if (x->replay_maxage && + !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) + xfrm_state_hold(x); wake_up(&km_waitq); - - xfrm_state_num++; - - if (x->bydst.next != NULL && - (xfrm_state_hmask + 1) < xfrm_state_hashmax && - xfrm_state_num > xfrm_state_hmask) - schedule_work(&xfrm_hash_work); -} - -/* xfrm_state_lock is held */ -static void __xfrm_state_bump_genids(struct xfrm_state *xnew) -{ - unsigned short family = xnew->props.family; - u32 reqid = xnew->props.reqid; - struct xfrm_state *x; - struct hlist_node *entry; - unsigned int h; - - h = xfrm_dst_hash(&xnew->id.daddr, &xnew->props.saddr, reqid, family); - hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { - if (x->props.family == family && - x->props.reqid == reqid && - !xfrm_addr_cmp(&x->id.daddr, &xnew->id.daddr, family) && - !xfrm_addr_cmp(&x->props.saddr, &xnew->props.saddr, family)) - x->genid = xfrm_state_genid; - } } void xfrm_state_insert(struct xfrm_state *x) { spin_lock_bh(&xfrm_state_lock); - __xfrm_state_bump_genids(x); __xfrm_state_insert(x); spin_unlock_bh(&xfrm_state_lock); -} -EXPORT_SYMBOL(xfrm_state_insert); - -/* xfrm_state_lock is held */ -static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create) -{ - unsigned int h = xfrm_dst_hash(daddr, saddr, reqid, family); - struct hlist_node *entry; - struct xfrm_state *x; - - hlist_for_each_entry(x, entry, xfrm_state_bydst+h, bydst) { - if (x->props.reqid != reqid || - x->props.mode != mode || - x->props.family != family || - x->km.state != XFRM_STATE_ACQ || - x->id.spi != 0) - continue; - - switch (family) { - case AF_INET: - if (x->id.daddr.a4 != daddr->a4 || - x->props.saddr.a4 != saddr->a4) - continue; - break; - case AF_INET6: - if (!ipv6_addr_equal((struct in6_addr *)x->id.daddr.a6, - (struct in6_addr *)daddr) || - !ipv6_addr_equal((struct in6_addr *) - x->props.saddr.a6, - (struct in6_addr *)saddr)) - continue; - break; - }; - xfrm_state_hold(x); - return x; - } - - if (!create) - return NULL; - - x = xfrm_state_alloc(); - if (likely(x)) { - switch (family) { - case AF_INET: - x->sel.daddr.a4 = daddr->a4; - x->sel.saddr.a4 = saddr->a4; - x->sel.prefixlen_d = 32; - x->sel.prefixlen_s = 32; - x->props.saddr.a4 = saddr->a4; - x->id.daddr.a4 = daddr->a4; - break; - - case AF_INET6: - ipv6_addr_copy((struct in6_addr *)x->sel.daddr.a6, - (struct in6_addr *)daddr); - ipv6_addr_copy((struct in6_addr *)x->sel.saddr.a6, - (struct in6_addr *)saddr); - x->sel.prefixlen_d = 128; - x->sel.prefixlen_s = 128; - ipv6_addr_copy((struct in6_addr *)x->props.saddr.a6, - (struct in6_addr *)saddr); - ipv6_addr_copy((struct in6_addr *)x->id.daddr.a6, - (struct in6_addr *)daddr); - break; - }; - - x->km.state = XFRM_STATE_ACQ; - x->id.proto = proto; - x->props.family = family; - x->props.mode = mode; - x->props.reqid = reqid; - x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES; - xfrm_state_hold(x); - x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; - add_timer(&x->timer); - hlist_add_head(&x->bydst, xfrm_state_bydst+h); - h = xfrm_src_hash(saddr, family); - hlist_add_head(&x->bysrc, xfrm_state_bysrc+h); - wake_up(&km_waitq); - } - - return x; + xfrm_flush_all_bundles(); } +EXPORT_SYMBOL(xfrm_state_insert); static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); int xfrm_state_add(struct xfrm_state *x) { + struct xfrm_state_afinfo *afinfo; struct xfrm_state *x1; int family; int err; - int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); family = x->props.family; + afinfo = xfrm_state_get_afinfo(family); + if (unlikely(afinfo == NULL)) + return -EAFNOSUPPORT; spin_lock_bh(&xfrm_state_lock); - x1 = __xfrm_state_locate(x, use_spi, family); + x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto); if (x1) { xfrm_state_put(x1); x1 = NULL; @@ -774,7 +489,7 @@ int xfrm_state_add(struct xfrm_state *x) goto out; } - if (use_spi && x->km.seq) { + if (x->km.seq) { x1 = __xfrm_find_acq_byseq(x->km.seq); if (x1 && xfrm_addr_cmp(&x1->id.daddr, &x->id.daddr, family)) { xfrm_state_put(x1); @@ -782,17 +497,20 @@ int xfrm_state_add(struct xfrm_state *x) } } - if (use_spi && !x1) - x1 = __find_acq_core(family, x->props.mode, x->props.reqid, - x->id.proto, - &x->id.daddr, &x->props.saddr, 0); + if (!x1) + x1 = afinfo->find_acq( + x->props.mode, x->props.reqid, x->id.proto, + &x->id.daddr, &x->props.saddr, 0); - __xfrm_state_bump_genids(x); __xfrm_state_insert(x); err = 0; out: spin_unlock_bh(&xfrm_state_lock); + xfrm_state_put_afinfo(afinfo); + + if (!err) + xfrm_flush_all_bundles(); if (x1) { xfrm_state_delete(x1); @@ -805,12 +523,16 @@ EXPORT_SYMBOL(xfrm_state_add); int xfrm_state_update(struct xfrm_state *x) { + struct xfrm_state_afinfo *afinfo; struct xfrm_state *x1; int err; - int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); + + afinfo = xfrm_state_get_afinfo(x->props.family); + if (unlikely(afinfo == NULL)) + return -EAFNOSUPPORT; spin_lock_bh(&xfrm_state_lock); - x1 = __xfrm_state_locate(x, use_spi, x->props.family); + x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto); err = -ESRCH; if (!x1) @@ -830,6 +552,7 @@ int xfrm_state_update(struct xfrm_state *x) out: spin_unlock_bh(&xfrm_state_lock); + xfrm_state_put_afinfo(afinfo); if (err) return err; @@ -845,15 +568,11 @@ int xfrm_state_update(struct xfrm_state *x) if (likely(x1->km.state == XFRM_STATE_VALID)) { if (x->encap && x1->encap) memcpy(x1->encap, x->encap, sizeof(*x1->encap)); - if (x->coaddr && x1->coaddr) { - memcpy(x1->coaddr, x->coaddr, sizeof(*x1->coaddr)); - } - if (!use_spi && memcmp(&x1->sel, &x->sel, sizeof(x1->sel))) - memcpy(&x1->sel, &x->sel, sizeof(x1->sel)); memcpy(&x1->lft, &x->lft, sizeof(x1->lft)); x1->km.dying = 0; - mod_timer(&x1->timer, jiffies + HZ); + if (!mod_timer(&x1->timer, jiffies + HZ)) + xfrm_state_hold(x1); if (x1->curlft.use_time) xfrm_state_check_expire(x1); @@ -878,7 +597,8 @@ int xfrm_state_check_expire(struct xfrm_state *x) if (x->curlft.bytes >= x->lft.hard_byte_limit || x->curlft.packets >= x->lft.hard_packet_limit) { x->km.state = XFRM_STATE_EXPIRED; - mod_timer(&x->timer, jiffies); + if (!mod_timer(&x->timer, jiffies)) + xfrm_state_hold(x); return -EINVAL; } @@ -920,93 +640,46 @@ xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family) { struct xfrm_state *x; + struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); + if (!afinfo) + return NULL; spin_lock_bh(&xfrm_state_lock); - x = __xfrm_state_lookup(daddr, spi, proto, family); + x = afinfo->state_lookup(daddr, spi, proto); spin_unlock_bh(&xfrm_state_lock); + xfrm_state_put_afinfo(afinfo); return x; } EXPORT_SYMBOL(xfrm_state_lookup); -struct xfrm_state * -xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, - u8 proto, unsigned short family) -{ - struct xfrm_state *x; - - spin_lock_bh(&xfrm_state_lock); - x = __xfrm_state_lookup_byaddr(daddr, saddr, proto, family); - spin_unlock_bh(&xfrm_state_lock); - return x; -} -EXPORT_SYMBOL(xfrm_state_lookup_byaddr); - struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create, unsigned short family) { struct xfrm_state *x; - - spin_lock_bh(&xfrm_state_lock); - x = __find_acq_core(family, mode, reqid, proto, daddr, saddr, create); - spin_unlock_bh(&xfrm_state_lock); - - return x; -} -EXPORT_SYMBOL(xfrm_find_acq); - -#ifdef CONFIG_XFRM_SUB_POLICY -int -xfrm_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n, - unsigned short family) -{ - int err = 0; struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); if (!afinfo) - return -EAFNOSUPPORT; - - spin_lock_bh(&xfrm_state_lock); - if (afinfo->tmpl_sort) - err = afinfo->tmpl_sort(dst, src, n); - spin_unlock_bh(&xfrm_state_lock); - xfrm_state_put_afinfo(afinfo); - return err; -} -EXPORT_SYMBOL(xfrm_tmpl_sort); - -int -xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n, - unsigned short family) -{ - int err = 0; - struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); - if (!afinfo) - return -EAFNOSUPPORT; + return NULL; spin_lock_bh(&xfrm_state_lock); - if (afinfo->state_sort) - err = afinfo->state_sort(dst, src, n); + x = afinfo->find_acq(mode, reqid, proto, daddr, saddr, create); spin_unlock_bh(&xfrm_state_lock); xfrm_state_put_afinfo(afinfo); - return err; + return x; } -EXPORT_SYMBOL(xfrm_state_sort); -#endif +EXPORT_SYMBOL(xfrm_find_acq); /* Silly enough, but I'm lazy to build resolution list */ static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq) { int i; + struct xfrm_state *x; - for (i = 0; i <= xfrm_state_hmask; i++) { - struct hlist_node *entry; - struct xfrm_state *x; - - hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) { - if (x->km.seq == seq && - x->km.state == XFRM_STATE_ACQ) { + for (i = 0; i < XFRM_DST_HSIZE; i++) { + list_for_each_entry(x, xfrm_state_bydst+i, bydst) { + if (x->km.seq == seq && x->km.state == XFRM_STATE_ACQ) { xfrm_state_hold(x); return x; } @@ -1042,7 +715,7 @@ EXPORT_SYMBOL(xfrm_get_acqseq); void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi) { - unsigned int h; + u32 h; struct xfrm_state *x0; if (x->id.spi) @@ -1072,7 +745,8 @@ xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi) if (x->id.spi) { spin_lock_bh(&xfrm_state_lock); h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family); - hlist_add_head(&x->byspi, xfrm_state_byspi+h); + list_add(&x->byspi, xfrm_state_byspi+h); + xfrm_state_hold(x); spin_unlock_bh(&xfrm_state_lock); wake_up(&km_waitq); } @@ -1084,14 +758,13 @@ int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), { int i; struct xfrm_state *x; - struct hlist_node *entry; int count = 0; int err = 0; spin_lock_bh(&xfrm_state_lock); - for (i = 0; i <= xfrm_state_hmask; i++) { - hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) { - if (xfrm_id_proto_match(x->id.proto, proto)) + for (i = 0; i < XFRM_DST_HSIZE; i++) { + list_for_each_entry(x, xfrm_state_bydst+i, bydst) { + if (proto == IPSEC_PROTO_ANY || x->id.proto == proto) count++; } } @@ -1100,9 +773,9 @@ int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), goto out; } - for (i = 0; i <= xfrm_state_hmask; i++) { - hlist_for_each_entry(x, entry, xfrm_state_bydst+i, bydst) { - if (!xfrm_id_proto_match(x->id.proto, proto)) + for (i = 0; i < XFRM_DST_HSIZE; i++) { + list_for_each_entry(x, xfrm_state_bydst+i, bydst) { + if (proto != IPSEC_PROTO_ANY && x->id.proto != proto) continue; err = func(x, --count, data); if (err) @@ -1159,8 +832,10 @@ void xfrm_replay_notify(struct xfrm_state *x, int event) km_state_notify(x, &c); if (x->replay_maxage && - !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) + !mod_timer(&x->rtimer, jiffies + x->replay_maxage)) { + xfrm_state_hold(x); x->xflags &= ~XFRM_TIME_DEFER; + } } EXPORT_SYMBOL(xfrm_replay_notify); @@ -1178,6 +853,7 @@ static void xfrm_replay_timer_handler(unsigned long data) } spin_unlock(&x->lock); + xfrm_state_put(x); } int xfrm_replay_check(struct xfrm_state *x, u32 seq) @@ -1321,25 +997,6 @@ void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid) } EXPORT_SYMBOL(km_policy_expired); -int km_report(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr) -{ - int err = -EINVAL; - int ret; - struct xfrm_mgr *km; - - read_lock(&xfrm_km_lock); - list_for_each_entry(km, &xfrm_km_list, list) { - if (km->report) { - ret = km->report(proto, sel, addr); - if (!ret) - err = ret; - } - } - read_unlock(&xfrm_km_lock); - return err; -} -EXPORT_SYMBOL(km_report); - int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen) { int err; @@ -1361,7 +1018,7 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen err = -EINVAL; read_lock(&xfrm_km_lock); list_for_each_entry(km, &xfrm_km_list, list) { - pol = km->compile_policy(sk, optname, data, + pol = km->compile_policy(sk->sk_family, optname, data, optlen, &err); if (err >= 0) break; @@ -1408,8 +1065,11 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) write_lock_bh(&xfrm_state_afinfo_lock); if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) err = -ENOBUFS; - else + else { + afinfo->state_bydst = xfrm_state_bydst; + afinfo->state_byspi = xfrm_state_byspi; xfrm_state_afinfo[afinfo->family] = afinfo; + } write_unlock_bh(&xfrm_state_afinfo_lock); return err; } @@ -1426,8 +1086,11 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) { if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo)) err = -EINVAL; - else + else { xfrm_state_afinfo[afinfo->family] = NULL; + afinfo->state_byspi = NULL; + afinfo->state_bydst = NULL; + } } write_unlock_bh(&xfrm_state_afinfo_lock); return err; @@ -1543,17 +1206,12 @@ EXPORT_SYMBOL(xfrm_init_state); void __init xfrm_state_init(void) { - unsigned int sz; - - sz = sizeof(struct hlist_head) * 8; - - xfrm_state_bydst = xfrm_hash_alloc(sz); - xfrm_state_bysrc = xfrm_hash_alloc(sz); - xfrm_state_byspi = xfrm_hash_alloc(sz); - if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi) - panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes."); - xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1); + int i; + for (i=0; i #include #include #include @@ -28,9 +27,6 @@ #include #include #include -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -#include -#endif static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type) { @@ -90,22 +86,6 @@ static int verify_encap_tmpl(struct rtattr **xfrma) return 0; } -static int verify_one_addr(struct rtattr **xfrma, enum xfrm_attr_type_t type, - xfrm_address_t **addrp) -{ - struct rtattr *rt = xfrma[type - 1]; - - if (!rt) - return 0; - - if ((rt->rta_len - sizeof(*rt)) < sizeof(**addrp)) - return -EINVAL; - - if (addrp) - *addrp = RTA_DATA(rt); - - return 0; -} static inline int verify_sec_ctx_len(struct rtattr **xfrma) { @@ -176,19 +156,6 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, goto out; break; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - case IPPROTO_DSTOPTS: - case IPPROTO_ROUTING: - if (xfrma[XFRMA_ALG_COMP-1] || - xfrma[XFRMA_ALG_AUTH-1] || - xfrma[XFRMA_ALG_CRYPT-1] || - xfrma[XFRMA_ENCAP-1] || - xfrma[XFRMA_SEC_CTX-1] || - !xfrma[XFRMA_COADDR-1]) - goto out; - break; -#endif - default: goto out; }; @@ -203,14 +170,11 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, goto out; if ((err = verify_sec_ctx_len(xfrma))) goto out; - if ((err = verify_one_addr(xfrma, XFRMA_COADDR, NULL))) - goto out; err = -EINVAL; switch (p->mode) { - case XFRM_MODE_TRANSPORT: - case XFRM_MODE_TUNNEL: - case XFRM_MODE_ROUTEOPTIMIZATION: + case 0: + case 1: break; default: @@ -248,7 +212,6 @@ static int attach_one_algo(struct xfrm_algo **algpp, u8 *props, return -ENOMEM; memcpy(p, ualg, len); - strcpy(p->alg_name, algo->name); *algpp = p; return 0; } @@ -295,24 +258,6 @@ static int attach_sec_ctx(struct xfrm_state *x, struct rtattr *u_arg) return security_xfrm_state_alloc(x, uctx); } -static int attach_one_addr(xfrm_address_t **addrpp, struct rtattr *u_arg) -{ - struct rtattr *rta = u_arg; - xfrm_address_t *p, *uaddrp; - - if (!rta) - return 0; - - uaddrp = RTA_DATA(rta); - p = kmalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return -ENOMEM; - - memcpy(p, uaddrp, sizeof(*p)); - *addrpp = p; - return 0; -} - static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) { memcpy(&x->id, &p->id, sizeof(x->id)); @@ -402,8 +347,7 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p, goto error; if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1]))) goto error; - if ((err = attach_one_addr(&x->coaddr, xfrma[XFRMA_COADDR-1]))) - goto error; + err = xfrm_init_state(x); if (err) goto error; @@ -472,48 +416,16 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) return err; } -static struct xfrm_state *xfrm_user_state_lookup(struct xfrm_usersa_id *p, - struct rtattr **xfrma, - int *errp) -{ - struct xfrm_state *x = NULL; - int err; - - if (xfrm_id_proto_match(p->proto, IPSEC_PROTO_ANY)) { - err = -ESRCH; - x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family); - } else { - xfrm_address_t *saddr = NULL; - - err = verify_one_addr(xfrma, XFRMA_SRCADDR, &saddr); - if (err) - goto out; - - if (!saddr) { - err = -EINVAL; - goto out; - } - - x = xfrm_state_lookup_byaddr(&p->daddr, saddr, p->proto, - p->family); - } - - out: - if (!x && errp) - *errp = err; - return x; -} - static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) { struct xfrm_state *x; - int err = -ESRCH; + int err; struct km_event c; struct xfrm_usersa_id *p = NLMSG_DATA(nlh); - x = xfrm_user_state_lookup(p, (struct rtattr **)xfrma, &err); + x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family); if (x == NULL) - return err; + return -ESRCH; if ((err = security_xfrm_state_delete(x)) != 0) goto out; @@ -607,13 +519,6 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr) uctx->ctx_len = x->security->ctx_len; memcpy(uctx + 1, x->security->ctx_str, x->security->ctx_len); } - - if (x->coaddr) - RTA_PUT(skb, XFRMA_COADDR, sizeof(*x->coaddr), x->coaddr); - - if (x->lastused) - RTA_PUT(skb, XFRMA_LASTUSED, sizeof(x->lastused), &x->lastused); - nlh->nlmsg_len = skb->tail - b; out: sp->this_idx++; @@ -635,7 +540,7 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) info.nlmsg_flags = NLM_F_MULTI; info.this_idx = 0; info.start_idx = cb->args[0]; - (void) xfrm_state_walk(0, dump_one_state, &info); + (void) xfrm_state_walk(IPSEC_PROTO_ANY, dump_one_state, &info); cb->args[0] = info.this_idx; return skb->len; @@ -671,9 +576,10 @@ static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) struct xfrm_usersa_id *p = NLMSG_DATA(nlh); struct xfrm_state *x; struct sk_buff *resp_skb; - int err = -ESRCH; + int err; - x = xfrm_user_state_lookup(p, (struct rtattr **)xfrma, &err); + x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family); + err = -ESRCH; if (x == NULL) goto out_noput; @@ -786,22 +692,6 @@ static int verify_policy_dir(__u8 dir) return 0; } -static int verify_policy_type(__u8 type) -{ - switch (type) { - case XFRM_POLICY_TYPE_MAIN: -#ifdef CONFIG_XFRM_SUB_POLICY - case XFRM_POLICY_TYPE_SUB: -#endif - break; - - default: - return -EINVAL; - }; - - return 0; -} - static int verify_newpolicy_info(struct xfrm_userpolicy_info *p) { switch (p->share) { @@ -895,29 +785,6 @@ static int copy_from_user_tmpl(struct xfrm_policy *pol, struct rtattr **xfrma) return 0; } -static int copy_from_user_policy_type(u8 *tp, struct rtattr **xfrma) -{ - struct rtattr *rt = xfrma[XFRMA_POLICY_TYPE-1]; - struct xfrm_userpolicy_type *upt; - __u8 type = XFRM_POLICY_TYPE_MAIN; - int err; - - if (rt) { - if (rt->rta_len < sizeof(*upt)) - return -EINVAL; - - upt = RTA_DATA(rt); - type = upt->type; - } - - err = verify_policy_type(type); - if (err) - return err; - - *tp = type; - return 0; -} - static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p) { xp->priority = p->priority; @@ -956,20 +823,16 @@ static struct xfrm_policy *xfrm_policy_construct(struct xfrm_userpolicy_info *p, copy_from_user_policy(xp, p); - err = copy_from_user_policy_type(&xp->type, xfrma); - if (err) - goto error; - if (!(err = copy_from_user_tmpl(xp, xfrma))) err = copy_from_user_sec_ctx(xp, xfrma); - if (err) - goto error; + + if (err) { + *errp = err; + kfree(xp); + xp = NULL; + } return xp; - error: - *errp = err; - kfree(xp); - return NULL; } static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) @@ -1046,63 +909,27 @@ static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb) return -1; } -static int copy_sec_ctx(struct xfrm_sec_ctx *s, struct sk_buff *skb) -{ - int ctx_size = sizeof(struct xfrm_sec_ctx) + s->ctx_len; - struct rtattr *rt = __RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size); - struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt); - - uctx->exttype = XFRMA_SEC_CTX; - uctx->len = ctx_size; - uctx->ctx_doi = s->ctx_doi; - uctx->ctx_alg = s->ctx_alg; - uctx->ctx_len = s->ctx_len; - memcpy(uctx + 1, s->ctx_str, s->ctx_len); - return 0; - - rtattr_failure: - return -1; -} - -static inline int copy_to_user_state_sec_ctx(struct xfrm_state *x, struct sk_buff *skb) -{ - if (x->security) { - return copy_sec_ctx(x->security, skb); - } - return 0; -} - -static inline int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb) +static int copy_to_user_sec_ctx(struct xfrm_policy *xp, struct sk_buff *skb) { if (xp->security) { - return copy_sec_ctx(xp->security, skb); - } - return 0; -} - -#ifdef CONFIG_XFRM_SUB_POLICY -static int copy_to_user_policy_type(struct xfrm_policy *xp, struct sk_buff *skb) -{ - struct xfrm_userpolicy_type upt; - - memset(&upt, 0, sizeof(upt)); - upt.type = xp->type; - - RTA_PUT(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt); + int ctx_size = sizeof(struct xfrm_sec_ctx) + + xp->security->ctx_len; + struct rtattr *rt = __RTA_PUT(skb, XFRMA_SEC_CTX, ctx_size); + struct xfrm_user_sec_ctx *uctx = RTA_DATA(rt); + uctx->exttype = XFRMA_SEC_CTX; + uctx->len = ctx_size; + uctx->ctx_doi = xp->security->ctx_doi; + uctx->ctx_alg = xp->security->ctx_alg; + uctx->ctx_len = xp->security->ctx_len; + memcpy(uctx + 1, xp->security->ctx_str, xp->security->ctx_len); + } return 0; -rtattr_failure: + rtattr_failure: return -1; } -#else -static inline int copy_to_user_policy_type(struct xfrm_policy *xp, struct sk_buff *skb) -{ - return 0; -} -#endif - static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr) { struct xfrm_dump_info *sp = ptr; @@ -1126,8 +953,6 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr goto nlmsg_failure; if (copy_to_user_sec_ctx(xp, skb)) goto nlmsg_failure; - if (copy_to_user_policy_type(xp, skb) < 0) - goto nlmsg_failure; nlh->nlmsg_len = skb->tail - b; out: @@ -1149,10 +974,7 @@ static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb) info.nlmsg_flags = NLM_F_MULTI; info.this_idx = 0; info.start_idx = cb->args[0]; - (void) xfrm_policy_walk(XFRM_POLICY_TYPE_MAIN, dump_one_policy, &info); -#ifdef CONFIG_XFRM_SUB_POLICY - (void) xfrm_policy_walk(XFRM_POLICY_TYPE_SUB, dump_one_policy, &info); -#endif + (void) xfrm_policy_walk(dump_one_policy, &info); cb->args[0] = info.this_idx; return skb->len; @@ -1188,7 +1010,6 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr { struct xfrm_policy *xp; struct xfrm_userpolicy_id *p; - __u8 type = XFRM_POLICY_TYPE_MAIN; int err; struct km_event c; int delete; @@ -1196,16 +1017,12 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr p = NLMSG_DATA(nlh); delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; - err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma); - if (err) - return err; - err = verify_policy_dir(p->dir); if (err) return err; if (p->index) - xp = xfrm_policy_byid(type, p->dir, p->index, delete); + xp = xfrm_policy_byid(p->dir, p->index, delete); else { struct rtattr **rtattrs = (struct rtattr **)xfrma; struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1]; @@ -1222,7 +1039,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr if ((err = security_xfrm_policy_alloc(&tmp, uctx))) return err; } - xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete); + xp = xfrm_policy_bysel_ctx(p->dir, &p->sel, tmp.security, delete); security_xfrm_policy_free(&tmp); } if (xp == NULL) @@ -1405,16 +1222,9 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma) { - struct km_event c; - __u8 type = XFRM_POLICY_TYPE_MAIN; - int err; - - err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma); - if (err) - return err; +struct km_event c; - xfrm_policy_flush(type); - c.data.type = type; + xfrm_policy_flush(); c.event = nlh->nlmsg_type; c.seq = nlh->nlmsg_seq; c.pid = nlh->nlmsg_pid; @@ -1427,15 +1237,10 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void * struct xfrm_policy *xp; struct xfrm_user_polexpire *up = NLMSG_DATA(nlh); struct xfrm_userpolicy_info *p = &up->pol; - __u8 type = XFRM_POLICY_TYPE_MAIN; int err = -ENOENT; - err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma); - if (err) - return err; - if (p->index) - xp = xfrm_policy_byid(type, p->dir, p->index, 0); + xp = xfrm_policy_byid(p->dir, p->index, 0); else { struct rtattr **rtattrs = (struct rtattr **)xfrma; struct rtattr *rt = rtattrs[XFRMA_SEC_CTX-1]; @@ -1452,7 +1257,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void * if ((err = security_xfrm_policy_alloc(&tmp, uctx))) return err; } - xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, 0); + xp = xfrm_policy_bysel_ctx(p->dir, &p->sel, tmp.security, 0); security_xfrm_policy_free(&tmp); } @@ -1579,7 +1384,6 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = { [XFRM_MSG_FLUSHPOLICY - XFRM_MSG_BASE] = NLMSG_LENGTH(0), [XFRM_MSG_NEWAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), [XFRM_MSG_GETAE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_aevent_id), - [XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report), }; #undef XMSGSIZE @@ -1904,9 +1708,7 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, if (copy_to_user_tmpl(xp, skb) < 0) goto nlmsg_failure; - if (copy_to_user_state_sec_ctx(x, skb)) - goto nlmsg_failure; - if (copy_to_user_policy_type(xp, skb) < 0) + if (copy_to_user_sec_ctx(xp, skb)) goto nlmsg_failure; nlh->nlmsg_len = skb->tail - b; @@ -1940,7 +1742,7 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, /* User gives us xfrm_user_policy_info followed by an array of 0 * or more templates. */ -static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, +static struct xfrm_policy *xfrm_compile_policy(u16 family, int opt, u8 *data, int len, int *dir) { struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data; @@ -1948,7 +1750,7 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, struct xfrm_policy *xp; int nr; - switch (sk->sk_family) { + switch (family) { case AF_INET: if (opt != IP_XFRM_POLICY) { *dir = -EOPNOTSUPP; @@ -1988,18 +1790,8 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt, } copy_from_user_policy(xp, p); - xp->type = XFRM_POLICY_TYPE_MAIN; copy_templates(xp, ut, nr); - if (!xp->security) { - int err = security_xfrm_sock_policy_alloc(xp, sk); - if (err) { - kfree(xp); - *dir = err; - return NULL; - } - } - *dir = p->dir; return xp; @@ -2022,8 +1814,6 @@ static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp, goto nlmsg_failure; if (copy_to_user_sec_ctx(xp, skb)) goto nlmsg_failure; - if (copy_to_user_policy_type(xp, skb) < 0) - goto nlmsg_failure; upe->hard = !!hard; nlh->nlmsg_len = skb->tail - b; @@ -2095,8 +1885,6 @@ static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event * copy_to_user_policy(xp, p, dir); if (copy_to_user_tmpl(xp, skb) < 0) goto nlmsg_failure; - if (copy_to_user_policy_type(xp, skb) < 0) - goto nlmsg_failure; nlh->nlmsg_len = skb->tail - b; @@ -2114,9 +1902,6 @@ static int xfrm_notify_policy_flush(struct km_event *c) struct nlmsghdr *nlh; struct sk_buff *skb; unsigned char *b; -#ifdef CONFIG_XFRM_SUB_POLICY - struct xfrm_userpolicy_type upt; -#endif int len = NLMSG_LENGTH(0); skb = alloc_skb(len, GFP_ATOMIC); @@ -2126,13 +1911,6 @@ static int xfrm_notify_policy_flush(struct km_event *c) nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0); - nlh->nlmsg_flags = 0; - -#ifdef CONFIG_XFRM_SUB_POLICY - memset(&upt, 0, sizeof(upt)); - upt.type = c->data.type; - RTA_PUT(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt); -#endif nlh->nlmsg_len = skb->tail - b; @@ -2140,9 +1918,6 @@ static int xfrm_notify_policy_flush(struct km_event *c) return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_POLICY, GFP_ATOMIC); nlmsg_failure: -#ifdef CONFIG_XFRM_SUB_POLICY -rtattr_failure: -#endif kfree_skb(skb); return -1; } @@ -2167,64 +1942,19 @@ static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_ev } -static int build_report(struct sk_buff *skb, u8 proto, - struct xfrm_selector *sel, xfrm_address_t *addr) -{ - struct xfrm_user_report *ur; - struct nlmsghdr *nlh; - unsigned char *b = skb->tail; - - nlh = NLMSG_PUT(skb, 0, 0, XFRM_MSG_REPORT, sizeof(*ur)); - ur = NLMSG_DATA(nlh); - nlh->nlmsg_flags = 0; - - ur->proto = proto; - memcpy(&ur->sel, sel, sizeof(ur->sel)); - - if (addr) - RTA_PUT(skb, XFRMA_COADDR, sizeof(*addr), addr); - - nlh->nlmsg_len = skb->tail - b; - return skb->len; - -nlmsg_failure: -rtattr_failure: - skb_trim(skb, b - skb->data); - return -1; -} - -static int xfrm_send_report(u8 proto, struct xfrm_selector *sel, - xfrm_address_t *addr) -{ - struct sk_buff *skb; - size_t len; - - len = NLMSG_ALIGN(NLMSG_LENGTH(sizeof(struct xfrm_user_report))); - skb = alloc_skb(len, GFP_ATOMIC); - if (skb == NULL) - return -ENOMEM; - - if (build_report(skb, proto, sel, addr) < 0) - BUG(); - - NETLINK_CB(skb).dst_group = XFRMNLGRP_REPORT; - return netlink_broadcast(xfrm_nl, skb, 0, XFRMNLGRP_REPORT, GFP_ATOMIC); -} - static struct xfrm_mgr netlink_mgr = { .id = "netlink", .notify = xfrm_send_state_notify, .acquire = xfrm_send_acquire, .compile_policy = xfrm_compile_policy, .notify_policy = xfrm_send_policy_notify, - .report = xfrm_send_report, }; static int __init xfrm_user_init(void) { struct sock *nlsk; - printk(KERN_INFO "Initializing XFRM netlink socket\n"); + printk(KERN_INFO "Initializing IPsec netlink socket\n"); nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX, xfrm_netlink_rcv, THIS_MODULE); diff --git a/trunk/scripts/Kbuild.include b/trunk/scripts/Kbuild.include index bb19c1561f1e..2180c88cfe89 100644 --- a/trunk/scripts/Kbuild.include +++ b/trunk/scripts/Kbuild.include @@ -77,20 +77,14 @@ cc-option-align = $(subst -functions=0,,\ # cc-version # Usage gcc-ver := $(call cc-version, $(CC)) -cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) +cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \ + $(if $(1), $(1), $(CC))) # cc-ifversion # Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1) cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \ echo $(3); fi;) -# ld-option -# Usage: ldflags += $(call ld-option, -Wl$(comma)--hash-style=both) -ld-option = $(shell if $(CC) $(1) \ - -nostdlib -o ldtest$$$$.out -xc /dev/null \ - > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi; \ - rm -f ldtest$$$$.out) - ### # Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= # Usage: diff --git a/trunk/scripts/Makefile.headersinst b/trunk/scripts/Makefile.headersinst index 12e1daf875c8..aa9990a3ccd6 100644 --- a/trunk/scripts/Makefile.headersinst +++ b/trunk/scripts/Makefile.headersinst @@ -93,14 +93,14 @@ STUBDEF=__ASM_STUB_`echo $@ | tr a-z. A-Z_`; \ echo "\#ifndef $$STUBDEF" ; \ echo "\#define $$STUBDEF" ; \ echo "\# if $(ARCHDEF)" ; \ -if [ -r $(INSTALL_HDR_PATH)/include/$(archasm)/$@ ]; then \ +if [ -r $(srctree)/include/$(archasm)/$@ ]; then \ echo "\# include <$(archasm)/$@>" ; \ else \ echo "\# error $(archasm)/$@ does not exist in" \ "the $(ARCH) architecture" ; \ fi ; \ echo "\# elif $(ALTARCHDEF)" ; \ -if [ -r $(INSTALL_HDR_PATH)/include/$(altarchasm)/$@ ]; then \ +if [ -r $(srctree)/include/$(altarchasm)/$@ ]; then \ echo "\# include <$(altarchasm)/$@>" ; \ else \ echo "\# error $(altarchasm)/$@ does not exist in" \ @@ -149,9 +149,7 @@ endif hdrinst := -rR -f $(srctree)/scripts/Makefile.headersinst obj .PHONY: altarch-dir -# All the files in the normal arch dir must be created first, since we test -# for their existence. -altarch-dir: $(subdir-y) $(header-y) $(unifdef-y) $(objhdr-y) +altarch-dir: $(Q)$(MAKE) $(hdrinst)=include/asm-$(ALTARCH) dst=include/asm-$(ALTARCH) $(Q)$(MAKE) $(hdrinst)=include/asm dst=include/asm diff --git a/trunk/scripts/Makefile.host b/trunk/scripts/Makefile.host index 060f4c563a5c..18ecd4d5df7f 100644 --- a/trunk/scripts/Makefile.host +++ b/trunk/scripts/Makefile.host @@ -30,7 +30,7 @@ # libkconfig.so as the executable conf. # Note: Shared libraries consisting of C++ files are not supported -__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m)) +__hostprogs := $(sort $(hostprogs-y)$(hostprogs-m)) # hostprogs-y := tools/build may have been specified. Retreive directory host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f)))) diff --git a/trunk/scripts/Makefile.modpost b/trunk/scripts/Makefile.modpost index 0a64688c2b5d..a49550205dcc 100644 --- a/trunk/scripts/Makefile.modpost +++ b/trunk/scripts/Makefile.modpost @@ -40,7 +40,7 @@ include scripts/Kbuild.include include scripts/Makefile.lib kernelsymfile := $(objtree)/Module.symvers -modulesymfile := $(KBUILD_EXTMOD)/Module.symvers +modulesymfile := $(KBUILD_EXTMOD)/Modules.symvers # Step 1), find all modules listed in $(MODVERDIR)/ __modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) diff --git a/trunk/scripts/checkstack.pl b/trunk/scripts/checkstack.pl index f7844f6aa487..b34924663ac1 100755 --- a/trunk/scripts/checkstack.pl +++ b/trunk/scripts/checkstack.pl @@ -62,8 +62,6 @@ } elsif ($arch eq 'ppc64') { #XXX $re = qr/.*stdu.*r1,-($x{1,8})\(r1\)/o; - } elsif ($arch eq 'powerpc') { - $re = qr/.*st[dw]u.*r1,-($x{1,8})\(r1\)/o; } elsif ($arch =~ /^s390x?$/) { # 11160: a7 fb ff 60 aghi %r15,-160 $re = qr/.*ag?hi.*\%r15,-(([0-9]{2}|[3-9])[0-9]{2})/o; diff --git a/trunk/scripts/hdrcheck.sh b/trunk/scripts/hdrcheck.sh index b5ca35aa1741..b3bb683b56b6 100755 --- a/trunk/scripts/hdrcheck.sh +++ b/trunk/scripts/hdrcheck.sh @@ -1,8 +1,8 @@ #!/bin/sh -for FILE in `grep '^[ \t]*#[ \t]*include[ \t]*<' $2 | cut -f2 -d\< | cut -f1 -d\> | egrep ^linux\|^asm` ; do +for FILE in `grep '^#include <' $2 | cut -f2 -d\< | cut -f1 -d\> | egrep ^linux\|^asm` ; do if [ ! -r $1/$FILE ]; then - echo $2 requires $FILE, which does not exist in exported headers + echo $2 requires $FILE, which does not exist exit 1 fi done diff --git a/trunk/scripts/kconfig/confdata.c b/trunk/scripts/kconfig/confdata.c index a69d8acbf274..2ee48c377b66 100644 --- a/trunk/scripts/kconfig/confdata.c +++ b/trunk/scripts/kconfig/confdata.c @@ -357,7 +357,7 @@ int conf_read(const char *name) for (e = prop->expr; e; e = e->left.expr) if (e->right.sym->visible != no) flags &= e->right.sym->flags; - sym->flags &= flags | ~SYMBOL_DEF_USER; + sym->flags |= flags & SYMBOL_DEF_USER; } sym_change_count += conf_warnings || conf_unsaved; diff --git a/trunk/scripts/kernel-doc b/trunk/scripts/kernel-doc index c9ca0c23bd91..f9460a6218de 100755 --- a/trunk/scripts/kernel-doc +++ b/trunk/scripts/kernel-doc @@ -1518,7 +1518,6 @@ sub dump_function($$) { $prototype =~ s/^asmlinkage +//; $prototype =~ s/^inline +//; $prototype =~ s/^__inline__ +//; - $prototype =~ s/__devinit +//; $prototype =~ s/^#define +//; #ak added $prototype =~ s/__attribute__ \(\([a-z,]*\)\)//; diff --git a/trunk/scripts/mod/file2alias.c b/trunk/scripts/mod/file2alias.c index de76da80443f..37f67c23e11b 100644 --- a/trunk/scripts/mod/file2alias.c +++ b/trunk/scripts/mod/file2alias.c @@ -52,23 +52,6 @@ do { \ sprintf(str + strlen(str), "*"); \ } while(0) -/** - * Check that sizeof(device_id type) are consistent with size of section - * in .o file. If in-consistent then userspace and kernel does not agree - * on actual size which is a bug. - **/ -static void device_id_size_check(const char *modname, const char *device_id, - unsigned long size, unsigned long id_size) -{ - if (size % id_size || size < id_size) { - fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo " - "of the size of section __mod_%s_device_table=%lu.\n" - "Fix definition of struct %s_device_id " - "in mod_devicetable.h\n", - modname, device_id, id_size, device_id, size, device_id); - } -} - /* USB is special because the bcdDevice can be matched against a numeric range */ /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */ static void do_usb_entry(struct usb_device_id *id, @@ -169,8 +152,10 @@ static void do_usb_table(void *symval, unsigned long size, unsigned int i; const unsigned long id_size = sizeof(struct usb_device_id); - device_id_size_check(mod->name, "usb", size, id_size); - + if (size % id_size || size < id_size) { + warn("%s ids %lu bad size " + "(each on %lu)\n", mod->name, size, id_size); + } /* Leave last one: it's the terminator. */ size -= id_size; @@ -265,14 +250,6 @@ static int do_ccw_entry(const char *filename, return 1; } -/* looks like: "ap:tN" */ -static int do_ap_entry(const char *filename, - struct ap_device_id *id, char *alias) -{ - sprintf(alias, "ap:t%02X", id->dev_type); - return 1; -} - /* Looks like: "serio:tyNprNidNexN" */ static int do_serio_entry(const char *filename, struct serio_device_id *id, char *alias) @@ -399,7 +376,7 @@ static void do_input(char *alias, unsigned int i; for (i = min; i < max; i++) - if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG))) + if (arr[i / BITS_PER_LONG] & (1 << (i%BITS_PER_LONG))) sprintf(alias + strlen(alias), "%X,*", i); } @@ -457,7 +434,6 @@ static inline int sym_is(const char *symbol, const char *name) static void do_table(void *symval, unsigned long size, unsigned long id_size, - const char *device_id, void *function, struct module *mod) { @@ -465,7 +441,10 @@ static void do_table(void *symval, unsigned long size, char alias[500]; int (*do_entry)(const char *, void *entry, char *alias) = function; - device_id_size_check(mod->name, device_id, size, id_size); + if (size % id_size || size < id_size) { + warn("%s ids %lu bad size " + "(each on %lu)\n", mod->name, size, id_size); + } /* Leave last one: it's the terminator. */ size -= id_size; @@ -497,55 +476,40 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, + sym->st_value; if (sym_is(symname, "__mod_pci_device_table")) - do_table(symval, sym->st_size, - sizeof(struct pci_device_id), "pci", + do_table(symval, sym->st_size, sizeof(struct pci_device_id), do_pci_entry, mod); else if (sym_is(symname, "__mod_usb_device_table")) /* special case to handle bcdDevice ranges */ do_usb_table(symval, sym->st_size, mod); else if (sym_is(symname, "__mod_ieee1394_device_table")) - do_table(symval, sym->st_size, - sizeof(struct ieee1394_device_id), "ieee1394", + do_table(symval, sym->st_size, sizeof(struct ieee1394_device_id), do_ieee1394_entry, mod); else if (sym_is(symname, "__mod_ccw_device_table")) - do_table(symval, sym->st_size, - sizeof(struct ccw_device_id), "ccw", + do_table(symval, sym->st_size, sizeof(struct ccw_device_id), do_ccw_entry, mod); - else if (sym_is(symname, "__mod_ap_device_table")) - do_table(symval, sym->st_size, - sizeof(struct ap_device_id), "ap", - do_ap_entry, mod); else if (sym_is(symname, "__mod_serio_device_table")) - do_table(symval, sym->st_size, - sizeof(struct serio_device_id), "serio", + do_table(symval, sym->st_size, sizeof(struct serio_device_id), do_serio_entry, mod); else if (sym_is(symname, "__mod_pnp_device_table")) - do_table(symval, sym->st_size, - sizeof(struct pnp_device_id), "pnp", + do_table(symval, sym->st_size, sizeof(struct pnp_device_id), do_pnp_entry, mod); else if (sym_is(symname, "__mod_pnp_card_device_table")) - do_table(symval, sym->st_size, - sizeof(struct pnp_card_device_id), "pnp_card", + do_table(symval, sym->st_size, sizeof(struct pnp_card_device_id), do_pnp_card_entry, mod); else if (sym_is(symname, "__mod_pcmcia_device_table")) - do_table(symval, sym->st_size, - sizeof(struct pcmcia_device_id), "pcmcia", + do_table(symval, sym->st_size, sizeof(struct pcmcia_device_id), do_pcmcia_entry, mod); else if (sym_is(symname, "__mod_of_device_table")) - do_table(symval, sym->st_size, - sizeof(struct of_device_id), "of", + do_table(symval, sym->st_size, sizeof(struct of_device_id), do_of_entry, mod); else if (sym_is(symname, "__mod_vio_device_table")) - do_table(symval, sym->st_size, - sizeof(struct vio_device_id), "vio", + do_table(symval, sym->st_size, sizeof(struct vio_device_id), do_vio_entry, mod); else if (sym_is(symname, "__mod_i2c_device_table")) - do_table(symval, sym->st_size, - sizeof(struct i2c_device_id), "i2c", + do_table(symval, sym->st_size, sizeof(struct i2c_device_id), do_i2c_entry, mod); else if (sym_is(symname, "__mod_input_device_table")) - do_table(symval, sym->st_size, - sizeof(struct input_device_id), "input", + do_table(symval, sym->st_size, sizeof(struct input_device_id), do_input_entry, mod); } diff --git a/trunk/security/dummy.c b/trunk/security/dummy.c index aeee70565509..bbbfda70e131 100644 --- a/trunk/security/dummy.c +++ b/trunk/security/dummy.c @@ -709,10 +709,10 @@ static int dummy_socket_create (int family, int type, return 0; } -static int dummy_socket_post_create (struct socket *sock, int family, int type, - int protocol, int kern) +static void dummy_socket_post_create (struct socket *sock, int family, int type, + int protocol, int kern) { - return 0; + return; } static int dummy_socket_bind (struct socket *sock, struct sockaddr *address, @@ -791,7 +791,8 @@ static int dummy_socket_getpeersec_stream(struct socket *sock, char __user *optv return -ENOPROTOOPT; } -static int dummy_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) +static int dummy_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, + u32 *seclen) { return -ENOPROTOOPT; } @@ -805,38 +806,14 @@ static inline void dummy_sk_free_security (struct sock *sk) { } -static inline void dummy_sk_clone_security (const struct sock *sk, struct sock *newsk) -{ -} - -static inline void dummy_sk_getsecid(struct sock *sk, u32 *secid) -{ -} - -static inline void dummy_sock_graft(struct sock* sk, struct socket *parent) -{ -} - -static inline int dummy_inet_conn_request(struct sock *sk, - struct sk_buff *skb, struct request_sock *req) +static unsigned int dummy_sk_getsid(struct sock *sk, struct flowi *fl, u8 dir) { return 0; } - -static inline void dummy_inet_csk_clone(struct sock *newsk, - const struct request_sock *req) -{ -} - -static inline void dummy_req_classify_flow(const struct request_sock *req, - struct flowi *fl) -{ -} #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM -static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp, - struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk) +static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx) { return 0; } @@ -855,8 +832,7 @@ static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp) return 0; } -static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, - struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *pol, u32 secid) +static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) { return 0; } @@ -874,23 +850,6 @@ static int dummy_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir) { return 0; } - -static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x, - struct xfrm_policy *xp, struct flowi *fl) -{ - return 1; -} - -static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm) -{ - return 1; -} - -static int dummy_xfrm_decode_session(struct sk_buff *skb, u32 *fl, int ckall) -{ - return 0; -} - #endif /* CONFIG_SECURITY_NETWORK_XFRM */ static int dummy_register_security (const char *name, struct security_operations *ops) { @@ -917,15 +876,6 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz return -EINVAL; } -static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) -{ - return -EOPNOTSUPP; -} - -static void dummy_release_secctx(char *secdata, u32 seclen) -{ -} - #ifdef CONFIG_KEYS static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx, unsigned long flags) @@ -1078,8 +1028,6 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, d_instantiate); set_to_dummy_if_null(ops, getprocattr); set_to_dummy_if_null(ops, setprocattr); - set_to_dummy_if_null(ops, secid_to_secctx); - set_to_dummy_if_null(ops, release_secctx); #ifdef CONFIG_SECURITY_NETWORK set_to_dummy_if_null(ops, unix_stream_connect); set_to_dummy_if_null(ops, unix_may_send); @@ -1102,12 +1050,7 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, socket_getpeersec_dgram); set_to_dummy_if_null(ops, sk_alloc_security); set_to_dummy_if_null(ops, sk_free_security); - set_to_dummy_if_null(ops, sk_clone_security); - set_to_dummy_if_null(ops, sk_getsecid); - set_to_dummy_if_null(ops, sock_graft); - set_to_dummy_if_null(ops, inet_conn_request); - set_to_dummy_if_null(ops, inet_csk_clone); - set_to_dummy_if_null(ops, req_classify_flow); + set_to_dummy_if_null(ops, sk_getsid); #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_NETWORK_XFRM set_to_dummy_if_null(ops, xfrm_policy_alloc_security); @@ -1118,9 +1061,6 @@ void security_fixup_ops (struct security_operations *ops) set_to_dummy_if_null(ops, xfrm_state_free_security); set_to_dummy_if_null(ops, xfrm_state_delete_security); set_to_dummy_if_null(ops, xfrm_policy_lookup); - set_to_dummy_if_null(ops, xfrm_state_pol_flow_match); - set_to_dummy_if_null(ops, xfrm_flow_state_match); - set_to_dummy_if_null(ops, xfrm_decode_session); #endif /* CONFIG_SECURITY_NETWORK_XFRM */ #ifdef CONFIG_KEYS set_to_dummy_if_null(ops, key_alloc); diff --git a/trunk/security/seclvl.c b/trunk/security/seclvl.c index 8f6291991fbc..c26dd7de0471 100644 --- a/trunk/security/seclvl.c +++ b/trunk/security/seclvl.c @@ -16,7 +16,6 @@ * (at your option) any later version. */ -#include #include #include #include @@ -198,27 +197,26 @@ static unsigned char hashedPassword[SHA1_DIGEST_SIZE]; static int plaintext_to_sha1(unsigned char *hash, const char *plaintext, unsigned int len) { - struct hash_desc desc; + struct crypto_tfm *tfm; struct scatterlist sg; - int err; - if (len > PAGE_SIZE) { seclvl_printk(0, KERN_ERR, "Plaintext password too large (%d " "characters). Largest possible is %lu " "bytes.\n", len, PAGE_SIZE); return -EINVAL; } - desc.tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(desc.tfm)) { + tfm = crypto_alloc_tfm("sha1", CRYPTO_TFM_REQ_MAY_SLEEP); + if (tfm == NULL) { seclvl_printk(0, KERN_ERR, "Failed to load transform for SHA1\n"); return -EINVAL; } sg_init_one(&sg, (u8 *)plaintext, len); - desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; - err = crypto_hash_digest(&desc, &sg, len, hash); - crypto_free_hash(desc.tfm); - return err; + crypto_digest_init(tfm); + crypto_digest_update(tfm, &sg, 1); + crypto_digest_final(tfm, hash); + crypto_free_tfm(tfm); + return 0; } /** diff --git a/trunk/security/selinux/hooks.c b/trunk/security/selinux/hooks.c index 5a66c4c09f7a..a91c961ba38b 100644 --- a/trunk/security/selinux/hooks.c +++ b/trunk/security/selinux/hooks.c @@ -12,8 +12,6 @@ * Copyright (C) 2003 Red Hat, Inc., James Morris * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. * - * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. - * Paul Moore, * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -76,7 +74,6 @@ #include "objsec.h" #include "netif.h" #include "xfrm.h" -#include "selinux_netlabel.h" #define XATTR_SELINUX_SUFFIX "selinux" #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX @@ -272,17 +269,17 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) { struct sk_security_struct *ssec; + if (family != PF_UNIX) + return 0; + ssec = kzalloc(sizeof(*ssec), priority); if (!ssec) return -ENOMEM; ssec->sk = sk; ssec->peer_sid = SECINITSID_UNLABELED; - ssec->sid = SECINITSID_UNLABELED; sk->sk_security = ssec; - selinux_netlbl_sk_security_init(ssec, family); - return 0; } @@ -290,6 +287,9 @@ static void sk_free_security(struct sock *sk) { struct sk_security_struct *ssec = sk->sk_security; + if (sk->sk_family != PF_UNIX) + return; + sk->sk_security = NULL; kfree(ssec); } @@ -2400,7 +2400,6 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t static int selinux_file_permission(struct file *file, int mask) { - int rc; struct inode *inode = file->f_dentry->d_inode; if (!mask) { @@ -2412,12 +2411,8 @@ static int selinux_file_permission(struct file *file, int mask) if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) mask |= MAY_APPEND; - rc = file_has_perm(current, file, - file_mask_to_av(inode->i_mode, mask)); - if (rc) - return rc; - - return selinux_netlbl_inode_permission(inode, mask); + return file_has_perm(current, file, + file_mask_to_av(inode->i_mode, mask)); } static int selinux_file_alloc_security(struct file *file) @@ -3068,13 +3063,11 @@ static int selinux_socket_create(int family, int type, return err; } -static int selinux_socket_post_create(struct socket *sock, int family, - int type, int protocol, int kern) +static void selinux_socket_post_create(struct socket *sock, int family, + int type, int protocol, int kern) { - int err = 0; struct inode_security_struct *isec; struct task_security_struct *tsec; - struct sk_security_struct *sksec; u32 newsid; isec = SOCK_INODE(sock)->i_security; @@ -3085,15 +3078,7 @@ static int selinux_socket_post_create(struct socket *sock, int family, isec->sid = kern ? SECINITSID_KERNEL : newsid; isec->initialized = 1; - if (sock->sk) { - sksec = sock->sk->sk_security; - sksec->sid = isec->sid; - err = selinux_netlbl_socket_post_create(sock, - family, - isec->sid); - } - - return err; + return; } /* Range of port numbers used to automatically bind. @@ -3274,13 +3259,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) { - int rc; - - rc = socket_has_perm(current, sock, SOCKET__WRITE); - if (rc) - return rc; - - return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE); + return socket_has_perm(current, sock, SOCKET__WRITE); } static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, @@ -3348,9 +3327,8 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, /* server child socket */ ssec = newsk->sk_security; ssec->peer_sid = isec->sid; - err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid); - - return err; + + return 0; } static int selinux_socket_unix_may_send(struct socket *sock, @@ -3376,29 +3354,11 @@ static int selinux_socket_unix_may_send(struct socket *sock, } static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, - struct avc_audit_data *ad, u16 family, char *addrp, int len) + struct avc_audit_data *ad, u32 sock_sid, u16 sock_class, + u16 family, char *addrp, int len) { int err = 0; u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0; - struct socket *sock; - u16 sock_class = 0; - u32 sock_sid = 0; - - read_lock_bh(&sk->sk_callback_lock); - sock = sk->sk_socket; - if (sock) { - struct inode *inode; - inode = SOCK_INODE(sock); - if (inode) { - struct inode_security_struct *isec; - isec = inode->i_security; - sock_sid = isec->sid; - sock_class = isec->sclass; - } - } - read_unlock_bh(&sk->sk_callback_lock); - if (!sock_sid) - goto out; if (!skb->dev) goto out; @@ -3458,10 +3418,12 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { u16 family; + u16 sock_class = 0; char *addrp; int len, err = 0; + u32 sock_sid = 0; + struct socket *sock; struct avc_audit_data ad; - struct sk_security_struct *sksec = sk->sk_security; family = sk->sk_family; if (family != PF_INET && family != PF_INET6) @@ -3471,6 +3433,22 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP)) family = PF_INET; + read_lock_bh(&sk->sk_callback_lock); + sock = sk->sk_socket; + if (sock) { + struct inode *inode; + inode = SOCK_INODE(sock); + if (inode) { + struct inode_security_struct *isec; + isec = inode->i_security; + sock_sid = isec->sid; + sock_class = isec->sclass; + } + } + read_unlock_bh(&sk->sk_callback_lock); + if (!sock_sid) + goto out; + AVC_AUDIT_DATA_INIT(&ad, NET); ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; ad.u.net.family = family; @@ -3480,19 +3458,16 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) goto out; if (selinux_compat_net) - err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family, + err = selinux_sock_rcv_skb_compat(sk, skb, &ad, sock_sid, + sock_class, family, addrp, len); else - err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET, + err = avc_has_perm(sock_sid, skb->secmark, SECCLASS_PACKET, PACKET__RECV, &ad); if (err) goto out; - err = selinux_netlbl_sock_rcv_skb(sksec, skb, &ad); - if (err) - goto out; - - err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad); + err = selinux_xfrm_sock_rcv_skb(sock_sid, skb); out: return err; } @@ -3515,9 +3490,8 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op peer_sid = ssec->peer_sid; } else if (isec->sclass == SECCLASS_TCP_SOCKET) { - peer_sid = selinux_netlbl_socket_getpeersec_stream(sock); - if (peer_sid == SECSID_NULL) - peer_sid = selinux_socket_getpeer_stream(sock->sk); + peer_sid = selinux_socket_getpeer_stream(sock->sk); + if (peer_sid == SECSID_NULL) { err = -ENOPROTOOPT; goto out; @@ -3550,24 +3524,25 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op return err; } -static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) +static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen) { - u32 peer_secid = SECSID_NULL; int err = 0; + u32 peer_sid; - if (sock && (sock->sk->sk_family == PF_UNIX)) - selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); - else if (skb) { - peer_secid = selinux_netlbl_socket_getpeersec_dgram(skb); - if (peer_secid == SECSID_NULL) - peer_secid = selinux_socket_getpeer_dgram(skb); - } + if (skb->sk->sk_family == PF_UNIX) + selinux_get_inode_sid(SOCK_INODE(skb->sk->sk_socket), + &peer_sid); + else + peer_sid = selinux_socket_getpeer_dgram(skb); - if (peer_secid == SECSID_NULL) - err = -EINVAL; - *secid = peer_secid; + if (peer_sid == SECSID_NULL) + return -EINVAL; - return err; + err = security_sid_to_context(peer_sid, secdata, seclen); + if (err) + return err; + + return 0; } static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) @@ -3580,86 +3555,22 @@ static void selinux_sk_free_security(struct sock *sk) sk_free_security(sk); } -static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) +static unsigned int selinux_sk_getsid_security(struct sock *sk, struct flowi *fl, u8 dir) { - struct sk_security_struct *ssec = sk->sk_security; - struct sk_security_struct *newssec = newsk->sk_security; - - newssec->sid = ssec->sid; - newssec->peer_sid = ssec->peer_sid; - - selinux_netlbl_sk_clone_security(ssec, newssec); -} + struct inode_security_struct *isec; + u32 sock_sid = SECINITSID_ANY_SOCKET; -static void selinux_sk_getsecid(struct sock *sk, u32 *secid) -{ if (!sk) - *secid = SECINITSID_ANY_SOCKET; - else { - struct sk_security_struct *sksec = sk->sk_security; - - *secid = sksec->sid; - } -} - -static void selinux_sock_graft(struct sock* sk, struct socket *parent) -{ - struct inode_security_struct *isec = SOCK_INODE(parent)->i_security; - struct sk_security_struct *sksec = sk->sk_security; - - isec->sid = sksec->sid; - - selinux_netlbl_sock_graft(sk, parent); -} - -static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, - struct request_sock *req) -{ - struct sk_security_struct *sksec = sk->sk_security; - int err; - u32 newsid; - u32 peersid; - - newsid = selinux_netlbl_inet_conn_request(skb, sksec->sid); - if (newsid != SECSID_NULL) { - req->secid = newsid; - return 0; - } - - err = selinux_xfrm_decode_session(skb, &peersid, 0); - BUG_ON(err); - - if (peersid == SECSID_NULL) { - req->secid = sksec->sid; - return 0; - } - - err = security_sid_mls_copy(sksec->sid, peersid, &newsid); - if (err) - return err; - - req->secid = newsid; - return 0; -} - -static void selinux_inet_csk_clone(struct sock *newsk, - const struct request_sock *req) -{ - struct sk_security_struct *newsksec = newsk->sk_security; + return selinux_no_sk_sid(fl); - newsksec->sid = req->secid; - /* NOTE: Ideally, we should also get the isec->sid for the - new socket in sync, but we don't have the isec available yet. - So we will wait until sock_graft to do it, by which - time it will have been created and available. */ + read_lock_bh(&sk->sk_callback_lock); + isec = get_sock_isec(sk); - selinux_netlbl_sk_security_init(newsksec, req->rsk_ops->family); -} + if (isec) + sock_sid = isec->sid; -static void selinux_req_classify_flow(const struct request_sock *req, - struct flowi *fl) -{ - fl->secid = req->secid; + read_unlock_bh(&sk->sk_callback_lock); + return sock_sid; } static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) @@ -3701,24 +3612,12 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) #ifdef CONFIG_NETFILTER static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev, + struct inode_security_struct *isec, struct avc_audit_data *ad, u16 family, char *addrp, int len) { - int err = 0; + int err; u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0; - struct socket *sock; - struct inode *inode; - struct inode_security_struct *isec; - - sock = sk->sk_socket; - if (!sock) - goto out; - - inode = SOCK_INODE(sock); - if (!inode) - goto out; - - isec = inode->i_security; err = sel_netif_sids(dev, &if_sid, NULL); if (err) @@ -3783,16 +3682,26 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, char *addrp; int len, err = 0; struct sock *sk; + struct socket *sock; + struct inode *inode; struct sk_buff *skb = *pskb; + struct inode_security_struct *isec; struct avc_audit_data ad; struct net_device *dev = (struct net_device *)out; - struct sk_security_struct *sksec; sk = skb->sk; if (!sk) goto out; - sksec = sk->sk_security; + sock = sk->sk_socket; + if (!sock) + goto out; + + inode = SOCK_INODE(sock); + if (!inode) + goto out; + + isec = inode->i_security; AVC_AUDIT_DATA_INIT(&ad, NET); ad.u.net.netif = dev->name; @@ -3803,16 +3712,16 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, goto out; if (selinux_compat_net) - err = selinux_ip_postroute_last_compat(sk, dev, &ad, + err = selinux_ip_postroute_last_compat(sk, dev, isec, &ad, family, addrp, len); else - err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET, + err = avc_has_perm(isec->sid, skb->secmark, SECCLASS_PACKET, PACKET__SEND, &ad); if (err) goto out; - err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad); + err = selinux_xfrm_postroute_last(isec->sid, skb); out: return err ? NF_DROP : NF_ACCEPT; } @@ -4498,17 +4407,6 @@ static int selinux_setprocattr(struct task_struct *p, return size; } -static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) -{ - return security_sid_to_context(secid, secdata, seclen); -} - -static void selinux_release_secctx(char *secdata, u32 seclen) -{ - if (secdata) - kfree(secdata); -} - #ifdef CONFIG_KEYS static int selinux_key_alloc(struct key *k, struct task_struct *tsk, @@ -4689,9 +4587,6 @@ static struct security_operations selinux_ops = { .getprocattr = selinux_getprocattr, .setprocattr = selinux_setprocattr, - .secid_to_secctx = selinux_secid_to_secctx, - .release_secctx = selinux_release_secctx, - .unix_stream_connect = selinux_socket_unix_stream_connect, .unix_may_send = selinux_socket_unix_may_send, @@ -4713,12 +4608,7 @@ static struct security_operations selinux_ops = { .socket_getpeersec_dgram = selinux_socket_getpeersec_dgram, .sk_alloc_security = selinux_sk_alloc_security, .sk_free_security = selinux_sk_free_security, - .sk_clone_security = selinux_sk_clone_security, - .sk_getsecid = selinux_sk_getsecid, - .sock_graft = selinux_sock_graft, - .inet_conn_request = selinux_inet_conn_request, - .inet_csk_clone = selinux_inet_csk_clone, - .req_classify_flow = selinux_req_classify_flow, + .sk_getsid = selinux_sk_getsid_security, #ifdef CONFIG_SECURITY_NETWORK_XFRM .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, @@ -4729,9 +4619,6 @@ static struct security_operations selinux_ops = { .xfrm_state_free_security = selinux_xfrm_state_free, .xfrm_state_delete_security = selinux_xfrm_state_delete, .xfrm_policy_lookup = selinux_xfrm_policy_lookup, - .xfrm_state_pol_flow_match = selinux_xfrm_state_pol_flow_match, - .xfrm_flow_state_match = selinux_xfrm_flow_state_match, - .xfrm_decode_session = selinux_xfrm_decode_session, #endif #ifdef CONFIG_KEYS diff --git a/trunk/security/selinux/include/av_perm_to_string.h b/trunk/security/selinux/include/av_perm_to_string.h index 09fc8a2345eb..7c9b58380833 100644 --- a/trunk/security/selinux/include/av_perm_to_string.h +++ b/trunk/security/selinux/include/av_perm_to_string.h @@ -241,7 +241,6 @@ S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto") S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom") S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext") - S_(SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, "polmatch") S_(SECCLASS_PACKET, PACKET__SEND, "send") S_(SECCLASS_PACKET, PACKET__RECV, "recv") S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto") diff --git a/trunk/security/selinux/include/av_permissions.h b/trunk/security/selinux/include/av_permissions.h index 81f4f526c8b1..69fd4b48202c 100644 --- a/trunk/security/selinux/include/av_permissions.h +++ b/trunk/security/selinux/include/av_permissions.h @@ -911,7 +911,6 @@ #define ASSOCIATION__SENDTO 0x00000001UL #define ASSOCIATION__RECVFROM 0x00000002UL #define ASSOCIATION__SETCONTEXT 0x00000004UL -#define ASSOCIATION__POLMATCH 0x00000008UL #define NETLINK_KOBJECT_UEVENT_SOCKET__IOCTL 0x00000001UL #define NETLINK_KOBJECT_UEVENT_SOCKET__READ 0x00000002UL diff --git a/trunk/security/selinux/include/objsec.h b/trunk/security/selinux/include/objsec.h index 0a39bfd1319f..940178865fc7 100644 --- a/trunk/security/selinux/include/objsec.h +++ b/trunk/security/selinux/include/objsec.h @@ -99,16 +99,7 @@ struct netif_security_struct { struct sk_security_struct { struct sock *sk; /* back pointer to sk object */ - u32 sid; /* SID of this object */ u32 peer_sid; /* SID of peer */ -#ifdef CONFIG_NETLABEL - u16 sclass; /* sock security class */ - enum { /* NetLabel state */ - NLBL_UNSET = 0, - NLBL_REQUIRE, - NLBL_LABELED, - } nlbl_state; -#endif }; struct key_security_struct { diff --git a/trunk/security/selinux/include/security.h b/trunk/security/selinux/include/security.h index 911954a692fa..063af47bb231 100644 --- a/trunk/security/selinux/include/security.h +++ b/trunk/security/selinux/include/security.h @@ -78,8 +78,6 @@ int security_node_sid(u16 domain, void *addr, u32 addrlen, int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, u16 tclass); -int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid); - #define SECURITY_FS_USE_XATTR 1 /* use xattr */ #define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ #define SECURITY_FS_USE_TASK 3 /* use task SIDs, e.g. pipefs/sockfs */ diff --git a/trunk/security/selinux/include/selinux_netlabel.h b/trunk/security/selinux/include/selinux_netlabel.h deleted file mode 100644 index ecab4bddaaf4..000000000000 --- a/trunk/security/selinux/include/selinux_netlabel.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * SELinux interface to the NetLabel subsystem - * - * Author : Paul Moore - * - */ - -/* - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef _SELINUX_NETLABEL_H_ -#define _SELINUX_NETLABEL_H_ - -#include -#include -#include -#include -#include - -#include "avc.h" -#include "objsec.h" - -#ifdef CONFIG_NETLABEL -void selinux_netlbl_cache_invalidate(void); -int selinux_netlbl_socket_post_create(struct socket *sock, - int sock_family, - u32 sid); -void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); -u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid); -int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, - struct sk_buff *skb, - struct avc_audit_data *ad); -u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock); -u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb); -void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, - int family); -void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, - struct sk_security_struct *newssec); -int selinux_netlbl_inode_permission(struct inode *inode, int mask); -#else -static inline void selinux_netlbl_cache_invalidate(void) -{ - return; -} - -static inline int selinux_netlbl_socket_post_create(struct socket *sock, - int sock_family, - u32 sid) -{ - return 0; -} - -static inline void selinux_netlbl_sock_graft(struct sock *sk, - struct socket *sock) -{ - return; -} - -static inline u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, - u32 sock_sid) -{ - return SECSID_NULL; -} - -static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, - struct sk_buff *skb, - struct avc_audit_data *ad) -{ - return 0; -} - -static inline u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) -{ - return SECSID_NULL; -} - -static inline u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb) -{ - return SECSID_NULL; -} - -static inline void selinux_netlbl_sk_security_init( - struct sk_security_struct *ssec, - int family) -{ - return; -} - -static inline void selinux_netlbl_sk_clone_security( - struct sk_security_struct *ssec, - struct sk_security_struct *newssec) -{ - return; -} - -static inline int selinux_netlbl_inode_permission(struct inode *inode, - int mask) -{ - return 0; -} -#endif /* CONFIG_NETLABEL */ - -#endif diff --git a/trunk/security/selinux/include/xfrm.h b/trunk/security/selinux/include/xfrm.h index 81eb59890162..c96498a10eb8 100644 --- a/trunk/security/selinux/include/xfrm.h +++ b/trunk/security/selinux/include/xfrm.h @@ -2,25 +2,18 @@ * SELinux support for the XFRM LSM hooks * * Author : Trent Jaeger, - * Updated : Venkat Yekkirala, */ #ifndef _SELINUX_XFRM_H_ #define _SELINUX_XFRM_H_ -int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, - struct xfrm_user_sec_ctx *sec_ctx, struct sock *sk); +int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx); int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new); void selinux_xfrm_policy_free(struct xfrm_policy *xp); int selinux_xfrm_policy_delete(struct xfrm_policy *xp); -int selinux_xfrm_state_alloc(struct xfrm_state *x, - struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_sec_ctx *pol, u32 secid); +int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx); void selinux_xfrm_state_free(struct xfrm_state *x); int selinux_xfrm_state_delete(struct xfrm_state *x); -int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir); -int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, - struct xfrm_policy *xp, struct flowi *fl); -int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm); - +int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir); /* * Extract the security blob from the sock (it's actually on the socket) @@ -33,23 +26,30 @@ static inline struct inode_security_struct *get_sock_isec(struct sock *sk) return SOCK_INODE(sk->sk_socket)->i_security; } + +static inline u32 selinux_no_sk_sid(struct flowi *fl) +{ + /* NOTE: no sock occurs on ICMP reply, forwards, ... */ + /* icmp_reply: authorize as kernel packet */ + if (fl && fl->proto == IPPROTO_ICMP) { + return SECINITSID_KERNEL; + } + + return SECINITSID_ANY_SOCKET; +} + #ifdef CONFIG_SECURITY_NETWORK_XFRM -int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, - struct avc_audit_data *ad); -int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, - struct avc_audit_data *ad); +int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb); +int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb); u32 selinux_socket_getpeer_stream(struct sock *sk); u32 selinux_socket_getpeer_dgram(struct sk_buff *skb); -int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); #else -static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, - struct avc_audit_data *ad) +static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb) { return 0; } -static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, - struct avc_audit_data *ad) +static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb) { return 0; } @@ -63,11 +63,6 @@ static inline int selinux_socket_getpeer_dgram(struct sk_buff *skb) { return SECSID_NULL; } -static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) -{ - *sid = SECSID_NULL; - return 0; -} #endif #endif /* _SELINUX_XFRM_H_ */ diff --git a/trunk/security/selinux/ss/ebitmap.c b/trunk/security/selinux/ss/ebitmap.c index cfed1d30fa6a..47024a6e1844 100644 --- a/trunk/security/selinux/ss/ebitmap.c +++ b/trunk/security/selinux/ss/ebitmap.c @@ -3,14 +3,6 @@ * * Author : Stephen Smalley, */ -/* - * Updated: Hewlett-Packard - * - * Added ebitmap_export() and ebitmap_import() - * - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - */ - #include #include #include @@ -67,138 +59,6 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src) return 0; } -/** - * ebitmap_export - Export an ebitmap to a unsigned char bitmap string - * @src: the ebitmap to export - * @dst: the resulting bitmap string - * @dst_len: length of dst in bytes - * - * Description: - * Allocate a buffer at least src->highbit bits long and export the extensible - * bitmap into the buffer. The bitmap string will be in little endian format, - * i.e. LSB first. The value returned in dst_len may not the true size of the - * buffer as the length of the buffer is rounded up to a multiple of MAPTYPE. - * The caller must free the buffer when finished. Returns zero on success, - * negative values on failure. - * - */ -int ebitmap_export(const struct ebitmap *src, - unsigned char **dst, - size_t *dst_len) -{ - size_t bitmap_len; - unsigned char *bitmap; - struct ebitmap_node *iter_node; - MAPTYPE node_val; - size_t bitmap_byte; - unsigned char bitmask; - - bitmap_len = src->highbit / 8; - if (src->highbit % 7) - bitmap_len += 1; - if (bitmap_len == 0) - return -EINVAL; - - bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) + - sizeof(MAPTYPE), - GFP_ATOMIC); - if (bitmap == NULL) - return -ENOMEM; - - iter_node = src->node; - do { - bitmap_byte = iter_node->startbit / 8; - bitmask = 0x80; - node_val = iter_node->map; - do { - if (bitmask == 0) { - bitmap_byte++; - bitmask = 0x80; - } - if (node_val & (MAPTYPE)0x01) - bitmap[bitmap_byte] |= bitmask; - node_val >>= 1; - bitmask >>= 1; - } while (node_val > 0); - iter_node = iter_node->next; - } while (iter_node); - - *dst = bitmap; - *dst_len = bitmap_len; - return 0; -} - -/** - * ebitmap_import - Import an unsigned char bitmap string into an ebitmap - * @src: the bitmap string - * @src_len: the bitmap length in bytes - * @dst: the empty ebitmap - * - * Description: - * This function takes a little endian bitmap string in src and imports it into - * the ebitmap pointed to by dst. Returns zero on success, negative values on - * failure. - * - */ -int ebitmap_import(const unsigned char *src, - size_t src_len, - struct ebitmap *dst) -{ - size_t src_off = 0; - size_t node_limit; - struct ebitmap_node *node_new; - struct ebitmap_node *node_last = NULL; - u32 i_byte; - u32 i_bit; - unsigned char src_byte; - - while (src_off < src_len) { - if (src_len - src_off >= sizeof(MAPTYPE)) { - if (*(MAPTYPE *)&src[src_off] == 0) { - src_off += sizeof(MAPTYPE); - continue; - } - node_limit = sizeof(MAPTYPE); - } else { - for (src_byte = 0, i_byte = src_off; - i_byte < src_len && src_byte == 0; - i_byte++) - src_byte |= src[i_byte]; - if (src_byte == 0) - break; - node_limit = src_len - src_off; - } - - node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC); - if (unlikely(node_new == NULL)) { - ebitmap_destroy(dst); - return -ENOMEM; - } - node_new->startbit = src_off * 8; - for (i_byte = 0; i_byte < node_limit; i_byte++) { - src_byte = src[src_off++]; - for (i_bit = i_byte * 8; src_byte != 0; i_bit++) { - if (src_byte & 0x80) - node_new->map |= MAPBIT << i_bit; - src_byte <<= 1; - } - } - - if (node_last != NULL) - node_last->next = node_new; - else - dst->node = node_new; - node_last = node_new; - } - - if (likely(node_last != NULL)) - dst->highbit = node_last->startbit + MAPSIZE; - else - ebitmap_init(dst); - - return 0; -} - int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) { struct ebitmap_node *n1, *n2; diff --git a/trunk/security/selinux/ss/ebitmap.h b/trunk/security/selinux/ss/ebitmap.h index da2d4651b10d..8bf41055a6cb 100644 --- a/trunk/security/selinux/ss/ebitmap.h +++ b/trunk/security/selinux/ss/ebitmap.h @@ -69,12 +69,6 @@ static inline int ebitmap_node_get_bit(struct ebitmap_node * n, int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); -int ebitmap_export(const struct ebitmap *src, - unsigned char **dst, - size_t *dst_len); -int ebitmap_import(const unsigned char *src, - size_t src_len, - struct ebitmap *dst); int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); int ebitmap_get_bit(struct ebitmap *e, unsigned long bit); int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value); diff --git a/trunk/security/selinux/ss/mls.c b/trunk/security/selinux/ss/mls.c index 119bd6078ba1..7bc5b6440f70 100644 --- a/trunk/security/selinux/ss/mls.c +++ b/trunk/security/selinux/ss/mls.c @@ -10,13 +10,6 @@ * * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. */ -/* - * Updated: Hewlett-Packard - * - * Added support to import/export the MLS label - * - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - */ #include #include @@ -218,6 +211,26 @@ int mls_context_isvalid(struct policydb *p, struct context *c) return 1; } +/* + * Copies the MLS range from `src' into `dst'. + */ +static inline int mls_copy_context(struct context *dst, + struct context *src) +{ + int l, rc = 0; + + /* Copy the MLS range from the source context */ + for (l = 0; l < 2; l++) { + dst->range.level[l].sens = src->range.level[l].sens; + rc = ebitmap_cpy(&dst->range.level[l].cat, + &src->range.level[l].cat); + if (rc) + break; + } + + return rc; +} + /* * Set the MLS fields in the security context structure * `context' based on the string representation in @@ -572,152 +585,3 @@ int mls_compute_sid(struct context *scontext, return -EINVAL; } -/** - * mls_export_lvl - Export the MLS sensitivity levels - * @context: the security context - * @low: the low sensitivity level - * @high: the high sensitivity level - * - * Description: - * Given the security context copy the low MLS sensitivity level into lvl_low - * and the high sensitivity level in lvl_high. The MLS levels are only - * exported if the pointers are not NULL, if they are NULL then that level is - * not exported. - * - */ -void mls_export_lvl(const struct context *context, u32 *low, u32 *high) -{ - if (!selinux_mls_enabled) - return; - - if (low != NULL) - *low = context->range.level[0].sens - 1; - if (high != NULL) - *high = context->range.level[1].sens - 1; -} - -/** - * mls_import_lvl - Import the MLS sensitivity levels - * @context: the security context - * @low: the low sensitivity level - * @high: the high sensitivity level - * - * Description: - * Given the security context and the two sensitivty levels, set the MLS levels - * in the context according the two given as parameters. Returns zero on - * success, negative values on failure. - * - */ -void mls_import_lvl(struct context *context, u32 low, u32 high) -{ - if (!selinux_mls_enabled) - return; - - context->range.level[0].sens = low + 1; - context->range.level[1].sens = high + 1; -} - -/** - * mls_export_cat - Export the MLS categories - * @context: the security context - * @low: the low category - * @low_len: length of the cat_low bitmap in bytes - * @high: the high category - * @high_len: length of the cat_high bitmap in bytes - * - * Description: - * Given the security context export the low MLS category bitmap into cat_low - * and the high category bitmap into cat_high. The MLS categories are only - * exported if the pointers are not NULL, if they are NULL then that level is - * not exported. The caller is responsibile for freeing the memory when - * finished. Returns zero on success, negative values on failure. - * - */ -int mls_export_cat(const struct context *context, - unsigned char **low, - size_t *low_len, - unsigned char **high, - size_t *high_len) -{ - int rc = -EPERM; - - if (!selinux_mls_enabled) - return 0; - - if (low != NULL) { - rc = ebitmap_export(&context->range.level[0].cat, - low, - low_len); - if (rc != 0) - goto export_cat_failure; - } - if (high != NULL) { - rc = ebitmap_export(&context->range.level[1].cat, - high, - high_len); - if (rc != 0) - goto export_cat_failure; - } - - return 0; - -export_cat_failure: - if (low != NULL) - kfree(*low); - if (high != NULL) - kfree(*high); - return rc; -} - -/** - * mls_import_cat - Import the MLS categories - * @context: the security context - * @low: the low category - * @low_len: length of the cat_low bitmap in bytes - * @high: the high category - * @high_len: length of the cat_high bitmap in bytes - * - * Description: - * Given the security context and the two category bitmap strings import the - * categories into the security context. The MLS categories are only imported - * if the pointers are not NULL, if they are NULL they are skipped. Returns - * zero on success, negative values on failure. - * - */ -int mls_import_cat(struct context *context, - const unsigned char *low, - size_t low_len, - const unsigned char *high, - size_t high_len) -{ - int rc = -EPERM; - - if (!selinux_mls_enabled) - return 0; - - if (low != NULL) { - rc = ebitmap_import(low, - low_len, - &context->range.level[0].cat); - if (rc != 0) - goto import_cat_failure; - } - if (high != NULL) { - if (high == low) - rc = ebitmap_cpy(&context->range.level[1].cat, - &context->range.level[0].cat); - else - rc = ebitmap_import(high, - high_len, - &context->range.level[1].cat); - if (rc != 0) - goto import_cat_failure; - } - - return 0; - -import_cat_failure: - ebitmap_destroy(&context->range.level[0].cat); - ebitmap_destroy(&context->range.level[1].cat); - return rc; -} diff --git a/trunk/security/selinux/ss/mls.h b/trunk/security/selinux/ss/mls.h index df6032c6d492..fbb42f07dd7c 100644 --- a/trunk/security/selinux/ss/mls.h +++ b/trunk/security/selinux/ss/mls.h @@ -10,13 +10,6 @@ * * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. */ -/* - * Updated: Hewlett-Packard - * - * Added support to import/export the MLS label - * - * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - */ #ifndef _SS_MLS_H_ #define _SS_MLS_H_ @@ -24,26 +17,6 @@ #include "context.h" #include "policydb.h" -/* - * Copies the MLS range from `src' into `dst'. - */ -static inline int mls_copy_context(struct context *dst, - struct context *src) -{ - int l, rc = 0; - - /* Copy the MLS range from the source context */ - for (l = 0; l < 2; l++) { - dst->range.level[l].sens = src->range.level[l].sens; - rc = ebitmap_cpy(&dst->range.level[l].cat, - &src->range.level[l].cat); - if (rc) - break; - } - - return rc; -} - int mls_compute_context_len(struct context *context); void mls_sid_to_context(struct context *context, char **scontext); int mls_context_isvalid(struct policydb *p, struct context *c); @@ -69,19 +42,5 @@ int mls_compute_sid(struct context *scontext, int mls_setup_user_range(struct context *fromcon, struct user_datum *user, struct context *usercon); -void mls_export_lvl(const struct context *context, u32 *low, u32 *high); -void mls_import_lvl(struct context *context, u32 low, u32 high); - -int mls_export_cat(const struct context *context, - unsigned char **low, - size_t *low_len, - unsigned char **high, - size_t *high_len); -int mls_import_cat(struct context *context, - const unsigned char *low, - size_t low_len, - const unsigned char *high, - size_t high_len); - #endif /* _SS_MLS_H */ diff --git a/trunk/security/selinux/ss/policydb.c b/trunk/security/selinux/ss/policydb.c index f03960e697ce..0111990ba837 100644 --- a/trunk/security/selinux/ss/policydb.c +++ b/trunk/security/selinux/ss/policydb.c @@ -644,18 +644,10 @@ void policydb_destroy(struct policydb *p) kfree(lra); for (rt = p->range_tr; rt; rt = rt -> next) { - if (lrt) { - ebitmap_destroy(&lrt->range.level[0].cat); - ebitmap_destroy(&lrt->range.level[1].cat); - kfree(lrt); - } - lrt = rt; - } - if (lrt) { - ebitmap_destroy(&lrt->range.level[0].cat); - ebitmap_destroy(&lrt->range.level[1].cat); kfree(lrt); + lrt = rt; } + kfree(lrt); if (p->type_attr_map) { for (i = 0; i < p->p_types.nprim; i++) diff --git a/trunk/security/selinux/ss/services.c b/trunk/security/selinux/ss/services.c index 7eb69a602d8f..d2e80e62ff0c 100644 --- a/trunk/security/selinux/ss/services.c +++ b/trunk/security/selinux/ss/services.c @@ -13,11 +13,6 @@ * * Added conditional policy language extensions * - * Updated: Hewlett-Packard - * - * Added support for NetLabel - * - * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. * Copyright (C) 2003 - 2004 Tresys Technology, LLC * Copyright (C) 2003 Red Hat, Inc., James Morris @@ -34,8 +29,6 @@ #include #include #include -#include -#include #include "flask.h" #include "avc.h" @@ -47,8 +40,6 @@ #include "services.h" #include "conditional.h" #include "mls.h" -#include "objsec.h" -#include "selinux_netlabel.h" extern void selnl_notify_policyload(u32 seqno); unsigned int policydb_loaded_version; @@ -842,8 +833,6 @@ static int security_compute_sid(u32 ssid, goto out; } - context_init(&newcontext); - POLICY_RDLOCK; scontext = sidtab_search(&sidtab, ssid); @@ -861,6 +850,8 @@ static int security_compute_sid(u32 ssid, goto out_unlock; } + context_init(&newcontext); + /* Set the user identity. */ switch (specified) { case AVTAB_TRANSITION: @@ -1250,7 +1241,6 @@ int security_load_policy(void *data, size_t len) selinux_complete_init(); avc_ss_reset(seqno); selnl_notify_policyload(seqno); - selinux_netlbl_cache_invalidate(); return 0; } @@ -1305,7 +1295,6 @@ int security_load_policy(void *data, size_t len) avc_ss_reset(seqno); selnl_notify_policyload(seqno); - selinux_netlbl_cache_invalidate(); return 0; @@ -1828,75 +1817,6 @@ int security_get_bool_value(int bool) return rc; } -/* - * security_sid_mls_copy() - computes a new sid based on the given - * sid and the mls portion of mls_sid. - */ -int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) -{ - struct context *context1; - struct context *context2; - struct context newcon; - char *s; - u32 len; - int rc = 0; - - if (!ss_initialized || !selinux_mls_enabled) { - *new_sid = sid; - goto out; - } - - context_init(&newcon); - - POLICY_RDLOCK; - context1 = sidtab_search(&sidtab, sid); - if (!context1) { - printk(KERN_ERR "security_sid_mls_copy: unrecognized SID " - "%d\n", sid); - rc = -EINVAL; - goto out_unlock; - } - - context2 = sidtab_search(&sidtab, mls_sid); - if (!context2) { - printk(KERN_ERR "security_sid_mls_copy: unrecognized SID " - "%d\n", mls_sid); - rc = -EINVAL; - goto out_unlock; - } - - newcon.user = context1->user; - newcon.role = context1->role; - newcon.type = context1->type; - rc = mls_copy_context(&newcon, context2); - if (rc) - goto out_unlock; - - - /* Check the validity of the new context. */ - if (!policydb_context_isvalid(&policydb, &newcon)) { - rc = convert_context_handle_invalid_context(&newcon); - if (rc) - goto bad; - } - - rc = sidtab_context_to_sid(&sidtab, &newcon, new_sid); - goto out_unlock; - -bad: - if (!context_struct_to_string(&newcon, &s, &len)) { - audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR, - "security_sid_mls_copy: invalid context %s", s); - kfree(s); - } - -out_unlock: - POLICY_RDUNLOCK; - context_destroy(&newcon); -out: - return rc; -} - struct selinux_audit_rule { u32 au_seqno; struct context au_ctxt; @@ -2144,536 +2064,3 @@ void selinux_audit_set_callback(int (*callback)(void)) { aurule_callback = callback; } - -#ifdef CONFIG_NETLABEL -/* - * This is the structure we store inside the NetLabel cache block. - */ -#define NETLBL_CACHE(x) ((struct netlbl_cache *)(x)) -#define NETLBL_CACHE_T_NONE 0 -#define NETLBL_CACHE_T_SID 1 -#define NETLBL_CACHE_T_MLS 2 -struct netlbl_cache { - u32 type; - union { - u32 sid; - struct mls_range mls_label; - } data; -}; - -/** - * selinux_netlbl_cache_free - Free the NetLabel cached data - * @data: the data to free - * - * Description: - * This function is intended to be used as the free() callback inside the - * netlbl_lsm_cache structure. - * - */ -static void selinux_netlbl_cache_free(const void *data) -{ - struct netlbl_cache *cache = NETLBL_CACHE(data); - switch (cache->type) { - case NETLBL_CACHE_T_MLS: - ebitmap_destroy(&cache->data.mls_label.level[0].cat); - break; - } - kfree(data); -} - -/** - * selinux_netlbl_cache_add - Add an entry to the NetLabel cache - * @skb: the packet - * @ctx: the SELinux context - * - * Description: - * Attempt to cache the context in @ctx, which was derived from the packet in - * @skb, in the NetLabel subsystem cache. - * - */ -static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx) -{ - struct netlbl_cache *cache = NULL; - struct netlbl_lsm_secattr secattr; - - netlbl_secattr_init(&secattr); - - cache = kzalloc(sizeof(*cache), GFP_ATOMIC); - if (cache == NULL) - goto netlbl_cache_add_failure; - secattr.cache.free = selinux_netlbl_cache_free; - secattr.cache.data = (void *)cache; - - cache->type = NETLBL_CACHE_T_MLS; - if (ebitmap_cpy(&cache->data.mls_label.level[0].cat, - &ctx->range.level[0].cat) != 0) - goto netlbl_cache_add_failure; - cache->data.mls_label.level[1].cat.highbit = - cache->data.mls_label.level[0].cat.highbit; - cache->data.mls_label.level[1].cat.node = - cache->data.mls_label.level[0].cat.node; - cache->data.mls_label.level[0].sens = ctx->range.level[0].sens; - cache->data.mls_label.level[1].sens = ctx->range.level[0].sens; - - if (netlbl_cache_add(skb, &secattr) != 0) - goto netlbl_cache_add_failure; - - return; - -netlbl_cache_add_failure: - netlbl_secattr_destroy(&secattr, 1); -} - -/** - * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache - * - * Description: - * Invalidate the NetLabel security attribute mapping cache. - * - */ -void selinux_netlbl_cache_invalidate(void) -{ - netlbl_cache_invalidate(); -} - -/** - * selinux_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID - * @skb: the network packet - * @secattr: the NetLabel packet security attributes - * @base_sid: the SELinux SID to use as a context for MLS only attributes - * @sid: the SELinux SID - * - * Description: - * Convert the given NetLabel packet security attributes in @secattr into a - * SELinux SID. If the @secattr field does not contain a full SELinux - * SID/context then use the context in @base_sid as the foundation. If @skb - * is not NULL attempt to cache as much data as possibile. Returns zero on - * success, negative values on failure. - * - */ -static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb, - struct netlbl_lsm_secattr *secattr, - u32 base_sid, - u32 *sid) -{ - int rc = -EIDRM; - struct context *ctx; - struct context ctx_new; - struct netlbl_cache *cache; - - POLICY_RDLOCK; - - if (secattr->cache.data) { - cache = NETLBL_CACHE(secattr->cache.data); - switch (cache->type) { - case NETLBL_CACHE_T_SID: - *sid = cache->data.sid; - rc = 0; - break; - case NETLBL_CACHE_T_MLS: - ctx = sidtab_search(&sidtab, base_sid); - if (ctx == NULL) - goto netlbl_secattr_to_sid_return; - - ctx_new.user = ctx->user; - ctx_new.role = ctx->role; - ctx_new.type = ctx->type; - ctx_new.range.level[0].sens = - cache->data.mls_label.level[0].sens; - ctx_new.range.level[0].cat.highbit = - cache->data.mls_label.level[0].cat.highbit; - ctx_new.range.level[0].cat.node = - cache->data.mls_label.level[0].cat.node; - ctx_new.range.level[1].sens = - cache->data.mls_label.level[1].sens; - ctx_new.range.level[1].cat.highbit = - cache->data.mls_label.level[1].cat.highbit; - ctx_new.range.level[1].cat.node = - cache->data.mls_label.level[1].cat.node; - - rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid); - break; - default: - goto netlbl_secattr_to_sid_return; - } - } else if (secattr->mls_lvl_vld) { - ctx = sidtab_search(&sidtab, base_sid); - if (ctx == NULL) - goto netlbl_secattr_to_sid_return; - - ctx_new.user = ctx->user; - ctx_new.role = ctx->role; - ctx_new.type = ctx->type; - mls_import_lvl(&ctx_new, secattr->mls_lvl, secattr->mls_lvl); - if (secattr->mls_cat) { - if (mls_import_cat(&ctx_new, - secattr->mls_cat, - secattr->mls_cat_len, - NULL, - 0) != 0) - goto netlbl_secattr_to_sid_return; - ctx_new.range.level[1].cat.highbit = - ctx_new.range.level[0].cat.highbit; - ctx_new.range.level[1].cat.node = - ctx_new.range.level[0].cat.node; - } else { - ebitmap_init(&ctx_new.range.level[0].cat); - ebitmap_init(&ctx_new.range.level[1].cat); - } - if (mls_context_isvalid(&policydb, &ctx_new) != 1) - goto netlbl_secattr_to_sid_return_cleanup; - - rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid); - if (rc != 0) - goto netlbl_secattr_to_sid_return_cleanup; - - if (skb != NULL) - selinux_netlbl_cache_add(skb, &ctx_new); - ebitmap_destroy(&ctx_new.range.level[0].cat); - } else { - *sid = SECINITSID_UNLABELED; - rc = 0; - } - -netlbl_secattr_to_sid_return: - POLICY_RDUNLOCK; - return rc; -netlbl_secattr_to_sid_return_cleanup: - ebitmap_destroy(&ctx_new.range.level[0].cat); - goto netlbl_secattr_to_sid_return; -} - -/** - * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel - * @skb: the packet - * @base_sid: the SELinux SID to use as a context for MLS only attributes - * @sid: the SID - * - * Description: - * Call the NetLabel mechanism to get the security attributes of the given - * packet and use those attributes to determine the correct context/SID to - * assign to the packet. Returns zero on success, negative values on failure. - * - */ -static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, - u32 base_sid, - u32 *sid) -{ - int rc; - struct netlbl_lsm_secattr secattr; - - netlbl_secattr_init(&secattr); - rc = netlbl_skbuff_getattr(skb, &secattr); - if (rc == 0) - rc = selinux_netlbl_secattr_to_sid(skb, - &secattr, - base_sid, - sid); - netlbl_secattr_destroy(&secattr, 0); - - return rc; -} - -/** - * selinux_netlbl_socket_setsid - Label a socket using the NetLabel mechanism - * @sock: the socket to label - * @sid: the SID to use - * - * Description: - * Attempt to label a socket using the NetLabel mechanism using the given - * SID. Returns zero values on success, negative values on failure. - * - */ -static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid) -{ - int rc = -ENOENT; - struct sk_security_struct *sksec = sock->sk->sk_security; - struct netlbl_lsm_secattr secattr; - struct context *ctx; - - if (!ss_initialized) - return 0; - - POLICY_RDLOCK; - - ctx = sidtab_search(&sidtab, sid); - if (ctx == NULL) - goto netlbl_socket_setsid_return; - - netlbl_secattr_init(&secattr); - secattr.domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1], - GFP_ATOMIC); - mls_export_lvl(ctx, &secattr.mls_lvl, NULL); - secattr.mls_lvl_vld = 1; - mls_export_cat(ctx, - &secattr.mls_cat, - &secattr.mls_cat_len, - NULL, - NULL); - - rc = netlbl_socket_setattr(sock, &secattr); - if (rc == 0) - sksec->nlbl_state = NLBL_LABELED; - - netlbl_secattr_destroy(&secattr, 0); - -netlbl_socket_setsid_return: - POLICY_RDUNLOCK; - return rc; -} - -/** - * selinux_netlbl_sk_security_init - Setup the NetLabel fields - * @ssec: the sk_security_struct - * @family: the socket family - * - * Description: - * Called when a new sk_security_struct is allocated to initialize the NetLabel - * fields. - * - */ -void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, - int family) -{ - if (family == PF_INET) - ssec->nlbl_state = NLBL_REQUIRE; - else - ssec->nlbl_state = NLBL_UNSET; -} - -/** - * selinux_netlbl_sk_clone_security - Copy the NetLabel fields - * @ssec: the original sk_security_struct - * @newssec: the cloned sk_security_struct - * - * Description: - * Clone the NetLabel specific sk_security_struct fields from @ssec to - * @newssec. - * - */ -void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, - struct sk_security_struct *newssec) -{ - newssec->sclass = ssec->sclass; - if (ssec->nlbl_state != NLBL_UNSET) - newssec->nlbl_state = NLBL_REQUIRE; - else - newssec->nlbl_state = NLBL_UNSET; -} - -/** - * selinux_netlbl_socket_post_create - Label a socket using NetLabel - * @sock: the socket to label - * @sock_family: the socket family - * @sid: the SID to use - * - * Description: - * Attempt to label a socket using the NetLabel mechanism using the given - * SID. Returns zero values on success, negative values on failure. - * - */ -int selinux_netlbl_socket_post_create(struct socket *sock, - int sock_family, - u32 sid) -{ - struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; - struct sk_security_struct *sksec = sock->sk->sk_security; - - sksec->sclass = isec->sclass; - - if (sock_family != PF_INET) - return 0; - - sksec->nlbl_state = NLBL_REQUIRE; - return selinux_netlbl_socket_setsid(sock, sid); -} - -/** - * selinux_netlbl_sock_graft - Netlabel the new socket - * @sk: the new connection - * @sock: the new socket - * - * Description: - * The connection represented by @sk is being grafted onto @sock so set the - * socket's NetLabel to match the SID of @sk. - * - */ -void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) -{ - struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; - struct sk_security_struct *sksec = sk->sk_security; - - sksec->sclass = isec->sclass; - - if (sk->sk_family != PF_INET) - return; - - sksec->nlbl_state = NLBL_REQUIRE; - sksec->peer_sid = sksec->sid; - - /* Try to set the NetLabel on the socket to save time later, if we fail - * here we will pick up the pieces in later calls to - * selinux_netlbl_inode_permission(). */ - selinux_netlbl_socket_setsid(sock, sksec->sid); -} - -/** - * selinux_netlbl_inet_conn_request - Handle a new connection request - * @skb: the packet - * @sock_sid: the SID of the parent socket - * - * Description: - * If present, use the security attributes of the packet in @skb and the - * parent sock's SID to arrive at a SID for the new child sock. Returns the - * SID of the connection or SECSID_NULL on failure. - * - */ -u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid) -{ - int rc; - u32 peer_sid; - - rc = selinux_netlbl_skbuff_getsid(skb, sock_sid, &peer_sid); - if (rc != 0) - return SECSID_NULL; - - if (peer_sid == SECINITSID_UNLABELED) - return SECSID_NULL; - - return peer_sid; -} - -/** - * selinux_netlbl_inode_permission - Verify the socket is NetLabel labeled - * @inode: the file descriptor's inode - * @mask: the permission mask - * - * Description: - * Looks at a file's inode and if it is marked as a socket protected by - * NetLabel then verify that the socket has been labeled, if not try to label - * the socket now with the inode's SID. Returns zero on success, negative - * values on failure. - * - */ -int selinux_netlbl_inode_permission(struct inode *inode, int mask) -{ - int rc; - struct inode_security_struct *isec; - struct sk_security_struct *sksec; - struct socket *sock; - - if (!S_ISSOCK(inode->i_mode)) - return 0; - - sock = SOCKET_I(inode); - isec = inode->i_security; - sksec = sock->sk->sk_security; - down(&isec->sem); - if (unlikely(sksec->nlbl_state == NLBL_REQUIRE && - (mask & (MAY_WRITE | MAY_APPEND)))) { - lock_sock(sock->sk); - rc = selinux_netlbl_socket_setsid(sock, sksec->sid); - release_sock(sock->sk); - } else - rc = 0; - up(&isec->sem); - - return rc; -} - -/** - * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel - * @sksec: the sock's sk_security_struct - * @skb: the packet - * @ad: the audit data - * - * Description: - * Fetch the NetLabel security attributes from @skb and perform an access check - * against the receiving socket. Returns zero on success, negative values on - * error. - * - */ -int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, - struct sk_buff *skb, - struct avc_audit_data *ad) -{ - int rc; - u32 netlbl_sid; - u32 recv_perm; - - rc = selinux_netlbl_skbuff_getsid(skb, sksec->sid, &netlbl_sid); - if (rc != 0) - return rc; - - if (netlbl_sid == SECINITSID_UNLABELED) - return 0; - - switch (sksec->sclass) { - case SECCLASS_UDP_SOCKET: - recv_perm = UDP_SOCKET__RECV_MSG; - break; - case SECCLASS_TCP_SOCKET: - recv_perm = TCP_SOCKET__RECV_MSG; - break; - default: - recv_perm = RAWIP_SOCKET__RECV_MSG; - } - - rc = avc_has_perm(sksec->sid, - netlbl_sid, - sksec->sclass, - recv_perm, - ad); - if (rc == 0) - return 0; - - netlbl_skbuff_err(skb, rc); - return rc; -} - -/** - * selinux_netlbl_socket_getpeersec_stream - Return the connected peer's SID - * @sock: the socket - * - * Description: - * Examine @sock to find the connected peer's SID. Returns the SID on success - * or SECSID_NULL on error. - * - */ -u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock) -{ - struct sk_security_struct *sksec = sock->sk->sk_security; - - if (sksec->peer_sid == SECINITSID_UNLABELED) - return SECSID_NULL; - - return sksec->peer_sid; -} - -/** - * selinux_netlbl_socket_getpeersec_dgram - Return the SID of a NetLabel packet - * @skb: the packet - * - * Description: - * Examine @skb to find the SID assigned to it by NetLabel. Returns the SID on - * success, SECSID_NULL on error. - * - */ -u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb) -{ - int peer_sid; - struct sock *sk = skb->sk; - struct inode_security_struct *isec; - - if (sk == NULL || sk->sk_socket == NULL) - return SECSID_NULL; - - isec = SOCK_INODE(sk->sk_socket)->i_security; - if (selinux_netlbl_skbuff_getsid(skb, isec->sid, &peer_sid) != 0) - return SECSID_NULL; - if (peer_sid == SECINITSID_UNLABELED) - return SECSID_NULL; - - return peer_sid; -} -#endif /* CONFIG_NETLABEL */ diff --git a/trunk/security/selinux/xfrm.c b/trunk/security/selinux/xfrm.c index 3e742b850af6..6c985ced8102 100644 --- a/trunk/security/selinux/xfrm.c +++ b/trunk/security/selinux/xfrm.c @@ -6,12 +6,7 @@ * Authors: Serge Hallyn * Trent Jaeger * - * Updated: Venkat Yekkirala - * - * Granular IPSec Associations for use in MLS environments. - * * Copyright (C) 2005 International Business Machines Corporation - * Copyright (C) 2006 Trusted Computer Solutions, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -72,10 +67,10 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x) } /* - * LSM hook implementation that authorizes that a flow can use - * a xfrm policy rule. + * LSM hook implementation that authorizes that a socket can be used + * with the corresponding xfrm_sec_ctx and direction. */ -int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) +int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir) { int rc = 0; u32 sel_sid = SECINITSID_UNLABELED; @@ -89,130 +84,27 @@ int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) sel_sid = ctx->ctx_sid; } - rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION, - ASSOCIATION__POLMATCH, + rc = avc_has_perm(sk_sid, sel_sid, SECCLASS_ASSOCIATION, + ((dir == FLOW_DIR_IN) ? ASSOCIATION__RECVFROM : + ((dir == FLOW_DIR_OUT) ? ASSOCIATION__SENDTO : + (ASSOCIATION__SENDTO | ASSOCIATION__RECVFROM))), NULL); return rc; } -/* - * LSM hook implementation that authorizes that a state matches - * the given policy, flow combo. - */ - -int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp, - struct flowi *fl) -{ - u32 state_sid; - u32 pol_sid; - int err; - - if (x->security) - state_sid = x->security->ctx_sid; - else - state_sid = SECINITSID_UNLABELED; - - if (xp->security) - pol_sid = xp->security->ctx_sid; - else - pol_sid = SECINITSID_UNLABELED; - - err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION, - ASSOCIATION__POLMATCH, - NULL); - - if (err) - return 0; - - return selinux_xfrm_flow_state_match(fl, x); -} - -/* - * LSM hook implementation that authorizes that a particular outgoing flow - * can use a given security association. - */ - -int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm) -{ - int rc = 0; - u32 sel_sid = SECINITSID_UNLABELED; - struct xfrm_sec_ctx *ctx; - - /* Context sid is either set to label or ANY_ASSOC */ - if ((ctx = xfrm->security)) { - if (!selinux_authorizable_ctx(ctx)) - return 0; - - sel_sid = ctx->ctx_sid; - } - - rc = avc_has_perm(fl->secid, sel_sid, SECCLASS_ASSOCIATION, - ASSOCIATION__SENDTO, - NULL)? 0:1; - - return rc; -} - -/* - * LSM hook implementation that determines the sid for the session. - */ - -int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) -{ - struct sec_path *sp; - - *sid = SECSID_NULL; - - if (skb == NULL) - return 0; - - sp = skb->sp; - if (sp) { - int i, sid_set = 0; - - for (i = sp->len-1; i >= 0; i--) { - struct xfrm_state *x = sp->xvec[i]; - if (selinux_authorizable_xfrm(x)) { - struct xfrm_sec_ctx *ctx = x->security; - - if (!sid_set) { - *sid = ctx->ctx_sid; - sid_set = 1; - - if (!ckall) - break; - } - else if (*sid != ctx->ctx_sid) - return -EINVAL; - } - } - } - - return 0; -} - /* * Security blob allocation for xfrm_policy and xfrm_state * CTX does not have a meaningful value on input */ -static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, - struct xfrm_user_sec_ctx *uctx, struct xfrm_sec_ctx *pol, u32 sid) +static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *uctx) { int rc = 0; struct task_security_struct *tsec = current->security; - struct xfrm_sec_ctx *ctx = NULL; - char *ctx_str = NULL; - u32 str_len; - u32 ctx_sid; - - BUG_ON(uctx && pol); - - if (!uctx) - goto not_from_user; + struct xfrm_sec_ctx *ctx; - if (uctx->ctx_doi != XFRM_SC_ALG_SELINUX) - return -EINVAL; + BUG_ON(!uctx); + BUG_ON(uctx->ctx_doi != XFRM_SC_ALG_SELINUX); if (uctx->ctx_len >= PAGE_SIZE) return -ENOMEM; @@ -249,43 +141,9 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, return rc; -not_from_user: - if (pol) { - rc = security_sid_mls_copy(pol->ctx_sid, sid, &ctx_sid); - if (rc) - goto out; - } - else - ctx_sid = sid; - - rc = security_sid_to_context(ctx_sid, &ctx_str, &str_len); - if (rc) - goto out; - - *ctxp = ctx = kmalloc(sizeof(*ctx) + - str_len, - GFP_ATOMIC); - - if (!ctx) { - rc = -ENOMEM; - goto out; - } - - ctx->ctx_doi = XFRM_SC_DOI_LSM; - ctx->ctx_alg = XFRM_SC_ALG_SELINUX; - ctx->ctx_sid = ctx_sid; - ctx->ctx_len = str_len; - memcpy(ctx->ctx_str, - ctx_str, - str_len); - - goto out2; - out: *ctxp = NULL; kfree(ctx); -out2: - kfree(ctx_str); return rc; } @@ -293,23 +151,13 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, * LSM hook implementation that allocs and transfers uctx spec to * xfrm_policy. */ -int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, - struct xfrm_user_sec_ctx *uctx, struct sock *sk) +int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *uctx) { int err; - u32 sid; BUG_ON(!xp); - BUG_ON(uctx && sk); - if (sk) { - struct sk_security_struct *ssec = sk->sk_security; - sid = ssec->sid; - } - else - sid = SECSID_NULL; - - err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, NULL, sid); + err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx); return err; } @@ -369,14 +217,13 @@ int selinux_xfrm_policy_delete(struct xfrm_policy *xp) * LSM hook implementation that allocs and transfers sec_ctx spec to * xfrm_state. */ -int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx, - struct xfrm_sec_ctx *pol, u32 secid) +int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uctx) { int err; BUG_ON(!x); - err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, pol, secid); + err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx); return err; } @@ -482,30 +329,38 @@ int selinux_xfrm_state_delete(struct xfrm_state *x) * we need to check for unlabelled access since this may not have * gone thru the IPSec process. */ -int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, - struct avc_audit_data *ad) +int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb) { int i, rc = 0; struct sec_path *sp; - u32 sel_sid = SECINITSID_UNLABELED; sp = skb->sp; if (sp) { + /* + * __xfrm_policy_check does not approve unless xfrm_policy_ok + * says that spi's match for policy and the socket. + * + * Only need to verify the existence of an authorizable sp. + */ for (i = 0; i < sp->len; i++) { struct xfrm_state *x = sp->xvec[i]; - if (x && selinux_authorizable_xfrm(x)) { - struct xfrm_sec_ctx *ctx = x->security; - sel_sid = ctx->ctx_sid; - break; - } + if (x && selinux_authorizable_xfrm(x)) + goto accept; } } - rc = avc_has_perm(isec_sid, sel_sid, SECCLASS_ASSOCIATION, - ASSOCIATION__RECVFROM, ad); + /* check SELinux sock for unlabelled access */ + rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, + ASSOCIATION__RECVFROM, NULL); + if (rc) + goto drop; + +accept: + return 0; +drop: return rc; } @@ -516,8 +371,7 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, * If we do have a authorizable security association, then it has already been * checked in xfrm_policy_lookup hook. */ -int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, - struct avc_audit_data *ad) +int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb) { struct dst_entry *dst; int rc = 0; @@ -537,7 +391,7 @@ int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, } rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION, - ASSOCIATION__SENDTO, ad); + ASSOCIATION__SENDTO, NULL); out: return rc; } diff --git a/trunk/sound/aoa/Kconfig b/trunk/sound/aoa/Kconfig index 5d5813cec4c8..2f4334d19ccd 100644 --- a/trunk/sound/aoa/Kconfig +++ b/trunk/sound/aoa/Kconfig @@ -1,5 +1,5 @@ menu "Apple Onboard Audio driver" - depends on SND!=n && PPC_PMAC + depends on SND!=n && PPC config SND_AOA tristate "Apple Onboard Audio driver" diff --git a/trunk/sound/aoa/codecs/Kconfig b/trunk/sound/aoa/codecs/Kconfig index d5fbd6016e93..90cf58f68630 100644 --- a/trunk/sound/aoa/codecs/Kconfig +++ b/trunk/sound/aoa/codecs/Kconfig @@ -1,8 +1,6 @@ config SND_AOA_ONYX tristate "support Onyx chip" depends on SND_AOA - select I2C - select I2C_POWERMAC ---help--- This option enables support for the Onyx (pcm3052) codec chip found in the latest Apple machines @@ -20,8 +18,6 @@ config SND_AOA_ONYX config SND_AOA_TAS tristate "support TAS chips" depends on SND_AOA - select I2C - select I2C_POWERMAC ---help--- This option enables support for the tas chips found in a lot of Apple Machines, especially diff --git a/trunk/sound/aoa/codecs/snd-aoa-codec-tas.c b/trunk/sound/aoa/codecs/snd-aoa-codec-tas.c index 2ef55a17917c..16c0b6b0a805 100644 --- a/trunk/sound/aoa/codecs/snd-aoa-codec-tas.c +++ b/trunk/sound/aoa/codecs/snd-aoa-codec-tas.c @@ -66,8 +66,6 @@ #include #include #include -#include - MODULE_AUTHOR("Johannes Berg "); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("tas codec driver for snd-aoa"); @@ -93,10 +91,6 @@ struct tas { u8 bass, treble; u8 acr; int drc_range; - /* protects hardware access against concurrency from - * userspace when hitting controls and during - * codec init/suspend/resume */ - struct mutex mtx; }; static int tas_reset_init(struct tas *tas); @@ -237,10 +231,8 @@ static int tas_snd_vol_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); ucontrol->value.integer.value[0] = tas->cached_volume_l; ucontrol->value.integer.value[1] = tas->cached_volume_r; - mutex_unlock(&tas->mtx); return 0; } @@ -249,18 +241,14 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); if (tas->cached_volume_l == ucontrol->value.integer.value[0] - && tas->cached_volume_r == ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); + && tas->cached_volume_r == ucontrol->value.integer.value[1]) return 0; - } tas->cached_volume_l = ucontrol->value.integer.value[0]; tas->cached_volume_r = ucontrol->value.integer.value[1]; if (tas->hw_enabled) tas_set_volume(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -288,10 +276,8 @@ static int tas_snd_mute_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); ucontrol->value.integer.value[0] = !tas->mute_l; ucontrol->value.integer.value[1] = !tas->mute_r; - mutex_unlock(&tas->mtx); return 0; } @@ -300,18 +286,14 @@ static int tas_snd_mute_put(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); if (tas->mute_l == !ucontrol->value.integer.value[0] - && tas->mute_r == !ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); + && tas->mute_r == !ucontrol->value.integer.value[1]) return 0; - } tas->mute_l = !ucontrol->value.integer.value[0]; tas->mute_r = !ucontrol->value.integer.value[1]; if (tas->hw_enabled) tas_set_volume(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -340,10 +322,8 @@ static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol, struct tas *tas = snd_kcontrol_chip(kcontrol); int idx = kcontrol->private_value; - mutex_lock(&tas->mtx); ucontrol->value.integer.value[0] = tas->mixer_l[idx]; ucontrol->value.integer.value[1] = tas->mixer_r[idx]; - mutex_unlock(&tas->mtx); return 0; } @@ -354,19 +334,15 @@ static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol, struct tas *tas = snd_kcontrol_chip(kcontrol); int idx = kcontrol->private_value; - mutex_lock(&tas->mtx); if (tas->mixer_l[idx] == ucontrol->value.integer.value[0] - && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) { - mutex_unlock(&tas->mtx); + && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) return 0; - } tas->mixer_l[idx] = ucontrol->value.integer.value[0]; tas->mixer_r[idx] = ucontrol->value.integer.value[1]; if (tas->hw_enabled) tas_set_mixer(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -399,9 +375,7 @@ static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); ucontrol->value.integer.value[0] = tas->drc_range; - mutex_unlock(&tas->mtx); return 0; } @@ -410,16 +384,12 @@ static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); - if (tas->drc_range == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + if (tas->drc_range == ucontrol->value.integer.value[0]) return 0; - } tas->drc_range = ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas3004_set_drc(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -447,9 +417,7 @@ static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); ucontrol->value.integer.value[0] = tas->drc_enabled; - mutex_unlock(&tas->mtx); return 0; } @@ -458,16 +426,12 @@ static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); - if (tas->drc_enabled == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + if (tas->drc_enabled == ucontrol->value.integer.value[0]) return 0; - } tas->drc_enabled = ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas3004_set_drc(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -499,9 +463,7 @@ static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B); - mutex_unlock(&tas->mtx); return 0; } @@ -509,21 +471,15 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct tas *tas = snd_kcontrol_chip(kcontrol); - int oldacr; - - mutex_lock(&tas->mtx); - oldacr = tas->acr; + int oldacr = tas->acr; tas->acr &= ~TAS_ACR_INPUT_B; if (ucontrol->value.enumerated.item[0]) tas->acr |= TAS_ACR_INPUT_B; - if (oldacr == tas->acr) { - mutex_unlock(&tas->mtx); + if (oldacr == tas->acr) return 0; - } if (tas->hw_enabled) tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); - mutex_unlock(&tas->mtx); return 1; } @@ -562,9 +518,7 @@ static int tas_snd_treble_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); ucontrol->value.integer.value[0] = tas->treble; - mutex_unlock(&tas->mtx); return 0; } @@ -573,16 +527,12 @@ static int tas_snd_treble_put(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); - if (tas->treble == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + if (tas->treble == ucontrol->value.integer.value[0]) return 0; - } tas->treble = ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas_set_treble(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -610,9 +560,7 @@ static int tas_snd_bass_get(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); ucontrol->value.integer.value[0] = tas->bass; - mutex_unlock(&tas->mtx); return 0; } @@ -621,16 +569,12 @@ static int tas_snd_bass_put(struct snd_kcontrol *kcontrol, { struct tas *tas = snd_kcontrol_chip(kcontrol); - mutex_lock(&tas->mtx); - if (tas->bass == ucontrol->value.integer.value[0]) { - mutex_unlock(&tas->mtx); + if (tas->bass == ucontrol->value.integer.value[0]) return 0; - } tas->bass = ucontrol->value.integer.value[0]; if (tas->hw_enabled) tas_set_bass(tas); - mutex_unlock(&tas->mtx); return 1; } @@ -684,16 +628,16 @@ static int tas_reset_init(struct tas *tas) tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT; if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp)) - goto outerr; + return -ENODEV; tas->acr |= TAS_ACR_ANALOG_PDOWN | TAS_ACR_B_MONAUREAL | TAS_ACR_B_MON_SEL_RIGHT; if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) - goto outerr; + return -ENODEV; tmp = 0; if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp)) - goto outerr; + return -ENODEV; tas3004_set_drc(tas); @@ -705,11 +649,9 @@ static int tas_reset_init(struct tas *tas) tas->acr &= ~TAS_ACR_ANALOG_PDOWN; if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) - goto outerr; + return -ENODEV; return 0; - outerr: - return -ENODEV; } static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock) @@ -724,13 +666,11 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock break; case CLOCK_SWITCH_SLAVE: /* Clocks are back, re-init the codec */ - mutex_lock(&tas->mtx); tas_reset_init(tas); tas_set_volume(tas); tas_set_mixer(tas); tas->hw_enabled = 1; tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); - mutex_unlock(&tas->mtx); break; default: /* doesn't happen as of now */ @@ -744,23 +684,19 @@ static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock * our i2c device is suspended, and then take note of that! */ static int tas_suspend(struct tas *tas) { - mutex_lock(&tas->mtx); tas->hw_enabled = 0; tas->acr |= TAS_ACR_ANALOG_PDOWN; tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); - mutex_unlock(&tas->mtx); return 0; } static int tas_resume(struct tas *tas) { /* reset codec */ - mutex_lock(&tas->mtx); tas_reset_init(tas); tas_set_volume(tas); tas_set_mixer(tas); tas->hw_enabled = 1; - mutex_unlock(&tas->mtx); return 0; } @@ -803,14 +739,11 @@ static int tas_init_codec(struct aoa_codec *codec) return -EINVAL; } - mutex_lock(&tas->mtx); if (tas_reset_init(tas)) { printk(KERN_ERR PFX "tas failed to initialise\n"); - mutex_unlock(&tas->mtx); return -ENXIO; } tas->hw_enabled = 1; - mutex_unlock(&tas->mtx); if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, aoa_get_card(), @@ -889,7 +822,6 @@ static int tas_create(struct i2c_adapter *adapter, if (!tas) return -ENOMEM; - mutex_init(&tas->mtx); tas->i2c.driver = &tas_driver; tas->i2c.adapter = adapter; tas->i2c.addr = addr; @@ -918,7 +850,6 @@ static int tas_create(struct i2c_adapter *adapter, detach: i2c_detach_client(&tas->i2c); fail: - mutex_destroy(&tas->mtx); kfree(tas); return -EINVAL; } @@ -977,7 +908,6 @@ static int tas_i2c_detach(struct i2c_client *client) /* power down codec chip */ tas_write_reg(tas, TAS_REG_ACR, 1, &tmp); - mutex_destroy(&tas->mtx); kfree(tas); return 0; } diff --git a/trunk/sound/aoa/codecs/snd-aoa-codec-toonie.c b/trunk/sound/aoa/codecs/snd-aoa-codec-toonie.c index 3c7d1d8a9a6f..bcc555647e79 100644 --- a/trunk/sound/aoa/codecs/snd-aoa-codec-toonie.c +++ b/trunk/sound/aoa/codecs/snd-aoa-codec-toonie.c @@ -51,13 +51,6 @@ static struct transfer_info toonie_transfers[] = { {} }; -static int toonie_usable(struct codec_info_item *cii, - struct transfer_info *ti, - struct transfer_info *out) -{ - return 1; -} - #ifdef CONFIG_PM static int toonie_suspend(struct codec_info_item *cii, pm_message_t state) { @@ -76,7 +69,6 @@ static struct codec_info toonie_codec_info = { .sysclock_factor = 256, .bus_factor = 64, .owner = THIS_MODULE, - .usable = toonie_usable, #ifdef CONFIG_PM .suspend = toonie_suspend, .resume = toonie_resume, @@ -87,20 +79,19 @@ static int toonie_init_codec(struct aoa_codec *codec) { struct toonie *toonie = codec_to_toonie(codec); - /* nothing connected? what a joke! */ - if (toonie->codec.connected != 1) - return -ENOTCONN; - if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, toonie, &ops)) { printk(KERN_ERR PFX "failed to create toonie snd device!\n"); return -ENODEV; } + /* nothing connected? what a joke! */ + if (toonie->codec.connected != 1) + return -ENOTCONN; + if (toonie->codec.soundbus_dev->attach_codec(toonie->codec.soundbus_dev, aoa_get_card(), &toonie_codec_info, toonie)) { printk(KERN_ERR PFX "error creating toonie pcm\n"); - snd_device_free(aoa_get_card(), toonie); return -ENODEV; } diff --git a/trunk/sound/aoa/core/snd-aoa-gpio-feature.c b/trunk/sound/aoa/core/snd-aoa-gpio-feature.c index 7c26089527f6..7ae0c0bdfad8 100644 --- a/trunk/sound/aoa/core/snd-aoa-gpio-feature.c +++ b/trunk/sound/aoa/core/snd-aoa-gpio-feature.c @@ -56,7 +56,7 @@ static struct device_node *get_gpio(char *name, { struct device_node *np, *gpio; u32 *reg; - const char *audio_gpio; + char *audio_gpio; *gpioptr = -1; @@ -112,10 +112,7 @@ static struct device_node *get_gpio(char *name, static void get_irq(struct device_node * np, int *irqptr) { - if (np) - *irqptr = irq_of_parse_and_map(np, 0); - else - *irqptr = NO_IRQ; + *irqptr = irq_of_parse_and_map(np, 0); } /* 0x4 is outenable, 0x1 is out, thus 4 or 5 */ @@ -325,7 +322,7 @@ static int ftr_set_notify(struct gpio_runtime *rt, return -EINVAL; } - if (irq == NO_IRQ) + if (irq == -1) return -ENODEV; mutex_lock(¬if->mutex); diff --git a/trunk/sound/aoa/core/snd-aoa-gpio-pmf.c b/trunk/sound/aoa/core/snd-aoa-gpio-pmf.c index 2836c3218391..3d57fd1aec4b 100644 --- a/trunk/sound/aoa/core/snd-aoa-gpio-pmf.c +++ b/trunk/sound/aoa/core/snd-aoa-gpio-pmf.c @@ -18,7 +18,7 @@ static void pmf_gpio_set_##name(struct gpio_runtime *rt, int on)\ \ if (unlikely(!rt)) return; \ rc = pmf_call_function(rt->node, #name "-mute", &args); \ - if (rc && rc != -ENODEV) \ + if (rc) \ printk(KERN_WARNING "pmf_gpio_set_" #name \ " failed, rc: %d\n", rc); \ rt->implementation_private &= ~(1<change_sleep); spin_lock_init(&ctl->read_lock); ctl->card = card; - ctl->prefer_pcm_subdevice = -1; - ctl->prefer_rawmidi_subdevice = -1; ctl->pid = current->pid; file->private_data = ctl; write_lock_irqsave(&card->ctl_files_rwlock, flags); @@ -238,16 +236,11 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, kctl.id.index = ncontrol->index; kctl.count = ncontrol->count ? ncontrol->count : 1; access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : - (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| - SNDRV_CTL_ELEM_ACCESS_INACTIVE| - SNDRV_CTL_ELEM_ACCESS_DINDIRECT| - SNDRV_CTL_ELEM_ACCESS_INDIRECT| - SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE| - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK)); + (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE| + SNDRV_CTL_ELEM_ACCESS_DINDIRECT|SNDRV_CTL_ELEM_ACCESS_INDIRECT)); kctl.info = ncontrol->info; kctl.get = ncontrol->get; kctl.put = ncontrol->put; - kctl.tlv.p = ncontrol->tlv.p; kctl.private_value = ncontrol->private_value; kctl.private_data = private_data; return snd_ctl_new(&kctl, access); @@ -889,8 +882,6 @@ struct user_element { struct snd_ctl_elem_info info; void *elem_data; /* element data */ unsigned long elem_data_size; /* size of element data in bytes */ - void *tlv_data; /* TLV data */ - unsigned long tlv_data_size; /* TLV data size */ void *priv_data; /* private data (like strings for enumerated type) */ unsigned long priv_data_size; /* size of private data in bytes */ }; @@ -925,48 +916,9 @@ static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol, return change; } -static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol, - int op_flag, - unsigned int size, - unsigned int __user *tlv) -{ - struct user_element *ue = kcontrol->private_data; - int change = 0; - void *new_data; - - if (op_flag > 0) { - if (size > 1024 * 128) /* sane value */ - return -EINVAL; - new_data = kmalloc(size, GFP_KERNEL); - if (new_data == NULL) - return -ENOMEM; - if (copy_from_user(new_data, tlv, size)) { - kfree(new_data); - return -EFAULT; - } - change = ue->tlv_data_size != size; - if (!change) - change = memcmp(ue->tlv_data, new_data, size); - kfree(ue->tlv_data); - ue->tlv_data = new_data; - ue->tlv_data_size = size; - } else { - if (! ue->tlv_data_size || ! ue->tlv_data) - return -ENXIO; - if (size < ue->tlv_data_size) - return -ENOSPC; - if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size)) - return -EFAULT; - } - return change; -} - static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol) { - struct user_element *ue = kcontrol->private_data; - if (ue->tlv_data) - kfree(ue->tlv_data); - kfree(ue); + kfree(kcontrol->private_data); } static int snd_ctl_elem_add(struct snd_ctl_file *file, @@ -985,8 +937,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, return -EINVAL; access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| - SNDRV_CTL_ELEM_ACCESS_INACTIVE| - SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE)); + SNDRV_CTL_ELEM_ACCESS_INACTIVE)); info->id.numid = 0; memset(&kctl, 0, sizeof(kctl)); down_write(&card->controls_rwsem); @@ -1012,10 +963,6 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, kctl.get = snd_ctl_elem_user_get; if (access & SNDRV_CTL_ELEM_ACCESS_WRITE) kctl.put = snd_ctl_elem_user_put; - if (access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE) { - kctl.tlv.c = snd_ctl_elem_user_tlv; - access |= SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; - } switch (info->type) { case SNDRV_CTL_ELEM_TYPE_BOOLEAN: private_size = sizeof(char); @@ -1050,7 +997,6 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, if (ue == NULL) return -ENOMEM; ue->info = *info; - ue->info.access = 0; ue->elem_data = (char *)ue + sizeof(*ue); ue->elem_data_size = private_size; kctl.private_free = snd_ctl_elem_user_free; @@ -1121,67 +1067,6 @@ static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr) return 0; } -static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file, - struct snd_ctl_tlv __user *_tlv, - int op_flag) -{ - struct snd_card *card = file->card; - struct snd_ctl_tlv tlv; - struct snd_kcontrol *kctl; - struct snd_kcontrol_volatile *vd; - unsigned int len; - int err = 0; - - if (copy_from_user(&tlv, _tlv, sizeof(tlv))) - return -EFAULT; - if (tlv.length < sizeof(unsigned int) * 3) - return -EINVAL; - down_read(&card->controls_rwsem); - kctl = snd_ctl_find_numid(card, tlv.numid); - if (kctl == NULL) { - err = -ENOENT; - goto __kctl_end; - } - if (kctl->tlv.p == NULL) { - err = -ENXIO; - goto __kctl_end; - } - vd = &kctl->vd[tlv.numid - kctl->id.numid]; - if ((op_flag == 0 && (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) == 0) || - (op_flag > 0 && (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_WRITE) == 0) || - (op_flag < 0 && (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND) == 0)) { - err = -ENXIO; - goto __kctl_end; - } - if (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { - if (file && vd->owner != NULL && vd->owner != file) { - err = -EPERM; - goto __kctl_end; - } - err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv); - if (err > 0) { - up_read(&card->controls_rwsem); - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id); - return 0; - } - } else { - if (op_flag) { - err = -ENXIO; - goto __kctl_end; - } - len = kctl->tlv.p[1] + 2 * sizeof(unsigned int); - if (tlv.length < len) { - err = -ENOMEM; - goto __kctl_end; - } - if (copy_to_user(_tlv->tlv, kctl->tlv.p, len)) - err = -EFAULT; - } - __kctl_end: - up_read(&card->controls_rwsem); - return err; -} - static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct snd_ctl_file *ctl; @@ -1201,11 +1086,11 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg case SNDRV_CTL_IOCTL_CARD_INFO: return snd_ctl_card_info(card, ctl, cmd, argp); case SNDRV_CTL_IOCTL_ELEM_LIST: - return snd_ctl_elem_list(card, argp); + return snd_ctl_elem_list(ctl->card, argp); case SNDRV_CTL_IOCTL_ELEM_INFO: return snd_ctl_elem_info_user(ctl, argp); case SNDRV_CTL_IOCTL_ELEM_READ: - return snd_ctl_elem_read_user(card, argp); + return snd_ctl_elem_read_user(ctl->card, argp); case SNDRV_CTL_IOCTL_ELEM_WRITE: return snd_ctl_elem_write_user(ctl, argp); case SNDRV_CTL_IOCTL_ELEM_LOCK: @@ -1220,12 +1105,6 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg return snd_ctl_elem_remove(ctl, argp); case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS: return snd_ctl_subscribe_events(ctl, ip); - case SNDRV_CTL_IOCTL_TLV_READ: - return snd_ctl_tlv_ioctl(ctl, argp, 0); - case SNDRV_CTL_IOCTL_TLV_WRITE: - return snd_ctl_tlv_ioctl(ctl, argp, 1); - case SNDRV_CTL_IOCTL_TLV_COMMAND: - return snd_ctl_tlv_ioctl(ctl, argp, -1); case SNDRV_CTL_IOCTL_POWER: return -ENOPROTOOPT; case SNDRV_CTL_IOCTL_POWER_STATE: @@ -1459,11 +1338,6 @@ static int snd_ctl_dev_disconnect(struct snd_device *device) struct snd_card *card = device->device_data; struct list_head *flist; struct snd_ctl_file *ctl; - int err, cardnum; - - snd_assert(card != NULL, return -ENXIO); - cardnum = card->number; - snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); down_read(&card->controls_rwsem); list_for_each(flist, &card->ctl_files) { @@ -1472,10 +1346,6 @@ static int snd_ctl_dev_disconnect(struct snd_device *device) kill_fasync(&ctl->fasync, SIGIO, POLL_ERR); } up_read(&card->controls_rwsem); - - if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, - card, -1)) < 0) - return err; return 0; } @@ -1496,6 +1366,23 @@ static int snd_ctl_dev_free(struct snd_device *device) return 0; } +/* + * de-registration of the control device + */ +static int snd_ctl_dev_unregister(struct snd_device *device) +{ + struct snd_card *card = device->device_data; + int err, cardnum; + + snd_assert(card != NULL, return -ENXIO); + cardnum = card->number; + snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); + if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, + card, -1)) < 0) + return err; + return snd_ctl_dev_free(device); +} + /* * create control core: * called from init.c @@ -1506,6 +1393,7 @@ int snd_ctl_create(struct snd_card *card) .dev_free = snd_ctl_dev_free, .dev_register = snd_ctl_dev_register, .dev_disconnect = snd_ctl_dev_disconnect, + .dev_unregister = snd_ctl_dev_unregister }; snd_assert(card != NULL, return -ENXIO); diff --git a/trunk/sound/core/control_compat.c b/trunk/sound/core/control_compat.c index ab48962c48ce..3c0161bb5ba4 100644 --- a/trunk/sound/core/control_compat.c +++ b/trunk/sound/core/control_compat.c @@ -407,10 +407,6 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns case SNDRV_CTL_IOCTL_POWER_STATE: case SNDRV_CTL_IOCTL_ELEM_LOCK: case SNDRV_CTL_IOCTL_ELEM_UNLOCK: - case SNDRV_CTL_IOCTL_ELEM_REMOVE: - case SNDRV_CTL_IOCTL_TLV_READ: - case SNDRV_CTL_IOCTL_TLV_WRITE: - case SNDRV_CTL_IOCTL_TLV_COMMAND: return snd_ctl_ioctl(file, cmd, (unsigned long)argp); case SNDRV_CTL_IOCTL_ELEM_LIST32: return snd_ctl_elem_list_compat(ctl->card, argp); diff --git a/trunk/sound/core/device.c b/trunk/sound/core/device.c index ccb25816ac9e..6ce4da4a1081 100644 --- a/trunk/sound/core/device.c +++ b/trunk/sound/core/device.c @@ -71,7 +71,7 @@ EXPORT_SYMBOL(snd_device_new); * @device_data: the data pointer to release * * Removes the device from the list on the card and invokes the - * callbacks, dev_disconnect and dev_free, corresponding to the state. + * callback, dev_unregister or dev_free, corresponding to the state. * Then release the device. * * Returns zero if successful, or a negative error code on failure or if the @@ -90,14 +90,16 @@ int snd_device_free(struct snd_card *card, void *device_data) continue; /* unlink */ list_del(&dev->list); - if (dev->state == SNDRV_DEV_REGISTERED && - dev->ops->dev_disconnect) - if (dev->ops->dev_disconnect(dev)) - snd_printk(KERN_ERR - "device disconnect failure\n"); - if (dev->ops->dev_free) { - if (dev->ops->dev_free(dev)) - snd_printk(KERN_ERR "device free failure\n"); + if ((dev->state == SNDRV_DEV_REGISTERED || + dev->state == SNDRV_DEV_DISCONNECTED) && + dev->ops->dev_unregister) { + if (dev->ops->dev_unregister(dev)) + snd_printk(KERN_ERR "device unregister failure\n"); + } else { + if (dev->ops->dev_free) { + if (dev->ops->dev_free(dev)) + snd_printk(KERN_ERR "device free failure\n"); + } } kfree(dev); return 0; diff --git a/trunk/sound/core/hwdep.c b/trunk/sound/core/hwdep.c index 9aa9d94891f0..8bd0dcc93eba 100644 --- a/trunk/sound/core/hwdep.c +++ b/trunk/sound/core/hwdep.c @@ -42,7 +42,7 @@ static DEFINE_MUTEX(register_mutex); static int snd_hwdep_free(struct snd_hwdep *hwdep); static int snd_hwdep_dev_free(struct snd_device *device); static int snd_hwdep_dev_register(struct snd_device *device); -static int snd_hwdep_dev_disconnect(struct snd_device *device); +static int snd_hwdep_dev_unregister(struct snd_device *device); static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device) @@ -353,7 +353,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device, static struct snd_device_ops ops = { .dev_free = snd_hwdep_dev_free, .dev_register = snd_hwdep_dev_register, - .dev_disconnect = snd_hwdep_dev_disconnect, + .dev_unregister = snd_hwdep_dev_unregister }; snd_assert(rhwdep != NULL, return -EINVAL); @@ -439,7 +439,7 @@ static int snd_hwdep_dev_register(struct snd_device *device) return 0; } -static int snd_hwdep_dev_disconnect(struct snd_device *device) +static int snd_hwdep_dev_unregister(struct snd_device *device) { struct snd_hwdep *hwdep = device->device_data; @@ -454,9 +454,9 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); #endif snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); - list_del_init(&hwdep->list); + list_del(&hwdep->list); mutex_unlock(®ister_mutex); - return 0; + return snd_hwdep_free(hwdep); } #ifdef CONFIG_PROC_FS @@ -497,7 +497,7 @@ static void __init snd_hwdep_proc_init(void) static void __exit snd_hwdep_proc_done(void) { - snd_info_free_entry(snd_hwdep_proc_entry); + snd_info_unregister(snd_hwdep_proc_entry); } #else /* !CONFIG_PROC_FS */ #define snd_hwdep_proc_init() diff --git a/trunk/sound/core/info.c b/trunk/sound/core/info.c index e43662b33f16..340332c6d973 100644 --- a/trunk/sound/core/info.c +++ b/trunk/sound/core/info.c @@ -78,7 +78,6 @@ struct snd_info_private_data { static int snd_info_version_init(void); static int snd_info_version_done(void); -static void snd_info_disconnect(struct snd_info_entry *entry); /* resize the proc r/w buffer */ @@ -175,15 +174,15 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig) switch (entry->content) { case SNDRV_INFO_CONTENT_TEXT: switch (orig) { - case SEEK_SET: + case 0: /* SEEK_SET */ file->f_pos = offset; ret = file->f_pos; goto out; - case SEEK_CUR: + case 1: /* SEEK_CUR */ file->f_pos += offset; ret = file->f_pos; goto out; - case SEEK_END: + case 2: /* SEEK_END */ default: ret = -EINVAL; goto out; @@ -305,7 +304,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file) mutex_lock(&info_mutex); p = PDE(inode); entry = p == NULL ? NULL : (struct snd_info_entry *)p->data; - if (entry == NULL || ! entry->p) { + if (entry == NULL || entry->disconnected) { mutex_unlock(&info_mutex); return -ENODEV; } @@ -587,10 +586,10 @@ int __exit snd_info_done(void) snd_info_version_done(); if (snd_proc_root) { #if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE) - snd_info_free_entry(snd_seq_root); + snd_info_unregister(snd_seq_root); #endif #ifdef CONFIG_SND_OSSEMUL - snd_info_free_entry(snd_oss_root); + snd_info_unregister(snd_oss_root); #endif snd_remove_proc_entry(&proc_root, snd_proc_root); } @@ -649,28 +648,17 @@ int snd_info_card_register(struct snd_card *card) * de-register the card proc file * called from init.c */ -void snd_info_card_disconnect(struct snd_card *card) +int snd_info_card_free(struct snd_card *card) { - snd_assert(card != NULL, return); - mutex_lock(&info_mutex); + snd_assert(card != NULL, return -ENXIO); if (card->proc_root_link) { snd_remove_proc_entry(snd_proc_root, card->proc_root_link); card->proc_root_link = NULL; } - if (card->proc_root) - snd_info_disconnect(card->proc_root); - mutex_unlock(&info_mutex); -} - -/* - * release the card proc file resources - * called from init.c - */ -int snd_info_card_free(struct snd_card *card) -{ - snd_assert(card != NULL, return -ENXIO); - snd_info_free_entry(card->proc_root); - card->proc_root = NULL; + if (card->proc_root) { + snd_info_unregister(card->proc_root); + card->proc_root = NULL; + } return 0; } @@ -779,8 +767,6 @@ static struct snd_info_entry *snd_info_create_entry(const char *name) entry->mode = S_IFREG | S_IRUGO; entry->content = SNDRV_INFO_CONTENT_TEXT; mutex_init(&entry->access); - INIT_LIST_HEAD(&entry->children); - INIT_LIST_HEAD(&entry->list); return entry; } @@ -833,24 +819,6 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card, EXPORT_SYMBOL(snd_info_create_card_entry); -static void snd_info_disconnect(struct snd_info_entry *entry) -{ - struct list_head *p, *n; - struct proc_dir_entry *root; - - list_for_each_safe(p, n, &entry->children) { - snd_info_disconnect(list_entry(p, struct snd_info_entry, list)); - } - - if (! entry->p) - return; - list_del_init(&entry->list); - root = entry->parent == NULL ? snd_proc_root : entry->parent->p; - snd_assert(root, return); - snd_remove_proc_entry(root, entry->p); - entry->p = NULL; -} - static int snd_info_dev_free_entry(struct snd_device *device) { struct snd_info_entry *entry = device->device_data; @@ -864,6 +832,19 @@ static int snd_info_dev_register_entry(struct snd_device *device) return snd_info_register(entry); } +static int snd_info_dev_disconnect_entry(struct snd_device *device) +{ + struct snd_info_entry *entry = device->device_data; + entry->disconnected = 1; + return 0; +} + +static int snd_info_dev_unregister_entry(struct snd_device *device) +{ + struct snd_info_entry *entry = device->device_data; + return snd_info_unregister(entry); +} + /** * snd_card_proc_new - create an info entry for the given card * @card: the card instance @@ -890,7 +871,8 @@ int snd_card_proc_new(struct snd_card *card, const char *name, static struct snd_device_ops ops = { .dev_free = snd_info_dev_free_entry, .dev_register = snd_info_dev_register_entry, - /* disconnect is done via snd_info_card_disconnect() */ + .dev_disconnect = snd_info_dev_disconnect_entry, + .dev_unregister = snd_info_dev_unregister_entry }; struct snd_info_entry *entry; int err; @@ -919,11 +901,6 @@ void snd_info_free_entry(struct snd_info_entry * entry) { if (entry == NULL) return; - if (entry->p) { - mutex_lock(&info_mutex); - snd_info_disconnect(entry); - mutex_unlock(&info_mutex); - } kfree(entry->name); if (entry->private_free) entry->private_free(entry); @@ -958,14 +935,38 @@ int snd_info_register(struct snd_info_entry * entry) p->size = entry->size; p->data = entry; entry->p = p; - if (entry->parent) - list_add_tail(&entry->list, &entry->parent->children); mutex_unlock(&info_mutex); return 0; } EXPORT_SYMBOL(snd_info_register); +/** + * snd_info_unregister - de-register the info entry + * @entry: the info entry + * + * De-registers the info entry and releases the instance. + * + * Returns zero if successful, or a negative error code on failure. + */ +int snd_info_unregister(struct snd_info_entry * entry) +{ + struct proc_dir_entry *root; + + if (! entry) + return 0; + snd_assert(entry->p != NULL, return -ENXIO); + root = entry->parent == NULL ? snd_proc_root : entry->parent->p; + snd_assert(root, return -ENXIO); + mutex_lock(&info_mutex); + snd_remove_proc_entry(root, entry->p); + mutex_unlock(&info_mutex); + snd_info_free_entry(entry); + return 0; +} + +EXPORT_SYMBOL(snd_info_unregister); + /* */ @@ -998,7 +999,8 @@ static int __init snd_info_version_init(void) static int __exit snd_info_version_done(void) { - snd_info_free_entry(snd_info_version_entry); + if (snd_info_version_entry) + snd_info_unregister(snd_info_version_entry); return 0; } diff --git a/trunk/sound/core/info_oss.c b/trunk/sound/core/info_oss.c index 3ebc34919c76..bb2c40d0ab66 100644 --- a/trunk/sound/core/info_oss.c +++ b/trunk/sound/core/info_oss.c @@ -131,8 +131,10 @@ int snd_info_minor_register(void) int snd_info_minor_unregister(void) { - snd_info_free_entry(snd_sndstat_proc_entry); - snd_sndstat_proc_entry = NULL; + if (snd_sndstat_proc_entry) { + snd_info_unregister(snd_sndstat_proc_entry); + snd_sndstat_proc_entry = NULL; + } return 0; } diff --git a/trunk/sound/core/init.c b/trunk/sound/core/init.c index d7607a25acdf..4d9258884e44 100644 --- a/trunk/sound/core/init.c +++ b/trunk/sound/core/init.c @@ -81,6 +81,8 @@ static inline int init_info_for_card(struct snd_card *card) #define init_info_for_card(card) #endif +static void snd_card_free_thread(void * __card); + /** * snd_card_new - create and initialize a soundcard structure * @idx: card index (address) [0 ... (SNDRV_CARDS-1)] @@ -143,6 +145,7 @@ struct snd_card *snd_card_new(int idx, const char *xid, INIT_LIST_HEAD(&card->ctl_files); spin_lock_init(&card->files_lock); init_waitqueue_head(&card->shutdown_sleep); + INIT_WORK(&card->free_workq, snd_card_free_thread, card); #ifdef CONFIG_PM mutex_init(&card->power_lock); init_waitqueue_head(&card->power_sleep); @@ -307,7 +310,6 @@ int snd_card_disconnect(struct snd_card *card) if (err < 0) snd_printk(KERN_ERR "not all devices for card %i can be disconnected\n", card->number); - snd_info_card_disconnect(card); return 0; } @@ -324,10 +326,22 @@ EXPORT_SYMBOL(snd_card_disconnect); * Returns zero. Frees all associated devices and frees the control * interface associated to given soundcard. */ -static int snd_card_do_free(struct snd_card *card) +int snd_card_free(struct snd_card *card) { struct snd_shutdown_f_ops *s_f_ops; + if (card == NULL) + return -EINVAL; + mutex_lock(&snd_card_mutex); + snd_cards[card->number] = NULL; + mutex_unlock(&snd_card_mutex); + +#ifdef CONFIG_PM + wake_up(&card->power_sleep); +#endif + /* wait, until all devices are ready for the free operation */ + wait_event(card->shutdown_sleep, card->files == NULL); + #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) if (snd_mixer_oss_notify_callback) snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE); @@ -346,7 +360,7 @@ static int snd_card_do_free(struct snd_card *card) } if (card->private_free) card->private_free(card); - snd_info_free_entry(card->proc_id); + snd_info_unregister(card->proc_id); if (snd_info_card_free(card) < 0) { snd_printk(KERN_WARNING "unable to free card info\n"); /* Not fatal error */ @@ -356,59 +370,61 @@ static int snd_card_do_free(struct snd_card *card) card->s_f_ops = s_f_ops->next; kfree(s_f_ops); } - kfree(card); - return 0; -} - -static int snd_card_free_prepare(struct snd_card *card) -{ - if (card == NULL) - return -EINVAL; - (void) snd_card_disconnect(card); mutex_lock(&snd_card_mutex); - snd_cards[card->number] = NULL; snd_cards_lock &= ~(1 << card->number); mutex_unlock(&snd_card_mutex); -#ifdef CONFIG_PM - wake_up(&card->power_sleep); -#endif + kfree(card); return 0; } -int snd_card_free_when_closed(struct snd_card *card) +EXPORT_SYMBOL(snd_card_free); + +static void snd_card_free_thread(void * __card) { - int free_now = 0; - int ret = snd_card_free_prepare(card); - if (ret) - return ret; + struct snd_card *card = __card; + struct module * module = card->module; - spin_lock(&card->files_lock); - if (card->files == NULL) - free_now = 1; - else - card->free_on_last_close = 1; - spin_unlock(&card->files_lock); + if (!try_module_get(module)) { + snd_printk(KERN_ERR "unable to lock toplevel module for card %i in free thread\n", card->number); + module = NULL; + } - if (free_now) - snd_card_do_free(card); - return 0; -} + snd_card_free(card); -EXPORT_SYMBOL(snd_card_free_when_closed); + module_put(module); +} -int snd_card_free(struct snd_card *card) +/** + * snd_card_free_in_thread - call snd_card_free() in thread + * @card: soundcard structure + * + * This function schedules the call of snd_card_free() function in a + * work queue. When all devices are released (non-busy), the work + * is woken up and calls snd_card_free(). + * + * When a card can be disconnected at any time by hotplug service, + * this function should be used in disconnect (or detach) callback + * instead of calling snd_card_free() directly. + * + * Returns - zero otherwise a negative error code if the start of thread failed. + */ +int snd_card_free_in_thread(struct snd_card *card) { - int ret = snd_card_free_prepare(card); - if (ret) - return ret; + if (card->files == NULL) { + snd_card_free(card); + return 0; + } - /* wait, until all devices are ready for the free operation */ - wait_event(card->shutdown_sleep, card->files == NULL); - snd_card_do_free(card); - return 0; + if (schedule_work(&card->free_workq)) + return 0; + + snd_printk(KERN_ERR "schedule_work() failed in snd_card_free_in_thread for card %i\n", card->number); + /* try to free the structure immediately */ + snd_card_free(card); + return -EFAULT; } -EXPORT_SYMBOL(snd_card_free); +EXPORT_SYMBOL(snd_card_free_in_thread); static void choose_default_id(struct snd_card *card) { @@ -609,9 +625,9 @@ int __init snd_card_info_init(void) int __exit snd_card_info_done(void) { - snd_info_free_entry(snd_card_info_entry); + snd_info_unregister(snd_card_info_entry); #ifdef MODULE - snd_info_free_entry(snd_card_module_info_entry); + snd_info_unregister(snd_card_module_info_entry); #endif return 0; } @@ -692,16 +708,15 @@ EXPORT_SYMBOL(snd_card_file_add); * * This function removes the file formerly added to the card via * snd_card_file_add() function. - * If all files are removed and snd_card_free_when_closed() was - * called beforehand, it processes the pending release of - * resources. + * If all files are removed and the release of the card is + * scheduled, it will wake up the the thread to call snd_card_free() + * (see snd_card_free_in_thread() function). * * Returns zero or a negative error code. */ int snd_card_file_remove(struct snd_card *card, struct file *file) { struct snd_monitor_file *mfile, *pfile = NULL; - int last_close = 0; spin_lock(&card->files_lock); mfile = card->files; @@ -716,14 +731,9 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) pfile = mfile; mfile = mfile->next; } - if (card->files == NULL) - last_close = 1; spin_unlock(&card->files_lock); - if (last_close) { + if (card->files == NULL) wake_up(&card->shutdown_sleep); - if (card->free_on_last_close) - snd_card_do_free(card); - } if (!mfile) { snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); return -ENOENT; diff --git a/trunk/sound/core/oss/mixer_oss.c b/trunk/sound/core/oss/mixer_oss.c index f4c67042e3ac..71b5080fa66d 100644 --- a/trunk/sound/core/oss/mixer_oss.c +++ b/trunk/sound/core/oss/mixer_oss.c @@ -988,12 +988,13 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mix if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) { struct snd_ctl_elem_info *uinfo; - uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); + uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL); if (! uinfo) { up_read(&mixer->card->controls_rwsem); return -ENOMEM; } + memset(uinfo, 0, sizeof(*uinfo)); if (kctl->info(kctl, uinfo)) { up_read(&mixer->card->controls_rwsem); return 0; @@ -1193,8 +1194,10 @@ static void snd_mixer_oss_proc_init(struct snd_mixer_oss *mixer) static void snd_mixer_oss_proc_done(struct snd_mixer_oss *mixer) { - snd_info_free_entry(mixer->proc_entry); - mixer->proc_entry = NULL; + if (mixer->proc_entry) { + snd_info_unregister(mixer->proc_entry); + mixer->proc_entry = NULL; + } } #else /* !CONFIG_PROC_FS */ #define snd_mixer_oss_proc_init(mix) @@ -1310,19 +1313,21 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd) card->mixer_oss = mixer; snd_mixer_oss_build(mixer); snd_mixer_oss_proc_init(mixer); - } else { + } else if (cmd == SND_MIXER_OSS_NOTIFY_DISCONNECT) { + mixer = card->mixer_oss; + if (mixer == NULL || !mixer->oss_dev_alloc) + return 0; + snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0); + mixer->oss_dev_alloc = 0; + } else { /* free */ mixer = card->mixer_oss; if (mixer == NULL) return 0; - if (mixer->oss_dev_alloc) { #ifdef SNDRV_OSS_INFO_DEV_MIXERS - snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIXERS, mixer->card->number); + snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIXERS, mixer->card->number); #endif + if (mixer->oss_dev_alloc) snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0); - mixer->oss_dev_alloc = 0; - } - if (cmd == SND_MIXER_OSS_NOTIFY_DISCONNECT) - return 0; snd_mixer_oss_proc_done(mixer); return snd_mixer_oss_free1(mixer); } diff --git a/trunk/sound/core/oss/pcm_oss.c b/trunk/sound/core/oss/pcm_oss.c index 505b23ec4058..f5ff4f4a16ee 100644 --- a/trunk/sound/core/oss/pcm_oss.c +++ b/trunk/sound/core/oss/pcm_oss.c @@ -2228,8 +2228,6 @@ static int snd_pcm_oss_open_file(struct file *file, for (idx = 0; idx < 2; idx++) { if (setup[idx].disable) continue; - if (! pcm->streams[idx].substream_count) - continue; /* no matching substream */ if (idx == SNDRV_PCM_STREAM_PLAYBACK) { if (! (f_mode & FMODE_WRITE)) continue; @@ -2846,9 +2844,11 @@ static void snd_pcm_oss_proc_done(struct snd_pcm *pcm) int stream; for (stream = 0; stream < 2; ++stream) { struct snd_pcm_str *pstr = &pcm->streams[stream]; - snd_info_free_entry(pstr->oss.proc_entry); - pstr->oss.proc_entry = NULL; - snd_pcm_oss_proc_free_setup_list(pstr); + if (pstr->oss.proc_entry) { + snd_info_unregister(pstr->oss.proc_entry); + pstr->oss.proc_entry = NULL; + snd_pcm_oss_proc_free_setup_list(pstr); + } } } #else /* !CONFIG_SND_VERBOSE_PROCFS */ @@ -2929,12 +2929,6 @@ static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm) snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, pcm->card, 1); } - if (dsp_map[pcm->card->number] == (int)pcm->device) { -#ifdef SNDRV_OSS_INFO_DEV_AUDIO - snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number); -#endif - } - pcm->oss.reg = 0; } return 0; } @@ -2942,7 +2936,15 @@ static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm) static int snd_pcm_oss_unregister_minor(struct snd_pcm *pcm) { snd_pcm_oss_disconnect_minor(pcm); - snd_pcm_oss_proc_done(pcm); + if (pcm->oss.reg) { + if (dsp_map[pcm->card->number] == (int)pcm->device) { +#ifdef SNDRV_OSS_INFO_DEV_AUDIO + snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number); +#endif + } + pcm->oss.reg = 0; + snd_pcm_oss_proc_done(pcm); + } return 0; } diff --git a/trunk/sound/core/pcm.c b/trunk/sound/core/pcm.c index bf8f412988b8..7581edd7b9ff 100644 --- a/trunk/sound/core/pcm.c +++ b/trunk/sound/core/pcm.c @@ -42,6 +42,7 @@ static int snd_pcm_free(struct snd_pcm *pcm); static int snd_pcm_dev_free(struct snd_device *device); static int snd_pcm_dev_register(struct snd_device *device); static int snd_pcm_dev_disconnect(struct snd_device *device); +static int snd_pcm_dev_unregister(struct snd_device *device); static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) { @@ -493,13 +494,19 @@ static int snd_pcm_stream_proc_init(struct snd_pcm_str *pstr) static int snd_pcm_stream_proc_done(struct snd_pcm_str *pstr) { #ifdef CONFIG_SND_PCM_XRUN_DEBUG - snd_info_free_entry(pstr->proc_xrun_debug_entry); - pstr->proc_xrun_debug_entry = NULL; + if (pstr->proc_xrun_debug_entry) { + snd_info_unregister(pstr->proc_xrun_debug_entry); + pstr->proc_xrun_debug_entry = NULL; + } #endif - snd_info_free_entry(pstr->proc_info_entry); - pstr->proc_info_entry = NULL; - snd_info_free_entry(pstr->proc_root); - pstr->proc_root = NULL; + if (pstr->proc_info_entry) { + snd_info_unregister(pstr->proc_info_entry); + pstr->proc_info_entry = NULL; + } + if (pstr->proc_root) { + snd_info_unregister(pstr->proc_root); + pstr->proc_root = NULL; + } return 0; } @@ -563,19 +570,29 @@ static int snd_pcm_substream_proc_init(struct snd_pcm_substream *substream) return 0; } - + static int snd_pcm_substream_proc_done(struct snd_pcm_substream *substream) { - snd_info_free_entry(substream->proc_info_entry); - substream->proc_info_entry = NULL; - snd_info_free_entry(substream->proc_hw_params_entry); - substream->proc_hw_params_entry = NULL; - snd_info_free_entry(substream->proc_sw_params_entry); - substream->proc_sw_params_entry = NULL; - snd_info_free_entry(substream->proc_status_entry); - substream->proc_status_entry = NULL; - snd_info_free_entry(substream->proc_root); - substream->proc_root = NULL; + if (substream->proc_info_entry) { + snd_info_unregister(substream->proc_info_entry); + substream->proc_info_entry = NULL; + } + if (substream->proc_hw_params_entry) { + snd_info_unregister(substream->proc_hw_params_entry); + substream->proc_hw_params_entry = NULL; + } + if (substream->proc_sw_params_entry) { + snd_info_unregister(substream->proc_sw_params_entry); + substream->proc_sw_params_entry = NULL; + } + if (substream->proc_status_entry) { + snd_info_unregister(substream->proc_status_entry); + substream->proc_status_entry = NULL; + } + if (substream->proc_root) { + snd_info_unregister(substream->proc_root); + substream->proc_root = NULL; + } return 0; } #else /* !CONFIG_SND_VERBOSE_PROCFS */ @@ -679,6 +696,7 @@ int snd_pcm_new(struct snd_card *card, char *id, int device, .dev_free = snd_pcm_dev_free, .dev_register = snd_pcm_dev_register, .dev_disconnect = snd_pcm_dev_disconnect, + .dev_unregister = snd_pcm_dev_unregister }; snd_assert(rpcm != NULL, return -EINVAL); @@ -722,7 +740,6 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr) substream = pstr->substream; while (substream) { substream_next = substream->next; - snd_pcm_timer_done(substream); snd_pcm_substream_proc_done(substream); kfree(substream); substream = substream_next; @@ -739,12 +756,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr) static int snd_pcm_free(struct snd_pcm *pcm) { - struct snd_pcm_notify *notify; - snd_assert(pcm != NULL, return -ENXIO); - list_for_each_entry(notify, &snd_pcm_notify_list, list) { - notify->n_unregister(pcm); - } if (pcm->private_free) pcm->private_free(pcm); snd_pcm_lib_preallocate_free_for_all(pcm); @@ -792,8 +804,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, kctl = snd_ctl_file(list); if (kctl->pid == current->pid) { prefer_subdevice = kctl->prefer_pcm_subdevice; - if (prefer_subdevice != -1) - break; + break; } } up_read(&card->controls_rwsem); @@ -907,28 +918,6 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) substream->pstr->substream_opened--; } -static ssize_t show_pcm_class(struct class_device *class_device, char *buf) -{ - struct snd_pcm *pcm; - const char *str; - static const char *strs[SNDRV_PCM_CLASS_LAST + 1] = { - [SNDRV_PCM_CLASS_GENERIC] = "generic", - [SNDRV_PCM_CLASS_MULTI] = "multi", - [SNDRV_PCM_CLASS_MODEM] = "modem", - [SNDRV_PCM_CLASS_DIGITIZER] = "digitizer", - }; - - if (! (pcm = class_get_devdata(class_device)) || - pcm->dev_class > SNDRV_PCM_CLASS_LAST) - str = "none"; - else - str = strs[pcm->dev_class]; - return snprintf(buf, PAGE_SIZE, "%s\n", str); -} - -static struct class_device_attribute pcm_attrs = - __ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL); - static int snd_pcm_dev_register(struct snd_device *device) { int cidx, err; @@ -967,8 +956,6 @@ static int snd_pcm_dev_register(struct snd_device *device) mutex_unlock(®ister_mutex); return err; } - snd_add_device_sysfs_file(devtype, pcm->card, pcm->device, - &pcm_attrs); for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) snd_pcm_timer_init(substream); } @@ -984,22 +971,35 @@ static int snd_pcm_dev_register(struct snd_device *device) static int snd_pcm_dev_disconnect(struct snd_device *device) { struct snd_pcm *pcm = device->device_data; - struct snd_pcm_notify *notify; + struct list_head *list; struct snd_pcm_substream *substream; - int cidx, devtype; + int cidx; mutex_lock(®ister_mutex); - if (list_empty(&pcm->list)) - goto unlock; - list_del_init(&pcm->list); for (cidx = 0; cidx < 2; cidx++) for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) if (substream->runtime) substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; - list_for_each_entry(notify, &snd_pcm_notify_list, list) { + list_for_each(list, &snd_pcm_notify_list) { + struct snd_pcm_notify *notify; + notify = list_entry(list, struct snd_pcm_notify, list); notify->n_disconnect(pcm); } + mutex_unlock(®ister_mutex); + return 0; +} + +static int snd_pcm_dev_unregister(struct snd_device *device) +{ + int cidx, devtype; + struct snd_pcm_substream *substream; + struct list_head *list; + struct snd_pcm *pcm = device->device_data; + + snd_assert(pcm != NULL, return -ENXIO); + mutex_lock(®ister_mutex); + list_del(&pcm->list); for (cidx = 0; cidx < 2; cidx++) { devtype = -1; switch (cidx) { @@ -1011,20 +1011,23 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) break; } snd_unregister_device(devtype, pcm->card, pcm->device); + for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) + snd_pcm_timer_done(substream); + } + list_for_each(list, &snd_pcm_notify_list) { + struct snd_pcm_notify *notify; + notify = list_entry(list, struct snd_pcm_notify, list); + notify->n_unregister(pcm); } - unlock: mutex_unlock(®ister_mutex); - return 0; + return snd_pcm_free(pcm); } int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) { struct list_head *p; - snd_assert(notify != NULL && - notify->n_register != NULL && - notify->n_unregister != NULL && - notify->n_disconnect, return -EINVAL); + snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL); mutex_lock(®ister_mutex); if (nfree) { list_del(¬ify->list); @@ -1087,7 +1090,8 @@ static void snd_pcm_proc_init(void) static void snd_pcm_proc_done(void) { - snd_info_free_entry(snd_pcm_proc_entry); + if (snd_pcm_proc_entry) + snd_info_unregister(snd_pcm_proc_entry); } #else /* !CONFIG_PROC_FS */ diff --git a/trunk/sound/core/pcm_compat.c b/trunk/sound/core/pcm_compat.c index 2b539799d23b..2b8aab6fd6cd 100644 --- a/trunk/sound/core/pcm_compat.c +++ b/trunk/sound/core/pcm_compat.c @@ -478,7 +478,7 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l * mmap of PCM status/control records because of the size * incompatibility. */ - pcm_file->no_compat_mmap = 1; + substream->no_mmap_ctrl = 1; switch (cmd) { case SNDRV_PCM_IOCTL_PVERSION: diff --git a/trunk/sound/core/pcm_memory.c b/trunk/sound/core/pcm_memory.c index be030cb4d373..067d2056db9a 100644 --- a/trunk/sound/core/pcm_memory.c +++ b/trunk/sound/core/pcm_memory.c @@ -101,7 +101,7 @@ int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream) { snd_pcm_lib_preallocate_dma_free(substream); #ifdef CONFIG_SND_VERBOSE_PROCFS - snd_info_free_entry(substream->proc_prealloc_entry); + snd_info_unregister(substream->proc_prealloc_entry); substream->proc_prealloc_entry = NULL; #endif return 0; diff --git a/trunk/sound/core/pcm_native.c b/trunk/sound/core/pcm_native.c index 0224c70414f5..439f047929e1 100644 --- a/trunk/sound/core/pcm_native.c +++ b/trunk/sound/core/pcm_native.c @@ -1992,9 +1992,35 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) return 0; } +static void snd_pcm_add_file(struct snd_pcm_str *str, + struct snd_pcm_file *pcm_file) +{ + pcm_file->next = str->files; + str->files = pcm_file; +} + +static void snd_pcm_remove_file(struct snd_pcm_str *str, + struct snd_pcm_file *pcm_file) +{ + struct snd_pcm_file * pcm_file1; + if (str->files == pcm_file) { + str->files = pcm_file->next; + } else { + pcm_file1 = str->files; + while (pcm_file1 && pcm_file1->next != pcm_file) + pcm_file1 = pcm_file1->next; + if (pcm_file1 != NULL) + pcm_file1->next = pcm_file->next; + } +} + static void pcm_release_private(struct snd_pcm_substream *substream) { + struct snd_pcm_file *pcm_file = substream->file; + snd_pcm_unlink(substream); + snd_pcm_remove_file(substream->pstr, pcm_file); + kfree(pcm_file); } void snd_pcm_release_substream(struct snd_pcm_substream *substream) @@ -2034,6 +2060,7 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, return 0; } + substream->no_mmap_ctrl = 0; err = snd_pcm_hw_constraints_init(substream); if (err < 0) { snd_printd("snd_pcm_hw_constraints_init failed\n"); @@ -2078,16 +2105,19 @@ static int snd_pcm_open_file(struct file *file, if (err < 0) return err; - pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); - if (pcm_file == NULL) { - snd_pcm_release_substream(substream); - return -ENOMEM; - } - pcm_file->substream = substream; - if (substream->ref_count == 1) { + if (substream->ref_count > 1) + pcm_file = substream->file; + else { + pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); + if (pcm_file == NULL) { + snd_pcm_release_substream(substream); + return -ENOMEM; + } str = substream->pstr; substream->file = pcm_file; substream->pcm_release = pcm_release_private; + pcm_file->substream = substream; + snd_pcm_add_file(str, pcm_file); } file->private_data = pcm_file; *rpcm_file = pcm_file; @@ -2179,7 +2209,6 @@ static int snd_pcm_release(struct inode *inode, struct file *file) fasync_helper(-1, file, 0, &substream->runtime->fasync); mutex_lock(&pcm->open_mutex); snd_pcm_release_substream(substream); - kfree(pcm_file); mutex_unlock(&pcm->open_mutex); wake_up(&pcm->open_wait); module_put(pcm->card->module); @@ -3241,11 +3270,11 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) offset = area->vm_pgoff << PAGE_SHIFT; switch (offset) { case SNDRV_PCM_MMAP_OFFSET_STATUS: - if (pcm_file->no_compat_mmap) + if (substream->no_mmap_ctrl) return -ENXIO; return snd_pcm_mmap_status(substream, file, area); case SNDRV_PCM_MMAP_OFFSET_CONTROL: - if (pcm_file->no_compat_mmap) + if (substream->no_mmap_ctrl) return -ENXIO; return snd_pcm_mmap_control(substream, file, area); default: diff --git a/trunk/sound/core/rawmidi.c b/trunk/sound/core/rawmidi.c index 269c467ca9bb..8c15c66eb4aa 100644 --- a/trunk/sound/core/rawmidi.c +++ b/trunk/sound/core/rawmidi.c @@ -55,6 +55,7 @@ static int snd_rawmidi_free(struct snd_rawmidi *rawmidi); static int snd_rawmidi_dev_free(struct snd_device *device); static int snd_rawmidi_dev_register(struct snd_device *device); static int snd_rawmidi_dev_disconnect(struct snd_device *device); +static int snd_rawmidi_dev_unregister(struct snd_device *device); static LIST_HEAD(snd_rawmidi_devices); static DEFINE_MUTEX(register_mutex); @@ -430,8 +431,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) kctl = snd_ctl_file(list); if (kctl->pid == current->pid) { subdevice = kctl->prefer_rawmidi_subdevice; - if (subdevice != -1) - break; + break; } } up_read(&card->controls_rwsem); @@ -1426,6 +1426,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, .dev_free = snd_rawmidi_dev_free, .dev_register = snd_rawmidi_dev_register, .dev_disconnect = snd_rawmidi_dev_disconnect, + .dev_unregister = snd_rawmidi_dev_unregister }; snd_assert(rrawmidi != NULL, return -EINVAL); @@ -1478,14 +1479,6 @@ static void snd_rawmidi_free_substreams(struct snd_rawmidi_str *stream) static int snd_rawmidi_free(struct snd_rawmidi *rmidi) { snd_assert(rmidi != NULL, return -ENXIO); - - snd_info_free_entry(rmidi->proc_entry); - rmidi->proc_entry = NULL; - mutex_lock(®ister_mutex); - if (rmidi->ops && rmidi->ops->dev_unregister) - rmidi->ops->dev_unregister(rmidi); - mutex_unlock(®ister_mutex); - snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); if (rmidi->private_free) @@ -1594,6 +1587,21 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) mutex_lock(®ister_mutex); list_del_init(&rmidi->list); + mutex_unlock(®ister_mutex); + return 0; +} + +static int snd_rawmidi_dev_unregister(struct snd_device *device) +{ + struct snd_rawmidi *rmidi = device->device_data; + + snd_assert(rmidi != NULL, return -ENXIO); + mutex_lock(®ister_mutex); + list_del(&rmidi->list); + if (rmidi->proc_entry) { + snd_info_unregister(rmidi->proc_entry); + rmidi->proc_entry = NULL; + } #ifdef CONFIG_SND_OSSEMUL if (rmidi->ossreg) { if ((int)rmidi->device == midi_map[rmidi->card->number]) { @@ -1607,9 +1615,17 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) rmidi->ossreg = 0; } #endif /* CONFIG_SND_OSSEMUL */ + if (rmidi->ops && rmidi->ops->dev_unregister) + rmidi->ops->dev_unregister(rmidi); snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); mutex_unlock(®ister_mutex); - return 0; +#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) + if (rmidi->seq_dev) { + snd_device_free(rmidi->card, rmidi->seq_dev); + rmidi->seq_dev = NULL; + } +#endif + return snd_rawmidi_free(rmidi); } /** diff --git a/trunk/sound/core/rtctimer.c b/trunk/sound/core/rtctimer.c index 412dd62b654e..84704ccb1829 100644 --- a/trunk/sound/core/rtctimer.c +++ b/trunk/sound/core/rtctimer.c @@ -156,7 +156,7 @@ static int __init rtctimer_init(void) static void __exit rtctimer_exit(void) { if (rtctimer) { - snd_timer_global_free(rtctimer); + snd_timer_global_unregister(rtctimer); rtctimer = NULL; } } diff --git a/trunk/sound/core/seq/oss/seq_oss.c b/trunk/sound/core/seq/oss/seq_oss.c index 92858cf8b6eb..e7234135641c 100644 --- a/trunk/sound/core/seq/oss/seq_oss.c +++ b/trunk/sound/core/seq/oss/seq_oss.c @@ -303,7 +303,8 @@ register_proc(void) static void unregister_proc(void) { - snd_info_free_entry(info_entry); + if (info_entry) + snd_info_unregister(info_entry); info_entry = NULL; } #endif /* CONFIG_PROC_FS */ diff --git a/trunk/sound/core/seq/seq_device.c b/trunk/sound/core/seq/seq_device.c index b79d011813c0..4260de90f36f 100644 --- a/trunk/sound/core/seq/seq_device.c +++ b/trunk/sound/core/seq/seq_device.c @@ -90,6 +90,7 @@ static int snd_seq_device_free(struct snd_seq_device *dev); static int snd_seq_device_dev_free(struct snd_device *device); static int snd_seq_device_dev_register(struct snd_device *device); static int snd_seq_device_dev_disconnect(struct snd_device *device); +static int snd_seq_device_dev_unregister(struct snd_device *device); static int init_device(struct snd_seq_device *dev, struct ops_list *ops); static int free_device(struct snd_seq_device *dev, struct ops_list *ops); @@ -188,6 +189,7 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize, .dev_free = snd_seq_device_dev_free, .dev_register = snd_seq_device_dev_register, .dev_disconnect = snd_seq_device_dev_disconnect, + .dev_unregister = snd_seq_device_dev_unregister }; if (result) @@ -306,6 +308,15 @@ static int snd_seq_device_dev_disconnect(struct snd_device *device) return 0; } +/* + * unregister the existing device + */ +static int snd_seq_device_dev_unregister(struct snd_device *device) +{ + struct snd_seq_device *dev = device->device_data; + return snd_seq_device_free(dev); +} + /* * register device driver * id = driver id @@ -361,9 +372,10 @@ static struct ops_list * create_driver(char *id) { struct ops_list *ops; - ops = kzalloc(sizeof(*ops), GFP_KERNEL); + ops = kmalloc(sizeof(*ops), GFP_KERNEL); if (ops == NULL) return ops; + memset(ops, 0, sizeof(*ops)); /* set up driver entry */ strlcpy(ops->id, id, sizeof(ops->id)); @@ -562,7 +574,7 @@ static void __exit alsa_seq_device_exit(void) { remove_drivers(); #ifdef CONFIG_PROC_FS - snd_info_free_entry(info_entry); + snd_info_unregister(info_entry); #endif if (num_ops) snd_printk(KERN_ERR "drivers not released (%d)\n", num_ops); diff --git a/trunk/sound/core/seq/seq_info.c b/trunk/sound/core/seq/seq_info.c index 8a7fe5cca1c9..142e9e6882c9 100644 --- a/trunk/sound/core/seq/seq_info.c +++ b/trunk/sound/core/seq/seq_info.c @@ -64,9 +64,9 @@ int __init snd_seq_info_init(void) int __exit snd_seq_info_done(void) { - snd_info_free_entry(queues_entry); - snd_info_free_entry(clients_entry); - snd_info_free_entry(timer_entry); + snd_info_unregister(queues_entry); + snd_info_unregister(clients_entry); + snd_info_unregister(timer_entry); return 0; } #endif diff --git a/trunk/sound/core/sgbuf.c b/trunk/sound/core/sgbuf.c index c30669f14ac0..6e4d4ab34632 100644 --- a/trunk/sound/core/sgbuf.c +++ b/trunk/sound/core/sgbuf.c @@ -68,18 +68,21 @@ void *snd_malloc_sgbuf_pages(struct device *device, dmab->area = NULL; dmab->addr = 0; - dmab->private_data = sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL); + dmab->private_data = sgbuf = kmalloc(sizeof(*sgbuf), GFP_KERNEL); if (! sgbuf) return NULL; + memset(sgbuf, 0, sizeof(*sgbuf)); sgbuf->dev = device; pages = snd_sgbuf_aligned_pages(size); sgbuf->tblsize = sgbuf_align_table(pages); - sgbuf->table = kcalloc(sgbuf->tblsize, sizeof(*sgbuf->table), GFP_KERNEL); + sgbuf->table = kmalloc(sizeof(*sgbuf->table) * sgbuf->tblsize, GFP_KERNEL); if (! sgbuf->table) goto _failed; - sgbuf->page_table = kcalloc(sgbuf->tblsize, sizeof(*sgbuf->page_table), GFP_KERNEL); + memset(sgbuf->table, 0, sizeof(*sgbuf->table) * sgbuf->tblsize); + sgbuf->page_table = kmalloc(sizeof(*sgbuf->page_table) * sgbuf->tblsize, GFP_KERNEL); if (! sgbuf->page_table) goto _failed; + memset(sgbuf->page_table, 0, sizeof(*sgbuf->page_table) * sgbuf->tblsize); /* allocate each page */ for (i = 0; i < pages; i++) { diff --git a/trunk/sound/core/sound.c b/trunk/sound/core/sound.c index efa476c5210a..7edd1fc58b17 100644 --- a/trunk/sound/core/sound.c +++ b/trunk/sound/core/sound.c @@ -268,11 +268,7 @@ int snd_register_device(int type, struct snd_card *card, int dev, snd_minors[minor] = preg; if (card) device = card->dev; - preg->class_dev = class_device_create(sound_class, NULL, - MKDEV(major, minor), - device, "%s", name); - if (preg->class_dev) - class_set_devdata(preg->class_dev, private_data); + class_device_create(sound_class, NULL, MKDEV(major, minor), device, "%s", name); mutex_unlock(&sound_mutex); return 0; @@ -280,24 +276,6 @@ int snd_register_device(int type, struct snd_card *card, int dev, EXPORT_SYMBOL(snd_register_device); -/* find the matching minor record - * return the index of snd_minor, or -1 if not found - */ -static int find_snd_minor(int type, struct snd_card *card, int dev) -{ - int cardnum, minor; - struct snd_minor *mptr; - - cardnum = card ? card->number : -1; - for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) - if ((mptr = snd_minors[minor]) != NULL && - mptr->type == type && - mptr->card == cardnum && - mptr->device == dev) - return minor; - return -1; -} - /** * snd_unregister_device - unregister the device on the given card * @type: the device type, SNDRV_DEVICE_TYPE_XXX @@ -311,42 +289,32 @@ static int find_snd_minor(int type, struct snd_card *card, int dev) */ int snd_unregister_device(int type, struct snd_card *card, int dev) { - int minor; + int cardnum, minor; + struct snd_minor *mptr; + cardnum = card ? card->number : -1; mutex_lock(&sound_mutex); - minor = find_snd_minor(type, card, dev); - if (minor < 0) { + for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) + if ((mptr = snd_minors[minor]) != NULL && + mptr->type == type && + mptr->card == cardnum && + mptr->device == dev) + break; + if (minor == ARRAY_SIZE(snd_minors)) { mutex_unlock(&sound_mutex); return -EINVAL; } class_device_destroy(sound_class, MKDEV(major, minor)); - kfree(snd_minors[minor]); snd_minors[minor] = NULL; mutex_unlock(&sound_mutex); + kfree(mptr); return 0; } EXPORT_SYMBOL(snd_unregister_device); -int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev, - const struct class_device_attribute *attr) -{ - int minor, ret = -EINVAL; - struct class_device *cdev; - - mutex_lock(&sound_mutex); - minor = find_snd_minor(type, card, dev); - if (minor >= 0 && (cdev = snd_minors[minor]->class_dev) != NULL) - ret = class_device_create_file(cdev, attr); - mutex_unlock(&sound_mutex); - return ret; - -} - -EXPORT_SYMBOL(snd_add_device_sysfs_file); - #ifdef CONFIG_PROC_FS /* * INFO PART @@ -419,7 +387,8 @@ int __init snd_minor_info_init(void) int __exit snd_minor_info_done(void) { - snd_info_free_entry(snd_minor_info_entry); + if (snd_minor_info_entry) + snd_info_unregister(snd_minor_info_entry); return 0; } #endif /* CONFIG_PROC_FS */ diff --git a/trunk/sound/core/sound_oss.c b/trunk/sound/core/sound_oss.c index b2fc40aa520b..74f0fe5a1ba0 100644 --- a/trunk/sound/core/sound_oss.c +++ b/trunk/sound/core/sound_oss.c @@ -270,7 +270,8 @@ int __init snd_minor_info_oss_init(void) int __exit snd_minor_info_oss_done(void) { - snd_info_free_entry(snd_minor_info_oss_entry); + if (snd_minor_info_oss_entry) + snd_info_unregister(snd_minor_info_oss_entry); return 0; } #endif /* CONFIG_PROC_FS */ diff --git a/trunk/sound/core/timer.c b/trunk/sound/core/timer.c index 10a79aed33f8..0a984e881c10 100644 --- a/trunk/sound/core/timer.c +++ b/trunk/sound/core/timer.c @@ -88,7 +88,7 @@ static DEFINE_MUTEX(register_mutex); static int snd_timer_free(struct snd_timer *timer); static int snd_timer_dev_free(struct snd_device *device); static int snd_timer_dev_register(struct snd_device *device); -static int snd_timer_dev_disconnect(struct snd_device *device); +static int snd_timer_dev_unregister(struct snd_device *device); static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left); @@ -718,7 +718,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) } } if (timer->flags & SNDRV_TIMER_FLG_RESCHED) - snd_timer_reschedule(timer, timer->sticks); + snd_timer_reschedule(timer, ticks_left); if (timer->running) { if (timer->hw.flags & SNDRV_TIMER_HW_STOP) { timer->hw.stop(timer); @@ -773,7 +773,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, static struct snd_device_ops ops = { .dev_free = snd_timer_dev_free, .dev_register = snd_timer_dev_register, - .dev_disconnect = snd_timer_dev_disconnect, + .dev_unregister = snd_timer_dev_unregister }; snd_assert(tid != NULL, return -EINVAL); @@ -813,21 +813,6 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, static int snd_timer_free(struct snd_timer *timer) { snd_assert(timer != NULL, return -ENXIO); - - mutex_lock(®ister_mutex); - if (! list_empty(&timer->open_list_head)) { - struct list_head *p, *n; - struct snd_timer_instance *ti; - snd_printk(KERN_WARNING "timer %p is busy?\n", timer); - list_for_each_safe(p, n, &timer->open_list_head) { - list_del_init(p); - ti = list_entry(p, struct snd_timer_instance, open_list); - ti->timer = NULL; - } - } - list_del(&timer->device_list); - mutex_unlock(®ister_mutex); - if (timer->private_free) timer->private_free(timer); kfree(timer); @@ -882,13 +867,30 @@ static int snd_timer_dev_register(struct snd_device *dev) return 0; } -static int snd_timer_dev_disconnect(struct snd_device *device) +static int snd_timer_unregister(struct snd_timer *timer) { - struct snd_timer *timer = device->device_data; + struct list_head *p, *n; + struct snd_timer_instance *ti; + + snd_assert(timer != NULL, return -ENXIO); mutex_lock(®ister_mutex); - list_del_init(&timer->device_list); + if (! list_empty(&timer->open_list_head)) { + snd_printk(KERN_WARNING "timer 0x%lx is busy?\n", (long)timer); + list_for_each_safe(p, n, &timer->open_list_head) { + list_del_init(p); + ti = list_entry(p, struct snd_timer_instance, open_list); + ti->timer = NULL; + } + } + list_del(&timer->device_list); mutex_unlock(®ister_mutex); - return 0; + return snd_timer_free(timer); +} + +static int snd_timer_dev_unregister(struct snd_device *device) +{ + struct snd_timer *timer = device->device_data; + return snd_timer_unregister(timer); } void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp) @@ -953,12 +955,18 @@ int snd_timer_global_register(struct snd_timer *timer) return snd_timer_dev_register(&dev); } +int snd_timer_global_unregister(struct snd_timer *timer) +{ + return snd_timer_unregister(timer); +} + /* * System timer */ struct snd_timer_system_private { struct timer_list tlist; + struct timer * timer; unsigned long last_expires; unsigned long last_jiffies; unsigned long correction; @@ -970,7 +978,7 @@ static void snd_timer_s_function(unsigned long data) struct snd_timer_system_private *priv = timer->private_data; unsigned long jiff = jiffies; if (time_after(jiff, priv->last_expires)) - priv->correction += (long)jiff - (long)priv->last_expires; + priv->correction = (long)jiff - (long)priv->last_expires; snd_timer_interrupt(timer, (long)jiff - (long)priv->last_jiffies); } @@ -986,7 +994,7 @@ static int snd_timer_s_start(struct snd_timer * timer) njiff++; } else { njiff += timer->sticks - priv->correction; - priv->correction = 0; + priv->correction -= timer->sticks; } priv->last_expires = priv->tlist.expires = njiff; add_timer(&priv->tlist); @@ -1005,7 +1013,6 @@ static int snd_timer_s_stop(struct snd_timer * timer) timer->sticks = priv->last_expires - jiff; else timer->sticks = 1; - priv->correction = 0; return 0; } @@ -1119,7 +1126,7 @@ static void __init snd_timer_proc_init(void) static void __exit snd_timer_proc_done(void) { - snd_info_free_entry(snd_timer_proc_entry); + snd_info_unregister(snd_timer_proc_entry); } #else /* !CONFIG_PROC_FS */ #define snd_timer_proc_init() @@ -1975,7 +1982,7 @@ static void __exit alsa_timer_exit(void) /* unregister the system timer */ list_for_each_safe(p, n, &snd_timer_list) { struct snd_timer *timer = list_entry(p, struct snd_timer, device_list); - snd_timer_free(timer); + snd_timer_unregister(timer); } snd_timer_proc_done(); #ifdef SNDRV_OSS_INFO_DEV_TIMERS @@ -1998,4 +2005,5 @@ EXPORT_SYMBOL(snd_timer_notify); EXPORT_SYMBOL(snd_timer_global_new); EXPORT_SYMBOL(snd_timer_global_free); EXPORT_SYMBOL(snd_timer_global_register); +EXPORT_SYMBOL(snd_timer_global_unregister); EXPORT_SYMBOL(snd_timer_interrupt); diff --git a/trunk/sound/drivers/Kconfig b/trunk/sound/drivers/Kconfig index 7971285dfd5b..395c4ef52ac9 100644 --- a/trunk/sound/drivers/Kconfig +++ b/trunk/sound/drivers/Kconfig @@ -73,19 +73,6 @@ config SND_MTPAV To compile this driver as a module, choose M here: the module will be called snd-mtpav. -config SND_MTS64 - tristate "ESI Miditerminal 4140 driver" - depends on SND && PARPORT - select SND_RAWMIDI - help - The ESI Miditerminal 4140 is a 4 In 4 Out MIDI Interface with - additional SMPTE Timecode capabilities for the parallel port. - - Say 'Y' to include support for this device. - - To compile this driver as a module, chose 'M' here: the module - will be called snd-mts64. - config SND_SERIAL_U16550 tristate "UART16550 serial MIDI driver" depends on SND diff --git a/trunk/sound/drivers/Makefile b/trunk/sound/drivers/Makefile index c9bad6d67e73..cb98c3d662be 100644 --- a/trunk/sound/drivers/Makefile +++ b/trunk/sound/drivers/Makefile @@ -5,7 +5,6 @@ snd-dummy-objs := dummy.o snd-mtpav-objs := mtpav.o -snd-mts64-objs := mts64.o snd-serial-u16550-objs := serial-u16550.o snd-virmidi-objs := virmidi.o @@ -14,6 +13,5 @@ obj-$(CONFIG_SND_DUMMY) += snd-dummy.o obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o -obj-$(CONFIG_SND_MTS64) += snd-mts64.o obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/ diff --git a/trunk/sound/drivers/dummy.c b/trunk/sound/drivers/dummy.c index 42001efa9f3e..ffeafaf2ecca 100644 --- a/trunk/sound/drivers/dummy.c +++ b/trunk/sound/drivers/dummy.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -286,7 +285,7 @@ static struct snd_pcm_hardware snd_card_dummy_playback = .channels_max = USE_CHANNELS_MAX, .buffer_bytes_max = MAX_BUFFER_SIZE, .period_bytes_min = 64, - .period_bytes_max = MAX_PERIOD_SIZE, + .period_bytes_max = MAX_BUFFER_SIZE, .periods_min = USE_PERIODS_MIN, .periods_max = USE_PERIODS_MAX, .fifo_size = 0, @@ -444,13 +443,10 @@ static int __init snd_card_dummy_pcm(struct snd_dummy *dummy, int device, int su } #define DUMMY_VOLUME(xname, xindex, addr) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .index = xindex, \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ .info = snd_dummy_volume_info, \ .get = snd_dummy_volume_get, .put = snd_dummy_volume_put, \ - .private_value = addr, \ - .tlv = { .p = db_scale_dummy } } + .private_value = addr } static int snd_dummy_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) @@ -501,8 +497,6 @@ static int snd_dummy_volume_put(struct snd_kcontrol *kcontrol, return change; } -static DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0); - #define DUMMY_CAPSRC(xname, xindex, addr) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ .info = snd_dummy_capsrc_info, \ @@ -553,13 +547,13 @@ static struct snd_kcontrol_new snd_dummy_controls[] = { DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER), DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER), DUMMY_VOLUME("Synth Volume", 0, MIXER_ADDR_SYNTH), -DUMMY_CAPSRC("Synth Capture Switch", 0, MIXER_ADDR_SYNTH), +DUMMY_CAPSRC("Synth Capture Switch", 0, MIXER_ADDR_MASTER), DUMMY_VOLUME("Line Volume", 0, MIXER_ADDR_LINE), -DUMMY_CAPSRC("Line Capture Switch", 0, MIXER_ADDR_LINE), +DUMMY_CAPSRC("Line Capture Switch", 0, MIXER_ADDR_MASTER), DUMMY_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC), -DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MIC), +DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MASTER), DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD), -DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_CD) +DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_MASTER) }; static int __init snd_card_dummy_new_mixer(struct snd_dummy *dummy) diff --git a/trunk/sound/drivers/mpu401/mpu401.c b/trunk/sound/drivers/mpu401/mpu401.c index 2de181ad0b05..17cc105b26fc 100644 --- a/trunk/sound/drivers/mpu401/mpu401.c +++ b/trunk/sound/drivers/mpu401/mpu401.c @@ -211,7 +211,7 @@ static void __devexit snd_mpu401_pnp_remove(struct pnp_dev *dev) struct snd_card *card = (struct snd_card *) pnp_get_drvdata(dev); snd_card_disconnect(card); - snd_card_free_when_closed(card); + snd_card_free_in_thread(card); } static struct pnp_driver snd_mpu401_pnp_driver = { diff --git a/trunk/sound/drivers/mts64.c b/trunk/sound/drivers/mts64.c deleted file mode 100644 index 169987302ae4..000000000000 --- a/trunk/sound/drivers/mts64.c +++ /dev/null @@ -1,1091 +0,0 @@ -/* - * ALSA Driver for Ego Systems Inc. (ESI) Miditerminal 4140 - * Copyright (c) 2006 by Matthias König - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CARD_NAME "Miditerminal 4140" -#define DRIVER_NAME "MTS64" -#define PLATFORM_DRIVER "snd_mts64" - -static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; -static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; - -static struct platform_device *platform_devices[SNDRV_CARDS]; -static int device_count; - -module_param_array(index, int, NULL, S_IRUGO); -MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, NULL, S_IRUGO); -MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, NULL, S_IRUGO); -MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); - -MODULE_AUTHOR("Matthias Koenig "); -MODULE_DESCRIPTION("ESI Miditerminal 4140"); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("{{ESI,Miditerminal 4140}}"); - -/********************************************************************* - * Chip specific - *********************************************************************/ -#define MTS64_NUM_INPUT_PORTS 5 -#define MTS64_NUM_OUTPUT_PORTS 4 -#define MTS64_SMPTE_SUBSTREAM 4 - -struct mts64 { - spinlock_t lock; - struct snd_card *card; - struct snd_rawmidi *rmidi; - struct pardevice *pardev; - int pardev_claimed; - - int open_count; - int current_midi_output_port; - int current_midi_input_port; - u8 mode[MTS64_NUM_INPUT_PORTS]; - struct snd_rawmidi_substream *midi_input_substream[MTS64_NUM_INPUT_PORTS]; - int smpte_switch; - u8 time[4]; /* [0]=hh, [1]=mm, [2]=ss, [3]=ff */ - u8 fps; -}; - -static int snd_mts64_free(struct mts64 *mts) -{ - kfree(mts); - return 0; -} - -static int __devinit snd_mts64_create(struct snd_card *card, - struct pardevice *pardev, - struct mts64 **rchip) -{ - struct mts64 *mts; - - *rchip = NULL; - - mts = kzalloc(sizeof(struct mts64), GFP_KERNEL); - if (mts == NULL) - return -ENOMEM; - - /* Init chip specific data */ - spin_lock_init(&mts->lock); - mts->card = card; - mts->pardev = pardev; - mts->current_midi_output_port = -1; - mts->current_midi_input_port = -1; - - *rchip = mts; - - return 0; -} - -/********************************************************************* - * HW register related constants - *********************************************************************/ - -/* Status Bits */ -#define MTS64_STAT_BSY 0x80 -#define MTS64_STAT_BIT_SET 0x20 /* readout process, bit is set */ -#define MTS64_STAT_PORT 0x10 /* read byte is a port number */ - -/* Control Bits */ -#define MTS64_CTL_READOUT 0x08 /* enable readout */ -#define MTS64_CTL_WRITE_CMD 0x06 -#define MTS64_CTL_WRITE_DATA 0x02 -#define MTS64_CTL_STROBE 0x01 - -/* Command */ -#define MTS64_CMD_RESET 0xfe -#define MTS64_CMD_PROBE 0x8f /* Used in probing procedure */ -#define MTS64_CMD_SMPTE_SET_TIME 0xe8 -#define MTS64_CMD_SMPTE_SET_FPS 0xee -#define MTS64_CMD_SMPTE_STOP 0xef -#define MTS64_CMD_SMPTE_FPS_24 0xe3 -#define MTS64_CMD_SMPTE_FPS_25 0xe2 -#define MTS64_CMD_SMPTE_FPS_2997 0xe4 -#define MTS64_CMD_SMPTE_FPS_30D 0xe1 -#define MTS64_CMD_SMPTE_FPS_30 0xe0 -#define MTS64_CMD_COM_OPEN 0xf8 /* setting the communication mode */ -#define MTS64_CMD_COM_CLOSE1 0xff /* clearing communication mode */ -#define MTS64_CMD_COM_CLOSE2 0xf5 - -/********************************************************************* - * Hardware specific functions - *********************************************************************/ -static void mts64_enable_readout(struct parport *p); -static void mts64_disable_readout(struct parport *p); -static int mts64_device_ready(struct parport *p); -static int mts64_device_init(struct parport *p); -static int mts64_device_open(struct mts64 *mts); -static int mts64_device_close(struct mts64 *mts); -static u8 mts64_map_midi_input(u8 c); -static int mts64_probe(struct parport *p); -static u16 mts64_read(struct parport *p); -static u8 mts64_read_char(struct parport *p); -static void mts64_smpte_start(struct parport *p, - u8 hours, u8 minutes, - u8 seconds, u8 frames, - u8 idx); -static void mts64_smpte_stop(struct parport *p); -static void mts64_write_command(struct parport *p, u8 c); -static void mts64_write_data(struct parport *p, u8 c); -static void mts64_write_midi(struct mts64 *mts, u8 c, int midiport); - - -/* Enables the readout procedure - * - * Before we can read a midi byte from the device, we have to set - * bit 3 of control port. - */ -static void mts64_enable_readout(struct parport *p) -{ - u8 c; - - c = parport_read_control(p); - c |= MTS64_CTL_READOUT; - parport_write_control(p, c); -} - -/* Disables readout - * - * Readout is disabled by clearing bit 3 of control - */ -static void mts64_disable_readout(struct parport *p) -{ - u8 c; - - c = parport_read_control(p); - c &= ~MTS64_CTL_READOUT; - parport_write_control(p, c); -} - -/* waits for device ready - * - * Checks if BUSY (Bit 7 of status) is clear - * 1 device ready - * 0 failure - */ -static int mts64_device_ready(struct parport *p) -{ - int i; - u8 c; - - for (i = 0; i < 0xffff; ++i) { - c = parport_read_status(p); - c &= MTS64_STAT_BSY; - if (c != 0) - return 1; - } - - return 0; -} - -/* Init device (LED blinking startup magic) - * - * Returns: - * 0 init ok - * -EIO failure - */ -static int __devinit mts64_device_init(struct parport *p) -{ - int i; - - mts64_write_command(p, MTS64_CMD_RESET); - - for (i = 0; i < 64; ++i) { - msleep(100); - - if (mts64_probe(p) == 0) { - /* success */ - mts64_disable_readout(p); - return 0; - } - } - mts64_disable_readout(p); - - return -EIO; -} - -/* - * Opens the device (set communication mode) - */ -static int mts64_device_open(struct mts64 *mts) -{ - int i; - struct parport *p = mts->pardev->port; - - for (i = 0; i < 5; ++i) - mts64_write_command(p, MTS64_CMD_COM_OPEN); - - return 0; -} - -/* - * Close device (clear communication mode) - */ -static int mts64_device_close(struct mts64 *mts) -{ - int i; - struct parport *p = mts->pardev->port; - - for (i = 0; i < 5; ++i) { - mts64_write_command(p, MTS64_CMD_COM_CLOSE1); - mts64_write_command(p, MTS64_CMD_COM_CLOSE2); - } - - return 0; -} - -/* map hardware port to substream number - * - * When reading a byte from the device, the device tells us - * on what port the byte is. This HW port has to be mapped to - * the midiport (substream number). - * substream 0-3 are Midiports 1-4 - * substream 4 is SMPTE Timecode - * The mapping is done by the table: - * HW | 0 | 1 | 2 | 3 | 4 - * SW | 0 | 1 | 4 | 2 | 3 - */ -static u8 mts64_map_midi_input(u8 c) -{ - static u8 map[] = { 0, 1, 4, 2, 3 }; - - return map[c]; -} - - -/* Probe parport for device - * - * Do we have a Miditerminal 4140 on parport? - * Returns: - * 0 device found - * -ENODEV no device - */ -static int __devinit mts64_probe(struct parport *p) -{ - u8 c; - - mts64_smpte_stop(p); - mts64_write_command(p, MTS64_CMD_PROBE); - - msleep(50); - - c = mts64_read(p); - - c &= 0x00ff; - if (c != MTS64_CMD_PROBE) - return -ENODEV; - else - return 0; - -} - -/* Read byte incl. status from device - * - * Returns: - * data in lower 8 bits and status in upper 8 bits - */ -static u16 mts64_read(struct parport *p) -{ - u8 data, status; - - mts64_device_ready(p); - mts64_enable_readout(p); - status = parport_read_status(p); - data = mts64_read_char(p); - mts64_disable_readout(p); - - return (status << 8) | data; -} - -/* Read a byte from device - * - * Note, that readout mode has to be enabled. - * readout procedure is as follows: - * - Write number of the Bit to read to DATA - * - Read STATUS - * - Bit 5 of STATUS indicates if Bit is set - * - * Returns: - * Byte read from device - */ -static u8 mts64_read_char(struct parport *p) -{ - u8 c = 0; - u8 status; - u8 i; - - for (i = 0; i < 8; ++i) { - parport_write_data(p, i); - c >>= 1; - status = parport_read_status(p); - if (status & MTS64_STAT_BIT_SET) - c |= 0x80; - } - - return c; -} - -/* Starts SMPTE Timecode generation - * - * The device creates SMPTE Timecode by hardware. - * 0 24 fps - * 1 25 fps - * 2 29.97 fps - * 3 30 fps (Drop-frame) - * 4 30 fps - */ -static void mts64_smpte_start(struct parport *p, - u8 hours, u8 minutes, - u8 seconds, u8 frames, - u8 idx) -{ - static u8 fps[5] = { MTS64_CMD_SMPTE_FPS_24, - MTS64_CMD_SMPTE_FPS_25, - MTS64_CMD_SMPTE_FPS_2997, - MTS64_CMD_SMPTE_FPS_30D, - MTS64_CMD_SMPTE_FPS_30 }; - - mts64_write_command(p, MTS64_CMD_SMPTE_SET_TIME); - mts64_write_command(p, frames); - mts64_write_command(p, seconds); - mts64_write_command(p, minutes); - mts64_write_command(p, hours); - - mts64_write_command(p, MTS64_CMD_SMPTE_SET_FPS); - mts64_write_command(p, fps[idx]); -} - -/* Stops SMPTE Timecode generation - */ -static void mts64_smpte_stop(struct parport *p) -{ - mts64_write_command(p, MTS64_CMD_SMPTE_STOP); -} - -/* Write a command byte to device - */ -static void mts64_write_command(struct parport *p, u8 c) -{ - mts64_device_ready(p); - - parport_write_data(p, c); - - parport_write_control(p, MTS64_CTL_WRITE_CMD); - parport_write_control(p, MTS64_CTL_WRITE_CMD | MTS64_CTL_STROBE); - parport_write_control(p, MTS64_CTL_WRITE_CMD); -} - -/* Write a data byte to device - */ -static void mts64_write_data(struct parport *p, u8 c) -{ - mts64_device_ready(p); - - parport_write_data(p, c); - - parport_write_control(p, MTS64_CTL_WRITE_DATA); - parport_write_control(p, MTS64_CTL_WRITE_DATA | MTS64_CTL_STROBE); - parport_write_control(p, MTS64_CTL_WRITE_DATA); -} - -/* Write a MIDI byte to midiport - * - * midiport ranges from 0-3 and maps to Ports 1-4 - * assumptions: communication mode is on - */ -static void mts64_write_midi(struct mts64 *mts, u8 c, - int midiport) -{ - struct parport *p = mts->pardev->port; - - /* check current midiport */ - if (mts->current_midi_output_port != midiport) - mts64_write_command(p, midiport); - - /* write midi byte */ - mts64_write_data(p, c); -} - -/********************************************************************* - * Control elements - *********************************************************************/ - -/* SMPTE Switch */ -static int snd_mts64_ctl_smpte_switch_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int snd_mts64_ctl_smpte_switch_get(struct snd_kcontrol* kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - - spin_lock_irq(&mts->lock); - uctl->value.integer.value[0] = mts->smpte_switch; - spin_unlock_irq(&mts->lock); - - return 0; -} - -/* smpte_switch is not accessed from IRQ handler, so we just need - to protect the HW access */ -static int snd_mts64_ctl_smpte_switch_put(struct snd_kcontrol* kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - int changed = 0; - - spin_lock_irq(&mts->lock); - if (mts->smpte_switch == uctl->value.integer.value[0]) - goto __out; - - changed = 1; - mts->smpte_switch = uctl->value.integer.value[0]; - if (mts->smpte_switch) { - mts64_smpte_start(mts->pardev->port, - mts->time[0], mts->time[1], - mts->time[2], mts->time[3], - mts->fps); - } else { - mts64_smpte_stop(mts->pardev->port); - } -__out: - spin_unlock_irq(&mts->lock); - return changed; -} - -static struct snd_kcontrol_new mts64_ctl_smpte_switch __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Playback Switch", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0, - .info = snd_mts64_ctl_smpte_switch_info, - .get = snd_mts64_ctl_smpte_switch_get, - .put = snd_mts64_ctl_smpte_switch_put -}; - -/* Time */ -static int snd_mts64_ctl_smpte_time_h_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 23; - return 0; -} - -static int snd_mts64_ctl_smpte_time_f_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 99; - return 0; -} - -static int snd_mts64_ctl_smpte_time_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 59; - return 0; -} - -static int snd_mts64_ctl_smpte_time_get(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - int idx = kctl->private_value; - - spin_lock_irq(&mts->lock); - uctl->value.integer.value[0] = mts->time[idx]; - spin_unlock_irq(&mts->lock); - - return 0; -} - -static int snd_mts64_ctl_smpte_time_put(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - int idx = kctl->private_value; - int changed = 0; - - spin_lock_irq(&mts->lock); - if (mts->time[idx] != uctl->value.integer.value[0]) { - changed = 1; - mts->time[idx] = uctl->value.integer.value[0]; - } - spin_unlock_irq(&mts->lock); - - return changed; -} - -static struct snd_kcontrol_new mts64_ctl_smpte_time_hours __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Time Hours", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0, - .info = snd_mts64_ctl_smpte_time_h_info, - .get = snd_mts64_ctl_smpte_time_get, - .put = snd_mts64_ctl_smpte_time_put -}; - -static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Time Minutes", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 1, - .info = snd_mts64_ctl_smpte_time_info, - .get = snd_mts64_ctl_smpte_time_get, - .put = snd_mts64_ctl_smpte_time_put -}; - -static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Time Seconds", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 2, - .info = snd_mts64_ctl_smpte_time_info, - .get = snd_mts64_ctl_smpte_time_get, - .put = snd_mts64_ctl_smpte_time_put -}; - -static struct snd_kcontrol_new mts64_ctl_smpte_time_frames __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Time Frames", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 3, - .info = snd_mts64_ctl_smpte_time_f_info, - .get = snd_mts64_ctl_smpte_time_get, - .put = snd_mts64_ctl_smpte_time_put -}; - -/* FPS */ -static int snd_mts64_ctl_smpte_fps_info(struct snd_kcontrol *kctl, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[5] = { "24", - "25", - "29.97", - "30D", - "30" }; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 1; - uinfo->value.enumerated.items = 5; - if (uinfo->value.enumerated.item > 4) - uinfo->value.enumerated.item = 4; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_mts64_ctl_smpte_fps_get(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - - spin_lock_irq(&mts->lock); - uctl->value.enumerated.item[0] = mts->fps; - spin_unlock_irq(&mts->lock); - - return 0; -} - -static int snd_mts64_ctl_smpte_fps_put(struct snd_kcontrol *kctl, - struct snd_ctl_elem_value *uctl) -{ - struct mts64 *mts = snd_kcontrol_chip(kctl); - int changed = 0; - - spin_lock_irq(&mts->lock); - if (mts->fps != uctl->value.enumerated.item[0]) { - changed = 1; - mts->fps = uctl->value.enumerated.item[0]; - } - spin_unlock_irq(&mts->lock); - - return changed; -} - -static struct snd_kcontrol_new mts64_ctl_smpte_fps __devinitdata = { - .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, - .name = "SMPTE Fps", - .index = 0, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .private_value = 0, - .info = snd_mts64_ctl_smpte_fps_info, - .get = snd_mts64_ctl_smpte_fps_get, - .put = snd_mts64_ctl_smpte_fps_put -}; - - -static int __devinit snd_mts64_ctl_create(struct snd_card *card, - struct mts64 *mts) -{ - int err, i; - static struct snd_kcontrol_new *control[] = { - &mts64_ctl_smpte_switch, - &mts64_ctl_smpte_time_hours, - &mts64_ctl_smpte_time_minutes, - &mts64_ctl_smpte_time_seconds, - &mts64_ctl_smpte_time_frames, - &mts64_ctl_smpte_fps, - 0 }; - - for (i = 0; control[i]; ++i) { - err = snd_ctl_add(card, snd_ctl_new1(control[i], mts)); - if (err < 0) { - snd_printd("Cannot create control: %s\n", - control[i]->name); - return err; - } - } - - return 0; -} - -/********************************************************************* - * Rawmidi - *********************************************************************/ -#define MTS64_MODE_INPUT_TRIGGERED 0x01 - -static int snd_mts64_rawmidi_open(struct snd_rawmidi_substream *substream) -{ - struct mts64 *mts = substream->rmidi->private_data; - - if (mts->open_count == 0) { - /* We don't need a spinlock here, because this is just called - if the device has not been opened before. - So there aren't any IRQs from the device */ - mts64_device_open(mts); - - msleep(50); - } - ++(mts->open_count); - - return 0; -} - -static int snd_mts64_rawmidi_close(struct snd_rawmidi_substream *substream) -{ - struct mts64 *mts = substream->rmidi->private_data; - unsigned long flags; - - --(mts->open_count); - if (mts->open_count == 0) { - /* We need the spinlock_irqsave here because we can still - have IRQs at this point */ - spin_lock_irqsave(&mts->lock, flags); - mts64_device_close(mts); - spin_unlock_irqrestore(&mts->lock, flags); - - msleep(500); - - } else if (mts->open_count < 0) - mts->open_count = 0; - - return 0; -} - -static void snd_mts64_rawmidi_output_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct mts64 *mts = substream->rmidi->private_data; - u8 data; - unsigned long flags; - - spin_lock_irqsave(&mts->lock, flags); - while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) { - mts64_write_midi(mts, data, substream->number+1); - snd_rawmidi_transmit_ack(substream, 1); - } - spin_unlock_irqrestore(&mts->lock, flags); -} - -static void snd_mts64_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, - int up) -{ - struct mts64 *mts = substream->rmidi->private_data; - unsigned long flags; - - spin_lock_irqsave(&mts->lock, flags); - if (up) - mts->mode[substream->number] |= MTS64_MODE_INPUT_TRIGGERED; - else - mts->mode[substream->number] &= ~MTS64_MODE_INPUT_TRIGGERED; - - spin_unlock_irqrestore(&mts->lock, flags); -} - -static struct snd_rawmidi_ops snd_mts64_rawmidi_output_ops = { - .open = snd_mts64_rawmidi_open, - .close = snd_mts64_rawmidi_close, - .trigger = snd_mts64_rawmidi_output_trigger -}; - -static struct snd_rawmidi_ops snd_mts64_rawmidi_input_ops = { - .open = snd_mts64_rawmidi_open, - .close = snd_mts64_rawmidi_close, - .trigger = snd_mts64_rawmidi_input_trigger -}; - -/* Create and initialize the rawmidi component */ -static int __devinit snd_mts64_rawmidi_create(struct snd_card *card) -{ - struct mts64 *mts = card->private_data; - struct snd_rawmidi *rmidi; - struct snd_rawmidi_substream *substream; - struct list_head *list; - int err; - - err = snd_rawmidi_new(card, CARD_NAME, 0, - MTS64_NUM_OUTPUT_PORTS, - MTS64_NUM_INPUT_PORTS, - &rmidi); - if (err < 0) - return err; - - rmidi->private_data = mts; - strcpy(rmidi->name, CARD_NAME); - rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT | - SNDRV_RAWMIDI_INFO_INPUT | - SNDRV_RAWMIDI_INFO_DUPLEX; - - mts->rmidi = rmidi; - - /* register rawmidi ops */ - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, - &snd_mts64_rawmidi_output_ops); - snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, - &snd_mts64_rawmidi_input_ops); - - /* name substreams */ - /* output */ - list_for_each(list, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { - substream = list_entry(list, struct snd_rawmidi_substream, list); - sprintf(substream->name, - "Miditerminal %d", substream->number+1); - } - /* input */ - list_for_each(list, - &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) { - substream = list_entry(list, struct snd_rawmidi_substream, list); - mts->midi_input_substream[substream->number] = substream; - switch(substream->number) { - case MTS64_SMPTE_SUBSTREAM: - strcpy(substream->name, "Miditerminal SMPTE"); - break; - default: - sprintf(substream->name, - "Miditerminal %d", substream->number+1); - } - } - - /* controls */ - err = snd_mts64_ctl_create(card, mts); - - return err; -} - -/********************************************************************* - * parport stuff - *********************************************************************/ -static void snd_mts64_interrupt(int irq, void *private, struct pt_regs *r) -{ - struct mts64 *mts = ((struct snd_card*)private)->private_data; - u16 ret; - u8 status, data; - struct snd_rawmidi_substream *substream; - - spin_lock(&mts->lock); - ret = mts64_read(mts->pardev->port); - data = ret & 0x00ff; - status = ret >> 8; - - if (status & MTS64_STAT_PORT) { - mts->current_midi_input_port = mts64_map_midi_input(data); - } else { - if (mts->current_midi_input_port == -1) - goto __out; - substream = mts->midi_input_substream[mts->current_midi_input_port]; - if (mts->mode[substream->number] & MTS64_MODE_INPUT_TRIGGERED) - snd_rawmidi_receive(substream, &data, 1); - } -__out: - spin_unlock(&mts->lock); -} - -static int __devinit snd_mts64_probe_port(struct parport *p) -{ - struct pardevice *pardev; - int res; - - pardev = parport_register_device(p, DRIVER_NAME, - NULL, NULL, NULL, - 0, NULL); - if (!pardev) - return -EIO; - - if (parport_claim(pardev)) { - parport_unregister_device(pardev); - return -EIO; - } - - res = mts64_probe(p); - - parport_release(pardev); - parport_unregister_device(pardev); - - return res; -} - -static void __devinit snd_mts64_attach(struct parport *p) -{ - struct platform_device *device; - - device = platform_device_alloc(PLATFORM_DRIVER, device_count); - if (!device) - return; - - /* Temporary assignment to forward the parport */ - platform_set_drvdata(device, p); - - if (platform_device_register(device) < 0) { - platform_device_put(device); - return; - } - - /* Since we dont get the return value of probe - * We need to check if device probing succeeded or not */ - if (!platform_get_drvdata(device)) { - platform_device_unregister(device); - return; - } - - /* register device in global table */ - platform_devices[device_count] = device; - device_count++; -} - -static void snd_mts64_detach(struct parport *p) -{ - /* nothing to do here */ -} - -static struct parport_driver mts64_parport_driver = { - .name = "mts64", - .attach = snd_mts64_attach, - .detach = snd_mts64_detach -}; - -/********************************************************************* - * platform stuff - *********************************************************************/ -static void snd_mts64_card_private_free(struct snd_card *card) -{ - struct mts64 *mts = card->private_data; - struct pardevice *pardev = mts->pardev; - - if (pardev) { - if (mts->pardev_claimed) - parport_release(pardev); - parport_unregister_device(pardev); - } - - snd_mts64_free(mts); -} - -static int __devinit snd_mts64_probe(struct platform_device *pdev) -{ - struct pardevice *pardev; - struct parport *p; - int dev = pdev->id; - struct snd_card *card = NULL; - struct mts64 *mts = NULL; - int err; - - p = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - - if (dev >= SNDRV_CARDS) - return -ENODEV; - if (!enable[dev]) - return -ENOENT; - if ((err = snd_mts64_probe_port(p)) < 0) - return err; - - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (card == NULL) { - snd_printd("Cannot create card\n"); - return -ENOMEM; - } - strcpy(card->driver, DRIVER_NAME); - strcpy(card->shortname, "ESI " CARD_NAME); - sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, p->base, p->irq); - - pardev = parport_register_device(p, /* port */ - DRIVER_NAME, /* name */ - NULL, /* preempt */ - NULL, /* wakeup */ - snd_mts64_interrupt, /* ISR */ - PARPORT_DEV_EXCL, /* flags */ - (void *)card); /* private */ - if (pardev == NULL) { - snd_printd("Cannot register pardevice\n"); - err = -EIO; - goto __err; - } - - if ((err = snd_mts64_create(card, pardev, &mts)) < 0) { - snd_printd("Cannot create main component\n"); - parport_unregister_device(pardev); - goto __err; - } - card->private_data = mts; - card->private_free = snd_mts64_card_private_free; - - if ((err = snd_mts64_rawmidi_create(card)) < 0) { - snd_printd("Creating Rawmidi component failed\n"); - goto __err; - } - - /* claim parport */ - if (parport_claim(pardev)) { - snd_printd("Cannot claim parport 0x%lx\n", pardev->port->base); - err = -EIO; - goto __err; - } - mts->pardev_claimed = 1; - - /* init device */ - if ((err = mts64_device_init(p)) < 0) - goto __err; - - platform_set_drvdata(pdev, card); - - /* At this point card will be usable */ - if ((err = snd_card_register(card)) < 0) { - snd_printd("Cannot register card\n"); - goto __err; - } - - snd_printk("ESI Miditerminal 4140 on 0x%lx\n", p->base); - return 0; - -__err: - snd_card_free(card); - return err; -} - -static int snd_mts64_remove(struct platform_device *pdev) -{ - struct snd_card *card = platform_get_drvdata(pdev); - - if (card) - snd_card_free(card); - - return 0; -} - - -static struct platform_driver snd_mts64_driver = { - .probe = snd_mts64_probe, - .remove = snd_mts64_remove, - .driver = { - .name = PLATFORM_DRIVER - } -}; - -/********************************************************************* - * module init stuff - *********************************************************************/ -static void snd_mts64_unregister_all(void) -{ - int i; - - for (i = 0; i < SNDRV_CARDS; ++i) { - if (platform_devices[i]) { - platform_device_unregister(platform_devices[i]); - platform_devices[i] = NULL; - } - } - platform_driver_unregister(&snd_mts64_driver); - parport_unregister_driver(&mts64_parport_driver); -} - -static int __init snd_mts64_module_init(void) -{ - int err; - - if ((err = platform_driver_register(&snd_mts64_driver)) < 0) - return err; - - if (parport_register_driver(&mts64_parport_driver) != 0) { - platform_driver_unregister(&snd_mts64_driver); - return -EIO; - } - - if (device_count == 0) { - snd_mts64_unregister_all(); - return -ENODEV; - } - - return 0; -} - -static void __exit snd_mts64_module_exit(void) -{ - snd_mts64_unregister_all(); -} - -module_init(snd_mts64_module_init); -module_exit(snd_mts64_module_exit); diff --git a/trunk/sound/drivers/opl4/opl4_proc.c b/trunk/sound/drivers/opl4/opl4_proc.c index 1679300b7583..e552ec34166f 100644 --- a/trunk/sound/drivers/opl4/opl4_proc.c +++ b/trunk/sound/drivers/opl4/opl4_proc.c @@ -105,13 +105,13 @@ static long long snd_opl4_mem_proc_llseek(struct snd_info_entry *entry, void *fi struct file *file, long long offset, int orig) { switch (orig) { - case SEEK_SET: + case 0: /* SEEK_SET */ file->f_pos = offset; break; - case SEEK_CUR: + case 1: /* SEEK_CUR */ file->f_pos += offset; break; - case SEEK_END: /* offset is negative */ + case 2: /* SEEK_END, offset is negative */ file->f_pos = entry->size + offset; break; default: @@ -159,7 +159,8 @@ int snd_opl4_create_proc(struct snd_opl4 *opl4) void snd_opl4_free_proc(struct snd_opl4 *opl4) { - snd_info_free_entry(opl4->proc_entry); + if (opl4->proc_entry) + snd_info_unregister(opl4->proc_entry); } #endif /* CONFIG_PROC_FS */ diff --git a/trunk/sound/drivers/vx/vx_mixer.c b/trunk/sound/drivers/vx/vx_mixer.c index 1613ed844ac6..c1d7fcdd1973 100644 --- a/trunk/sound/drivers/vx/vx_mixer.c +++ b/trunk/sound/drivers/vx/vx_mixer.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include "vx_cmd.h" @@ -456,13 +455,10 @@ static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele static struct snd_kcontrol_new vx_control_output_level = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Master Playback Volume", .info = vx_output_level_info, .get = vx_output_level_get, .put = vx_output_level_put, - /* tlv will be filled later */ }; /* @@ -716,17 +712,12 @@ static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ return 0; } -static DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0); - static struct snd_kcontrol_new vx_control_audio_gain = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), /* name will be filled later */ .info = vx_audio_gain_info, .get = vx_audio_gain_get, - .put = vx_audio_gain_put, - .tlv = { .p = db_scale_audio_gain }, + .put = vx_audio_gain_put }; static struct snd_kcontrol_new vx_control_output_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -738,12 +729,9 @@ static struct snd_kcontrol_new vx_control_output_switch = { static struct snd_kcontrol_new vx_control_monitor_gain = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Monitoring Volume", - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .info = vx_audio_gain_info, /* shared */ .get = vx_audio_monitor_get, - .put = vx_audio_monitor_put, - .tlv = { .p = db_scale_audio_gain }, + .put = vx_audio_monitor_put }; static struct snd_kcontrol_new vx_control_monitor_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -930,7 +918,6 @@ int snd_vx_mixer_new(struct vx_core *chip) for (i = 0; i < chip->hw->num_outs; i++) { temp = vx_control_output_level; temp.index = i; - temp.tlv.p = chip->hw->output_level_db_scale; if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) return err; } diff --git a/trunk/sound/drivers/vx/vx_pcm.c b/trunk/sound/drivers/vx/vx_pcm.c index 7e65a103fbb2..c4af84995d05 100644 --- a/trunk/sound/drivers/vx/vx_pcm.c +++ b/trunk/sound/drivers/vx/vx_pcm.c @@ -1252,15 +1252,18 @@ static int vx_init_audio_io(struct vx_core *chip) chip->audio_info = rmh.Stat[1]; /* allocate pipes */ - chip->playback_pipes = kcalloc(chip->audio_outs, sizeof(struct vx_pipe *), GFP_KERNEL); + chip->playback_pipes = kmalloc(sizeof(struct vx_pipe *) * chip->audio_outs, GFP_KERNEL); if (!chip->playback_pipes) return -ENOMEM; - chip->capture_pipes = kcalloc(chip->audio_ins, sizeof(struct vx_pipe *), GFP_KERNEL); + chip->capture_pipes = kmalloc(sizeof(struct vx_pipe *) * chip->audio_ins, GFP_KERNEL); if (!chip->capture_pipes) { kfree(chip->playback_pipes); return -ENOMEM; } + memset(chip->playback_pipes, 0, sizeof(struct vx_pipe *) * chip->audio_outs); + memset(chip->capture_pipes, 0, sizeof(struct vx_pipe *) * chip->audio_ins); + preferred = chip->ibl.size; chip->ibl.size = 0; vx_set_ibl(chip, &chip->ibl); /* query the info */ diff --git a/trunk/sound/i2c/other/ak4xxx-adda.c b/trunk/sound/i2c/other/ak4xxx-adda.c index 5da49e2eb350..dc7cc2001b74 100644 --- a/trunk/sound/i2c/other/ak4xxx-adda.c +++ b/trunk/sound/i2c/other/ak4xxx-adda.c @@ -28,14 +28,12 @@ #include #include #include -#include #include MODULE_AUTHOR("Jaroslav Kysela , Takashi Iwai "); MODULE_DESCRIPTION("Routines for control of AK452x / AK43xx AD/DA converters"); MODULE_LICENSE("GPL"); -/* write the given register and save the data to the cache */ void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, unsigned char val) { @@ -43,7 +41,15 @@ void snd_akm4xxx_write(struct snd_akm4xxx *ak, int chip, unsigned char reg, ak->ops.write(ak, chip, reg, val); /* save the data */ - snd_akm4xxx_set(ak, chip, reg, val); + if (ak->type == SND_AK4524 || ak->type == SND_AK4528) { + if ((reg != 0x04 && reg != 0x05) || (val & 0x80) == 0) + snd_akm4xxx_set(ak, chip, reg, val); + else + snd_akm4xxx_set_ipga(ak, chip, reg, val); + } else { + /* AK4529, or else */ + snd_akm4xxx_set(ak, chip, reg, val); + } ak->ops.unlock(ak, chip); } @@ -67,6 +73,12 @@ static void ak4524_reset(struct snd_akm4xxx *ak, int state) for (reg = 0x04; reg < maxreg; reg++) snd_akm4xxx_write(ak, chip, reg, snd_akm4xxx_get(ak, chip, reg)); + if (ak->type == SND_AK4528) + continue; + /* IPGA */ + for (reg = 0x04; reg < 0x06; reg++) + snd_akm4xxx_write(ak, chip, reg, + snd_akm4xxx_get_ipga(ak, chip, reg)); } } @@ -125,48 +137,11 @@ void snd_akm4xxx_reset(struct snd_akm4xxx *ak, int state) case SND_AK4381: ak4381_reset(ak, state); break; - default: - break; } } EXPORT_SYMBOL(snd_akm4xxx_reset); - -/* - * Volume conversion table for non-linear volumes - * from -63.5dB (mute) to 0dB step 0.5dB - * - * Used for AK4524 input/ouput attenuation, AK4528, and - * AK5365 input attenuation - */ -static unsigned char vol_cvt_datt[128] = { - 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, - 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, - 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x0a, - 0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, - 0x10, 0x10, 0x11, 0x12, 0x12, 0x13, 0x13, 0x14, - 0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x1a, 0x1c, - 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x23, - 0x24, 0x25, 0x26, 0x28, 0x29, 0x2a, 0x2b, 0x2d, - 0x2e, 0x30, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, - 0x37, 0x38, 0x39, 0x3b, 0x3c, 0x3e, 0x3f, 0x40, - 0x41, 0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4a, - 0x4b, 0x4d, 0x4e, 0x50, 0x51, 0x52, 0x53, 0x54, - 0x55, 0x56, 0x58, 0x59, 0x5b, 0x5c, 0x5e, 0x5f, - 0x60, 0x61, 0x62, 0x64, 0x65, 0x66, 0x67, 0x69, - 0x6a, 0x6c, 0x6d, 0x6f, 0x70, 0x71, 0x72, 0x73, - 0x75, 0x76, 0x77, 0x79, 0x7a, 0x7c, 0x7d, 0x7f, -}; - -/* - * dB tables - */ -static DECLARE_TLV_DB_SCALE(db_scale_vol_datt, -6350, 50, 1); -static DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1); -static DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1); -static DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0); - /* * initialize all the ak4xxx chips */ @@ -180,6 +155,8 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) 0x01, 0x03, /* 1: ADC/DAC enable */ 0x04, 0x00, /* 4: ADC left muted */ 0x05, 0x00, /* 5: ADC right muted */ + 0x04, 0x80, /* 4: ADC IPGA gain 0dB */ + 0x05, 0x80, /* 5: ADC IPGA gain 0dB */ 0x06, 0x00, /* 6: DAC left muted */ 0x07, 0x00, /* 7: DAC right muted */ 0xff, 0xff @@ -261,9 +238,6 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) int chip, num_chips; unsigned char *ptr, reg, data, *inits; - memset(ak->images, 0, sizeof(ak->images)); - memset(ak->volumes, 0, sizeof(ak->volumes)); - switch (ak->type) { case SND_AK4524: inits = inits_ak4524; @@ -289,9 +263,6 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) inits = inits_ak4381; num_chips = ak->num_dacs / 2; break; - case SND_AK5365: - /* FIXME: any init sequence? */ - return; default: snd_BUG(); return; @@ -309,23 +280,14 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak) EXPORT_SYMBOL(snd_akm4xxx_init); -/* - * Mixer callbacks - */ -#define AK_IPGA (1<<20) /* including IPGA */ -#define AK_VOL_CVT (1<<21) /* need dB conversion */ -#define AK_NEEDSMSB (1<<22) /* need MSB update bit */ -#define AK_INVERT (1<<23) /* data is inverted */ #define AK_GET_CHIP(val) (((val) >> 8) & 0xff) #define AK_GET_ADDR(val) ((val) & 0xff) -#define AK_GET_SHIFT(val) (((val) >> 16) & 0x0f) -#define AK_GET_VOL_CVT(val) (((val) >> 21) & 1) -#define AK_GET_IPGA(val) (((val) >> 20) & 1) -#define AK_GET_NEEDSMSB(val) (((val) >> 22) & 1) +#define AK_GET_SHIFT(val) (((val) >> 16) & 0x7f) #define AK_GET_INVERT(val) (((val) >> 23) & 1) #define AK_GET_MASK(val) (((val) >> 24) & 0xff) #define AK_COMPOSE(chip,addr,shift,mask) \ (((chip) << 8) | (addr) | ((shift) << 16) | ((mask) << 24)) +#define AK_INVERT (1<<23) static int snd_akm4xxx_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) @@ -345,39 +307,31 @@ static int snd_akm4xxx_volume_get(struct snd_kcontrol *kcontrol, struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); int chip = AK_GET_CHIP(kcontrol->private_value); int addr = AK_GET_ADDR(kcontrol->private_value); - - ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr); + int invert = AK_GET_INVERT(kcontrol->private_value); + unsigned int mask = AK_GET_MASK(kcontrol->private_value); + unsigned char val = snd_akm4xxx_get(ak, chip, addr); + + ucontrol->value.integer.value[0] = invert ? mask - val : val; return 0; } -static int put_ak_reg(struct snd_kcontrol *kcontrol, int addr, - unsigned char nval) +static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) { struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - unsigned int mask = AK_GET_MASK(kcontrol->private_value); int chip = AK_GET_CHIP(kcontrol->private_value); + int addr = AK_GET_ADDR(kcontrol->private_value); + int invert = AK_GET_INVERT(kcontrol->private_value); + unsigned int mask = AK_GET_MASK(kcontrol->private_value); + unsigned char nval = ucontrol->value.integer.value[0] % (mask+1); + int change; - if (snd_akm4xxx_get_vol(ak, chip, addr) == nval) - return 0; - - snd_akm4xxx_set_vol(ak, chip, addr, nval); - if (AK_GET_VOL_CVT(kcontrol->private_value) && nval < 128) - nval = vol_cvt_datt[nval]; - if (AK_GET_IPGA(kcontrol->private_value) && nval >= 128) - nval++; /* need to correct + 1 since both 127 and 128 are 0dB */ - if (AK_GET_INVERT(kcontrol->private_value)) + if (invert) nval = mask - nval; - if (AK_GET_NEEDSMSB(kcontrol->private_value)) - nval |= 0x80; - snd_akm4xxx_write(ak, chip, addr, nval); - return 1; -} - -static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - return put_ak_reg(kcontrol, AK_GET_ADDR(kcontrol->private_value), - ucontrol->value.integer.value[0]); + change = snd_akm4xxx_get(ak, chip, addr) != nval; + if (change) + snd_akm4xxx_write(ak, chip, addr, nval); + return change; } static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol, @@ -398,21 +352,77 @@ static int snd_akm4xxx_stereo_volume_get(struct snd_kcontrol *kcontrol, struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); int chip = AK_GET_CHIP(kcontrol->private_value); int addr = AK_GET_ADDR(kcontrol->private_value); + int invert = AK_GET_INVERT(kcontrol->private_value); + unsigned int mask = AK_GET_MASK(kcontrol->private_value); + unsigned char val = snd_akm4xxx_get(ak, chip, addr); + + ucontrol->value.integer.value[0] = invert ? mask - val : val; + + val = snd_akm4xxx_get(ak, chip, addr+1); + ucontrol->value.integer.value[1] = invert ? mask - val : val; - ucontrol->value.integer.value[0] = snd_akm4xxx_get_vol(ak, chip, addr); - ucontrol->value.integer.value[1] = snd_akm4xxx_get_vol(ak, chip, addr+1); return 0; } static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); + int chip = AK_GET_CHIP(kcontrol->private_value); int addr = AK_GET_ADDR(kcontrol->private_value); - int change; + int invert = AK_GET_INVERT(kcontrol->private_value); + unsigned int mask = AK_GET_MASK(kcontrol->private_value); + unsigned char nval = ucontrol->value.integer.value[0] % (mask+1); + int change0, change1; + + if (invert) + nval = mask - nval; + change0 = snd_akm4xxx_get(ak, chip, addr) != nval; + if (change0) + snd_akm4xxx_write(ak, chip, addr, nval); + + nval = ucontrol->value.integer.value[1] % (mask+1); + if (invert) + nval = mask - nval; + change1 = snd_akm4xxx_get(ak, chip, addr+1) != nval; + if (change1) + snd_akm4xxx_write(ak, chip, addr+1, nval); + + + return change0 || change1; +} - change = put_ak_reg(kcontrol, addr, ucontrol->value.integer.value[0]); - change |= put_ak_reg(kcontrol, addr + 1, - ucontrol->value.integer.value[1]); +static int snd_akm4xxx_ipga_gain_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 36; + return 0; +} + +static int snd_akm4xxx_ipga_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); + int chip = AK_GET_CHIP(kcontrol->private_value); + int addr = AK_GET_ADDR(kcontrol->private_value); + ucontrol->value.integer.value[0] = + snd_akm4xxx_get_ipga(ak, chip, addr) & 0x7f; + return 0; +} + +static int snd_akm4xxx_ipga_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); + int chip = AK_GET_CHIP(kcontrol->private_value); + int addr = AK_GET_ADDR(kcontrol->private_value); + unsigned char nval = (ucontrol->value.integer.value[0] % 37) | 0x80; + int change = snd_akm4xxx_get_ipga(ak, chip, addr) != nval; + if (change) + snd_akm4xxx_write(ak, chip, addr, nval); return change; } @@ -462,280 +472,179 @@ static int snd_akm4xxx_deemphasis_put(struct snd_kcontrol *kcontrol, return change; } -static int ak4xxx_switch_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} - -static int ak4xxx_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol); - int chip = AK_GET_CHIP(kcontrol->private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - int shift = AK_GET_SHIFT(kcontrol->private_value); - int invert = AK_GET_INVERT(kcontrol->private_value); - unsigned char val = snd_akm4xxx_get(ak, chip, addr); - - if (invert) - val = ! val; - ucontrol->value.integer.value[0] = (val & (1<private_value); - int addr = AK_GET_ADDR(kcontrol->private_value); - int shift = AK_GET_SHIFT(kcontrol->private_value); - int invert = AK_GET_INVERT(kcontrol->private_value); - long flag = ucontrol->value.integer.value[0]; - unsigned char val, oval; - int change; - - if (invert) - flag = ! flag; - oval = snd_akm4xxx_get(ak, chip, addr); - if (flag) - val = oval | (1<num_dacs; ) { - memset(&knew, 0, sizeof(knew)); - if (! ak->dac_info || ! ak->dac_info[mixer_ch].name) { - knew.name = "DAC Volume"; - knew.index = mixer_ch + ak->idx_offset * 2; + memset(ctl, 0, sizeof(*ctl)); + if (ak->channel_names == NULL) { + strcpy(ctl->id.name, "DAC Volume"); num_stereo = 1; + ctl->id.index = mixer_ch + ak->idx_offset * 2; } else { - knew.name = ak->dac_info[mixer_ch].name; - num_stereo = ak->dac_info[mixer_ch].num_channels; + strcpy(ctl->id.name, ak->channel_names[mixer_ch]); + num_stereo = ak->num_stereo[mixer_ch]; + ctl->id.index = 0; } - knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - knew.count = 1; - knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ; + ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + ctl->count = 1; if (num_stereo == 2) { - knew.info = snd_akm4xxx_stereo_volume_info; - knew.get = snd_akm4xxx_stereo_volume_get; - knew.put = snd_akm4xxx_stereo_volume_put; + ctl->info = snd_akm4xxx_stereo_volume_info; + ctl->get = snd_akm4xxx_stereo_volume_get; + ctl->put = snd_akm4xxx_stereo_volume_put; } else { - knew.info = snd_akm4xxx_volume_info; - knew.get = snd_akm4xxx_volume_get; - knew.put = snd_akm4xxx_volume_put; + ctl->info = snd_akm4xxx_volume_info; + ctl->get = snd_akm4xxx_volume_get; + ctl->put = snd_akm4xxx_volume_put; } switch (ak->type) { case SND_AK4524: /* register 6 & 7 */ - knew.private_value = - AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127) | - AK_VOL_CVT; - knew.tlv.p = db_scale_vol_datt; + ctl->private_value = + AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); break; case SND_AK4528: /* register 4 & 5 */ - knew.private_value = - AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127) | - AK_VOL_CVT; - knew.tlv.p = db_scale_vol_datt; + ctl->private_value = + AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); break; case SND_AK4529: { /* registers 2-7 and b,c */ int val = idx < 6 ? idx + 2 : (idx - 6) + 0xb; - knew.private_value = + ctl->private_value = AK_COMPOSE(0, val, 0, 255) | AK_INVERT; - knew.tlv.p = db_scale_8bit; break; } case SND_AK4355: /* register 4-9, chip #0 only */ - knew.private_value = AK_COMPOSE(0, idx + 4, 0, 255); - knew.tlv.p = db_scale_8bit; + ctl->private_value = AK_COMPOSE(0, idx + 4, 0, 255); break; - case SND_AK4358: { - /* register 4-9 and 11-12, chip #0 only */ - int addr = idx < 6 ? idx + 4 : idx + 5; - knew.private_value = - AK_COMPOSE(0, addr, 0, 127) | AK_NEEDSMSB; - knew.tlv.p = db_scale_7bit; + case SND_AK4358: + if (idx >= 6) + /* register 4-9, chip #0 only */ + ctl->private_value = + AK_COMPOSE(0, idx + 5, 0, 255); + else + /* register 4-9, chip #0 only */ + ctl->private_value = + AK_COMPOSE(0, idx + 4, 0, 255); break; - } case SND_AK4381: /* register 3 & 4 */ - knew.private_value = + ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); - knew.tlv.p = db_scale_linear; break; default: - return -EINVAL; + err = -EINVAL; + goto __error; } - err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); + ctl->private_data = ak; + err = snd_ctl_add(ak->card, + snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| + SNDRV_CTL_ELEM_ACCESS_WRITE)); if (err < 0) - return err; + goto __error; idx += num_stereo; mixer_ch++; } - return 0; -} - -static int build_adc_controls(struct snd_akm4xxx *ak) -{ - int idx, err, mixer_ch, num_stereo; - struct snd_kcontrol_new knew; - - mixer_ch = 0; - for (idx = 0; idx < ak->num_adcs;) { - memset(&knew, 0, sizeof(knew)); - if (! ak->adc_info || ! ak->adc_info[mixer_ch].name) { - knew.name = "ADC Volume"; - knew.index = mixer_ch + ak->idx_offset * 2; - num_stereo = 1; - } else { - knew.name = ak->adc_info[mixer_ch].name; - num_stereo = ak->adc_info[mixer_ch].num_channels; - } - knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - knew.count = 1; - knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ; - if (num_stereo == 2) { - knew.info = snd_akm4xxx_stereo_volume_info; - knew.get = snd_akm4xxx_stereo_volume_get; - knew.put = snd_akm4xxx_stereo_volume_put; - } else { - knew.info = snd_akm4xxx_volume_info; - knew.get = snd_akm4xxx_volume_get; - knew.put = snd_akm4xxx_volume_put; - } + for (idx = 0; idx < ak->num_adcs && ak->type == SND_AK4524; ++idx) { + memset(ctl, 0, sizeof(*ctl)); + strcpy(ctl->id.name, "ADC Volume"); + ctl->id.index = idx + ak->idx_offset * 2; + ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + ctl->count = 1; + ctl->info = snd_akm4xxx_volume_info; + ctl->get = snd_akm4xxx_volume_get; + ctl->put = snd_akm4xxx_volume_put; /* register 4 & 5 */ - if (ak->type == SND_AK5365) - knew.private_value = - AK_COMPOSE(idx/2, (idx%2) + 4, 0, 151) | - AK_VOL_CVT | AK_IPGA; - else - knew.private_value = - AK_COMPOSE(idx/2, (idx%2) + 4, 0, 163) | - AK_VOL_CVT | AK_IPGA; - knew.tlv.p = db_scale_vol_datt; - err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); + ctl->private_value = + AK_COMPOSE(idx/2, (idx%2) + 4, 0, 127); + ctl->private_data = ak; + err = snd_ctl_add(ak->card, + snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| + SNDRV_CTL_ELEM_ACCESS_WRITE)); if (err < 0) - return err; - - if (ak->type == SND_AK5365 && (idx % 2) == 0) { - if (! ak->adc_info || - ! ak->adc_info[mixer_ch].switch_name) - knew.name = "Capture Switch"; - else - knew.name = ak->adc_info[mixer_ch].switch_name; - knew.info = ak4xxx_switch_info; - knew.get = ak4xxx_switch_get; - knew.put = ak4xxx_switch_put; - knew.access = 0; - /* register 2, bit 0 (SMUTE): 0 = normal operation, - 1 = mute */ - knew.private_value = - AK_COMPOSE(idx/2, 2, 0, 0) | AK_INVERT; - err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); - if (err < 0) - return err; - } - - idx += num_stereo; - mixer_ch++; + goto __error; + + memset(ctl, 0, sizeof(*ctl)); + strcpy(ctl->id.name, "IPGA Analog Capture Volume"); + ctl->id.index = idx + ak->idx_offset * 2; + ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + ctl->count = 1; + ctl->info = snd_akm4xxx_ipga_gain_info; + ctl->get = snd_akm4xxx_ipga_gain_get; + ctl->put = snd_akm4xxx_ipga_gain_put; + /* register 4 & 5 */ + ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 4, 0, 0); + ctl->private_data = ak; + err = snd_ctl_add(ak->card, + snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| + SNDRV_CTL_ELEM_ACCESS_WRITE)); + if (err < 0) + goto __error; } - return 0; -} - -static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs) -{ - int idx, err; - struct snd_kcontrol_new knew; - + if (ak->type == SND_AK4355 || ak->type == SND_AK4358) + num_emphs = 1; + else + num_emphs = ak->num_dacs / 2; for (idx = 0; idx < num_emphs; idx++) { - memset(&knew, 0, sizeof(knew)); - knew.name = "Deemphasis"; - knew.index = idx + ak->idx_offset; - knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - knew.count = 1; - knew.info = snd_akm4xxx_deemphasis_info; - knew.get = snd_akm4xxx_deemphasis_get; - knew.put = snd_akm4xxx_deemphasis_put; + memset(ctl, 0, sizeof(*ctl)); + strcpy(ctl->id.name, "Deemphasis"); + ctl->id.index = idx + ak->idx_offset; + ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + ctl->count = 1; + ctl->info = snd_akm4xxx_deemphasis_info; + ctl->get = snd_akm4xxx_deemphasis_get; + ctl->put = snd_akm4xxx_deemphasis_put; switch (ak->type) { case SND_AK4524: case SND_AK4528: /* register 3 */ - knew.private_value = AK_COMPOSE(idx, 3, 0, 0); + ctl->private_value = AK_COMPOSE(idx, 3, 0, 0); break; case SND_AK4529: { int shift = idx == 3 ? 6 : (2 - idx) * 2; /* register 8 with shift */ - knew.private_value = AK_COMPOSE(0, 8, shift, 0); + ctl->private_value = AK_COMPOSE(0, 8, shift, 0); break; } case SND_AK4355: case SND_AK4358: - knew.private_value = AK_COMPOSE(idx, 3, 0, 0); + ctl->private_value = AK_COMPOSE(idx, 3, 0, 0); break; case SND_AK4381: - knew.private_value = AK_COMPOSE(idx, 1, 1, 0); + ctl->private_value = AK_COMPOSE(idx, 1, 1, 0); break; - default: - return -EINVAL; } - err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); + ctl->private_data = ak; + err = snd_ctl_add(ak->card, + snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ| + SNDRV_CTL_ELEM_ACCESS_WRITE)); if (err < 0) - return err; + goto __error; } - return 0; -} - -int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak) -{ - int err, num_emphs; + err = 0; - err = build_dac_controls(ak); - if (err < 0) - return err; - - err = build_adc_controls(ak); - if (err < 0) - return err; - - if (ak->type == SND_AK4355 || ak->type == SND_AK4358) - num_emphs = 1; - else - num_emphs = ak->num_dacs / 2; - err = build_deemphasis(ak, num_emphs); - if (err < 0) - return err; - - return 0; + __error: + kfree(ctl); + return err; } - + EXPORT_SYMBOL(snd_akm4xxx_build_controls); static int __init alsa_akm4xxx_module_init(void) diff --git a/trunk/sound/isa/ad1816a/ad1816a_lib.c b/trunk/sound/isa/ad1816a/ad1816a_lib.c index fd9b61eda0f3..8fcf2c151823 100644 --- a/trunk/sound/isa/ad1816a/ad1816a_lib.c +++ b/trunk/sound/isa/ad1816a/ad1816a_lib.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -766,13 +765,6 @@ static int snd_ad1816a_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ele return change; } -#define AD1816A_SINGLE_TLV(xname, reg, shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .info = snd_ad1816a_info_single, \ - .get = snd_ad1816a_get_single, .put = snd_ad1816a_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } #define AD1816A_SINGLE(xname, reg, shift, mask, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_single, \ .get = snd_ad1816a_get_single, .put = snd_ad1816a_put_single, \ @@ -830,14 +822,6 @@ static int snd_ad1816a_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ return change; } -#define AD1816A_DOUBLE_TLV(xname, reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .info = snd_ad1816a_info_double, \ - .get = snd_ad1816a_get_double, .put = snd_ad1816a_put_double, \ - .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } - #define AD1816A_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ad1816a_info_double, \ .get = snd_ad1816a_get_double, .put = snd_ad1816a_put_double, \ @@ -906,44 +890,28 @@ static int snd_ad1816a_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ return change; } -static DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); -static DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); -static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); -static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); -static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); - static struct snd_kcontrol_new snd_ad1816a_controls[] __devinitdata = { AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1, - db_scale_5bit), +AD1816A_DOUBLE("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1), AD1816A_DOUBLE("PCM Playback Switch", AD1816A_VOICE_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("PCM Playback Volume", AD1816A_VOICE_ATT, 8, 0, 63, 1, - db_scale_6bit), +AD1816A_DOUBLE("PCM Playback Volume", AD1816A_VOICE_ATT, 8, 0, 63, 1), AD1816A_DOUBLE("Line Playback Switch", AD1816A_LINE_GAIN_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Line Playback Volume", AD1816A_LINE_GAIN_ATT, 8, 0, 31, 1, - db_scale_5bit_12db_max), +AD1816A_DOUBLE("Line Playback Volume", AD1816A_LINE_GAIN_ATT, 8, 0, 31, 1), AD1816A_DOUBLE("CD Playback Switch", AD1816A_CD_GAIN_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("CD Playback Volume", AD1816A_CD_GAIN_ATT, 8, 0, 31, 1, - db_scale_5bit_12db_max), +AD1816A_DOUBLE("CD Playback Volume", AD1816A_CD_GAIN_ATT, 8, 0, 31, 1), AD1816A_DOUBLE("Synth Playback Switch", AD1816A_SYNTH_GAIN_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Synth Playback Volume", AD1816A_SYNTH_GAIN_ATT, 8, 0, 31, 1, - db_scale_5bit_12db_max), +AD1816A_DOUBLE("Synth Playback Volume", AD1816A_SYNTH_GAIN_ATT, 8, 0, 31, 1), AD1816A_DOUBLE("FM Playback Switch", AD1816A_FM_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("FM Playback Volume", AD1816A_FM_ATT, 8, 0, 63, 1, - db_scale_6bit), +AD1816A_DOUBLE("FM Playback Volume", AD1816A_FM_ATT, 8, 0, 63, 1), AD1816A_SINGLE("Mic Playback Switch", AD1816A_MIC_GAIN_ATT, 15, 1, 1), -AD1816A_SINGLE_TLV("Mic Playback Volume", AD1816A_MIC_GAIN_ATT, 8, 31, 1, - db_scale_5bit_12db_max), +AD1816A_SINGLE("Mic Playback Volume", AD1816A_MIC_GAIN_ATT, 8, 31, 1), AD1816A_SINGLE("Mic Boost", AD1816A_MIC_GAIN_ATT, 14, 1, 0), AD1816A_DOUBLE("Video Playback Switch", AD1816A_VID_GAIN_ATT, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Video Playback Volume", AD1816A_VID_GAIN_ATT, 8, 0, 31, 1, - db_scale_5bit_12db_max), +AD1816A_DOUBLE("Video Playback Volume", AD1816A_VID_GAIN_ATT, 8, 0, 31, 1), AD1816A_SINGLE("Phone Capture Switch", AD1816A_PHONE_IN_GAIN_ATT, 15, 1, 1), -AD1816A_SINGLE_TLV("Phone Capture Volume", AD1816A_PHONE_IN_GAIN_ATT, 0, 15, 1, - db_scale_4bit), +AD1816A_SINGLE("Phone Capture Volume", AD1816A_PHONE_IN_GAIN_ATT, 0, 15, 1), AD1816A_SINGLE("Phone Playback Switch", AD1816A_PHONE_OUT_ATT, 7, 1, 1), -AD1816A_SINGLE_TLV("Phone Playback Volume", AD1816A_PHONE_OUT_ATT, 0, 31, 1, - db_scale_5bit), +AD1816A_SINGLE("Phone Playback Volume", AD1816A_PHONE_OUT_ATT, 0, 31, 1), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", @@ -952,8 +920,7 @@ AD1816A_SINGLE_TLV("Phone Playback Volume", AD1816A_PHONE_OUT_ATT, 0, 31, 1, .put = snd_ad1816a_put_mux, }, AD1816A_DOUBLE("Capture Switch", AD1816A_ADC_PGA, 15, 7, 1, 1), -AD1816A_DOUBLE_TLV("Capture Volume", AD1816A_ADC_PGA, 8, 0, 15, 0, - db_scale_rec_gain), +AD1816A_DOUBLE("Capture Volume", AD1816A_ADC_PGA, 8, 0, 15, 0), AD1816A_SINGLE("3D Control - Switch", AD1816A_3D_PHAT_CTRL, 15, 1, 1), AD1816A_SINGLE("3D Control - Level", AD1816A_3D_PHAT_CTRL, 0, 15, 0), }; diff --git a/trunk/sound/isa/ad1848/ad1848_lib.c b/trunk/sound/isa/ad1848/ad1848_lib.c index a6fbd5d1d62f..e711f87d5fd1 100644 --- a/trunk/sound/isa/ad1848/ad1848_lib.c +++ b/trunk/sound/isa/ad1848/ad1848_lib.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -119,8 +118,6 @@ void snd_ad1848_out(struct snd_ad1848 *chip, #endif } -EXPORT_SYMBOL(snd_ad1848_out); - static void snd_ad1848_dout(struct snd_ad1848 *chip, unsigned char reg, unsigned char value) { @@ -944,8 +941,6 @@ int snd_ad1848_create(struct snd_card *card, return 0; } -EXPORT_SYMBOL(snd_ad1848_create); - static struct snd_pcm_ops snd_ad1848_playback_ops = { .open = snd_ad1848_playback_open, .close = snd_ad1848_playback_close, @@ -993,16 +988,12 @@ int snd_ad1848_pcm(struct snd_ad1848 *chip, int device, struct snd_pcm **rpcm) return 0; } -EXPORT_SYMBOL(snd_ad1848_pcm); - const struct snd_pcm_ops *snd_ad1848_get_pcm_ops(int direction) { return direction == SNDRV_PCM_STREAM_PLAYBACK ? &snd_ad1848_playback_ops : &snd_ad1848_capture_ops; } -EXPORT_SYMBOL(snd_ad1848_get_pcm_ops); - /* * MIXER part */ @@ -1180,8 +1171,7 @@ static int snd_ad1848_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e /* */ -int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip, - const struct ad1848_mix_elem *c) +int snd_ad1848_add_ctl(struct snd_ad1848 *chip, const char *name, int index, int type, unsigned long value) { static struct snd_kcontrol_new newctls[] = { [AD1848_MIX_SINGLE] = { @@ -1206,46 +1196,32 @@ int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip, struct snd_kcontrol *ctl; int err; - ctl = snd_ctl_new1(&newctls[c->type], chip); + ctl = snd_ctl_new1(&newctls[type], chip); if (! ctl) return -ENOMEM; - strlcpy(ctl->id.name, c->name, sizeof(ctl->id.name)); - ctl->id.index = c->index; - ctl->private_value = c->private_value; - if (c->tlv) { - ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; - ctl->tlv.p = c->tlv; - } + strlcpy(ctl->id.name, name, sizeof(ctl->id.name)); + ctl->id.index = index; + ctl->private_value = value; if ((err = snd_ctl_add(chip->card, ctl)) < 0) return err; return 0; } -EXPORT_SYMBOL(snd_ad1848_add_ctl_elem); - -static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); -static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); -static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); static struct ad1848_mix_elem snd_ad1848_controls[] = { AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), -AD1848_DOUBLE_TLV("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1, - db_scale_6bit), +AD1848_DOUBLE("PCM Playback Volume", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 0, 0, 63, 1), AD1848_DOUBLE("Aux Playback Switch", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -AD1848_DOUBLE_TLV("Aux Playback Volume", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), +AD1848_DOUBLE("Aux Playback Volume", 0, AD1848_AUX1_LEFT_INPUT, AD1848_AUX1_RIGHT_INPUT, 0, 0, 31, 1), AD1848_DOUBLE("Aux Playback Switch", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -AD1848_DOUBLE_TLV("Aux Playback Volume", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 0, 0, 31, 1, - db_scale_5bit_12db_max), -AD1848_DOUBLE_TLV("Capture Volume", 0, AD1848_LEFT_INPUT, AD1848_RIGHT_INPUT, 0, 0, 15, 0, - db_scale_rec_gain), +AD1848_DOUBLE("Aux Playback Volume", 1, AD1848_AUX2_LEFT_INPUT, AD1848_AUX2_RIGHT_INPUT, 0, 0, 31, 1), +AD1848_DOUBLE("Capture Volume", 0, AD1848_LEFT_INPUT, AD1848_RIGHT_INPUT, 0, 0, 15, 0), { .name = "Capture Source", .type = AD1848_MIX_CAPTURE, }, AD1848_SINGLE("Loopback Capture Switch", 0, AD1848_LOOPBACK, 0, 1, 0), -AD1848_SINGLE_TLV("Loopback Capture Volume", 0, AD1848_LOOPBACK, 1, 63, 0, - db_scale_6bit), +AD1848_SINGLE("Loopback Capture Volume", 0, AD1848_LOOPBACK, 1, 63, 0) }; int snd_ad1848_mixer(struct snd_ad1848 *chip) @@ -1269,7 +1245,12 @@ int snd_ad1848_mixer(struct snd_ad1848 *chip) return 0; } +EXPORT_SYMBOL(snd_ad1848_out); +EXPORT_SYMBOL(snd_ad1848_create); +EXPORT_SYMBOL(snd_ad1848_pcm); +EXPORT_SYMBOL(snd_ad1848_get_pcm_ops); EXPORT_SYMBOL(snd_ad1848_mixer); +EXPORT_SYMBOL(snd_ad1848_add_ctl); /* * INIT part diff --git a/trunk/sound/isa/es18xx.c b/trunk/sound/isa/es18xx.c index 85818200333f..34998de9968c 100644 --- a/trunk/sound/isa/es18xx.c +++ b/trunk/sound/isa/es18xx.c @@ -2038,80 +2038,7 @@ MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver."); static struct platform_device *platform_devices[SNDRV_CARDS]; #ifdef CONFIG_PNP -static int pnp_registered, pnpc_registered; - -static struct pnp_device_id snd_audiodrive_pnpbiosids[] = { - { .id = "ESS1869" }, - { .id = "" } /* end */ -}; - -MODULE_DEVICE_TABLE(pnp, snd_audiodrive_pnpbiosids); - -/* PnP main device initialization */ -static int __devinit snd_audiodrive_pnp_init_main(int dev, struct pnp_dev *pdev, - struct pnp_resource_table *cfg) -{ - int err; - - pnp_init_resource_table(cfg); - if (port[dev] != SNDRV_AUTO_PORT) - pnp_resource_change(&cfg->port_resource[0], port[dev], 16); - if (fm_port[dev] != SNDRV_AUTO_PORT) - pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4); - if (mpu_port[dev] != SNDRV_AUTO_PORT) - pnp_resource_change(&cfg->port_resource[2], mpu_port[dev], 2); - if (dma1[dev] != SNDRV_AUTO_DMA) - pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1); - if (dma2[dev] != SNDRV_AUTO_DMA) - pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1); - if (irq[dev] != SNDRV_AUTO_IRQ) - pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1); - if (pnp_device_is_isapnp(pdev)) { - err = pnp_manual_config_dev(pdev, cfg, 0); - if (err < 0) - snd_printk(KERN_ERR PFX "PnP manual resources are invalid, using auto config\n"); - } - err = pnp_activate_dev(pdev); - if (err < 0) { - snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n"); - return -EBUSY; - } - /* ok. hack using Vendor-Defined Card-Level registers */ - /* skip csn and logdev initialization - already done in isapnp_configure */ - if (pnp_device_is_isapnp(pdev)) { - isapnp_cfg_begin(isapnp_card_number(pdev), isapnp_csn_number(pdev)); - isapnp_write_byte(0x27, pnp_irq(pdev, 0)); /* Hardware Volume IRQ Number */ - if (mpu_port[dev] != SNDRV_AUTO_PORT) - isapnp_write_byte(0x28, pnp_irq(pdev, 0)); /* MPU-401 IRQ Number */ - isapnp_write_byte(0x72, pnp_irq(pdev, 0)); /* second IRQ */ - isapnp_cfg_end(); - } - port[dev] = pnp_port_start(pdev, 0); - fm_port[dev] = pnp_port_start(pdev, 1); - mpu_port[dev] = pnp_port_start(pdev, 2); - dma1[dev] = pnp_dma(pdev, 0); - dma2[dev] = pnp_dma(pdev, 1); - irq[dev] = pnp_irq(pdev, 0); - snd_printdd("PnP ES18xx: port=0x%lx, fm port=0x%lx, mpu port=0x%lx\n", port[dev], fm_port[dev], mpu_port[dev]); - snd_printdd("PnP ES18xx: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]); - return 0; -} - -static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard, - struct pnp_dev *pdev) -{ - struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); - - if (!cfg) - return -ENOMEM; - acard->dev = pdev; - if (snd_audiodrive_pnp_init_main(dev, acard->dev, cfg) < 0) { - kfree(cfg); - return -EBUSY; - } - kfree(cfg); - return 0; -} +static int pnp_registered; static struct pnp_card_device_id snd_audiodrive_pnpids[] = { /* ESS 1868 (integrated on Compaq dual P-Pro motherboard and Genius 18PnP 3D) */ @@ -2134,11 +2061,13 @@ static struct pnp_card_device_id snd_audiodrive_pnpids[] = { MODULE_DEVICE_TABLE(pnp_card, snd_audiodrive_pnpids); -static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard, +static int __devinit snd_audiodrive_pnp(int dev, struct snd_audiodrive *acard, struct pnp_card_link *card, const struct pnp_card_device_id *id) { + struct pnp_dev *pdev; struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL); + int err; if (!cfg) return -ENOMEM; @@ -2153,16 +2082,58 @@ static int __devinit snd_audiodrive_pnpc(int dev, struct snd_audiodrive *acard, return -EBUSY; } /* Control port initialization */ - if (pnp_activate_dev(acard->devc) < 0) { + err = pnp_activate_dev(acard->devc); + if (err < 0) { snd_printk(KERN_ERR PFX "PnP control configure failure (out of resources?)\n"); + kfree(cfg); return -EAGAIN; } snd_printdd("pnp: port=0x%llx\n", (unsigned long long)pnp_port_start(acard->devc, 0)); - if (snd_audiodrive_pnp_init_main(dev, acard->dev, cfg) < 0) { + /* PnP initialization */ + pdev = acard->dev; + pnp_init_resource_table(cfg); + if (port[dev] != SNDRV_AUTO_PORT) + pnp_resource_change(&cfg->port_resource[0], port[dev], 16); + if (fm_port[dev] != SNDRV_AUTO_PORT) + pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4); + if (mpu_port[dev] != SNDRV_AUTO_PORT) + pnp_resource_change(&cfg->port_resource[2], mpu_port[dev], 2); + if (dma1[dev] != SNDRV_AUTO_DMA) + pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1); + if (dma2[dev] != SNDRV_AUTO_DMA) + pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1); + if (irq[dev] != SNDRV_AUTO_IRQ) + pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1); + err = pnp_manual_config_dev(pdev, cfg, 0); + if (err < 0) + snd_printk(KERN_ERR PFX "PnP manual resources are invalid, using auto config\n"); + err = pnp_activate_dev(pdev); + if (err < 0) { + snd_printk(KERN_ERR PFX "PnP configure failure (out of resources?)\n"); kfree(cfg); return -EBUSY; } + /* ok. hack using Vendor-Defined Card-Level registers */ + /* skip csn and logdev initialization - already done in isapnp_configure */ + if (pnp_device_is_isapnp(pdev)) { + isapnp_cfg_begin(isapnp_card_number(pdev), isapnp_csn_number(pdev)); + isapnp_write_byte(0x27, pnp_irq(pdev, 0)); /* Hardware Volume IRQ Number */ + if (mpu_port[dev] != SNDRV_AUTO_PORT) + isapnp_write_byte(0x28, pnp_irq(pdev, 0)); /* MPU-401 IRQ Number */ + isapnp_write_byte(0x72, pnp_irq(pdev, 0)); /* second IRQ */ + isapnp_cfg_end(); + } else { + snd_printk(KERN_ERR PFX "unable to install ISA PnP hack, expect malfunction\n"); + } + port[dev] = pnp_port_start(pdev, 0); + fm_port[dev] = pnp_port_start(pdev, 1); + mpu_port[dev] = pnp_port_start(pdev, 2); + dma1[dev] = pnp_dma(pdev, 0); + dma2[dev] = pnp_dma(pdev, 1); + irq[dev] = pnp_irq(pdev, 0); + snd_printdd("PnP ES18xx: port=0x%lx, fm port=0x%lx, mpu port=0x%lx\n", port[dev], fm_port[dev], mpu_port[dev]); + snd_printdd("PnP ES18xx: dma1=%i, dma2=%i, irq=%i\n", dma1[dev], dma2[dev], irq[dev]); kfree(cfg); return 0; } @@ -2331,69 +2302,7 @@ static struct platform_driver snd_es18xx_nonpnp_driver = { #ifdef CONFIG_PNP static unsigned int __devinitdata es18xx_pnp_devices; -static int __devinit snd_audiodrive_pnp_detect(struct pnp_dev *pdev, - const struct pnp_device_id *id) -{ - static int dev; - int err; - struct snd_card *card; - - if (pnp_device_is_isapnp(pdev)) - return -ENOENT; /* we have another procedure - card */ - for (; dev < SNDRV_CARDS; dev++) { - if (enable[dev] && isapnp[dev]) - break; - } - if (dev >= SNDRV_CARDS) - return -ENODEV; - - card = snd_es18xx_card_new(dev); - if (! card) - return -ENOMEM; - if ((err = snd_audiodrive_pnp(dev, card->private_data, pdev)) < 0) { - snd_card_free(card); - return err; - } - snd_card_set_dev(card, &pdev->dev); - if ((err = snd_audiodrive_probe(card, dev)) < 0) { - snd_card_free(card); - return err; - } - pnp_set_drvdata(pdev, card); - dev++; - es18xx_pnp_devices++; - return 0; -} - -static void __devexit snd_audiodrive_pnp_remove(struct pnp_dev * pdev) -{ - snd_card_free(pnp_get_drvdata(pdev)); - pnp_set_drvdata(pdev, NULL); -} - -#ifdef CONFIG_PM -static int snd_audiodrive_pnp_suspend(struct pnp_dev *pdev, pm_message_t state) -{ - return snd_es18xx_suspend(pnp_get_drvdata(pdev), state); -} -static int snd_audiodrive_pnp_resume(struct pnp_dev *pdev) -{ - return snd_es18xx_resume(pnp_get_drvdata(pdev)); -} -#endif - -static struct pnp_driver es18xx_pnp_driver = { - .name = "es18xx-pnpbios", - .id_table = snd_audiodrive_pnpbiosids, - .probe = snd_audiodrive_pnp_detect, - .remove = __devexit_p(snd_audiodrive_pnp_remove), -#ifdef CONFIG_PM - .suspend = snd_audiodrive_pnp_suspend, - .resume = snd_audiodrive_pnp_resume, -#endif -}; - -static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, +static int __devinit snd_audiodrive_pnp_detect(struct pnp_card_link *pcard, const struct pnp_card_device_id *pid) { static int dev; @@ -2411,7 +2320,7 @@ static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, if (! card) return -ENOMEM; - if ((res = snd_audiodrive_pnpc(dev, card->private_data, pcard, pid)) < 0) { + if ((res = snd_audiodrive_pnp(dev, card->private_data, pcard, pid)) < 0) { snd_card_free(card); return res; } @@ -2427,19 +2336,19 @@ static int __devinit snd_audiodrive_pnpc_detect(struct pnp_card_link *pcard, return 0; } -static void __devexit snd_audiodrive_pnpc_remove(struct pnp_card_link * pcard) +static void __devexit snd_audiodrive_pnp_remove(struct pnp_card_link * pcard) { snd_card_free(pnp_get_card_drvdata(pcard)); pnp_set_card_drvdata(pcard, NULL); } #ifdef CONFIG_PM -static int snd_audiodrive_pnpc_suspend(struct pnp_card_link *pcard, pm_message_t state) +static int snd_audiodrive_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state) { return snd_es18xx_suspend(pnp_get_card_drvdata(pcard), state); } -static int snd_audiodrive_pnpc_resume(struct pnp_card_link *pcard) +static int snd_audiodrive_pnp_resume(struct pnp_card_link *pcard) { return snd_es18xx_resume(pnp_get_card_drvdata(pcard)); } @@ -2450,11 +2359,11 @@ static struct pnp_card_driver es18xx_pnpc_driver = { .flags = PNP_DRIVER_RES_DISABLE, .name = "es18xx", .id_table = snd_audiodrive_pnpids, - .probe = snd_audiodrive_pnpc_detect, - .remove = __devexit_p(snd_audiodrive_pnpc_remove), + .probe = snd_audiodrive_pnp_detect, + .remove = __devexit_p(snd_audiodrive_pnp_remove), #ifdef CONFIG_PM - .suspend = snd_audiodrive_pnpc_suspend, - .resume = snd_audiodrive_pnpc_resume, + .suspend = snd_audiodrive_pnp_suspend, + .resume = snd_audiodrive_pnp_resume, #endif }; #endif /* CONFIG_PNP */ @@ -2464,10 +2373,8 @@ static void __init_or_module snd_es18xx_unregister_all(void) int i; #ifdef CONFIG_PNP - if (pnpc_registered) - pnp_unregister_card_driver(&es18xx_pnpc_driver); if (pnp_registered) - pnp_unregister_driver(&es18xx_pnp_driver); + pnp_unregister_card_driver(&es18xx_pnpc_driver); #endif for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) platform_device_unregister(platform_devices[i]); @@ -2498,13 +2405,11 @@ static int __init alsa_card_es18xx_init(void) } #ifdef CONFIG_PNP - err = pnp_register_driver(&es18xx_pnp_driver); - if (!err) - pnp_registered = 1; err = pnp_register_card_driver(&es18xx_pnpc_driver); - if (!err) - pnpc_registered = 1; - cards += es18xx_pnp_devices; + if (!err) { + pnp_registered = 1; + cards += es18xx_pnp_devices; + } #endif if(!cards) { diff --git a/trunk/sound/isa/gus/gus_mem_proc.c b/trunk/sound/isa/gus/gus_mem_proc.c index 80f0a83818b2..4080255007d5 100644 --- a/trunk/sound/isa/gus/gus_mem_proc.c +++ b/trunk/sound/isa/gus/gus_mem_proc.c @@ -61,13 +61,13 @@ static long long snd_gf1_mem_proc_llseek(struct snd_info_entry *entry, struct gus_proc_private *priv = entry->private_data; switch (orig) { - case SEEK_SET: + case 0: /* SEEK_SET */ file->f_pos = offset; break; - case SEEK_CUR: + case 1: /* SEEK_CUR */ file->f_pos += offset; break; - case SEEK_END: /* offset is negative */ + case 2: /* SEEK_END, offset is negative */ file->f_pos = priv->size + offset; break; default: diff --git a/trunk/sound/isa/opl3sa2.c b/trunk/sound/isa/opl3sa2.c index da92bf6c392b..4031b61b797f 100644 --- a/trunk/sound/isa/opl3sa2.c +++ b/trunk/sound/isa/opl3sa2.c @@ -33,7 +33,6 @@ #include #include #include -#include #include @@ -338,14 +337,6 @@ static irqreturn_t snd_opl3sa2_interrupt(int irq, void *dev_id, struct pt_regs * .info = snd_opl3sa2_info_single, \ .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \ .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } -#define OPL3SA2_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .index = xindex, \ - .info = snd_opl3sa2_info_single, \ - .get = snd_opl3sa2_get_single, .put = snd_opl3sa2_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } static int snd_opl3sa2_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -404,14 +395,6 @@ static int snd_opl3sa2_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_ .info = snd_opl3sa2_info_double, \ .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } -#define OPL3SA2_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .index = xindex, \ - .info = snd_opl3sa2_info_double, \ - .get = snd_opl3sa2_get_double, .put = snd_opl3sa2_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22), \ - .tlv = { .p = (xtlv) } } static int snd_opl3sa2_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -486,16 +469,11 @@ static int snd_opl3sa2_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_ return change; } -static DECLARE_TLV_DB_SCALE(db_scale_master, -3000, 200, 0); -static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); - static struct snd_kcontrol_new snd_opl3sa2_controls[] = { OPL3SA2_DOUBLE("Master Playback Switch", 0, 0x07, 0x08, 7, 7, 1, 1), -OPL3SA2_DOUBLE_TLV("Master Playback Volume", 0, 0x07, 0x08, 0, 0, 15, 1, - db_scale_master), +OPL3SA2_DOUBLE("Master Playback Volume", 0, 0x07, 0x08, 0, 0, 15, 1), OPL3SA2_SINGLE("Mic Playback Switch", 0, 0x09, 7, 1, 1), -OPL3SA2_SINGLE_TLV("Mic Playback Volume", 0, 0x09, 0, 31, 1, - db_scale_5bit_12db_max), +OPL3SA2_SINGLE("Mic Playback Volume", 0, 0x09, 0, 31, 1) }; static struct snd_kcontrol_new snd_opl3sa2_tone_controls[] = { diff --git a/trunk/sound/oss/Kconfig b/trunk/sound/oss/Kconfig index 97e38b665587..f4980ca5c05c 100644 --- a/trunk/sound/oss/Kconfig +++ b/trunk/sound/oss/Kconfig @@ -5,20 +5,6 @@ # # Prompt user for primary drivers. -config OSS_OBSOLETE_DRIVER - bool "Obsolete OSS drivers" - depends on SOUND_PRIME - help - This option enables support for obsolete OSS drivers that - are scheduled for removal in the near future since there - are ALSA drivers for the same hardware. - - Please contact Adrian Bunk if you had to - say Y here because your soundcard is not properly supported - by ALSA. - - If unsure, say N. - config SOUND_BT878 tristate "BT878 audio dma" depends on SOUND_PRIME && PCI @@ -37,7 +23,7 @@ config SOUND_BT878 config SOUND_EMU10K1 tristate "Creative SBLive! (EMU10K1)" - depends on SOUND_PRIME && PCI && OSS_OBSOLETE_DRIVER + depends on SOUND_PRIME && PCI ---help--- Say Y or M if you have a PCI sound card using the EMU10K1 chipset, such as the Creative SBLive!, SB PCI512 or Emu-APS. @@ -45,7 +31,7 @@ config SOUND_EMU10K1 For more information on this driver and the degree of support for the different card models please check: - + It is now possible to load dsp microcode patches into the EMU10K1 chip. These patches are used to implement real time sound @@ -63,7 +49,7 @@ config MIDI_EMU10K1 config SOUND_FUSION tristate "Crystal SoundFusion (CS4280/461x)" - depends on SOUND_PRIME && PCI && OSS_OBSOLETE_DRIVER + depends on SOUND_PRIME && PCI help This module drives the Crystal SoundFusion devices (CS4280/46xx series) when wired as native sound drivers with AC97 codecs. If @@ -154,7 +140,7 @@ config SOUND_TRIDENT system support" and "Sysctl support", and after the /proc file system has been mounted, executing the command - command what is enabled + command what is enabled echo 0>/proc/ALi5451 pcm out is also set to S/PDIF out. (Default). @@ -454,7 +440,7 @@ config SOUND_DMAP config SOUND_AD1816 tristate "AD1816(A) based cards (EXPERIMENTAL)" - depends on EXPERIMENTAL && SOUND_OSS && OSS_OBSOLETE_DRIVER + depends on EXPERIMENTAL && SOUND_OSS help Say M here if you have a sound card based on the Analog Devices AD1816(A) chip. @@ -464,21 +450,21 @@ config SOUND_AD1816 config SOUND_AD1889 tristate "AD1889 based cards (AD1819 codec) (EXPERIMENTAL)" - depends on EXPERIMENTAL && SOUND_OSS && PCI && OSS_OBSOLETE_DRIVER + depends on EXPERIMENTAL && SOUND_OSS && PCI help Say M here if you have a sound card based on the Analog Devices AD1889 chip. config SOUND_ADLIB tristate "Adlib Cards" - depends on SOUND_OSS && OSS_OBSOLETE_DRIVER + depends on SOUND_OSS help Includes ASB 64 4D. Information on programming AdLib cards is available at . config SOUND_ACI_MIXER tristate "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20)" - depends on SOUND_OSS && OSS_OBSOLETE_DRIVER + depends on SOUND_OSS ---help--- ACI (Audio Command Interface) is a protocol used to communicate with the microcontroller on some sound cards produced by miro and @@ -600,7 +586,7 @@ config SOUND_MPU401 config SOUND_NM256 tristate "NM256AV/NM256ZX audio support" - depends on SOUND_OSS && OSS_OBSOLETE_DRIVER + depends on SOUND_OSS help Say M here to include audio support for the NeoMagic 256AV/256ZX chipsets. These are the audio chipsets found in the Sony @@ -720,7 +706,7 @@ config SOUND_YM3812 config SOUND_OPL3SA2 tristate "Yamaha OPL3-SA2 and SA3 based PnP cards" - depends on SOUND_OSS && OSS_OBSOLETE_DRIVER + depends on SOUND_OSS help Say Y or M if you have a card based on one of these Yamaha sound chipsets or the "SAx", which is actually a SA3. Read @@ -852,7 +838,7 @@ config SOUND_WAVEARTIST config SOUND_TVMIXER tristate "TV card (bt848) mixer support" - depends on SOUND_PRIME && I2C && VIDEO_V4L1 + depends on SOUND_PRIME && I2C help Support for audio mixer facilities on the BT848 TV frame-grabber card. diff --git a/trunk/sound/oss/dmasound/dmasound_awacs.c b/trunk/sound/oss/dmasound/dmasound_awacs.c index 9ae659f82430..4359903f4376 100644 --- a/trunk/sound/oss/dmasound/dmasound_awacs.c +++ b/trunk/sound/oss/dmasound/dmasound_awacs.c @@ -347,8 +347,8 @@ int setup_audio_gpio(const char *name, const char* compatible, int *gpio_addr, int* gpio_pol) { struct device_node *np; - const u32* pp; - + u32* pp; + np = find_devices("gpio"); if (!np) return -ENODEV; @@ -356,8 +356,7 @@ setup_audio_gpio(const char *name, const char* compatible, int *gpio_addr, int* np = np->child; while(np != 0) { if (name) { - const char *property = - get_property(np,"audio-gpio",NULL); + char *property = get_property(np,"audio-gpio",NULL); if (property != 0 && strcmp(property,name) == 0) break; } else if (compatible && device_is_compatible(np, compatible)) @@ -366,11 +365,11 @@ setup_audio_gpio(const char *name, const char* compatible, int *gpio_addr, int* } if (!np) return -ENODEV; - pp = get_property(np, "AAPL,address", NULL); + pp = (u32 *)get_property(np, "AAPL,address", NULL); if (!pp) return -ENODEV; *gpio_addr = (*pp) & 0x0000ffff; - pp = get_property(np, "audio-gpio-active-state", NULL); + pp = (u32 *)get_property(np, "audio-gpio-active-state", NULL); if (pp) *gpio_pol = *pp; else diff --git a/trunk/sound/pci/Kconfig b/trunk/sound/pci/Kconfig index 8a6b1803c763..d7ad32f514da 100644 --- a/trunk/sound/pci/Kconfig +++ b/trunk/sound/pci/Kconfig @@ -16,16 +16,16 @@ config SND_AD1889 will be called snd-ad1889. config SND_ALS300 - tristate "Avance Logic ALS300/ALS300+" - depends on SND - select SND_PCM - select SND_AC97_CODEC - select SND_OPL3_LIB - help - Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+ + tristate "Avance Logic ALS300/ALS300+" + depends on SND + select SND_PCM + select SND_AC97_CODEC + select SND_OPL3_LIB + help + Say 'Y' or 'M' to include support for Avance Logic ALS300/ALS300+ - To compile this driver as a module, choose M here: the module - will be called snd-als300 + To compile this driver as a module, choose M here: the module + will be called snd-als300 config SND_ALS4000 tristate "Avance Logic ALS4000" @@ -78,49 +78,49 @@ config SND_ATIIXP_MODEM will be called snd-atiixp-modem. config SND_AU8810 - tristate "Aureal Advantage" - depends on SND + tristate "Aureal Advantage" + depends on SND select SND_MPU401_UART select SND_AC97_CODEC - help + help Say Y here to include support for Aureal Advantage soundcards. Supported features: Hardware Mixer, SRC, EQ and SPDIF output. - 3D support code is in place, but not yet useable. For more info, - email the ALSA developer list, or . + 3D support code is in place, but not yet useable. For more info, + email the ALSA developer list, or . To compile this driver as a module, choose M here: the module will be called snd-au8810. - + config SND_AU8820 - tristate "Aureal Vortex" - depends on SND + tristate "Aureal Vortex" + depends on SND select SND_MPU401_UART select SND_AC97_CODEC - help + help Say Y here to include support for Aureal Vortex soundcards. - Supported features: Hardware Mixer and SRC. For more info, email - the ALSA developer list, or . + Supported features: Hardware Mixer and SRC. For more info, email + the ALSA developer list, or . To compile this driver as a module, choose M here: the module will be called snd-au8820. - + config SND_AU8830 - tristate "Aureal Vortex 2" - depends on SND + tristate "Aureal Vortex 2" + depends on SND select SND_MPU401_UART select SND_AC97_CODEC - help + help Say Y here to include support for Aureal Vortex 2 soundcards. - Supported features: Hardware Mixer, SRC, EQ and SPDIF output. - 3D support code is in place, but not yet useable. For more info, - email the ALSA developer list, or . + Supported features: Hardware Mixer, SRC, EQ and SPDIF output. + 3D support code is in place, but not yet useable. For more info, + email the ALSA developer list, or . To compile this driver as a module, choose M here: the module will be called snd-au8830. - + config SND_AZT3328 tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)" depends on SND && EXPERIMENTAL @@ -135,10 +135,10 @@ config SND_AZT3328 will be called snd-azt3328. config SND_BT87X - tristate "Bt87x Audio Capture" - depends on SND + tristate "Bt87x Audio Capture" + depends on SND select SND_PCM - help + help If you want to record audio from TV cards based on Brooktree Bt878/Bt879 chips, say Y here and read . @@ -209,7 +209,7 @@ config SND_CS46XX config SND_CS46XX_NEW_DSP bool "Cirrus Logic (Sound Fusion) New DSP support" depends on SND_CS46XX - default y + default y help Say Y here to use a new DSP image for SPDIF and dual codecs. @@ -225,7 +225,7 @@ config SND_CS5535AUDIO referred to as NS CS5535 IO or AMD CS5535 IO companion in various literature. This driver also supports the CS5536 audio device. However, for both chips, on certain boards, you may - need to use ac97_quirk=hp_only if your board has physically + need to use ac97_quirk=hp_only if your board has physically mapped headphone out to master output. If that works for you, send lspci -vvv output to the mailing list so that your board can be identified in the quirks list. @@ -468,13 +468,10 @@ config SND_FM801_TEA575X_BOOL FM801 chip with a TEA5757 tuner connected to GPIO1-3 pins (Media Forte SF256-PCS-02) into the snd-fm801 driver. - This will enable support for the old V4L1 API. - config SND_FM801_TEA575X tristate depends on SND_FM801_TEA575X_BOOL default SND_FM801 - select VIDEO_V4L1 select VIDEO_DEV config SND_HDA_INTEL @@ -744,17 +741,4 @@ config SND_YMFPCI To compile this driver as a module, choose M here: the module will be called snd-ymfpci. -config SND_AC97_POWER_SAVE - bool "AC97 Power-Saving Mode" - depends on SND_AC97_CODEC && EXPERIMENTAL - default n - help - Say Y here to enable the aggressive power-saving support of - AC97 codecs. In this mode, the power-mode is dynamically - controlled at each open/close. - - The mode is activated by passing power_save=1 option to - snd-ac97-codec driver. You can toggle it dynamically over - sysfs, too. - endmenu diff --git a/trunk/sound/pci/ac97/ac97_codec.c b/trunk/sound/pci/ac97/ac97_codec.c index a79e91850ba3..0abf2808d59f 100644 --- a/trunk/sound/pci/ac97/ac97_codec.c +++ b/trunk/sound/pci/ac97/ac97_codec.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -48,11 +47,6 @@ static int enable_loopback; module_param(enable_loopback, bool, 0444); MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control"); -#ifdef CONFIG_SND_AC97_POWER_SAVE -static int power_save; -module_param(power_save, bool, 0644); -MODULE_PARM_DESC(power_save, "Enable AC97 power-saving control"); -#endif /* */ @@ -157,7 +151,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { { 0x4e534300, 0xffffffff, "LM4540,43,45,46,48", NULL, NULL }, // only guess --jk { 0x4e534331, 0xffffffff, "LM4549", NULL, NULL }, { 0x4e534350, 0xffffffff, "LM4550", patch_lm4550, NULL }, // volume wrap fix -{ 0x50534304, 0xffffffff, "UCB1400", patch_ucb1400, NULL }, +{ 0x50534304, 0xffffffff, "UCB1400", NULL, NULL }, { 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH }, { 0x54524102, 0xffffffff, "TR28022", NULL, NULL }, { 0x54524106, 0xffffffff, "TR28026", NULL, NULL }, @@ -193,8 +187,6 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { }; -static void update_power_regs(struct snd_ac97 *ac97); - /* * I/O routines */ @@ -562,18 +554,6 @@ int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value } err = snd_ac97_update_bits(ac97, reg, val_mask, val); snd_ac97_page_restore(ac97, page_save); -#ifdef CONFIG_SND_AC97_POWER_SAVE - /* check analog mixer power-down */ - if ((val_mask & 0x8000) && - (kcontrol->private_value & (1<<30))) { - if (val & 0x8000) - ac97->power_up &= ~(1 << (reg>>1)); - else - ac97->power_up |= 1 << (reg>>1); - if (power_save) - update_power_regs(ac97); - } -#endif return err; } @@ -593,7 +573,7 @@ AC97_SINGLE("PC Speaker Playback Volume", AC97_PC_BEEP, 1, 15, 1) }; static const struct snd_kcontrol_new snd_ac97_controls_mic_boost = - AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0); + AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_MIC, 6, 1, 0); static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"}; @@ -635,7 +615,7 @@ AC97_SINGLE("Simulated Stereo Enhancement", AC97_GENERAL_PURPOSE, 14, 1, 0), AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0), AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0), AC97_ENUM("Mono Output Select", std_enum[2]), -AC97_ENUM("Mic Select", std_enum[3]), +AC97_ENUM("Mic Select Capture Switch", std_enum[3]), AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0) }; @@ -982,10 +962,6 @@ static int snd_ac97_bus_dev_free(struct snd_device *device) static int snd_ac97_free(struct snd_ac97 *ac97) { if (ac97) { -#ifdef CONFIG_SND_AC97_POWER_SAVE - if (ac97->power_workq) - destroy_workqueue(ac97->power_workq); -#endif snd_ac97_proc_done(ac97); if (ac97->bus) ac97->bus->codec[ac97->num] = NULL; @@ -1141,9 +1117,7 @@ struct snd_kcontrol *snd_ac97_cnew(const struct snd_kcontrol_new *_template, str /* * create mute switch(es) for normal stereo controls */ -static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg, - int check_stereo, int check_amix, - struct snd_ac97 *ac97) +static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg, int check_stereo, struct snd_ac97 *ac97) { struct snd_kcontrol *kctl; int err; @@ -1163,14 +1137,10 @@ static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg, } if (mute_mask == 0x8080) { struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1); - if (check_amix) - tmp.private_value |= (1 << 30); tmp.index = ac97->num; kctl = snd_ctl_new1(&tmp, ac97); } else { struct snd_kcontrol_new tmp = AC97_SINGLE(name, reg, 15, 1, 1); - if (check_amix) - tmp.private_value |= (1 << 30); tmp.index = ac97->num; kctl = snd_ctl_new1(&tmp, ac97); } @@ -1182,32 +1152,6 @@ static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg, return 0; } -/* - * set dB information - */ -static DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); -static DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); -static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); -static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); -static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); - -static unsigned int *find_db_scale(unsigned int maxval) -{ - switch (maxval) { - case 0x0f: return db_scale_4bit; - case 0x1f: return db_scale_5bit; - case 0x3f: return db_scale_6bit; - } - return NULL; -} - -static void set_tlv_db_scale(struct snd_kcontrol *kctl, unsigned int *tlv) -{ - kctl->tlv.p = tlv; - if (tlv) - kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; -} - /* * create a volume for normal stereo/mono controls */ @@ -1230,10 +1174,6 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne tmp.index = ac97->num; kctl = snd_ctl_new1(&tmp, ac97); } - if (reg >= AC97_PHONE && reg <= AC97_PCM) - set_tlv_db_scale(kctl, db_scale_5bit_12db_max); - else - set_tlv_db_scale(kctl, find_db_scale(lo_max)); err = snd_ctl_add(card, kctl); if (err < 0) return err; @@ -1246,9 +1186,7 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne /* * create a mute-switch and a volume for normal stereo/mono controls */ -static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx, - int reg, int check_stereo, int check_amix, - struct snd_ac97 *ac97) +static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx, int reg, int check_stereo, struct snd_ac97 *ac97) { int err; char name[44]; @@ -1259,9 +1197,7 @@ static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx, if (snd_ac97_try_bit(ac97, reg, 15)) { sprintf(name, "%s Switch", pfx); - if ((err = snd_ac97_cmute_new_stereo(card, name, reg, - check_stereo, check_amix, - ac97)) < 0) + if ((err = snd_ac97_cmute_new_stereo(card, name, reg, check_stereo, ac97)) < 0) return err; } check_volume_resolution(ac97, reg, &lo_max, &hi_max); @@ -1273,10 +1209,8 @@ static int snd_ac97_cmix_new_stereo(struct snd_card *card, const char *pfx, return 0; } -#define snd_ac97_cmix_new(card, pfx, reg, acheck, ac97) \ - snd_ac97_cmix_new_stereo(card, pfx, reg, 0, acheck, ac97) -#define snd_ac97_cmute_new(card, name, reg, acheck, ac97) \ - snd_ac97_cmute_new_stereo(card, name, reg, 0, acheck, ac97) +#define snd_ac97_cmix_new(card, pfx, reg, ac97) snd_ac97_cmix_new_stereo(card, pfx, reg, 0, ac97) +#define snd_ac97_cmute_new(card, name, reg, ac97) snd_ac97_cmute_new_stereo(card, name, reg, 0, ac97) static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97); @@ -1292,11 +1226,9 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) /* AD claims to remove this control from AD1887, although spec v2.2 does not allow this */ if (snd_ac97_try_volume_mix(ac97, AC97_MASTER)) { if (ac97->flags & AC97_HAS_NO_MASTER_VOL) - err = snd_ac97_cmute_new(card, "Master Playback Switch", - AC97_MASTER, 0, ac97); + err = snd_ac97_cmute_new(card, "Master Playback Switch", AC97_MASTER, ac97); else - err = snd_ac97_cmix_new(card, "Master Playback", - AC97_MASTER, 0, ac97); + err = snd_ac97_cmix_new(card, "Master Playback", AC97_MASTER, ac97); if (err < 0) return err; } @@ -1313,7 +1245,6 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 0, &max); kctl->private_value &= ~(0xff << 16); kctl->private_value |= (int)max << 16; - set_tlv_db_scale(kctl, find_db_scale(max)); snd_ac97_write_cache(ac97, AC97_CENTER_LFE_MASTER, ac97->regs[AC97_CENTER_LFE_MASTER] | max); } @@ -1327,7 +1258,6 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) snd_ac97_change_volume_params2(ac97, AC97_CENTER_LFE_MASTER, 8, &max); kctl->private_value &= ~(0xff << 16); kctl->private_value |= (int)max << 16; - set_tlv_db_scale(kctl, find_db_scale(max)); snd_ac97_write_cache(ac97, AC97_CENTER_LFE_MASTER, ac97->regs[AC97_CENTER_LFE_MASTER] | max << 8); } @@ -1335,23 +1265,19 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) if ((snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) && !(ac97->flags & AC97_AD_MULTI)) { /* Surround Master (0x38) is with stereo mutes */ - if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", - AC97_SURROUND_MASTER, 1, 0, - ac97)) < 0) + if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", AC97_SURROUND_MASTER, 1, ac97)) < 0) return err; } /* build headphone controls */ if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) { - if ((err = snd_ac97_cmix_new(card, "Headphone Playback", - AC97_HEADPHONE, 0, ac97)) < 0) + if ((err = snd_ac97_cmix_new(card, "Headphone Playback", AC97_HEADPHONE, ac97)) < 0) return err; } /* build master mono controls */ if (snd_ac97_try_volume_mix(ac97, AC97_MASTER_MONO)) { - if ((err = snd_ac97_cmix_new(card, "Master Mono Playback", - AC97_MASTER_MONO, 0, ac97)) < 0) + if ((err = snd_ac97_cmix_new(card, "Master Mono Playback", AC97_MASTER_MONO, ac97)) < 0) return err; } @@ -1375,9 +1301,8 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) ((ac97->flags & AC97_HAS_PC_BEEP) || snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) { for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0) + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0) return err; - set_tlv_db_scale(kctl, db_scale_4bit); snd_ac97_write_cache(ac97, AC97_PC_BEEP, snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e); } @@ -1385,8 +1310,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) /* build Phone controls */ if (!(ac97->flags & AC97_HAS_NO_PHONE)) { if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) { - if ((err = snd_ac97_cmix_new(card, "Phone Playback", - AC97_PHONE, 1, ac97)) < 0) + if ((err = snd_ac97_cmix_new(card, "Phone Playback", AC97_PHONE, ac97)) < 0) return err; } } @@ -1394,8 +1318,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) /* build MIC controls */ if (!(ac97->flags & AC97_HAS_NO_MIC)) { if (snd_ac97_try_volume_mix(ac97, AC97_MIC)) { - if ((err = snd_ac97_cmix_new(card, "Mic Playback", - AC97_MIC, 1, ac97)) < 0) + if ((err = snd_ac97_cmix_new(card, "Mic Playback", AC97_MIC, ac97)) < 0) return err; if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_boost, ac97))) < 0) return err; @@ -1404,16 +1327,14 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) /* build Line controls */ if (snd_ac97_try_volume_mix(ac97, AC97_LINE)) { - if ((err = snd_ac97_cmix_new(card, "Line Playback", - AC97_LINE, 1, ac97)) < 0) + if ((err = snd_ac97_cmix_new(card, "Line Playback", AC97_LINE, ac97)) < 0) return err; } /* build CD controls */ if (!(ac97->flags & AC97_HAS_NO_CD)) { if (snd_ac97_try_volume_mix(ac97, AC97_CD)) { - if ((err = snd_ac97_cmix_new(card, "CD Playback", - AC97_CD, 1, ac97)) < 0) + if ((err = snd_ac97_cmix_new(card, "CD Playback", AC97_CD, ac97)) < 0) return err; } } @@ -1421,8 +1342,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) /* build Video controls */ if (!(ac97->flags & AC97_HAS_NO_VIDEO)) { if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) { - if ((err = snd_ac97_cmix_new(card, "Video Playback", - AC97_VIDEO, 1, ac97)) < 0) + if ((err = snd_ac97_cmix_new(card, "Video Playback", AC97_VIDEO, ac97)) < 0) return err; } } @@ -1430,8 +1350,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) /* build Aux controls */ if (!(ac97->flags & AC97_HAS_NO_AUX)) { if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) { - if ((err = snd_ac97_cmix_new(card, "Aux Playback", - AC97_AUX, 1, ac97)) < 0) + if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, ac97)) < 0) return err; } } @@ -1444,38 +1363,31 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) else init_val = 0x9f1f; for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97))) < 0) + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97))) < 0) return err; - set_tlv_db_scale(kctl, db_scale_5bit); ac97->spec.ad18xx.pcmreg[0] = init_val; if (ac97->scaps & AC97_SCAP_SURROUND_DAC) { for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97))) < 0) + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97))) < 0) return err; - set_tlv_db_scale(kctl, db_scale_5bit); ac97->spec.ad18xx.pcmreg[1] = init_val; } if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) { for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97))) < 0) + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97))) < 0) return err; - set_tlv_db_scale(kctl, db_scale_5bit); for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[idx], ac97))) < 0) + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[idx], ac97))) < 0) return err; - set_tlv_db_scale(kctl, db_scale_5bit); ac97->spec.ad18xx.pcmreg[2] = init_val; } snd_ac97_write_cache(ac97, AC97_PCM, init_val); } else { if (!(ac97->flags & AC97_HAS_NO_STD_PCM)) { if (ac97->flags & AC97_HAS_NO_PCM_VOL) - err = snd_ac97_cmute_new(card, - "PCM Playback Switch", - AC97_PCM, 0, ac97); + err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97); else - err = snd_ac97_cmix_new(card, "PCM Playback", - AC97_PCM, 0, ac97); + err = snd_ac97_cmix_new(card, "PCM Playback", AC97_PCM, ac97); if (err < 0) return err; } @@ -1486,23 +1398,19 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0) return err; if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) { - err = snd_ac97_cmute_new(card, "Capture Switch", - AC97_REC_GAIN, 0, ac97); - if (err < 0) + if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0) return err; } - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0) + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0) return err; - set_tlv_db_scale(kctl, db_scale_rec_gain); snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000); snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000); } /* build MIC Capture controls */ if (snd_ac97_try_volume_mix(ac97, AC97_REC_GAIN_MIC)) { for (idx = 0; idx < 2; idx++) - if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_mic_capture[idx], ac97))) < 0) + if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic_capture[idx], ac97))) < 0) return err; - set_tlv_db_scale(kctl, db_scale_rec_gain); snd_ac97_write_cache(ac97, AC97_REC_GAIN_MIC, 0x0000); } @@ -1573,12 +1481,6 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97) } /* build S/PDIF controls */ - - /* Hack for ASUS P5P800-VM, which does not indicate S/PDIF capability */ - if (ac97->subsystem_vendor == 0x1043 && - ac97->subsystem_device == 0x810f) - ac97->ext_id |= AC97_EI_SPDIF; - if ((ac97->ext_id & AC97_EI_SPDIF) && !(ac97->scaps & AC97_SCAP_NO_SPDIF)) { if (ac97->build_ops->build_spdif) { if ((err = ac97->build_ops->build_spdif(ac97)) < 0) @@ -1915,25 +1817,18 @@ static int snd_ac97_dev_register(struct snd_device *device) return 0; } -/* disconnect ac97 codec */ -static int snd_ac97_dev_disconnect(struct snd_device *device) +/* unregister ac97 codec */ +static int snd_ac97_dev_unregister(struct snd_device *device) { struct snd_ac97 *ac97 = device->device_data; if (ac97->dev.bus) device_unregister(&ac97->dev); - return 0; + return snd_ac97_free(ac97); } /* build_ops to do nothing */ static struct snd_ac97_build_ops null_build_ops; -#ifdef CONFIG_SND_AC97_POWER_SAVE -static void do_update_power(void *data) -{ - update_power_regs(data); -} -#endif - /** * snd_ac97_mixer - create an Codec97 component * @bus: the AC97 bus which codec is attached to @@ -1965,7 +1860,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, static struct snd_device_ops ops = { .dev_free = snd_ac97_dev_free, .dev_register = snd_ac97_dev_register, - .dev_disconnect = snd_ac97_dev_disconnect, + .dev_unregister = snd_ac97_dev_unregister, }; snd_assert(rac97 != NULL, return -EINVAL); @@ -1988,10 +1883,6 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, bus->codec[ac97->num] = ac97; mutex_init(&ac97->reg_mutex); mutex_init(&ac97->page_mutex); -#ifdef CONFIG_SND_AC97_POWER_SAVE - ac97->power_workq = create_workqueue("ac97"); - INIT_WORK(&ac97->power_work, do_update_power, ac97); -#endif #ifdef CONFIG_PCI if (ac97->pci) { @@ -2226,8 +2117,15 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, return -ENOMEM; } } - if (ac97_is_audio(ac97)) - update_power_regs(ac97); + /* make sure the proper powerdown bits are cleared */ + if (ac97->scaps && ac97_is_audio(ac97)) { + reg = snd_ac97_read(ac97, AC97_EXTENDED_STATUS); + if (ac97->scaps & AC97_SCAP_SURROUND_DAC) + reg &= ~AC97_EA_PRJ; + if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) + reg &= ~(AC97_EA_PRI | AC97_EA_PRK); + snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, reg); + } snd_ac97_proc_init(ac97); if ((err = snd_device_new(card, SNDRV_DEV_CODEC, ac97, &ops)) < 0) { snd_ac97_free(ac97); @@ -2255,152 +2153,19 @@ static void snd_ac97_powerdown(struct snd_ac97 *ac97) snd_ac97_write(ac97, AC97_HEADPHONE, 0x9f9f); } - /* surround, CLFE, mic powerdown */ - power = ac97->regs[AC97_EXTENDED_STATUS]; - if (ac97->scaps & AC97_SCAP_SURROUND_DAC) - power |= AC97_EA_PRJ; - if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) - power |= AC97_EA_PRI | AC97_EA_PRK; - power |= AC97_EA_PRL; - snd_ac97_write(ac97, AC97_EXTENDED_STATUS, power); - - /* powerdown external amplifier */ - if (ac97->scaps & AC97_SCAP_INV_EAPD) - power = ac97->regs[AC97_POWERDOWN] & ~AC97_PD_EAPD; - else if (! (ac97->scaps & AC97_SCAP_EAPD_LED)) - power = ac97->regs[AC97_POWERDOWN] | AC97_PD_EAPD; - power |= AC97_PD_PR6; /* Headphone amplifier powerdown */ - power |= AC97_PD_PR0 | AC97_PD_PR1; /* ADC & DAC powerdown */ + power = ac97->regs[AC97_POWERDOWN] | 0x8000; /* EAPD */ + power |= 0x4000; /* Headphone amplifier powerdown */ + power |= 0x0300; /* ADC & DAC powerdown */ snd_ac97_write(ac97, AC97_POWERDOWN, power); udelay(100); - power |= AC97_PD_PR2 | AC97_PD_PR3; /* Analog Mixer powerdown */ + power |= 0x0400; /* Analog Mixer powerdown (Vref on) */ + snd_ac97_write(ac97, AC97_POWERDOWN, power); + udelay(100); +#if 0 + /* FIXME: this causes click noises on some boards at resume */ + power |= 0x3800; /* AC-link powerdown, internal Clk disable */ snd_ac97_write(ac97, AC97_POWERDOWN, power); -#ifdef CONFIG_SND_AC97_POWER_SAVE - if (power_save) { - udelay(100); - /* AC-link powerdown, internal Clk disable */ - /* FIXME: this may cause click noises on some boards */ - power |= AC97_PD_PR4 | AC97_PD_PR5; - snd_ac97_write(ac97, AC97_POWERDOWN, power); - } -#endif -} - - -struct ac97_power_reg { - unsigned short reg; - unsigned short power_reg; - unsigned short mask; -}; - -enum { PWIDX_ADC, PWIDX_FRONT, PWIDX_CLFE, PWIDX_SURR, PWIDX_MIC, PWIDX_SIZE }; - -static struct ac97_power_reg power_regs[PWIDX_SIZE] = { - [PWIDX_ADC] = { AC97_PCM_LR_ADC_RATE, AC97_POWERDOWN, AC97_PD_PR0}, - [PWIDX_FRONT] = { AC97_PCM_FRONT_DAC_RATE, AC97_POWERDOWN, AC97_PD_PR1}, - [PWIDX_CLFE] = { AC97_PCM_LFE_DAC_RATE, AC97_EXTENDED_STATUS, - AC97_EA_PRI | AC97_EA_PRK}, - [PWIDX_SURR] = { AC97_PCM_SURR_DAC_RATE, AC97_EXTENDED_STATUS, - AC97_EA_PRJ}, - [PWIDX_MIC] = { AC97_PCM_MIC_ADC_RATE, AC97_EXTENDED_STATUS, - AC97_EA_PRL}, -}; - -#ifdef CONFIG_SND_AC97_POWER_SAVE -/** - * snd_ac97_update_power - update the powerdown register - * @ac97: the codec instance - * @reg: the rate register, e.g. AC97_PCM_FRONT_DAC_RATE - * @powerup: non-zero when power up the part - * - * Update the AC97 powerdown register bits of the given part. - */ -int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup) -{ - int i; - - if (! ac97) - return 0; - - if (reg) { - /* SPDIF requires DAC power, too */ - if (reg == AC97_SPDIF) - reg = AC97_PCM_FRONT_DAC_RATE; - for (i = 0; i < PWIDX_SIZE; i++) { - if (power_regs[i].reg == reg) { - if (powerup) - ac97->power_up |= (1 << i); - else - ac97->power_up &= ~(1 << i); - break; - } - } - } - - if (! power_save) - return 0; - - if (! powerup && ac97->power_workq) - /* adjust power-down bits after two seconds delay - * (for avoiding loud click noises for many (OSS) apps - * that open/close frequently) - */ - queue_delayed_work(ac97->power_workq, &ac97->power_work, HZ*2); - else - update_power_regs(ac97); - - return 0; -} - -EXPORT_SYMBOL(snd_ac97_update_power); -#endif /* CONFIG_SND_AC97_POWER_SAVE */ - -static void update_power_regs(struct snd_ac97 *ac97) -{ - unsigned int power_up, bits; - int i; - -#ifdef CONFIG_SND_AC97_POWER_SAVE - if (power_save) - power_up = ac97->power_up; - else { -#endif - power_up = (1 << PWIDX_FRONT) | (1 << PWIDX_ADC); - power_up |= (1 << PWIDX_MIC); - if (ac97->scaps & AC97_SCAP_SURROUND_DAC) - power_up |= (1 << PWIDX_SURR); - if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) - power_up |= (1 << PWIDX_CLFE); -#ifdef CONFIG_SND_AC97_POWER_SAVE - } #endif - if (power_up) { - if (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2) { - /* needs power-up analog mix and vref */ - snd_ac97_update_bits(ac97, AC97_POWERDOWN, - AC97_PD_PR3, 0); - msleep(1); - snd_ac97_update_bits(ac97, AC97_POWERDOWN, - AC97_PD_PR2, 0); - } - } - for (i = 0; i < PWIDX_SIZE; i++) { - if (power_up & (1 << i)) - bits = 0; - else - bits = power_regs[i].mask; - snd_ac97_update_bits(ac97, power_regs[i].power_reg, - power_regs[i].mask, bits); - } - if (! power_up) { - if (! (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2)) { - /* power down analog mix and vref */ - snd_ac97_update_bits(ac97, AC97_POWERDOWN, - AC97_PD_PR2, AC97_PD_PR2); - snd_ac97_update_bits(ac97, AC97_POWERDOWN, - AC97_PD_PR3, AC97_PD_PR3); - } - } } @@ -2719,7 +2484,6 @@ static int tune_mute_led(struct snd_ac97 *ac97) msw->put = master_mute_sw_put; snd_ac97_remove_ctl(ac97, "External Amplifier", NULL); snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, 0x8000); /* mute LED on */ - ac97->scaps |= AC97_SCAP_EAPD_LED; return 0; } diff --git a/trunk/sound/pci/ac97/ac97_patch.c b/trunk/sound/pci/ac97/ac97_patch.c index dc28b111a06d..094cfc1f3a19 100644 --- a/trunk/sound/pci/ac97/ac97_patch.c +++ b/trunk/sound/pci/ac97/ac97_patch.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include "ac97_patch.h" #include "ac97_id.h" @@ -52,20 +51,6 @@ static int patch_build_controls(struct snd_ac97 * ac97, const struct snd_kcontro return 0; } -/* replace with a new TLV */ -static void reset_tlv(struct snd_ac97 *ac97, const char *name, - unsigned int *tlv) -{ - struct snd_ctl_elem_id sid; - struct snd_kcontrol *kctl; - memset(&sid, 0, sizeof(sid)); - strcpy(sid.name, name); - sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; - kctl = snd_ctl_find_id(ac97->bus->card, &sid); - if (kctl && kctl->tlv.p) - kctl->tlv.p = tlv; -} - /* set to the page, update bits and restore the page */ static int ac97_update_bits_page(struct snd_ac97 *ac97, unsigned short reg, unsigned short mask, unsigned short value, unsigned short page) { @@ -481,7 +466,7 @@ int patch_wolfson05(struct snd_ac97 * ac97) ac97->build_ops = &patch_wolfson_wm9705_ops; #ifdef CONFIG_TOUCHSCREEN_WM9705 /* WM9705 touchscreen uses AUX and VIDEO for touch */ - ac97->flags |= AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX; + ac97->flags |=3D AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX; #endif return 0; } @@ -1395,17 +1380,6 @@ static void ad1888_resume(struct snd_ac97 *ac97) #endif -static const struct snd_ac97_res_table ad1819_restbl[] = { - { AC97_PHONE, 0x9f1f }, - { AC97_MIC, 0x9f1f }, - { AC97_LINE, 0x9f1f }, - { AC97_CD, 0x9f1f }, - { AC97_VIDEO, 0x9f1f }, - { AC97_AUX, 0x9f1f }, - { AC97_PCM, 0x9f1f }, - { } /* terminator */ -}; - int patch_ad1819(struct snd_ac97 * ac97) { unsigned short scfg; @@ -1413,7 +1387,6 @@ int patch_ad1819(struct snd_ac97 * ac97) // patch for Analog Devices scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG); snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x7000); /* select all codecs */ - ac97->res_table = ad1819_restbl; return 0; } @@ -1549,16 +1522,12 @@ static const struct snd_kcontrol_new snd_ac97_controls_ad1885[] = { AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */ }; -static DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0); - static int patch_ad1885_specific(struct snd_ac97 * ac97) { int err; if ((err = patch_build_controls(ac97, snd_ac97_controls_ad1885, ARRAY_SIZE(snd_ac97_controls_ad1885))) < 0) return err; - reset_tlv(ac97, "Headphone Playback Volume", - db_scale_6bit_6db_max); return 0; } @@ -1582,27 +1551,12 @@ int patch_ad1885(struct snd_ac97 * ac97) return 0; } -static int patch_ad1886_specific(struct snd_ac97 * ac97) -{ - reset_tlv(ac97, "Headphone Playback Volume", - db_scale_6bit_6db_max); - return 0; -} - -static struct snd_ac97_build_ops patch_ad1886_build_ops = { - .build_specific = &patch_ad1886_specific, -#ifdef CONFIG_PM - .resume = ad18xx_resume -#endif -}; - int patch_ad1886(struct snd_ac97 * ac97) { patch_ad1881(ac97); /* Presario700 workaround */ /* for Jack Sense/SPDIF Register misetting causing */ snd_ac97_write_cache(ac97, AC97_AD_JACK_SPDIF, 0x0010); - ac97->build_ops = &patch_ad1886_build_ops; return 0; } @@ -2061,8 +2015,6 @@ static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = { /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */ }; -static DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0); - static int patch_alc650_specific(struct snd_ac97 * ac97) { int err; @@ -2073,9 +2025,6 @@ static int patch_alc650_specific(struct snd_ac97 * ac97) if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0) return err; } - if (ac97->id != AC97_ID_ALC650F) - reset_tlv(ac97, "Master Playback Volume", - db_scale_5bit_3db_max); return 0; } @@ -2259,8 +2208,7 @@ int patch_alc655(struct snd_ac97 * ac97) val &= ~(1 << 1); /* Pin 47 is spdif input pin */ else { /* ALC655 */ if (ac97->subsystem_vendor == 0x1462 && - (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */ - ac97->subsystem_device == 0x0161)) /* LG K1 Express */ + ac97->subsystem_device == 0x0131) /* MSI S270 laptop */ val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */ else val |= (1 << 1); /* Pin 47 is spdif input pin */ @@ -2811,10 +2759,6 @@ int patch_vt1616(struct snd_ac97 * ac97) */ int patch_vt1617a(struct snd_ac97 * ac97) { - /* bring analog power consumption to normal, like WinXP driver - * for EPIA SP - */ - snd_ac97_write_cache(ac97, 0x5c, 0x20); ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; return 0; @@ -2928,41 +2872,3 @@ int patch_lm4550(struct snd_ac97 *ac97) ac97->res_table = lm4550_restbl; return 0; } - -/* - * UCB1400 codec (http://www.semiconductors.philips.com/acrobat_download/datasheets/UCB1400-02.pdf) - */ -static const struct snd_kcontrol_new snd_ac97_controls_ucb1400[] = { -/* enable/disable headphone driver which allows direct connection to - stereo headphone without the use of external DC blocking - capacitors */ -AC97_SINGLE("Headphone Driver", 0x6a, 6, 1, 0), -/* Filter used to compensate the DC offset is added in the ADC to remove idle - tones from the audio band. */ -AC97_SINGLE("DC Filter", 0x6a, 4, 1, 0), -/* Control smart-low-power mode feature. Allows automatic power down - of unused blocks in the ADC analog front end and the PLL. */ -AC97_SINGLE("Smart Low Power Mode", 0x6c, 4, 3, 0), -}; - -static int patch_ucb1400_specific(struct snd_ac97 * ac97) -{ - int idx, err; - for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_ucb1400); idx++) - if ((err = snd_ctl_add(ac97->bus->card, snd_ctl_new1(&snd_ac97_controls_ucb1400[idx], ac97))) < 0) - return err; - return 0; -} - -static struct snd_ac97_build_ops patch_ucb1400_ops = { - .build_specific = patch_ucb1400_specific, -}; - -int patch_ucb1400(struct snd_ac97 * ac97) -{ - ac97->build_ops = &patch_ucb1400_ops; - /* enable headphone driver and smart low power mode by default */ - snd_ac97_write(ac97, 0x6a, 0x0050); - snd_ac97_write(ac97, 0x6c, 0x0030); - return 0; -} diff --git a/trunk/sound/pci/ac97/ac97_patch.h b/trunk/sound/pci/ac97/ac97_patch.h index 741979217207..adcaa04586cb 100644 --- a/trunk/sound/pci/ac97/ac97_patch.h +++ b/trunk/sound/pci/ac97/ac97_patch.h @@ -58,6 +58,5 @@ int patch_cm9780(struct snd_ac97 * ac97); int patch_vt1616(struct snd_ac97 * ac97); int patch_vt1617a(struct snd_ac97 * ac97); int patch_it2646(struct snd_ac97 * ac97); -int patch_ucb1400(struct snd_ac97 * ac97); int mpatch_si3036(struct snd_ac97 * ac97); int patch_lm4550(struct snd_ac97 * ac97); diff --git a/trunk/sound/pci/ac97/ac97_pcm.c b/trunk/sound/pci/ac97/ac97_pcm.c index 3758d07182f8..f684aa2c0067 100644 --- a/trunk/sound/pci/ac97/ac97_pcm.c +++ b/trunk/sound/pci/ac97/ac97_pcm.c @@ -269,7 +269,6 @@ int snd_ac97_set_rate(struct snd_ac97 *ac97, int reg, unsigned int rate) return -EINVAL; } - snd_ac97_update_power(ac97, reg, 1); switch (reg) { case AC97_PCM_MIC_ADC_RATE: if ((ac97->regs[AC97_EXTENDED_STATUS] & AC97_EA_VRM) == 0) /* MIC VRA */ @@ -607,7 +606,6 @@ int snd_ac97_pcm_open(struct ac97_pcm *pcm, unsigned int rate, goto error; } } - pcm->cur_dbl = r; spin_unlock_irq(&pcm->bus->bus_lock); for (i = 3; i < 12; i++) { if (!(slots & (1 << i))) @@ -653,21 +651,6 @@ int snd_ac97_pcm_close(struct ac97_pcm *pcm) unsigned short slots = pcm->aslots; int i, cidx; -#ifdef CONFIG_SND_AC97_POWER_SAVE - int r = pcm->cur_dbl; - for (i = 3; i < 12; i++) { - if (!(slots & (1 << i))) - continue; - for (cidx = 0; cidx < 4; cidx++) { - if (pcm->r[r].rslots[cidx] & (1 << i)) { - int reg = get_slot_reg(pcm, cidx, i, r); - snd_ac97_update_power(pcm->r[r].codec[cidx], - reg, 0); - } - } - } -#endif - bus = pcm->bus; spin_lock_irq(&pcm->bus->bus_lock); for (i = 3; i < 12; i++) { @@ -677,7 +660,6 @@ int snd_ac97_pcm_close(struct ac97_pcm *pcm) bus->used_slots[pcm->stream][cidx] &= ~(1 << i); } pcm->aslots = 0; - pcm->cur_dbl = 0; spin_unlock_irq(&pcm->bus->bus_lock); return 0; } diff --git a/trunk/sound/pci/ac97/ac97_proc.c b/trunk/sound/pci/ac97/ac97_proc.c index a3fdd7da911c..2118df50b9d6 100644 --- a/trunk/sound/pci/ac97/ac97_proc.c +++ b/trunk/sound/pci/ac97/ac97_proc.c @@ -457,10 +457,14 @@ void snd_ac97_proc_init(struct snd_ac97 * ac97) void snd_ac97_proc_done(struct snd_ac97 * ac97) { - snd_info_free_entry(ac97->proc_regs); - ac97->proc_regs = NULL; - snd_info_free_entry(ac97->proc); - ac97->proc = NULL; + if (ac97->proc_regs) { + snd_info_unregister(ac97->proc_regs); + ac97->proc_regs = NULL; + } + if (ac97->proc) { + snd_info_unregister(ac97->proc); + ac97->proc = NULL; + } } void snd_ac97_bus_proc_init(struct snd_ac97_bus * bus) @@ -481,6 +485,8 @@ void snd_ac97_bus_proc_init(struct snd_ac97_bus * bus) void snd_ac97_bus_proc_done(struct snd_ac97_bus * bus) { - snd_info_free_entry(bus->proc); - bus->proc = NULL; + if (bus->proc) { + snd_info_unregister(bus->proc); + bus->proc = NULL; + } } diff --git a/trunk/sound/pci/ac97/ak4531_codec.c b/trunk/sound/pci/ac97/ak4531_codec.c index c153cb79c518..94c26ec05882 100644 --- a/trunk/sound/pci/ac97/ak4531_codec.c +++ b/trunk/sound/pci/ac97/ak4531_codec.c @@ -27,7 +27,6 @@ #include #include -#include MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("Universal routines for AK4531 codec"); @@ -64,14 +63,6 @@ static void snd_ak4531_dump(struct snd_ak4531 *ak4531) .info = snd_ak4531_info_single, \ .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \ .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22) } -#define AK4531_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .index = xindex, \ - .info = snd_ak4531_info_single, \ - .get = snd_ak4531_get_single, .put = snd_ak4531_put_single, \ - .private_value = reg | (shift << 16) | (mask << 24) | (invert << 22), \ - .tlv = { .p = (xtlv) } } static int snd_ak4531_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -131,14 +122,6 @@ static int snd_ak4531_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_e .info = snd_ak4531_info_double, \ .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \ .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22) } -#define AK4531_DOUBLE_TLV(xname, xindex, left_reg, right_reg, left_shift, right_shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .index = xindex, \ - .info = snd_ak4531_info_double, \ - .get = snd_ak4531_get_double, .put = snd_ak4531_put_double, \ - .private_value = left_reg | (right_reg << 8) | (left_shift << 16) | (right_shift << 19) | (mask << 24) | (invert << 22), \ - .tlv = { .p = (xtlv) } } static int snd_ak4531_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -267,62 +250,50 @@ static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl return change; } -static DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0); -static DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0); -static DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0); - static struct snd_kcontrol_new snd_ak4531_controls[] = { -AK4531_DOUBLE_TLV("Master Playback Switch", 0, - AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1, - db_scale_master), +AK4531_DOUBLE("Master Playback Switch", 0, AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1), AK4531_DOUBLE("Master Playback Volume", 0, AK4531_LMASTER, AK4531_RMASTER, 0, 0, 0x1f, 1), -AK4531_SINGLE_TLV("Master Mono Playback Switch", 0, AK4531_MONO_OUT, 7, 1, 1, - db_scale_mono), +AK4531_SINGLE("Master Mono Playback Switch", 0, AK4531_MONO_OUT, 7, 1, 1), AK4531_SINGLE("Master Mono Playback Volume", 0, AK4531_MONO_OUT, 0, 0x07, 1), AK4531_DOUBLE("PCM Switch", 0, AK4531_LVOICE, AK4531_RVOICE, 7, 7, 1, 1), -AK4531_DOUBLE_TLV("PCM Volume", 0, AK4531_LVOICE, AK4531_RVOICE, 0, 0, 0x1f, 1, - db_scale_input), +AK4531_DOUBLE("PCM Volume", 0, AK4531_LVOICE, AK4531_RVOICE, 0, 0, 0x1f, 1), AK4531_DOUBLE("PCM Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 3, 2, 1, 0), AK4531_DOUBLE("PCM Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 2, 2, 1, 0), AK4531_DOUBLE("PCM Switch", 1, AK4531_LFM, AK4531_RFM, 7, 7, 1, 1), -AK4531_DOUBLE_TLV("PCM Volume", 1, AK4531_LFM, AK4531_RFM, 0, 0, 0x1f, 1, - db_scale_input), +AK4531_DOUBLE("PCM Volume", 1, AK4531_LFM, AK4531_RFM, 0, 0, 0x1f, 1), AK4531_DOUBLE("PCM Playback Switch", 1, AK4531_OUT_SW1, AK4531_OUT_SW1, 6, 5, 1, 0), AK4531_INPUT_SW("PCM Capture Route", 1, AK4531_LIN_SW1, AK4531_RIN_SW1, 6, 5), AK4531_DOUBLE("CD Switch", 0, AK4531_LCD, AK4531_RCD, 7, 7, 1, 1), -AK4531_DOUBLE_TLV("CD Volume", 0, AK4531_LCD, AK4531_RCD, 0, 0, 0x1f, 1, - db_scale_input), +AK4531_DOUBLE("CD Volume", 0, AK4531_LCD, AK4531_RCD, 0, 0, 0x1f, 1), AK4531_DOUBLE("CD Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 2, 1, 1, 0), AK4531_INPUT_SW("CD Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 2, 1), AK4531_DOUBLE("Line Switch", 0, AK4531_LLINE, AK4531_RLINE, 7, 7, 1, 1), -AK4531_DOUBLE_TLV("Line Volume", 0, AK4531_LLINE, AK4531_RLINE, 0, 0, 0x1f, 1, - db_scale_input), +AK4531_DOUBLE("Line Volume", 0, AK4531_LLINE, AK4531_RLINE, 0, 0, 0x1f, 1), AK4531_DOUBLE("Line Playback Switch", 0, AK4531_OUT_SW1, AK4531_OUT_SW1, 4, 3, 1, 0), AK4531_INPUT_SW("Line Capture Route", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 4, 3), AK4531_DOUBLE("Aux Switch", 0, AK4531_LAUXA, AK4531_RAUXA, 7, 7, 1, 1), -AK4531_DOUBLE_TLV("Aux Volume", 0, AK4531_LAUXA, AK4531_RAUXA, 0, 0, 0x1f, 1, - db_scale_input), +AK4531_DOUBLE("Aux Volume", 0, AK4531_LAUXA, AK4531_RAUXA, 0, 0, 0x1f, 1), AK4531_DOUBLE("Aux Playback Switch", 0, AK4531_OUT_SW2, AK4531_OUT_SW2, 5, 4, 1, 0), AK4531_INPUT_SW("Aux Capture Route", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 4, 3), AK4531_SINGLE("Mono Switch", 0, AK4531_MONO1, 7, 1, 1), -AK4531_SINGLE_TLV("Mono Volume", 0, AK4531_MONO1, 0, 0x1f, 1, db_scale_input), +AK4531_SINGLE("Mono Volume", 0, AK4531_MONO1, 0, 0x1f, 1), AK4531_SINGLE("Mono Playback Switch", 0, AK4531_OUT_SW2, 0, 1, 0), AK4531_DOUBLE("Mono Capture Switch", 0, AK4531_LIN_SW2, AK4531_RIN_SW2, 0, 0, 1, 0), AK4531_SINGLE("Mono Switch", 1, AK4531_MONO2, 7, 1, 1), -AK4531_SINGLE_TLV("Mono Volume", 1, AK4531_MONO2, 0, 0x1f, 1, db_scale_input), +AK4531_SINGLE("Mono Volume", 1, AK4531_MONO2, 0, 0x1f, 1), AK4531_SINGLE("Mono Playback Switch", 1, AK4531_OUT_SW2, 1, 1, 0), AK4531_DOUBLE("Mono Capture Switch", 1, AK4531_LIN_SW2, AK4531_RIN_SW2, 1, 1, 1, 0), -AK4531_SINGLE_TLV("Mic Volume", 0, AK4531_MIC, 0, 0x1f, 1, db_scale_input), +AK4531_SINGLE("Mic Volume", 0, AK4531_MIC, 0, 0x1f, 1), AK4531_SINGLE("Mic Switch", 0, AK4531_MIC, 7, 1, 1), AK4531_SINGLE("Mic Playback Switch", 0, AK4531_OUT_SW1, 0, 1, 0), AK4531_DOUBLE("Mic Capture Switch", 0, AK4531_LIN_SW1, AK4531_RIN_SW1, 0, 0, 1, 0), diff --git a/trunk/sound/pci/ca0106/ca0106_mixer.c b/trunk/sound/pci/ca0106/ca0106_mixer.c index 9855f528ea78..146eed70dce6 100644 --- a/trunk/sound/pci/ca0106/ca0106_mixer.c +++ b/trunk/sound/pci/ca0106/ca0106_mixer.c @@ -70,13 +70,9 @@ #include #include #include -#include #include "ca0106.h" -static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1); -static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1); - static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -473,24 +469,18 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol, #define CA_VOLUME(xname,chid,reg) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ .info = snd_ca0106_volume_info, \ .get = snd_ca0106_volume_get, \ .put = snd_ca0106_volume_put, \ - .tlv = { .p = snd_ca0106_db_scale1 }, \ .private_value = ((chid) << 8) | (reg) \ } #define I2C_VOLUME(xname,chid) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ .info = snd_ca0106_i2c_volume_info, \ .get = snd_ca0106_i2c_volume_get, \ .put = snd_ca0106_i2c_volume_put, \ - .tlv = { .p = snd_ca0106_db_scale2 }, \ .private_value = chid \ } diff --git a/trunk/sound/pci/cs4281.c b/trunk/sound/pci/cs4281.c index 1990430a21c1..9631456ec3de 100644 --- a/trunk/sound/pci/cs4281.c +++ b/trunk/sound/pci/cs4281.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -1055,8 +1054,6 @@ static int snd_cs4281_put_volume(struct snd_kcontrol *kcontrol, return change; } -static DECLARE_TLV_DB_SCALE(db_scale_dsp, -4650, 150, 0); - static struct snd_kcontrol_new snd_cs4281_fm_vol = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1065,7 +1062,6 @@ static struct snd_kcontrol_new snd_cs4281_fm_vol = .get = snd_cs4281_get_volume, .put = snd_cs4281_put_volume, .private_value = ((BA0_FMLVC << 16) | BA0_FMRVC), - .tlv = { .p = db_scale_dsp }, }; static struct snd_kcontrol_new snd_cs4281_pcm_vol = @@ -1076,7 +1072,6 @@ static struct snd_kcontrol_new snd_cs4281_pcm_vol = .get = snd_cs4281_get_volume, .put = snd_cs4281_put_volume, .private_value = ((BA0_PPLVC << 16) | BA0_PPRVC), - .tlv = { .p = db_scale_dsp }, }; static void snd_cs4281_mixer_free_ac97_bus(struct snd_ac97_bus *bus) diff --git a/trunk/sound/pci/cs46xx/dsp_spos.c b/trunk/sound/pci/cs46xx/dsp_spos.c index 89c402770a1d..5c9711c0265c 100644 --- a/trunk/sound/pci/cs46xx/dsp_spos.c +++ b/trunk/sound/pci/cs46xx/dsp_spos.c @@ -868,23 +868,35 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip) struct dsp_spos_instance * ins = chip->dsp_spos_instance; int i; - snd_info_free_entry(ins->proc_sym_info_entry); - ins->proc_sym_info_entry = NULL; - - snd_info_free_entry(ins->proc_modules_info_entry); - ins->proc_modules_info_entry = NULL; - - snd_info_free_entry(ins->proc_parameter_dump_info_entry); - ins->proc_parameter_dump_info_entry = NULL; - - snd_info_free_entry(ins->proc_sample_dump_info_entry); - ins->proc_sample_dump_info_entry = NULL; - - snd_info_free_entry(ins->proc_scb_info_entry); - ins->proc_scb_info_entry = NULL; - - snd_info_free_entry(ins->proc_task_info_entry); - ins->proc_task_info_entry = NULL; + if (ins->proc_sym_info_entry) { + snd_info_unregister(ins->proc_sym_info_entry); + ins->proc_sym_info_entry = NULL; + } + + if (ins->proc_modules_info_entry) { + snd_info_unregister(ins->proc_modules_info_entry); + ins->proc_modules_info_entry = NULL; + } + + if (ins->proc_parameter_dump_info_entry) { + snd_info_unregister(ins->proc_parameter_dump_info_entry); + ins->proc_parameter_dump_info_entry = NULL; + } + + if (ins->proc_sample_dump_info_entry) { + snd_info_unregister(ins->proc_sample_dump_info_entry); + ins->proc_sample_dump_info_entry = NULL; + } + + if (ins->proc_scb_info_entry) { + snd_info_unregister(ins->proc_scb_info_entry); + ins->proc_scb_info_entry = NULL; + } + + if (ins->proc_task_info_entry) { + snd_info_unregister(ins->proc_task_info_entry); + ins->proc_task_info_entry = NULL; + } mutex_lock(&chip->spos_mutex); for (i = 0; i < ins->nscb; ++i) { @@ -893,8 +905,10 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip) } mutex_unlock(&chip->spos_mutex); - snd_info_free_entry(ins->proc_dsp_dir); - ins->proc_dsp_dir = NULL; + if (ins->proc_dsp_dir) { + snd_info_unregister (ins->proc_dsp_dir); + ins->proc_dsp_dir = NULL; + } return 0; } diff --git a/trunk/sound/pci/cs46xx/dsp_spos_scb_lib.c b/trunk/sound/pci/cs46xx/dsp_spos_scb_lib.c index 343f51d5311b..232b337852ff 100644 --- a/trunk/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/trunk/sound/pci/cs46xx/dsp_spos_scb_lib.c @@ -233,7 +233,7 @@ void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb) snd_printdd("cs46xx_dsp_proc_free_scb_desc: freeing %s\n",scb->scb_name); - snd_info_free_entry(scb->proc_info); + snd_info_unregister(scb->proc_info); scb->proc_info = NULL; snd_assert (scb_info != NULL, return); diff --git a/trunk/sound/pci/cs5535audio/Makefile b/trunk/sound/pci/cs5535audio/Makefile index ad947b4c04cc..2911a8adc1f2 100644 --- a/trunk/sound/pci/cs5535audio/Makefile +++ b/trunk/sound/pci/cs5535audio/Makefile @@ -4,7 +4,7 @@ snd-cs5535audio-objs := cs5535audio.o cs5535audio_pcm.o -ifeq ($(CONFIG_PM),y) +ifdef CONFIG_PM snd-cs5535audio-objs += cs5535audio_pm.o endif diff --git a/trunk/sound/pci/echoaudio/echoaudio.c b/trunk/sound/pci/echoaudio/echoaudio.c index c3dafa29054f..27a8dbe6f6a8 100644 --- a/trunk/sound/pci/echoaudio/echoaudio.c +++ b/trunk/sound/pci/echoaudio/echoaudio.c @@ -236,9 +236,9 @@ static int pcm_open(struct snd_pcm_substream *substream, chip = snd_pcm_substream_chip(substream); runtime = substream->runtime; - pipe = kzalloc(sizeof(struct audiopipe), GFP_KERNEL); - if (!pipe) + if (!(pipe = kmalloc(sizeof(struct audiopipe), GFP_KERNEL))) return -ENOMEM; + memset(pipe, 0, sizeof(struct audiopipe)); pipe->index = -1; /* Not configured yet */ /* Set up hw capabilities and contraints */ diff --git a/trunk/sound/pci/emu10k1/emu10k1.c b/trunk/sound/pci/emu10k1/emu10k1.c index 493ec0816bb3..289bcd99c19c 100644 --- a/trunk/sound/pci/emu10k1/emu10k1.c +++ b/trunk/sound/pci/emu10k1/emu10k1.c @@ -232,7 +232,7 @@ static int snd_emu10k1_suspend(struct pci_dev *pci, pm_message_t state) return 0; } -static int snd_emu10k1_resume(struct pci_dev *pci) +int snd_emu10k1_resume(struct pci_dev *pci) { struct snd_card *card = pci_get_drvdata(pci); struct snd_emu10k1 *emu = card->private_data; diff --git a/trunk/sound/pci/emu10k1/emu10k1_main.c b/trunk/sound/pci/emu10k1/emu10k1_main.c index be65d4db8e27..f9b5c3dc3b34 100644 --- a/trunk/sound/pci/emu10k1/emu10k1_main.c +++ b/trunk/sound/pci/emu10k1/emu10k1_main.c @@ -927,7 +927,6 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0151_chip = 1, .spk71 = 1, .spdif_bug = 1, - .adc_1361t = 1, /* 24 bit capture instead of 16bit */ .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, .driver = "Audigy2", .name = "Audigy 2 EX [1005]", @@ -937,17 +936,6 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0151_chip = 1, .spk71 = 1, .spdif_bug = 1} , - /* Dell OEM/Creative Labs Audigy 2 ZS */ - /* See ALSA bug#1365 */ - {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10031102, - .driver = "Audigy2", .name = "Audigy 2 ZS [SB0353]", - .id = "Audigy2", - .emu10k2_chip = 1, - .ca0102_chip = 1, - .ca0151_chip = 1, - .spk71 = 1, - .spdif_bug = 1, - .ac97_chip = 1} , {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]", .id = "Audigy2", diff --git a/trunk/sound/pci/emu10k1/emu10k1x.c b/trunk/sound/pci/emu10k1/emu10k1x.c index da1610a571b8..bda8bdf59935 100644 --- a/trunk/sound/pci/emu10k1/emu10k1x.c +++ b/trunk/sound/pci/emu10k1/emu10k1x.c @@ -1626,7 +1626,12 @@ static struct pci_driver driver = { // initialization of the module static int __init alsa_card_emu10k1x_init(void) { - return pci_register_driver(&driver); + int err; + + if ((err = pci_register_driver(&driver)) > 0) + return err; + + return 0; } // clean up the module diff --git a/trunk/sound/pci/emu10k1/emufx.c b/trunk/sound/pci/emu10k1/emufx.c index 13cd6ce89811..dfba00230d4d 100644 --- a/trunk/sound/pci/emu10k1/emufx.c +++ b/trunk/sound/pci/emu10k1/emufx.c @@ -35,7 +35,6 @@ #include #include -#include #include #if 0 /* for testing purposes - digital out -> capture */ @@ -267,7 +266,6 @@ static const u32 treble_table[41][5] = { { 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 } }; -/* dB gain = (float) 20 * log10( float(db_table_value) / 0x8000000 ) */ static const u32 db_table[101] = { 0x00000000, 0x01571f82, 0x01674b41, 0x01783a1b, 0x0189f540, 0x019c8651, 0x01aff763, 0x01c45306, 0x01d9a446, 0x01eff6b8, @@ -292,9 +290,6 @@ static const u32 db_table[101] = { 0x7fffffff, }; -/* EMU10k1/EMU10k2 DSP control db gain */ -static DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1); - static const u32 onoff_table[2] = { 0x00000000, 0x00000001 }; @@ -760,11 +755,6 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, knew.device = gctl->id.device; knew.subdevice = gctl->id.subdevice; knew.info = snd_emu10k1_gpr_ctl_info; - if (gctl->tlv.p) { - knew.tlv.p = gctl->tlv.p; - knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ; - } knew.get = snd_emu10k1_gpr_ctl_get; knew.put = snd_emu10k1_gpr_ctl_put; memset(nctl, 0, sizeof(*nctl)); @@ -1023,7 +1013,6 @@ snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl, ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; ctl->min = 0; ctl->max = 100; - ctl->tlv.p = snd_emu10k1_db_scale1; ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; } @@ -1038,7 +1027,6 @@ snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl, ctl->gpr[1] = gpr + 1; ctl->value[1] = defval; ctl->min = 0; ctl->max = 100; - ctl->tlv.p = snd_emu10k1_db_scale1; ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; } diff --git a/trunk/sound/pci/emu10k1/irq.c b/trunk/sound/pci/emu10k1/irq.c index 1076af4c3669..a8b31286b6db 100644 --- a/trunk/sound/pci/emu10k1/irq.c +++ b/trunk/sound/pci/emu10k1/irq.c @@ -37,13 +37,9 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs) int handled = 0; while ((status = inl(emu->port + IPR)) != 0) { - //snd_printk(KERN_INFO "emu10k1 irq - status = 0x%x\n", status); + //printk("emu10k1 irq - status = 0x%x\n", status); orig_status = status; handled = 1; - if ((status & 0xffffffff) == 0xffffffff) { - snd_printk(KERN_INFO "snd-emu10k1: Suspected sound card removal\n"); - break; - } if (status & IPR_PCIERROR) { snd_printk(KERN_ERR "interrupt: PCI error\n"); snd_emu10k1_intr_disable(emu, INTE_PCIERRORENABLE); diff --git a/trunk/sound/pci/emu10k1/p16v.c b/trunk/sound/pci/emu10k1/p16v.c index 4e0f95438f47..9905651935fb 100644 --- a/trunk/sound/pci/emu10k1/p16v.c +++ b/trunk/sound/pci/emu10k1/p16v.c @@ -100,7 +100,6 @@ #include #include #include -#include #include #include "p16v.h" @@ -785,16 +784,12 @@ static int snd_p16v_capture_channel_put(struct snd_kcontrol *kcontrol, } return change; } -static DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1); #define P16V_VOL(xname,xreg,xhl) { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ .info = snd_p16v_volume_info, \ .get = snd_p16v_volume_get, \ .put = snd_p16v_volume_put, \ - .tlv = { .p = snd_p16v_db_scale1 }, \ .private_value = ((xreg) | ((xhl) << 8)) \ } diff --git a/trunk/sound/pci/es1938.c b/trunk/sound/pci/es1938.c index 3ce5a4e7e31f..cc0f34f68185 100644 --- a/trunk/sound/pci/es1938.c +++ b/trunk/sound/pci/es1938.c @@ -62,7 +62,6 @@ #include #include #include -#include #include @@ -1165,14 +1164,6 @@ static int snd_es1938_reg_read(struct es1938 *chip, unsigned char reg) return snd_es1938_read(chip, reg); } -#define ES1938_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,\ - .name = xname, .index = xindex, \ - .info = snd_es1938_info_single, \ - .get = snd_es1938_get_single, .put = snd_es1938_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ - .tlv = { .p = xtlv } } #define ES1938_SINGLE(xname, xindex, reg, shift, mask, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ .info = snd_es1938_info_single, \ @@ -1226,14 +1217,6 @@ static int snd_es1938_put_single(struct snd_kcontrol *kcontrol, return snd_es1938_reg_bits(chip, reg, mask, val) != val; } -#define ES1938_DOUBLE_TLV(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,\ - .name = xname, .index = xindex, \ - .info = snd_es1938_info_double, \ - .get = snd_es1938_get_double, .put = snd_es1938_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22), \ - .tlv = { .p = xtlv } } #define ES1938_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ .info = snd_es1938_info_double, \ @@ -1314,41 +1297,8 @@ static int snd_es1938_put_double(struct snd_kcontrol *kcontrol, return change; } -static unsigned int db_scale_master[] = { - TLV_DB_RANGE_HEAD(2), - 0, 54, TLV_DB_SCALE_ITEM(-3600, 50, 1), - 54, 63, TLV_DB_SCALE_ITEM(-900, 100, 0), -}; - -static unsigned int db_scale_audio1[] = { - TLV_DB_RANGE_HEAD(2), - 0, 8, TLV_DB_SCALE_ITEM(-3300, 300, 1), - 8, 15, TLV_DB_SCALE_ITEM(-900, 150, 0), -}; - -static unsigned int db_scale_audio2[] = { - TLV_DB_RANGE_HEAD(2), - 0, 8, TLV_DB_SCALE_ITEM(-3450, 300, 1), - 8, 15, TLV_DB_SCALE_ITEM(-1050, 150, 0), -}; - -static unsigned int db_scale_mic[] = { - TLV_DB_RANGE_HEAD(2), - 0, 8, TLV_DB_SCALE_ITEM(-2400, 300, 1), - 8, 15, TLV_DB_SCALE_ITEM(0, 150, 0), -}; - -static unsigned int db_scale_line[] = { - TLV_DB_RANGE_HEAD(2), - 0, 8, TLV_DB_SCALE_ITEM(-3150, 300, 1), - 8, 15, TLV_DB_SCALE_ITEM(-750, 150, 0), -}; - -static DECLARE_TLV_DB_SCALE(db_scale_capture, 0, 150, 0); - static struct snd_kcontrol_new snd_es1938_controls[] = { -ES1938_DOUBLE_TLV("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0, - db_scale_master), +ES1938_DOUBLE("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0), ES1938_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1359,27 +1309,19 @@ ES1938_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1), }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READ | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Hardware Master Playback Switch", + .access = SNDRV_CTL_ELEM_ACCESS_READ, .info = snd_es1938_info_hw_switch, .get = snd_es1938_get_hw_switch, - .tlv = { .p = db_scale_master }, }, ES1938_SINGLE("Hardware Volume Split", 0, 0x64, 7, 1, 0), -ES1938_DOUBLE_TLV("Line Playback Volume", 0, 0x3e, 0x3e, 4, 0, 15, 0, - db_scale_line), +ES1938_DOUBLE("Line Playback Volume", 0, 0x3e, 0x3e, 4, 0, 15, 0), ES1938_DOUBLE("CD Playback Volume", 0, 0x38, 0x38, 4, 0, 15, 0), -ES1938_DOUBLE_TLV("FM Playback Volume", 0, 0x36, 0x36, 4, 0, 15, 0, - db_scale_mic), -ES1938_DOUBLE_TLV("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("Mic Playback Volume", 0, 0x1a, 0x1a, 4, 0, 15, 0, - db_scale_mic), -ES1938_DOUBLE_TLV("Aux Playback Volume", 0, 0x3a, 0x3a, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0, - db_scale_capture), +ES1938_DOUBLE("FM Playback Volume", 0, 0x36, 0x36, 4, 0, 15, 0), +ES1938_DOUBLE("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0), +ES1938_DOUBLE("Mic Playback Volume", 0, 0x1a, 0x1a, 4, 0, 15, 0), +ES1938_DOUBLE("Aux Playback Volume", 0, 0x3a, 0x3a, 4, 0, 15, 0), +ES1938_DOUBLE("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0), ES1938_SINGLE("PC Speaker Volume", 0, 0x3c, 0, 7, 0), ES1938_SINGLE("Record Monitor", 0, 0xa8, 3, 1, 0), ES1938_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1), @@ -1390,26 +1332,16 @@ ES1938_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1), .get = snd_es1938_get_mux, .put = snd_es1938_put_mux, }, -ES1938_DOUBLE_TLV("Mono Input Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("PCM Capture Volume", 0, 0x69, 0x69, 4, 0, 15, 0, - db_scale_audio2), -ES1938_DOUBLE_TLV("Mic Capture Volume", 0, 0x68, 0x68, 4, 0, 15, 0, - db_scale_mic), -ES1938_DOUBLE_TLV("Line Capture Volume", 0, 0x6e, 0x6e, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("FM Capture Volume", 0, 0x6b, 0x6b, 4, 0, 15, 0, - db_scale_mic), -ES1938_DOUBLE_TLV("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("CD Capture Volume", 0, 0x6a, 0x6a, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0, - db_scale_line), -ES1938_DOUBLE_TLV("PCM Playback Volume", 0, 0x7c, 0x7c, 4, 0, 15, 0, - db_scale_audio2), -ES1938_DOUBLE_TLV("PCM Playback Volume", 1, 0x14, 0x14, 4, 0, 15, 0, - db_scale_audio1), +ES1938_DOUBLE("Mono Input Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0), +ES1938_DOUBLE("PCM Capture Volume", 0, 0x69, 0x69, 4, 0, 15, 0), +ES1938_DOUBLE("Mic Capture Volume", 0, 0x68, 0x68, 4, 0, 15, 0), +ES1938_DOUBLE("Line Capture Volume", 0, 0x6e, 0x6e, 4, 0, 15, 0), +ES1938_DOUBLE("FM Capture Volume", 0, 0x6b, 0x6b, 4, 0, 15, 0), +ES1938_DOUBLE("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0), +ES1938_DOUBLE("CD Capture Volume", 0, 0x6a, 0x6a, 4, 0, 15, 0), +ES1938_DOUBLE("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0), +ES1938_DOUBLE("PCM Playback Volume", 0, 0x7c, 0x7c, 4, 0, 15, 0), +ES1938_DOUBLE("PCM Playback Volume", 1, 0x14, 0x14, 4, 0, 15, 0), ES1938_SINGLE("3D Control - Level", 0, 0x52, 0, 63, 0), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, diff --git a/trunk/sound/pci/es1968.c b/trunk/sound/pci/es1968.c index f3c40385c87d..3c5ab7c2e72d 100644 --- a/trunk/sound/pci/es1968.c +++ b/trunk/sound/pci/es1968.c @@ -1905,7 +1905,7 @@ static void es1968_update_hw_volume(unsigned long private_data) /* Figure out which volume control button was pushed, based on differences from the default register values. */ - x = inb(chip->io_port + 0x1c) & 0xee; + x = inb(chip->io_port + 0x1c); /* Reset the volume control registers. */ outb(0x88, chip->io_port + 0x1c); outb(0x88, chip->io_port + 0x1d); @@ -1921,8 +1921,7 @@ static void es1968_update_hw_volume(unsigned long private_data) /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */ spin_lock_irqsave(&chip->ac97_lock, flags); val = chip->ac97->regs[AC97_MASTER]; - switch (x) { - case 0x88: + if (x & 1) { /* mute */ val ^= 0x8000; chip->ac97->regs[AC97_MASTER] = val; @@ -1930,31 +1929,26 @@ static void es1968_update_hw_volume(unsigned long private_data) outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_switch->id); - break; - case 0xaa: - /* volume up */ - if ((val & 0x7f) > 0) - val--; - if ((val & 0x7f00) > 0) - val -= 0x0100; - chip->ac97->regs[AC97_MASTER] = val; - outw(val, chip->io_port + ESM_AC97_DATA); - outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); - snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, - &chip->master_volume->id); - break; - case 0x66: - /* volume down */ - if ((val & 0x7f) < 0x1f) - val++; - if ((val & 0x7f00) < 0x1f00) - val += 0x0100; + } else { + val &= 0x7fff; + if (((x>>1) & 7) > 4) { + /* volume up */ + if ((val & 0xff) > 0) + val--; + if ((val & 0xff00) > 0) + val -= 0x0100; + } else { + /* volume down */ + if ((val & 0xff) < 0x1f) + val++; + if ((val & 0xff00) < 0x1f00) + val += 0x0100; + } chip->ac97->regs[AC97_MASTER] = val; outw(val, chip->io_port + ESM_AC97_DATA); outb(AC97_MASTER, chip->io_port + ESM_AC97_INDEX); snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_volume->id); - break; } spin_unlock_irqrestore(&chip->ac97_lock, flags); } diff --git a/trunk/sound/pci/fm801.c b/trunk/sound/pci/fm801.c index bdfda1997d5b..13868c985126 100644 --- a/trunk/sound/pci/fm801.c +++ b/trunk/sound/pci/fm801.c @@ -2,7 +2,6 @@ * The driver for the ForteMedia FM801 based soundcards * Copyright (c) by Jaroslav Kysela * - * Support FM only card by Andy Shevchenko * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -56,7 +54,6 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card * * 1 = MediaForte 256-PCS * 2 = MediaForte 256-PCPR * 3 = MediaForte 64-PCR - * 16 = setup tuner only (this is additional bit), i.e. SF-64-PCR FM card * High 16-bits are video (radio) device number + 1 */ static int tea575x_tuner[SNDRV_CARDS]; @@ -161,7 +158,6 @@ struct fm801 { unsigned int multichannel: 1, /* multichannel support */ secondary: 1; /* secondary codec */ unsigned char secondary_addr; /* address of the secondary codec */ - unsigned int tea575x_tuner; /* tuner flags */ unsigned short ply_ctrl; /* playback control */ unsigned short cap_ctrl; /* capture control */ @@ -322,8 +318,10 @@ static unsigned int channels[] = { 2, 4, 6 }; +#define CHANNELS sizeof(channels) / sizeof(channels[0]) + static struct snd_pcm_hw_constraint_list hw_constraints_channels = { - .count = ARRAY_SIZE(channels), + .count = CHANNELS, .list = channels, .mask = 0, }; @@ -1054,13 +1052,6 @@ static int snd_fm801_put_single(struct snd_kcontrol *kcontrol, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_fm801_info_double, \ .get = snd_fm801_get_double, .put = snd_fm801_put_double, \ .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24) } -#define FM801_DOUBLE_TLV(xname, reg, shift_left, shift_right, mask, invert, xtlv) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ - .name = xname, .info = snd_fm801_info_double, \ - .get = snd_fm801_get_double, .put = snd_fm801_put_double, \ - .private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24), \ - .tlv = { .p = (xtlv) } } static int snd_fm801_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) @@ -1157,19 +1148,14 @@ static int snd_fm801_put_mux(struct snd_kcontrol *kcontrol, return snd_fm801_update_bits(chip, FM801_REC_SRC, 7, val); } -static DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0); - #define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls) static struct snd_kcontrol_new snd_fm801_controls[] __devinitdata = { -FM801_DOUBLE_TLV("Wave Playback Volume", FM801_PCM_VOL, 0, 8, 31, 1, - db_scale_dsp), +FM801_DOUBLE("Wave Playback Volume", FM801_PCM_VOL, 0, 8, 31, 1), FM801_SINGLE("Wave Playback Switch", FM801_PCM_VOL, 15, 1, 1), -FM801_DOUBLE_TLV("I2S Playback Volume", FM801_I2S_VOL, 0, 8, 31, 1, - db_scale_dsp), +FM801_DOUBLE("I2S Playback Volume", FM801_I2S_VOL, 0, 8, 31, 1), FM801_SINGLE("I2S Playback Switch", FM801_I2S_VOL, 15, 1, 1), -FM801_DOUBLE_TLV("FM Playback Volume", FM801_FM_VOL, 0, 8, 31, 1, - db_scale_dsp), +FM801_DOUBLE("FM Playback Volume", FM801_FM_VOL, 0, 8, 31, 1), FM801_SINGLE("FM Playback Switch", FM801_FM_VOL, 15, 1, 1), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1267,9 +1253,6 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume) int id; unsigned short cmdw; - if (chip->tea575x_tuner & 0x0010) - goto __ac97_ok; - /* codec cold reset + AC'97 warm reset */ outw((1<<5) | (1<<6), FM801_REG(chip, CODEC_CTRL)); inw(FM801_REG(chip, CODEC_CTRL)); /* flush posting data */ @@ -1307,8 +1290,6 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume) wait_for_codec(chip, 0, AC97_VENDOR_ID1, msecs_to_jiffies(750)); } - __ac97_ok: - /* init volume */ outw(0x0808, FM801_REG(chip, PCM_VOL)); outw(0x9f1f, FM801_REG(chip, FM_VOL)); @@ -1317,12 +1298,9 @@ static int snd_fm801_chip_init(struct fm801 *chip, int resume) /* I2S control - I2S mode */ outw(0x0003, FM801_REG(chip, I2S_MODE)); - /* interrupt setup */ + /* interrupt setup - unmask MPU, PLAYBACK & CAPTURE */ cmdw = inw(FM801_REG(chip, IRQ_MASK)); - if (chip->irq < 0) - cmdw |= 0x00c3; /* mask everything, no PCM nor MPU */ - else - cmdw &= ~0x0083; /* unmask MPU, PLAYBACK & CAPTURE */ + cmdw &= ~0x0083; outw(cmdw, FM801_REG(chip, IRQ_MASK)); /* interrupt clear */ @@ -1387,23 +1365,20 @@ static int __devinit snd_fm801_create(struct snd_card *card, chip->card = card; chip->pci = pci; chip->irq = -1; - chip->tea575x_tuner = tea575x_tuner; if ((err = pci_request_regions(pci, "FM801")) < 0) { kfree(chip); pci_disable_device(pci); return err; } chip->port = pci_resource_start(pci, 0); - if ((tea575x_tuner & 0x0010) == 0) { - if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_DISABLED|IRQF_SHARED, - "FM801", chip)) { - snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq); - snd_fm801_free(chip); - return -EBUSY; - } - chip->irq = pci->irq; - pci_set_master(pci); + if (request_irq(pci->irq, snd_fm801_interrupt, IRQF_DISABLED|IRQF_SHARED, + "FM801", chip)) { + snd_printk(KERN_ERR "unable to grab IRQ %d\n", chip->irq); + snd_fm801_free(chip); + return -EBUSY; } + chip->irq = pci->irq; + pci_set_master(pci); pci_read_config_byte(pci, PCI_REVISION_ID, &rev); if (rev >= 0xb1) /* FM801-AU */ @@ -1419,12 +1394,12 @@ static int __devinit snd_fm801_create(struct snd_card *card, snd_card_set_dev(card, &pci->dev); #ifdef TEA575X_RADIO - if (tea575x_tuner > 0 && (tea575x_tuner & 0x000f) < 4) { + if (tea575x_tuner > 0 && (tea575x_tuner & 0xffff) < 4) { chip->tea.dev_nr = tea575x_tuner >> 16; chip->tea.card = card; chip->tea.freq_fixup = 10700; chip->tea.private_data = chip; - chip->tea.ops = &snd_fm801_tea_ops[(tea575x_tuner & 0x000f) - 1]; + chip->tea.ops = &snd_fm801_tea_ops[(tea575x_tuner & 0xffff) - 1]; snd_tea575x_init(&chip->tea); } #endif @@ -1464,9 +1439,6 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci, sprintf(card->longname, "%s at 0x%lx, irq %i", card->shortname, chip->port, chip->irq); - if (tea575x_tuner[dev] & 0x0010) - goto __fm801_tuner_only; - if ((err = snd_fm801_pcm(chip, 0, NULL)) < 0) { snd_card_free(card); return err; @@ -1493,7 +1465,6 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci, return err; } - __fm801_tuner_only: if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; diff --git a/trunk/sound/pci/hda/hda_codec.c b/trunk/sound/pci/hda/hda_codec.c index 9c3d7ac08068..23201f3eeb12 100644 --- a/trunk/sound/pci/hda/hda_codec.c +++ b/trunk/sound/pci/hda/hda_codec.c @@ -29,7 +29,6 @@ #include #include "hda_codec.h" #include -#include #include #include "hda_local.h" @@ -51,10 +50,8 @@ struct hda_vendor_id { /* codec vendor labels */ static struct hda_vendor_id hda_vendor_ids[] = { { 0x10ec, "Realtek" }, - { 0x1057, "Motorola" }, { 0x11d4, "Analog Devices" }, { 0x13f6, "C-Media" }, - { 0x14f1, "Conexant" }, { 0x434d, "C-Media" }, { 0x8384, "SigmaTel" }, {} /* terminator */ @@ -844,31 +841,6 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e return change; } -int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *_tlv) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - hda_nid_t nid = get_amp_nid(kcontrol); - int dir = get_amp_direction(kcontrol); - u32 caps, val1, val2; - - if (size < 4 * sizeof(unsigned int)) - return -ENOMEM; - caps = query_amp_caps(codec, nid, dir); - val2 = (((caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT) + 1) * 25; - val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); - val1 = ((int)val1) * ((int)val2); - if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) - return -EFAULT; - if (put_user(2 * sizeof(unsigned int), _tlv + 1)) - return -EFAULT; - if (put_user(val1, _tlv + 2)) - return -EFAULT; - if (put_user(val2, _tlv + 3)) - return -EFAULT; - return 0; -} - /* switch */ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -1505,10 +1477,10 @@ int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid, formats |= SNDRV_PCM_FMTBIT_S32_LE; if (val & AC_SUPPCM_BITS_32) bps = 32; - else if (val & AC_SUPPCM_BITS_24) - bps = 24; else if (val & AC_SUPPCM_BITS_20) bps = 20; + else if (val & AC_SUPPCM_BITS_24) + bps = 24; } } else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */ @@ -1944,7 +1916,7 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o /* front */ snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format); - if (mout->hp_nid && mout->hp_nid != nids[HDA_FRONT]) + if (mout->hp_nid) /* headphone out will just decode front left/right (stereo) */ snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format); /* extra outputs copied from front */ @@ -2012,7 +1984,7 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) * in the order of front, rear, CLFE, side, ... * * If more extra outputs (speaker and headphone) are found, the pins are - * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack + * assisnged to hp_pin and speaker_pins[], respectively. If no line-out jack * is detected, one of speaker of HP pins is assigned as the primary * output, i.e. to line_out_pins[0]. So, line_outs is always positive * if any analog output exists. @@ -2074,26 +2046,14 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c cfg->speaker_outs++; break; case AC_JACK_HP_OUT: - if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins)) - continue; - cfg->hp_pins[cfg->hp_outs] = nid; - cfg->hp_outs++; + cfg->hp_pin = nid; break; - case AC_JACK_MIC_IN: { - int preferred, alt; - if (loc == AC_JACK_LOC_FRONT) { - preferred = AUTO_PIN_FRONT_MIC; - alt = AUTO_PIN_MIC; - } else { - preferred = AUTO_PIN_MIC; - alt = AUTO_PIN_FRONT_MIC; - } - if (!cfg->input_pins[preferred]) - cfg->input_pins[preferred] = nid; - else if (!cfg->input_pins[alt]) - cfg->input_pins[alt] = nid; + case AC_JACK_MIC_IN: + if (loc == AC_JACK_LOC_FRONT) + cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid; + else + cfg->input_pins[AUTO_PIN_MIC] = nid; break; - } case AC_JACK_LINE_IN: if (loc == AC_JACK_LOC_FRONT) cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; @@ -2159,10 +2119,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c cfg->speaker_outs, cfg->speaker_pins[0], cfg->speaker_pins[1], cfg->speaker_pins[2], cfg->speaker_pins[3], cfg->speaker_pins[4]); - snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", - cfg->hp_outs, cfg->hp_pins[0], - cfg->hp_pins[1], cfg->hp_pins[2], - cfg->hp_pins[3], cfg->hp_pins[4]); + snd_printd(" hp=0x%x, dig_out=0x%x, din_in=0x%x\n", + cfg->hp_pin, cfg->dig_out_pin, cfg->dig_in_pin); snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," " cd=0x%x, aux=0x%x\n", cfg->input_pins[AUTO_PIN_MIC], @@ -2183,12 +2141,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c sizeof(cfg->speaker_pins)); cfg->speaker_outs = 0; memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); - } else if (cfg->hp_outs) { - cfg->line_outs = cfg->hp_outs; - memcpy(cfg->line_out_pins, cfg->hp_pins, - sizeof(cfg->hp_pins)); - cfg->hp_outs = 0; - memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); + } else if (cfg->hp_pin) { + cfg->line_outs = 1; + cfg->line_out_pins[0] = cfg->hp_pin; + cfg->hp_pin = 0; } } diff --git a/trunk/sound/pci/hda/hda_codec.h b/trunk/sound/pci/hda/hda_codec.h index c12bc4e8840f..40520e9d5a4b 100644 --- a/trunk/sound/pci/hda/hda_codec.h +++ b/trunk/sound/pci/hda/hda_codec.h @@ -479,7 +479,7 @@ struct hda_codec_ops { struct hda_amp_info { u32 key; /* hash key */ u32 amp_caps; /* amp capabilities */ - u16 vol[2]; /* current volume & mute */ + u16 vol[2]; /* current volume & mute*/ u16 status; /* update flag */ u16 next; /* next link */ }; diff --git a/trunk/sound/pci/hda/hda_generic.c b/trunk/sound/pci/hda/hda_generic.c index 97e9af130b71..85ad164ada59 100644 --- a/trunk/sound/pci/hda/hda_generic.c +++ b/trunk/sound/pci/hda/hda_generic.c @@ -46,18 +46,11 @@ struct hda_gnode { }; /* patch-specific record */ - -#define MAX_PCM_VOLS 2 -struct pcm_vol { - struct hda_gnode *node; /* Node for PCM volume */ - unsigned int index; /* connection of PCM volume */ -}; - struct hda_gspec { struct hda_gnode *dac_node[2]; /* DAC node */ struct hda_gnode *out_pin_node[2]; /* Output pin (Line-Out) node */ - struct pcm_vol pcm_vol[MAX_PCM_VOLS]; /* PCM volumes */ - unsigned int pcm_vol_nodes; /* number of PCM volumes */ + struct hda_gnode *pcm_vol_node[2]; /* Node for PCM volume */ + unsigned int pcm_vol_index[2]; /* connection of PCM volume */ struct hda_gnode *adc_node; /* ADC node */ struct hda_gnode *cap_vol_node; /* Node for capture volume */ @@ -292,11 +285,9 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, return node == spec->dac_node[dac_idx]; } spec->dac_node[dac_idx] = node; - if ((node->wid_caps & AC_WCAP_OUT_AMP) && - spec->pcm_vol_nodes < MAX_PCM_VOLS) { - spec->pcm_vol[spec->pcm_vol_nodes].node = node; - spec->pcm_vol[spec->pcm_vol_nodes].index = 0; - spec->pcm_vol_nodes++; + if (node->wid_caps & AC_WCAP_OUT_AMP) { + spec->pcm_vol_node[dac_idx] = node; + spec->pcm_vol_index[dac_idx] = 0; } return 1; /* found */ } @@ -316,16 +307,13 @@ static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec, select_input_connection(codec, node, i); unmute_input(codec, node, i); unmute_output(codec, node); - if (spec->dac_node[dac_idx] && - spec->pcm_vol_nodes < MAX_PCM_VOLS && - !(spec->dac_node[dac_idx]->wid_caps & - AC_WCAP_OUT_AMP)) { - if ((node->wid_caps & AC_WCAP_IN_AMP) || - (node->wid_caps & AC_WCAP_OUT_AMP)) { - int n = spec->pcm_vol_nodes; - spec->pcm_vol[n].node = node; - spec->pcm_vol[n].index = i; - spec->pcm_vol_nodes++; + if (! spec->pcm_vol_node[dac_idx]) { + if (node->wid_caps & AC_WCAP_IN_AMP) { + spec->pcm_vol_node[dac_idx] = node; + spec->pcm_vol_index[dac_idx] = i; + } else if (node->wid_caps & AC_WCAP_OUT_AMP) { + spec->pcm_vol_node[dac_idx] = node; + spec->pcm_vol_index[dac_idx] = 0; } } return 1; @@ -382,9 +370,7 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec, /* set PIN-Out enable */ snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, - AC_PINCTL_OUT_EN | - ((node->pin_caps & AC_PINCAP_HP_DRV) ? - AC_PINCTL_HP_EN : 0)); + AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); return node; } } @@ -475,19 +461,14 @@ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl) return "Front Line"; return "Line"; case AC_JACK_CD: -#if 0 if (pinctl) *pinctl |= AC_PINCTL_VREF_GRD; -#endif return "CD"; case AC_JACK_AUX: if ((location & 0x0f) == AC_JACK_LOC_FRONT) return "Front Aux"; return "Aux"; case AC_JACK_MIC_IN: - if (node->pin_caps & - (AC_PINCAP_VREF_80 << AC_PINCAP_VREF_SHIFT)) - *pinctl |= AC_PINCTL_VREF_80; if ((location & 0x0f) == AC_JACK_LOC_FRONT) return "Front Mic"; return "Mic"; @@ -575,29 +556,6 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, return 1; /* found */ } -/* add a capture source element */ -static void add_cap_src(struct hda_gspec *spec, int idx) -{ - struct hda_input_mux_item *csrc; - char *buf; - int num, ocap; - - num = spec->input_mux.num_items; - csrc = &spec->input_mux.items[num]; - buf = spec->cap_labels[num]; - for (ocap = 0; ocap < num; ocap++) { - if (! strcmp(buf, spec->cap_labels[ocap])) { - /* same label already exists, - * put the index number to be unique - */ - sprintf(buf, "%s %d", spec->cap_labels[ocap], num); - break; - } - } - csrc->index = idx; - spec->input_mux.num_items++; -} - /* * parse input */ @@ -618,26 +576,28 @@ static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node) * if it reaches to a proper input PIN, add the path as the * input path. */ - /* first, check the direct connections to PIN widgets */ - for (i = 0; i < adc_node->nconns; i++) { - node = hda_get_node(spec, adc_node->conn_list[i]); - if (node && node->type == AC_WID_PIN) { - err = parse_adc_sub_nodes(codec, spec, node); - if (err < 0) - return err; - else if (err > 0) - add_cap_src(spec, i); - } - } - /* ... then check the rests, more complicated connections */ for (i = 0; i < adc_node->nconns; i++) { node = hda_get_node(spec, adc_node->conn_list[i]); - if (node && node->type != AC_WID_PIN) { - err = parse_adc_sub_nodes(codec, spec, node); - if (err < 0) - return err; - else if (err > 0) - add_cap_src(spec, i); + if (! node) + continue; + err = parse_adc_sub_nodes(codec, spec, node); + if (err < 0) + return err; + else if (err > 0) { + struct hda_input_mux_item *csrc = &spec->input_mux.items[spec->input_mux.num_items]; + char *buf = spec->cap_labels[spec->input_mux.num_items]; + int ocap; + for (ocap = 0; ocap < spec->input_mux.num_items; ocap++) { + if (! strcmp(buf, spec->cap_labels[ocap])) { + /* same label already exists, + * put the index number to be unique + */ + sprintf(buf, "%s %d", spec->cap_labels[ocap], + spec->input_mux.num_items); + } + } + csrc->index = i; + spec->input_mux.num_items++; } } @@ -687,6 +647,9 @@ static int parse_input(struct hda_codec *codec) /* * create mixer controls if possible */ +#define DIR_OUT 0x1 +#define DIR_IN 0x2 + static int create_mixer(struct hda_codec *codec, struct hda_gnode *node, unsigned int index, const char *type, const char *dir_sfx) { @@ -759,97 +722,49 @@ static int check_existing_control(struct hda_codec *codec, const char *type, con /* * build output mixer controls */ -static int create_output_mixers(struct hda_codec *codec, const char **names) +static int build_output_controls(struct hda_codec *codec) { struct hda_gspec *spec = codec->spec; + static const char *types[2] = { "Master", "Headphone" }; int i, err; - for (i = 0; i < spec->pcm_vol_nodes; i++) { - err = create_mixer(codec, spec->pcm_vol[i].node, - spec->pcm_vol[i].index, - names[i], "Playback"); + for (i = 0; i < 2 && spec->pcm_vol_node[i]; i++) { + err = create_mixer(codec, spec->pcm_vol_node[i], + spec->pcm_vol_index[i], + types[i], "Playback"); if (err < 0) return err; } return 0; } -static int build_output_controls(struct hda_codec *codec) -{ - struct hda_gspec *spec = codec->spec; - static const char *types_speaker[] = { "Speaker", "Headphone" }; - static const char *types_line[] = { "Front", "Headphone" }; - - switch (spec->pcm_vol_nodes) { - case 1: - return create_mixer(codec, spec->pcm_vol[0].node, - spec->pcm_vol[0].index, - "Master", "Playback"); - case 2: - if (defcfg_type(spec->out_pin_node[0]) == AC_JACK_SPEAKER) - return create_output_mixers(codec, types_speaker); - else - return create_output_mixers(codec, types_line); - } - return 0; -} - /* create capture volume/switch */ static int build_input_controls(struct hda_codec *codec) { struct hda_gspec *spec = codec->spec; struct hda_gnode *adc_node = spec->adc_node; - int i, err; - static struct snd_kcontrol_new cap_sel = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .info = capture_source_info, - .get = capture_source_get, - .put = capture_source_put, - }; - - if (! adc_node || ! spec->input_mux.num_items) - return 0; /* not found */ + int err; - spec->cur_cap_src = 0; - select_input_connection(codec, adc_node, - spec->input_mux.items[0].index); + if (! adc_node) + return 0; /* not found */ /* create capture volume and switch controls if the ADC has an amp */ - /* do we have only a single item? */ - if (spec->input_mux.num_items == 1) { - err = create_mixer(codec, adc_node, - spec->input_mux.items[0].index, - NULL, "Capture"); - if (err < 0) - return err; - return 0; - } + err = create_mixer(codec, adc_node, 0, NULL, "Capture"); /* create input MUX if multiple sources are available */ - if ((err = snd_ctl_add(codec->bus->card, - snd_ctl_new1(&cap_sel, codec))) < 0) - return err; - - /* no volume control? */ - if (! (adc_node->wid_caps & AC_WCAP_IN_AMP) || - ! (adc_node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) - return 0; - - for (i = 0; i < spec->input_mux.num_items; i++) { - struct snd_kcontrol_new knew; - char name[32]; - sprintf(name, "%s Capture Volume", - spec->input_mux.items[i].label); - knew = (struct snd_kcontrol_new) - HDA_CODEC_VOLUME(name, adc_node->nid, - spec->input_mux.items[i].index, - HDA_INPUT); - if ((err = snd_ctl_add(codec->bus->card, - snd_ctl_new1(&knew, codec))) < 0) + if (spec->input_mux.num_items > 1) { + static struct snd_kcontrol_new cap_sel = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = capture_source_info, + .get = capture_source_get, + .put = capture_source_put, + }; + if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&cap_sel, codec))) < 0) return err; + spec->cur_cap_src = 0; + select_input_connection(codec, adc_node, spec->input_mux.items[0].index); } - return 0; } diff --git a/trunk/sound/pci/hda/hda_intel.c b/trunk/sound/pci/hda/hda_intel.c index e9d4cb4d07e1..79d63c99f092 100644 --- a/trunk/sound/pci/hda/hda_intel.c +++ b/trunk/sound/pci/hda/hda_intel.c @@ -55,7 +55,6 @@ static char *model; static int position_fix; static int probe_mask = -1; static int single_cmd; -static int disable_msi; module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); @@ -69,8 +68,6 @@ module_param(probe_mask, int, 0444); MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1)."); module_param(single_cmd, bool, 0444); MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs (for debugging only)."); -module_param(disable_msi, int, 0); -MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); /* just for backward compatibility */ @@ -255,7 +252,7 @@ enum { struct azx_dev { u32 *bdl; /* virtual address of the BDL */ dma_addr_t bdl_addr; /* physical address of the BDL */ - u32 *posbuf; /* position buffer pointer */ + volatile u32 *posbuf; /* position buffer pointer */ unsigned int bufsize; /* size of the play buffer in bytes */ unsigned int fragsize; /* size of each period in bytes */ @@ -274,8 +271,8 @@ struct azx_dev { /* for sanity check of position buffer */ unsigned int period_intr; - unsigned int opened :1; - unsigned int running :1; + unsigned int opened: 1; + unsigned int running: 1; }; /* CORB/RIRB */ @@ -333,9 +330,8 @@ struct azx { /* flags */ int position_fix; - unsigned int initialized :1; - unsigned int single_cmd :1; - unsigned int polling_mode :1; + unsigned int initialized: 1; + unsigned int single_cmd: 1; }; /* driver types */ @@ -520,36 +516,23 @@ static void azx_update_rirb(struct azx *chip) static unsigned int azx_rirb_get_response(struct hda_codec *codec) { struct azx *chip = codec->bus->private_data; - unsigned long timeout; + int timeout = 50; - again: - timeout = jiffies + msecs_to_jiffies(1000); - do { - if (chip->polling_mode) { - spin_lock_irq(&chip->reg_lock); - azx_update_rirb(chip); - spin_unlock_irq(&chip->reg_lock); + while (chip->rirb.cmds) { + if (! --timeout) { + snd_printk(KERN_ERR + "hda_intel: azx_get_response timeout, " + "switching to single_cmd mode...\n"); + chip->rirb.rp = azx_readb(chip, RIRBWP); + chip->rirb.cmds = 0; + /* switch to single_cmd mode */ + chip->single_cmd = 1; + azx_free_cmd_io(chip); + return -1; } - if (! chip->rirb.cmds) - return chip->rirb.res; /* the last value */ - schedule_timeout_interruptible(1); - } while (time_after_eq(timeout, jiffies)); - - if (!chip->polling_mode) { - snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, " - "switching to polling mode...\n"); - chip->polling_mode = 1; - goto again; + msleep(1); } - - snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " - "switching to single_cmd mode...\n"); - chip->rirb.rp = azx_readb(chip, RIRBWP); - chip->rirb.cmds = 0; - /* switch to single_cmd mode */ - chip->single_cmd = 1; - azx_free_cmd_io(chip); - return -1; + return chip->rirb.res; /* the last value */ } /* @@ -659,14 +642,14 @@ static int azx_reset(struct azx *chip) azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET); count = 50; - while (!azx_readb(chip, GCTL) && --count) + while (! azx_readb(chip, GCTL) && --count) msleep(1); - /* Brent Chartrand said to wait >= 540us for codecs to initialize */ + /* Brent Chartrand said to wait >= 540us for codecs to intialize */ msleep(1); /* check to see if controller is ready */ - if (!azx_readb(chip, GCTL)) { + if (! azx_readb(chip, GCTL)) { snd_printd("azx_reset: controller not ready!\n"); return -EBUSY; } @@ -675,7 +658,7 @@ static int azx_reset(struct azx *chip) azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UREN); /* detect codecs */ - if (!chip->codec_mask) { + if (! chip->codec_mask) { chip->codec_mask = azx_readw(chip, STATESTS); snd_printdd("codec_mask = 0x%x\n", chip->codec_mask); } @@ -783,7 +766,7 @@ static void azx_init_chip(struct azx *chip) azx_int_enable(chip); /* initialize the codec command I/O */ - if (!chip->single_cmd) + if (! chip->single_cmd) azx_init_cmd_io(chip); /* program the position buffer */ @@ -811,7 +794,7 @@ static void azx_init_chip(struct azx *chip) /* * interrupt handler */ -static irqreturn_t azx_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs) { struct azx *chip = dev_id; struct azx_dev *azx_dev; @@ -1016,9 +999,8 @@ static struct snd_pcm_hardware azx_pcm_hw = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | - /* No full-resume yet implemented */ - /* SNDRV_PCM_INFO_RESUME |*/ - SNDRV_PCM_INFO_PAUSE), + SNDRV_PCM_INFO_PAUSE /*|*/ + /*SNDRV_PCM_INFO_RESUME*/), .formats = SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_48000, .rate_min = 48000, @@ -1196,7 +1178,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream) if (chip->position_fix == POS_FIX_POSBUF || chip->position_fix == POS_FIX_AUTO) { /* use the position buffer */ - pos = le32_to_cpu(*azx_dev->posbuf); + pos = *azx_dev->posbuf; if (chip->position_fix == POS_FIX_AUTO && azx_dev->period_intr == 1 && ! pos) { printk(KERN_WARNING @@ -1240,12 +1222,7 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, struct snd_pcm *pcm; struct azx_pcm *apcm; - /* if no substreams are defined for both playback and capture, - * it's just a placeholder. ignore it. - */ - if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams) - return 0; - + snd_assert(cpcm->stream[0].substreams || cpcm->stream[1].substreams, return -EINVAL); snd_assert(cpcm->name, return -EINVAL); err = snd_pcm_new(chip->card, cpcm->name, pcm_dev, @@ -1271,8 +1248,7 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec, snd_dma_pci_data(chip->pci), 1024 * 64, 1024 * 128); chip->pcm[pcm_dev] = pcm; - if (chip->pcm_devs < pcm_dev + 1) - chip->pcm_devs = pcm_dev + 1; + chip->pcm_devs = pcm_dev + 1; return 0; } @@ -1350,7 +1326,7 @@ static int __devinit azx_init_stream(struct azx *chip) struct azx_dev *azx_dev = &chip->azx_dev[i]; azx_dev->bdl = (u32 *)(chip->bdl.area + off); azx_dev->bdl_addr = chip->bdl.addr + off; - azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8); + azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8); /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80); /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ @@ -1379,10 +1355,6 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state) snd_pcm_suspend_all(chip->pcm[i]); snd_hda_suspend(chip->bus, state); azx_free_cmd_io(chip); - if (chip->irq >= 0) - free_irq(chip->irq, chip); - if (!disable_msi) - pci_disable_msi(chip->pci); pci_disable_device(pci); pci_save_state(pci); return 0; @@ -1395,12 +1367,6 @@ static int azx_resume(struct pci_dev *pci) pci_restore_state(pci); pci_enable_device(pci); - if (!disable_msi) - pci_enable_msi(pci); - /* FIXME: need proper error handling */ - request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, - "HDA Intel", chip); - chip->irq = pci->irq; pci_set_master(pci); azx_init_chip(chip); snd_hda_resume(chip->bus); @@ -1432,14 +1398,12 @@ static int azx_free(struct azx *chip) azx_writel(chip, DPLBASE, 0); azx_writel(chip, DPUBASE, 0); - synchronize_irq(chip->irq); + /* wait a little for interrupts to finish */ + msleep(1); } - if (chip->irq >= 0) { + if (chip->irq >= 0) free_irq(chip->irq, (void*)chip); - if (!disable_msi) - pci_disable_msi(chip->pci); - } if (chip->remap_addr) iounmap(chip->remap_addr); @@ -1470,19 +1434,19 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, struct azx **rchip) { struct azx *chip; - int err; + int err = 0; static struct snd_device_ops ops = { .dev_free = azx_dev_free, }; *rchip = NULL; - err = pci_enable_device(pci); - if (err < 0) + if ((err = pci_enable_device(pci)) < 0) return err; chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (!chip) { + + if (NULL == chip) { snd_printk(KERN_ERR SFX "cannot allocate chip\n"); pci_disable_device(pci); return -ENOMEM; @@ -1508,14 +1472,13 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } #endif - err = pci_request_regions(pci, "ICH HD audio"); - if (err < 0) { + if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) { kfree(chip); pci_disable_device(pci); return err; } - chip->addr = pci_resource_start(pci, 0); + chip->addr = pci_resource_start(pci,0); chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci,0)); if (chip->remap_addr == NULL) { snd_printk(KERN_ERR SFX "ioremap error\n"); @@ -1523,9 +1486,6 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, goto errout; } - if (!disable_msi) - pci_enable_msi(pci); - if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED, "HDA Intel", (void*)chip)) { snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq); @@ -1559,7 +1519,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, } chip->num_streams = chip->playback_streams + chip->capture_streams; chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL); - if (!chip->azx_dev) { + if (! chip->azx_dev) { snd_printk(KERN_ERR "cannot malloc azx_dev\n"); goto errout; } @@ -1590,7 +1550,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, chip->initialized = 1; /* codec detection */ - if (!chip->codec_mask) { + if (! chip->codec_mask) { snd_printk(KERN_ERR SFX "no codecs found!\n"); err = -ENODEV; goto errout; @@ -1617,16 +1577,16 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id * { struct snd_card *card; struct azx *chip; - int err; + int err = 0; card = snd_card_new(index, id, THIS_MODULE, 0); - if (!card) { + if (NULL == card) { snd_printk(KERN_ERR SFX "Error creating card!\n"); return -ENOMEM; } - err = azx_create(card, pci, pci_id->driver_data, &chip); - if (err < 0) { + if ((err = azx_create(card, pci, pci_id->driver_data, + &chip)) < 0) { snd_card_free(card); return err; } diff --git a/trunk/sound/pci/hda/hda_local.h b/trunk/sound/pci/hda/hda_local.h index f9416c36396e..14e8aa2806ed 100644 --- a/trunk/sound/pci/hda/hda_local.h +++ b/trunk/sound/pci/hda/hda_local.h @@ -30,13 +30,9 @@ /* mono volume with index (index=0,1,...) (channel=1,2) */ #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ - SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \ .info = snd_hda_mixer_amp_volume_info, \ .get = snd_hda_mixer_amp_volume_get, \ .put = snd_hda_mixer_amp_volume_put, \ - .tlv = { .c = snd_hda_mixer_amp_tlv }, \ .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } /* stereo volume with index */ #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ @@ -67,7 +63,6 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *tlv); int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); @@ -229,8 +224,7 @@ struct auto_pin_cfg { hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ int speaker_outs; hda_nid_t speaker_pins[5]; - int hp_outs; - hda_nid_t hp_pins[5]; + hda_nid_t hp_pin; hda_nid_t input_pins[AUTO_PIN_LAST]; hda_nid_t dig_out_pin; hda_nid_t dig_in_pin; diff --git a/trunk/sound/pci/hda/hda_proc.c b/trunk/sound/pci/hda/hda_proc.c index d737f17695a3..c2f0fe85bf35 100644 --- a/trunk/sound/pci/hda/hda_proc.c +++ b/trunk/sound/pci/hda/hda_proc.c @@ -52,9 +52,10 @@ static void print_amp_caps(struct snd_info_buffer *buffer, struct hda_codec *codec, hda_nid_t nid, int dir) { unsigned int caps; - caps = snd_hda_param_read(codec, nid, - dir == HDA_OUTPUT ? - AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP); + if (dir == HDA_OUTPUT) + caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_OUT_CAP); + else + caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_IN_CAP); if (caps == -1 || caps == 0) { snd_iprintf(buffer, "N/A\n"); return; @@ -73,7 +74,10 @@ static void print_amp_vals(struct snd_info_buffer *buffer, unsigned int val; int i; - dir = dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT; + if (dir == HDA_OUTPUT) + dir = AC_AMP_GET_OUTPUT; + else + dir = AC_AMP_GET_INPUT; for (i = 0; i < indices; i++) { snd_iprintf(buffer, " ["); if (stereo) { diff --git a/trunk/sound/pci/hda/patch_analog.c b/trunk/sound/pci/hda/patch_analog.c index 511df07fa2a3..6823f2bc10b3 100644 --- a/trunk/sound/pci/hda/patch_analog.c +++ b/trunk/sound/pci/hda/patch_analog.c @@ -488,13 +488,9 @@ static struct snd_kcontrol_new ad1986a_mixers[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Volume", - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, .info = ad1986a_pcm_amp_vol_info, .get = ad1986a_pcm_amp_vol_get, .put = ad1986a_pcm_amp_vol_put, - .tlv = { .c = snd_hda_mixer_amp_tlv }, .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT) }, { @@ -641,7 +637,6 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { .info = snd_hda_mixer_amp_volume_info, .get = snd_hda_mixer_amp_volume_get, .put = ad1986a_laptop_master_vol_put, - .tlv = { .c = snd_hda_mixer_amp_tlv }, .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT), }, { @@ -796,8 +791,6 @@ static struct hda_board_config ad1986a_cfg_tbl[] = { .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */ { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b3, .config = AD1986A_3STACK }, /* ASUS P5RD2-VM / P5GPL-X SE */ - { .pci_subvendor = 0x1043, .pci_subdevice = 0x81cb, - .config = AD1986A_3STACK }, /* ASUS M2NPV-VM */ { .modelname = "laptop", .config = AD1986A_LAPTOP }, { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, .config = AD1986A_LAPTOP }, /* FSC V2060 */ @@ -810,8 +803,6 @@ static struct hda_board_config ad1986a_cfg_tbl[] = { .config = AD1986A_LAPTOP_EAPD }, /* Samsung X60 Chane */ { .pci_subvendor = 0x144d, .pci_subdevice = 0xc024, .config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */ - { .pci_subvendor = 0x144d, .pci_subdevice = 0xc026, - .config = AD1986A_LAPTOP_EAPD }, /* Samsung X10-T2300 Culesa */ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1153, .config = AD1986A_LAPTOP_EAPD }, /* ASUS M9 */ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1213, @@ -1635,12 +1626,10 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct ad198x_spec *spec = codec->spec; - int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, - spec->num_channel_mode, - &spec->multiout.max_channels); - if (! err && spec->need_dac_fix) + if (spec->need_dac_fix) spec->multiout.num_dacs = spec->multiout.max_channels / 2; - return err; + return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, + spec->num_channel_mode, &spec->multiout.max_channels); } /* 6-stack mode */ @@ -2471,7 +2460,7 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec) pin = spec->autocfg.speaker_pins[0]; if (pin) /* connect to front */ ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); - pin = spec->autocfg.hp_pins[0]; + pin = spec->autocfg.hp_pin; if (pin) /* connect to front */ ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); } @@ -2523,7 +2512,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) (err = ad1988_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0], "Speaker")) < 0 || - (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], + (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pin, "Headphone")) < 0 || (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) return err; diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c index d08d2e399c8f..18d105263fea 100644 --- a/trunk/sound/pci/hda/patch_realtek.c +++ b/trunk/sound/pci/hda/patch_realtek.c @@ -79,7 +79,6 @@ enum { ALC262_BASIC, ALC262_FUJITSU, ALC262_HP_BPC, - ALC262_BENQ_ED8, ALC262_AUTO, ALC262_MODEL_LAST /* last tag */ }; @@ -90,7 +89,6 @@ enum { ALC660_3ST, ALC861_3ST_DIG, ALC861_6ST_DIG, - ALC861_UNIWILL_M31, ALC861_AUTO, ALC861_MODEL_LAST, }; @@ -99,7 +97,6 @@ enum { enum { ALC882_3ST_DIG, ALC882_6ST_DIG, - ALC882_ARIMA, ALC882_AUTO, ALC882_MODEL_LAST, }; @@ -111,7 +108,6 @@ enum { ALC883_3ST_6ch, ALC883_6ST_DIG, ALC888_DEMO_BOARD, - ALC883_ACER, ALC883_AUTO, ALC883_MODEL_LAST, }; @@ -157,7 +153,6 @@ struct alc_spec { /* channel model */ const struct hda_channel_mode *channel_mode; int num_channel_mode; - int need_dac_fix; /* PCM information */ struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ @@ -195,7 +190,6 @@ struct alc_config_preset { hda_nid_t dig_in_nid; unsigned int num_channel_mode; const struct hda_channel_mode *channel_mode; - int need_dac_fix; unsigned int num_mux_defs; const struct hda_input_mux *input_mux; void (*unsol_event)(struct hda_codec *, unsigned int); @@ -268,12 +262,9 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct alc_spec *spec = codec->spec; - int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, - spec->num_channel_mode, - &spec->multiout.max_channels); - if (! err && spec->need_dac_fix) - spec->multiout.num_dacs = spec->multiout.max_channels / 2; - return err; + return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode, + spec->num_channel_mode, + &spec->multiout.max_channels); } /* @@ -553,7 +544,6 @@ static void setup_preset(struct alc_spec *spec, spec->channel_mode = preset->channel_mode; spec->num_channel_mode = preset->num_channel_mode; - spec->need_dac_fix = preset->need_dac_fix; spec->multiout.max_channels = spec->channel_mode[0].channels; @@ -1358,10 +1348,6 @@ static struct hda_verb alc880_pin_clevo_init_verbs[] = { }; static struct hda_verb alc880_pin_tcl_S700_init_verbs[] = { - /* change to EAPD mode */ - {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, - {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, - /* Headphone output */ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, /* Front output*/ @@ -1796,9 +1782,25 @@ static int alc_build_pcms(struct hda_codec *codec) } } - /* SPDIF for stream index #1 */ + /* If the use of more than one ADC is requested for the current + * model, configure a second analog capture-only PCM. + */ + if (spec->num_adc_nids > 1) { + codec->num_pcms++; + info++; + info->name = spec->stream_name_analog; + /* No playback stream for second PCM */ + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback; + info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0; + if (spec->stream_analog_capture) { + snd_assert(spec->adc_nids, return -EINVAL); + info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); + info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1]; + } + } + if (spec->multiout.dig_out_nid || spec->dig_in_nid) { - codec->num_pcms = 2; + codec->num_pcms++; info++; info->name = spec->stream_name_digital; if (spec->multiout.dig_out_nid && @@ -1813,24 +1815,6 @@ static int alc_build_pcms(struct hda_codec *codec) } } - /* If the use of more than one ADC is requested for the current - * model, configure a second analog capture-only PCM. - */ - /* Additional Analaog capture for index #2 */ - if (spec->num_adc_nids > 1 && spec->stream_analog_capture && - spec->adc_nids) { - codec->num_pcms = 3; - info++; - info->name = spec->stream_name_analog; - /* No playback stream for second PCM */ - info->stream[SNDRV_PCM_STREAM_PLAYBACK] = alc_pcm_null_playback; - info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0; - if (spec->stream_analog_capture) { - info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); - info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[1]; - } - } - return 0; } @@ -2146,10 +2130,7 @@ static struct hda_board_config alc880_cfg_tbl[] = { { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST }, { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST }, { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe212, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe213, .config = ALC880_3ST }, { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xe234, .config = ALC880_3ST }, { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST }, { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST }, { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST }, @@ -2164,7 +2145,6 @@ static struct hda_board_config alc880_cfg_tbl[] = { { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST }, { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST }, /* TCL S700 */ - { .modelname = "tcl", .config = ALC880_TCL_S700 }, { .pci_subvendor = 0x19db, .pci_subdevice = 0x4188, .config = ALC880_TCL_S700 }, /* Back 3 jack, front 2 jack (Internal add Aux-In) */ @@ -2176,13 +2156,8 @@ static struct hda_board_config alc880_cfg_tbl[] = { { .modelname = "3stack-digout", .config = ALC880_3ST_DIG }, { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG }, { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG }, - - /* Clevo laptops */ - { .modelname = "clevo", .config = ALC880_CLEVO }, - { .pci_subvendor = 0x1558, .pci_subdevice = 0x0520, - .config = ALC880_CLEVO }, /* Clevo m520G NB */ - { .pci_subvendor = 0x1558, .pci_subdevice = 0x0660, - .config = ALC880_CLEVO }, /* Clevo m665n */ + /* Clevo m520G NB */ + { .pci_subvendor = 0x1558, .pci_subdevice = 0x0520, .config = ALC880_CLEVO }, /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG }, @@ -2247,16 +2222,12 @@ static struct hda_board_config alc880_cfg_tbl[] = { { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG }, { .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG }, { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS }, - { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c2, .config = ALC880_ASUS_DIG }, /* Asus W6A */ { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG }, { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS }, { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG }, { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS }, - { .modelname = "asus-w1v", .config = ALC880_ASUS_W1V }, { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V }, - { .modelname = "asus-dig", .config = ALC880_ASUS_DIG }, { .pci_subvendor = 0x1043, .pci_subdevice = 0x8181, .config = ALC880_ASUS_DIG }, /* ASUS P4GPL-X */ - { .modelname = "asus-dig2", .config = ALC880_ASUS_DIG2 }, { .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 }, { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG }, @@ -2272,7 +2243,6 @@ static struct hda_board_config alc880_cfg_tbl[] = { { .modelname = "lg-lw", .config = ALC880_LG_LW }, { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW }, - { .pci_subvendor = 0x1854, .pci_subdevice = 0x0077, .config = ALC880_LG_LW }, #ifdef CONFIG_SND_DEBUG { .modelname = "test", .config = ALC880_TEST }, @@ -2293,7 +2263,6 @@ static struct alc_config_preset alc880_presets[] = { .dac_nids = alc880_dac_nids, .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), .channel_mode = alc880_threestack_modes, - .need_dac_fix = 1, .input_mux = &alc880_capture_source, }, [ALC880_3ST_DIG] = { @@ -2304,7 +2273,6 @@ static struct alc_config_preset alc880_presets[] = { .dig_out_nid = ALC880_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), .channel_mode = alc880_threestack_modes, - .need_dac_fix = 1, .input_mux = &alc880_capture_source, }, [ALC880_TCL_S700] = { @@ -2397,7 +2365,6 @@ static struct alc_config_preset alc880_presets[] = { .dac_nids = alc880_asus_dac_nids, .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), .channel_mode = alc880_asus_modes, - .need_dac_fix = 1, .input_mux = &alc880_capture_source, }, [ALC880_ASUS_DIG] = { @@ -2409,7 +2376,6 @@ static struct alc_config_preset alc880_presets[] = { .dig_out_nid = ALC880_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), .channel_mode = alc880_asus_modes, - .need_dac_fix = 1, .input_mux = &alc880_capture_source, }, [ALC880_ASUS_DIG2] = { @@ -2421,7 +2387,6 @@ static struct alc_config_preset alc880_presets[] = { .dig_out_nid = ALC880_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), .channel_mode = alc880_asus_modes, - .need_dac_fix = 1, .input_mux = &alc880_capture_source, }, [ALC880_ASUS_W1V] = { @@ -2433,7 +2398,6 @@ static struct alc_config_preset alc880_presets[] = { .dig_out_nid = ALC880_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), .channel_mode = alc880_asus_modes, - .need_dac_fix = 1, .input_mux = &alc880_capture_source, }, [ALC880_UNIWILL_DIG] = { @@ -2444,7 +2408,6 @@ static struct alc_config_preset alc880_presets[] = { .dig_out_nid = ALC880_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc880_asus_modes), .channel_mode = alc880_asus_modes, - .need_dac_fix = 1, .input_mux = &alc880_capture_source, }, [ALC880_CLEVO] = { @@ -2456,7 +2419,6 @@ static struct alc_config_preset alc880_presets[] = { .hp_nid = 0x03, .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes), .channel_mode = alc880_threestack_modes, - .need_dac_fix = 1, .input_mux = &alc880_capture_source, }, [ALC880_LG] = { @@ -2468,7 +2430,6 @@ static struct alc_config_preset alc880_presets[] = { .dig_out_nid = ALC880_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes), .channel_mode = alc880_lg_ch_modes, - .need_dac_fix = 1, .input_mux = &alc880_lg_capture_source, .unsol_event = alc880_lg_unsol_event, .init_hook = alc880_lg_automute, @@ -2753,7 +2714,7 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec) pin = spec->autocfg.speaker_pins[0]; if (pin) /* connect to front */ alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); - pin = spec->autocfg.hp_pins[0]; + pin = spec->autocfg.hp_pin; if (pin) /* connect to front */ alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); } @@ -2794,7 +2755,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec) (err = alc880_auto_create_extra_out(spec, spec->autocfg.speaker_pins[0], "Speaker")) < 0 || - (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], + (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pin, "Headphone")) < 0 || (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) return err; @@ -3736,7 +3697,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, return err; } - nid = cfg->hp_pins[0]; + nid = cfg->hp_pin; if (nid) { err = alc260_add_playback_controls(spec, nid, "Headphone"); if (err < 0) @@ -3806,7 +3767,7 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) if (nid) alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); - nid = spec->autocfg.hp_pins[0]; + nid = spec->autocfg.hp_pin; if (nid) alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); } @@ -3939,8 +3900,7 @@ static struct hda_board_config alc260_cfg_tbl[] = { { .pci_subvendor = 0x152d, .pci_subdevice = 0x0729, .config = ALC260_BASIC }, /* CTL Travel Master U553W */ { .modelname = "hp", .config = ALC260_HP }, - { .modelname = "hp-3013", .config = ALC260_HP_3013 }, - { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP_3013 }, + { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP_3013 }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 }, @@ -4306,13 +4266,6 @@ static struct hda_verb alc882_init_verbs[] = { { } }; -static struct hda_verb alc882_eapd_verbs[] = { - /* change to EAPD mode */ - {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, - {0x20, AC_VERB_SET_PROC_COEF, 0x3060}, - { } -}; - /* * generic initialization of ADC, input mixers and output mixers */ @@ -4444,9 +4397,6 @@ static struct hda_board_config alc882_cfg_tbl[] = { .config = ALC882_6ST_DIG }, /* Foxconn */ { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, .config = ALC882_6ST_DIG }, /* ECS to Intel*/ - { .modelname = "arima", .config = ALC882_ARIMA }, - { .pci_subvendor = 0x161f, .pci_subdevice = 0x2054, - .config = ALC882_ARIMA }, /* Arima W820Di1 */ { .modelname = "auto", .config = ALC882_AUTO }, {} }; @@ -4461,7 +4411,6 @@ static struct alc_config_preset alc882_presets[] = { .dig_in_nid = ALC882_DIGIN_NID, .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), .channel_mode = alc882_ch_modes, - .need_dac_fix = 1, .input_mux = &alc882_capture_source, }, [ALC882_6ST_DIG] = { @@ -4475,15 +4424,6 @@ static struct alc_config_preset alc882_presets[] = { .channel_mode = alc882_sixstack_modes, .input_mux = &alc882_capture_source, }, - [ALC882_ARIMA] = { - .mixers = { alc882_base_mixer, alc882_chmode_mixer }, - .init_verbs = { alc882_init_verbs, alc882_eapd_verbs }, - .num_dacs = ARRAY_SIZE(alc882_dac_nids), - .dac_nids = alc882_dac_nids, - .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes), - .channel_mode = alc882_sixstack_modes, - .input_mux = &alc882_capture_source, - }, }; @@ -4526,7 +4466,7 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) struct alc_spec *spec = codec->spec; hda_nid_t pin; - pin = spec->autocfg.hp_pins[0]; + pin = spec->autocfg.hp_pin; if (pin) /* connect to front */ alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */ } @@ -5059,23 +4999,16 @@ static struct snd_kcontrol_new alc883_capture_mixer[] = { */ static struct hda_board_config alc883_cfg_tbl[] = { { .modelname = "3stack-dig", .config = ALC883_3ST_2ch_DIG }, - { .modelname = "3stack-6ch-dig", .config = ALC883_3ST_6ch_DIG }, - { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, - .config = ALC883_3ST_6ch_DIG }, /* ECS to Intel*/ - { .modelname = "3stack-6ch", .config = ALC883_3ST_6ch }, - { .pci_subvendor = 0x108e, .pci_subdevice = 0x534d, - .config = ALC883_3ST_6ch }, - { .pci_subvendor = 0x8086, .pci_subdevice = 0xd601, - .config = ALC883_3ST_6ch }, /* D102GGC */ { .modelname = "6stack-dig", .config = ALC883_6ST_DIG }, + { .modelname = "6stack-dig-demo", .config = ALC888_DEMO_BOARD }, { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, .config = ALC883_6ST_DIG }, /* MSI */ { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, .config = ALC883_6ST_DIG }, /* Foxconn */ - { .modelname = "6stack-dig-demo", .config = ALC888_DEMO_BOARD }, - { .modelname = "acer", .config = ALC883_ACER }, - { .pci_subvendor = 0x1025, .pci_subdevice = 0/*0x0102*/, - .config = ALC883_ACER }, + { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, + .config = ALC883_3ST_6ch_DIG }, /* ECS to Intel*/ + { .pci_subvendor = 0x108e, .pci_subdevice = 0x534d, + .config = ALC883_3ST_6ch }, { .modelname = "auto", .config = ALC883_AUTO }, {} }; @@ -5105,7 +5038,6 @@ static struct alc_config_preset alc883_presets[] = { .dig_in_nid = ALC883_DIGIN_NID, .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), .channel_mode = alc883_3ST_6ch_modes, - .need_dac_fix = 1, .input_mux = &alc883_capture_source, }, [ALC883_3ST_6ch] = { @@ -5117,7 +5049,6 @@ static struct alc_config_preset alc883_presets[] = { .adc_nids = alc883_adc_nids, .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes), .channel_mode = alc883_3ST_6ch_modes, - .need_dac_fix = 1, .input_mux = &alc883_capture_source, }, [ALC883_6ST_DIG] = { @@ -5146,23 +5077,6 @@ static struct alc_config_preset alc883_presets[] = { .channel_mode = alc883_sixstack_modes, .input_mux = &alc883_capture_source, }, - [ALC883_ACER] = { - .mixers = { alc883_base_mixer, - alc883_chmode_mixer }, - /* On TravelMate laptops, GPIO 0 enables the internal speaker - * and the headphone jack. Turn this on and rely on the - * standard mute methods whenever the user wants to turn - * these outputs off. - */ - .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs }, - .num_dacs = ARRAY_SIZE(alc883_dac_nids), - .dac_nids = alc883_dac_nids, - .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), - .adc_nids = alc883_adc_nids, - .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), - .channel_mode = alc883_3ST_2ch_modes, - .input_mux = &alc883_capture_source, - }, }; @@ -5207,7 +5121,7 @@ static void alc883_auto_init_hp_out(struct hda_codec *codec) struct alc_spec *spec = codec->spec; hda_nid_t pin; - pin = spec->autocfg.hp_pins[0]; + pin = spec->autocfg.hp_pin; if (pin) /* connect to front */ /* use dac 0 */ alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); @@ -5303,10 +5217,8 @@ static int patch_alc883(struct hda_codec *codec) spec->stream_digital_playback = &alc883_pcm_digital_playback; spec->stream_digital_capture = &alc883_pcm_digital_capture; - if (! spec->adc_nids && spec->input_mux) { - spec->adc_nids = alc883_adc_nids; - spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); - } + spec->adc_nids = alc883_adc_nids; + spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids); codec->patch_ops = alc_patch_ops; if (board_config == ALC883_AUTO) @@ -5569,7 +5481,6 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { .info = snd_hda_mixer_amp_volume_info, .get = snd_hda_mixer_amp_volume_get, .put = alc262_fujitsu_master_vol_put, - .tlv = { .c = snd_hda_mixer_amp_tlv }, .private_value = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT), }, { @@ -5588,13 +5499,6 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = { { } /* end */ }; -/* additional init verbs for Benq laptops */ -static struct hda_verb alc262_EAPD_verbs[] = { - {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, - {0x20, AC_VERB_SET_PROC_COEF, 0x3070}, - {} -}; - /* add playback controls from the parsed DAC table */ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg) { @@ -5630,7 +5534,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct return err; } } - nid = cfg->hp_pins[0]; + nid = cfg->hp_pin; if (nid) { /* spec->multiout.hp_nid = 2; */ if (nid == 0x16) { @@ -5865,7 +5769,6 @@ static struct hda_board_config alc262_cfg_tbl[] = { { .modelname = "fujitsu", .config = ALC262_FUJITSU }, { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397, .config = ALC262_FUJITSU }, - { .modelname = "hp-bpc", .config = ALC262_HP_BPC }, { .pci_subvendor = 0x103c, .pci_subdevice = 0x208c, .config = ALC262_HP_BPC }, /* xw4400 */ { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, @@ -5874,9 +5777,6 @@ static struct hda_board_config alc262_cfg_tbl[] = { .config = ALC262_HP_BPC }, /* xw8400 */ { .pci_subvendor = 0x103c, .pci_subdevice = 0x12fe, .config = ALC262_HP_BPC }, /* xw9400 */ - { .modelname = "benq", .config = ALC262_BENQ_ED8 }, - { .pci_subvendor = 0x17ff, .pci_subdevice = 0x0560, - .config = ALC262_BENQ_ED8 }, { .modelname = "auto", .config = ALC262_AUTO }, {} }; @@ -5914,16 +5814,6 @@ static struct alc_config_preset alc262_presets[] = { .channel_mode = alc262_modes, .input_mux = &alc262_HP_capture_source, }, - [ALC262_BENQ_ED8] = { - .mixers = { alc262_base_mixer }, - .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs }, - .num_dacs = ARRAY_SIZE(alc262_dac_nids), - .dac_nids = alc262_dac_nids, - .hp_nid = 0x03, - .num_channel_mode = ARRAY_SIZE(alc262_modes), - .channel_mode = alc262_modes, - .input_mux = &alc262_capture_source, - }, }; static int patch_alc262(struct hda_codec *codec) @@ -6052,23 +5942,6 @@ static struct hda_channel_mode alc861_threestack_modes[2] = { { 2, alc861_threestack_ch2_init }, { 6, alc861_threestack_ch6_init }, }; -/* Set mic1 as input and unmute the mixer */ -static struct hda_verb alc861_uniwill_m31_ch2_init[] = { - { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/ - { } /* end */ -}; -/* Set mic1 as output and mute mixer */ -static struct hda_verb alc861_uniwill_m31_ch4_init[] = { - { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/ - { } /* end */ -}; - -static struct hda_channel_mode alc861_uniwill_m31_modes[2] = { - { 2, alc861_uniwill_m31_ch2_init }, - { 4, alc861_uniwill_m31_ch4_init }, -}; /* patch-ALC861 */ @@ -6147,47 +6020,6 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = { }, { } /* end */ }; -static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { - /* output mixer control */ - HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT), - /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */ - - /* Input mixer control */ - /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT), - HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */ - HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT), - - /* Capture mixer control */ - HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .count = 1, - .info = alc_mux_enum_info, - .get = alc_mux_enum_get, - .put = alc_mux_enum_put, - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Channel Mode", - .info = alc_ch_mode_info, - .get = alc_ch_mode_get, - .put = alc_ch_mode_put, - .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes), - }, - { } /* end */ -}; /* * generic initialization of ADC, input mixers and output mixers @@ -6316,67 +6148,6 @@ static struct hda_verb alc861_threestack_init_verbs[] = { {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, { } }; - -static struct hda_verb alc861_uniwill_m31_init_verbs[] = { - /* - * Unmute ADC0 and set the default input to mic-in - */ - /* port-A for surround (rear panel) */ - { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, - /* port-B for mic-in (rear panel) with vref */ - { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - /* port-C for line-in (rear panel) */ - { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - /* port-D for Front */ - { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, - { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 }, - /* port-E for HP out (front panel) */ - { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, // this has to be set to VREF80 - /* route front PCM to HP */ - { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 }, - /* port-F for mic-in (front panel) with vref */ - { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, - /* port-G for CLFE (rear panel) */ - { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, - /* port-H for side (rear panel) */ - { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 }, - /* CD-in */ - { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 }, - /* route front mic to ADC1*/ - {0x08, AC_VERB_SET_CONNECT_SEL, 0x00}, - {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - /* Unmute DAC0~3 & spdif out*/ - {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - - /* Unmute Mixer 14 (mic) 1c (Line in)*/ - {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - - /* Unmute Stereo Mixer 15 */ - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, //Output 0~12 step - - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, - {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, // hp used DAC 3 (Front) - {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)}, - { } -}; - /* * generic initialization of ADC, input mixers and output mixers */ @@ -6630,7 +6401,7 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec) struct alc_spec *spec = codec->spec; hda_nid_t pin; - pin = spec->autocfg.hp_pins[0]; + pin = spec->autocfg.hp_pin; if (pin) /* connect to front */ alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]); } @@ -6665,7 +6436,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || - (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0])) < 0 || + (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 || (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) return err; @@ -6706,14 +6477,10 @@ static struct hda_board_config alc861_cfg_tbl[] = { { .modelname = "3stack", .config = ALC861_3ST }, { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, .config = ALC861_3ST }, - { .modelname = "3stack-660", .config = ALC660_3ST }, { .pci_subvendor = 0x1043, .pci_subdevice = 0x81e7, .config = ALC660_3ST }, { .modelname = "3stack-dig", .config = ALC861_3ST_DIG }, { .modelname = "6stack-dig", .config = ALC861_6ST_DIG }, - { .modelname = "uniwill-m31", .config = ALC861_UNIWILL_M31}, - { .pci_subvendor = 0x1584, .pci_subdevice = 0x9072, - .config = ALC861_UNIWILL_M31 }, { .modelname = "auto", .config = ALC861_AUTO }, {} }; @@ -6726,7 +6493,6 @@ static struct alc_config_preset alc861_presets[] = { .dac_nids = alc861_dac_nids, .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), .channel_mode = alc861_threestack_modes, - .need_dac_fix = 1, .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), .adc_nids = alc861_adc_nids, .input_mux = &alc861_capture_source, @@ -6739,7 +6505,6 @@ static struct alc_config_preset alc861_presets[] = { .dig_out_nid = ALC861_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), .channel_mode = alc861_threestack_modes, - .need_dac_fix = 1, .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), .adc_nids = alc861_adc_nids, .input_mux = &alc861_capture_source, @@ -6763,25 +6528,10 @@ static struct alc_config_preset alc861_presets[] = { .dac_nids = alc660_dac_nids, .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes), .channel_mode = alc861_threestack_modes, - .need_dac_fix = 1, - .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), - .adc_nids = alc861_adc_nids, - .input_mux = &alc861_capture_source, - }, - [ALC861_UNIWILL_M31] = { - .mixers = { alc861_uniwill_m31_mixer }, - .init_verbs = { alc861_uniwill_m31_init_verbs }, - .num_dacs = ARRAY_SIZE(alc861_dac_nids), - .dac_nids = alc861_dac_nids, - .dig_out_nid = ALC861_DIGOUT_NID, - .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes), - .channel_mode = alc861_uniwill_m31_modes, - .need_dac_fix = 1, .num_adc_nids = ARRAY_SIZE(alc861_adc_nids), .adc_nids = alc861_adc_nids, .input_mux = &alc861_capture_source, }, - }; diff --git a/trunk/sound/pci/hda/patch_si3054.c b/trunk/sound/pci/hda/patch_si3054.c index 76ec3d75fa9e..250242cd6c70 100644 --- a/trunk/sound/pci/hda/patch_si3054.c +++ b/trunk/sound/pci/hda/patch_si3054.c @@ -298,7 +298,6 @@ struct hda_codec_preset snd_hda_preset_si3054[] = { { .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 }, { .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 }, { .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 }, - { .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 }, {} }; diff --git a/trunk/sound/pci/hda/patch_sigmatel.c b/trunk/sound/pci/hda/patch_sigmatel.c index 731b7b97ee71..ea99083a1024 100644 --- a/trunk/sound/pci/hda/patch_sigmatel.c +++ b/trunk/sound/pci/hda/patch_sigmatel.c @@ -36,15 +36,15 @@ #define NUM_CONTROL_ALLOC 32 #define STAC_HP_EVENT 0x37 +#define STAC_UNSOL_ENABLE (AC_USRSP_EN | STAC_HP_EVENT) #define STAC_REF 0 #define STAC_D945GTP3 1 #define STAC_D945GTP5 2 #define STAC_MACMINI 3 -#define STAC_922X_MODELS 4 /* number of 922x models */ -#define STAC_D965_3ST 4 -#define STAC_D965_5ST 5 -#define STAC_927X_MODELS 6 /* number of 922x models */ +#define STAC_D965_2112 4 +#define STAC_D965_284B 5 +#define STAC_922X_MODELS 6 /* number of 922x models */ struct sigmatel_spec { struct snd_kcontrol_new *mixers[4]; @@ -73,7 +73,6 @@ struct sigmatel_spec { hda_nid_t *pin_nids; unsigned int num_pins; unsigned int *pin_configs; - unsigned int *bios_pin_configs; /* codec specific stuff */ struct hda_verb *init; @@ -111,10 +110,24 @@ static hda_nid_t stac922x_adc_nids[2] = { 0x06, 0x07, }; +static hda_nid_t stac9227_adc_nids[2] = { + 0x07, 0x08, +}; + +#if 0 +static hda_nid_t d965_2112_dac_nids[3] = { + 0x02, 0x03, 0x05, +}; +#endif + static hda_nid_t stac922x_mux_nids[2] = { 0x12, 0x13, }; +static hda_nid_t stac9227_mux_nids[2] = { + 0x15, 0x16, +}; + static hda_nid_t stac927x_adc_nids[3] = { 0x07, 0x08, 0x09 }; @@ -123,17 +136,8 @@ static hda_nid_t stac927x_mux_nids[3] = { 0x15, 0x16, 0x17 }; -static hda_nid_t stac9205_adc_nids[2] = { - 0x12, 0x13 -}; - -static hda_nid_t stac9205_mux_nids[2] = { - 0x19, 0x1a -}; - static hda_nid_t stac9200_pin_nids[8] = { - 0x08, 0x09, 0x0d, 0x0e, - 0x0f, 0x10, 0x11, 0x12, + 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, }; static hda_nid_t stac922x_pin_nids[10] = { @@ -147,13 +151,6 @@ static hda_nid_t stac927x_pin_nids[14] = { 0x14, 0x21, 0x22, 0x23, }; -static hda_nid_t stac9205_pin_nids[12] = { - 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x14, 0x16, 0x17, 0x18, - 0x21, 0x22, - -}; - static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); @@ -193,23 +190,25 @@ static struct hda_verb stac922x_core_init[] = { {} }; -static struct hda_verb d965_core_init[] = { +static struct hda_verb stac9227_core_init[] = { /* set master volume and direct control */ - { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, + { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, /* unmute node 0x1b */ { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, - /* select node 0x03 as DAC */ - { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, {} }; -static struct hda_verb stac927x_core_init[] = { +static struct hda_verb d965_2112_core_init[] = { /* set master volume and direct control */ - { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, + { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, + /* unmute node 0x1b */ + { 0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, + /* select node 0x03 as DAC */ + { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x01}, {} }; -static struct hda_verb stac9205_core_init[] = { +static struct hda_verb stac927x_core_init[] = { /* set master volume and direct control */ { 0x24, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, {} @@ -278,21 +277,6 @@ static snd_kcontrol_new_t stac927x_mixer[] = { { } /* end */ }; -static snd_kcontrol_new_t stac9205_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Input Source", - .count = 1, - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, - }, - HDA_CODEC_VOLUME("InMux Capture Volume", 0x19, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("InVol Capture Volume", 0x1b, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("ADCMux Capture Switch", 0x1d, 0x0, HDA_OUTPUT), - { } /* end */ -}; - static int stac92xx_build_controls(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; @@ -357,67 +341,38 @@ static unsigned int d945gtp5_pin_configs[10] = { 0x02a19320, 0x40000100, }; +static unsigned int d965_2112_pin_configs[10] = { + 0x0221401f, 0x40000100, 0x40000100, 0x01014011, + 0x01a19021, 0x01813024, 0x01452130, 0x40000100, + 0x02a19320, 0x40000100, +}; + static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { [STAC_REF] = ref922x_pin_configs, [STAC_D945GTP3] = d945gtp3_pin_configs, [STAC_D945GTP5] = d945gtp5_pin_configs, [STAC_MACMINI] = d945gtp5_pin_configs, + [STAC_D965_2112] = d965_2112_pin_configs, }; static struct hda_board_config stac922x_cfg_tbl[] = { - { .modelname = "5stack", .config = STAC_D945GTP5 }, - { .modelname = "3stack", .config = STAC_D945GTP3 }, { .modelname = "ref", .pci_subvendor = PCI_VENDOR_ID_INTEL, .pci_subdevice = 0x2668, /* DFI LanParty */ .config = STAC_REF }, /* SigmaTel reference board */ - /* Intel 945G based systems */ { .pci_subvendor = PCI_VENDOR_ID_INTEL, .pci_subdevice = 0x0101, .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ { .pci_subvendor = PCI_VENDOR_ID_INTEL, .pci_subdevice = 0x0202, - .config = STAC_D945GTP3 }, /* Intel D945GNT - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x0606, - .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x0601, - .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x0111, - .config = STAC_D945GTP3 }, /* Intel D945GZP - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x1115, - .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x1116, - .config = STAC_D945GTP3 }, /* Intel D945GBO - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x1117, - .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x1118, - .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x1119, - .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x8826, - .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x5049, - .config = STAC_D945GTP3 }, /* Intel D945GCZ - 3 Stack */ + .config = STAC_D945GTP3 }, /* Intel D945GNT - 3 Stack, 9221 A1 */ { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x5055, - .config = STAC_D945GTP3 }, /* Intel D945GCZ - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x5048, - .config = STAC_D945GTP3 }, /* Intel D945GPB - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x0110, - .config = STAC_D945GTP3 }, /* Intel D945GLR - 3 Stack */ + .pci_subdevice = 0x0b0b, + .config = STAC_D945GTP3 }, /* Intel D945PSN - 3 Stack, 9221 A1 */ { .pci_subvendor = PCI_VENDOR_ID_INTEL, + .pci_subdevice = 0x0707, + .config = STAC_D945GTP5 }, /* Intel D945PSV - 5 Stack */ + { .pci_subvendor = PCI_VENDOR_ID_INTEL, .pci_subdevice = 0x0404, .config = STAC_D945GTP5 }, /* Intel D945GTP - 5 Stack */ { .pci_subvendor = PCI_VENDOR_ID_INTEL, @@ -429,214 +384,44 @@ static struct hda_board_config stac922x_cfg_tbl[] = { { .pci_subvendor = PCI_VENDOR_ID_INTEL, .pci_subdevice = 0x0417, .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ - /* Intel 945P based systems */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x0b0b, - .config = STAC_D945GTP3 }, /* Intel D945PSN - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x0112, - .config = STAC_D945GTP3 }, /* Intel D945PLN - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x0d0d, - .config = STAC_D945GTP3 }, /* Intel D945PLM - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x0909, - .config = STAC_D945GTP3 }, /* Intel D945PAW - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x0505, - .config = STAC_D945GTP3 }, /* Intel D945PLM - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x0707, - .config = STAC_D945GTP5 }, /* Intel D945PSV - 5 Stack */ - /* other systems */ { .pci_subvendor = 0x8384, .pci_subdevice = 0x7680, .config = STAC_MACMINI }, /* Apple Mac Mini (early 2006) */ - {} /* terminator */ -}; - -static unsigned int ref927x_pin_configs[14] = { - 0x02214020, 0x02a19080, 0x0181304e, 0x01014010, - 0x01a19040, 0x01011012, 0x01016011, 0x0101201f, - 0x183301f0, 0x18a001f0, 0x18a001f0, 0x01442070, - 0x01c42190, 0x40000100, -}; - -static unsigned int d965_3st_pin_configs[14] = { - 0x0221401f, 0x02a19120, 0x40000100, 0x01014011, - 0x01a19021, 0x01813024, 0x40000100, 0x40000100, - 0x40000100, 0x40000100, 0x40000100, 0x40000100, - 0x40000100, 0x40000100 -}; - -static unsigned int d965_5st_pin_configs[14] = { - 0x02214020, 0x02a19080, 0x0181304e, 0x01014010, - 0x01a19040, 0x01011012, 0x01016011, 0x40000100, - 0x40000100, 0x40000100, 0x40000100, 0x01442070, - 0x40000100, 0x40000100 -}; - -static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { - [STAC_REF] = ref927x_pin_configs, - [STAC_D965_3ST] = d965_3st_pin_configs, - [STAC_D965_5ST] = d965_5st_pin_configs, -}; - -static struct hda_board_config stac927x_cfg_tbl[] = { - { .modelname = "5stack", .config = STAC_D965_5ST }, - { .modelname = "3stack", .config = STAC_D965_3ST }, - { .modelname = "ref", - .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2668, /* DFI LanParty */ - .config = STAC_REF }, /* SigmaTel reference board */ - /* Intel 946 based systems */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x3d01, - .config = STAC_D965_3ST }, /* D946 configuration */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0xa301, - .config = STAC_D965_3ST }, /* Intel D946GZT - 3 stack */ - /* 965 based 3 stack systems */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2116, - .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2115, - .config = STAC_D965_3ST }, /* Intel DQ965WC - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2114, - .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2113, - .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ { .pci_subvendor = PCI_VENDOR_ID_INTEL, .pci_subdevice = 0x2112, - .config = STAC_D965_3ST }, /* Intel DG965MS - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2111, - .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2110, - .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2009, - .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2008, - .config = STAC_D965_3ST }, /* Intel DQ965GF - 3 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2007, - .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2006, - .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2005, - .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2004, - .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2003, - .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2002, - .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2001, - .config = STAC_D965_3ST }, /* Intel DQ965GF - 3 Stack */ - /* 965 based 5 stack systems */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2301, - .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2302, - .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2303, - .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ + .config = STAC_D965_2112 }, { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2304, - .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2305, - .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2501, - .config = STAC_D965_5ST }, /* Intel DG965MQ - 5 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2502, - .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2503, - .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ - { .pci_subvendor = PCI_VENDOR_ID_INTEL, - .pci_subdevice = 0x2504, - .config = STAC_D965_5ST }, /* Intel DQ965GF - 5 Stack */ + .pci_subdevice = 0x284b, + .config = STAC_D965_284B }, {} /* terminator */ }; -static unsigned int ref9205_pin_configs[12] = { - 0x40000100, 0x40000100, 0x01016011, 0x01014010, - 0x01813122, 0x01a19021, 0x40000100, 0x40000100, - 0x40000100, 0x40000100, 0x01441030, 0x01c41030 +static unsigned int ref927x_pin_configs[14] = { + 0x01813122, 0x01a19021, 0x01014010, 0x01016011, + 0x01012012, 0x01011014, 0x40000100, 0x40000100, + 0x40000100, 0x40000100, 0x40000100, 0x01441030, + 0x01c41030, 0x40000100, }; -static unsigned int *stac9205_brd_tbl[] = { - ref9205_pin_configs, +static unsigned int *stac927x_brd_tbl[] = { + ref927x_pin_configs, }; -static struct hda_board_config stac9205_cfg_tbl[] = { +static struct hda_board_config stac927x_cfg_tbl[] = { { .modelname = "ref", .pci_subvendor = PCI_VENDOR_ID_INTEL, .pci_subdevice = 0x2668, /* DFI LanParty */ .config = STAC_REF }, /* SigmaTel reference board */ - /* Dell laptops have BIOS problem */ - { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01b5, - .config = STAC_REF }, /* Dell Inspiron 630m */ - { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01c2, - .config = STAC_REF }, /* Dell Latitude D620 */ - { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01cb, - .config = STAC_REF }, /* Dell Latitude 120L */ {} /* terminator */ }; -static int stac92xx_save_bios_config_regs(struct hda_codec *codec) -{ - int i; - struct sigmatel_spec *spec = codec->spec; - - if (! spec->bios_pin_configs) { - spec->bios_pin_configs = kcalloc(spec->num_pins, - sizeof(*spec->bios_pin_configs), GFP_KERNEL); - if (! spec->bios_pin_configs) - return -ENOMEM; - } - - for (i = 0; i < spec->num_pins; i++) { - hda_nid_t nid = spec->pin_nids[i]; - unsigned int pin_cfg; - - pin_cfg = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_CONFIG_DEFAULT, 0x00); - snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n", - nid, pin_cfg); - spec->bios_pin_configs[i] = pin_cfg; - } - - return 0; -} - static void stac92xx_set_config_regs(struct hda_codec *codec) { int i; struct sigmatel_spec *spec = codec->spec; unsigned int pin_cfg; - if (! spec->pin_nids || ! spec->pin_configs) - return; - - for (i = 0; i < spec->num_pins; i++) { + for (i=0; i < spec->num_pins; i++) { snd_hda_codec_write(codec, spec->pin_nids[i], 0, AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, spec->pin_configs[i] & 0x000000ff); @@ -1010,29 +795,11 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, return 0; } -/* create volume control/switch for the given prefx type */ -static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs) -{ - char name[32]; - int err; - - sprintf(name, "%s Playback Volume", pfx); - err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, - HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); - if (err < 0) - return err; - sprintf(name, "%s Playback Switch", pfx); - err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name, - HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); - if (err < 0) - return err; - return 0; -} - /* add playback controls from the parsed DAC table */ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, const struct auto_pin_cfg *cfg) { + char name[32]; static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" }; @@ -1047,15 +814,26 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, if (i == 2) { /* Center/LFE */ - err = create_controls(spec, "Center", nid, 1); - if (err < 0) + if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Center Playback Volume", + HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) + return err; + if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "LFE Playback Volume", + HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) + return err; + if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Center Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) return err; - err = create_controls(spec, "LFE", nid, 2); - if (err < 0) + if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "LFE Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) return err; } else { - err = create_controls(spec, chname[i], nid, 3); - if (err < 0) + sprintf(name, "%s Playback Volume", chname[i]); + if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, + HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) + return err; + sprintf(name, "%s Playback Switch", chname[i]); + if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name, + HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) return err; } } @@ -1071,85 +849,39 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, return 0; } -static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) +/* add playback controls for HP output */ +static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin_cfg *cfg) { - int i; + struct sigmatel_spec *spec = codec->spec; + hda_nid_t pin = cfg->hp_pin; + hda_nid_t nid; + int i, err; + unsigned int wid_caps; - for (i = 0; i < spec->multiout.num_dacs; i++) { - if (spec->multiout.dac_nids[i] == nid) - return 1; - } - if (spec->multiout.hp_nid == nid) - return 1; - return 0; -} + if (! pin) + return 0; -static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) -{ - if (!spec->multiout.hp_nid) - spec->multiout.hp_nid = nid; - else if (spec->multiout.num_dacs > 4) { - printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid); - return 1; - } else { - spec->multiout.dac_nids[spec->multiout.num_dacs] = nid; - spec->multiout.num_dacs++; - } - return 0; -} + wid_caps = get_wcaps(codec, pin); + if (wid_caps & AC_WCAP_UNSOL_CAP) + spec->hp_detect = 1; -/* add playback controls for Speaker and HP outputs */ -static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, - struct auto_pin_cfg *cfg) -{ - struct sigmatel_spec *spec = codec->spec; - hda_nid_t nid; - int i, old_num_dacs, err; - - old_num_dacs = spec->multiout.num_dacs; - for (i = 0; i < cfg->hp_outs; i++) { - unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]); - if (wid_caps & AC_WCAP_UNSOL_CAP) - spec->hp_detect = 1; - nid = snd_hda_codec_read(codec, cfg->hp_pins[i], 0, - AC_VERB_GET_CONNECT_LIST, 0) & 0xff; - if (check_in_dac_nids(spec, nid)) - nid = 0; - if (! nid) - continue; - add_spec_dacs(spec, nid); - } - for (i = 0; i < cfg->speaker_outs; i++) { - nid = snd_hda_codec_read(codec, cfg->speaker_pins[0], 0, - AC_VERB_GET_CONNECT_LIST, 0) & 0xff; - if (check_in_dac_nids(spec, nid)) - nid = 0; - if (check_in_dac_nids(spec, nid)) - nid = 0; - if (! nid) + nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; + for (i = 0; i < cfg->line_outs; i++) { + if (! spec->multiout.dac_nids[i]) continue; - add_spec_dacs(spec, nid); + if (spec->multiout.dac_nids[i] == nid) + return 0; } - for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) { - static const char *pfxs[] = { - "Speaker", "External Speaker", "Speaker2", - }; - err = create_controls(spec, pfxs[i - old_num_dacs], - spec->multiout.dac_nids[i], 3); - if (err < 0) - return err; - } - if (spec->multiout.hp_nid) { - const char *pfx; - if (old_num_dacs == spec->multiout.num_dacs) - pfx = "Master"; - else - pfx = "Headphone"; - err = create_controls(spec, pfx, spec->multiout.hp_nid, 3); - if (err < 0) - return err; - } + spec->multiout.hp_nid = nid; + + /* control HP volume/switch on the output mixer amp */ + if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Headphone Playback Volume", + HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) + return err; + if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Headphone Playback Switch", + HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) + return err; return 0; } @@ -1163,28 +895,23 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const int i, j, k; for (i = 0; i < AUTO_PIN_LAST; i++) { - int index; - - if (!cfg->input_pins[i]) - continue; - index = -1; - for (j = 0; j < spec->num_muxes; j++) { - int num_cons; - num_cons = snd_hda_get_connections(codec, - spec->mux_nids[j], - con_lst, - HDA_MAX_NUM_INPUTS); - for (k = 0; k < num_cons; k++) - if (con_lst[k] == cfg->input_pins[i]) { - index = k; - goto found; - } + int index = -1; + if (cfg->input_pins[i]) { + imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; + + for (j=0; jnum_muxes; j++) { + int num_cons = snd_hda_get_connections(codec, spec->mux_nids[j], con_lst, HDA_MAX_NUM_INPUTS); + for (k=0; kinput_pins[i]) { + index = k; + break; + } + if (index >= 0) + break; + } + imux->items[imux->num_items].index = index; + imux->num_items++; } - continue; - found: - imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; - imux->items[imux->num_items].index = index; - imux->num_items++; } if (imux->num_items == 1) { @@ -1217,20 +944,11 @@ static void stac92xx_auto_init_multi_out(struct hda_codec *codec) static void stac92xx_auto_init_hp_out(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; - int i; + hda_nid_t pin; - for (i = 0; i < spec->autocfg.hp_outs; i++) { - hda_nid_t pin; - pin = spec->autocfg.hp_pins[i]; - if (pin) /* connect to front */ - stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); - } - for (i = 0; i < spec->autocfg.speaker_outs; i++) { - hda_nid_t pin; - pin = spec->autocfg.speaker_pins[i]; - if (pin) /* connect to front */ - stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN); - } + pin = spec->autocfg.hp_pin; + if (pin) /* connect to front */ + stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); } static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) @@ -1276,7 +994,7 @@ static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin_cfg *cfg) { struct sigmatel_spec *spec = codec->spec; - hda_nid_t pin = cfg->hp_pins[0]; + hda_nid_t pin = cfg->hp_pin; unsigned int wid_caps; if (! pin) @@ -1289,57 +1007,6 @@ static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, return 0; } -/* add playback controls for LFE output */ -static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec, - struct auto_pin_cfg *cfg) -{ - struct sigmatel_spec *spec = codec->spec; - int err; - hda_nid_t lfe_pin = 0x0; - int i; - - /* - * search speaker outs and line outs for a mono speaker pin - * with an amp. If one is found, add LFE controls - * for it. - */ - for (i = 0; i < spec->autocfg.speaker_outs && lfe_pin == 0x0; i++) { - hda_nid_t pin = spec->autocfg.speaker_pins[i]; - unsigned long wcaps = get_wcaps(codec, pin); - wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); - if (wcaps == AC_WCAP_OUT_AMP) - /* found a mono speaker with an amp, must be lfe */ - lfe_pin = pin; - } - - /* if speaker_outs is 0, then speakers may be in line_outs */ - if (lfe_pin == 0 && spec->autocfg.speaker_outs == 0) { - for (i = 0; i < spec->autocfg.line_outs && lfe_pin == 0x0; i++) { - hda_nid_t pin = spec->autocfg.line_out_pins[i]; - unsigned long cfg; - cfg = snd_hda_codec_read(codec, pin, 0, - AC_VERB_GET_CONFIG_DEFAULT, - 0x00); - if (get_defcfg_device(cfg) == AC_JACK_SPEAKER) { - unsigned long wcaps = get_wcaps(codec, pin); - wcaps &= (AC_WCAP_STEREO | AC_WCAP_OUT_AMP); - if (wcaps == AC_WCAP_OUT_AMP) - /* found a mono speaker with an amp, - must be lfe */ - lfe_pin = pin; - } - } - } - - if (lfe_pin) { - err = create_controls(spec, "LFE", lfe_pin, 1); - if (err < 0) - return err; - } - - return 0; -} - static int stac9200_parse_auto_config(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; @@ -1354,9 +1021,6 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) if ((err = stac9200_auto_create_hp_ctls(codec, &spec->autocfg)) < 0) return err; - if ((err = stac9200_auto_create_lfe_ctls(codec, &spec->autocfg)) < 0) - return err; - if (spec->autocfg.dig_out_pin) spec->multiout.dig_out_nid = 0x05; if (spec->autocfg.dig_in_pin) @@ -1409,15 +1073,6 @@ static void stac922x_gpio_mute(struct hda_codec *codec, int pin, int muted) AC_VERB_SET_GPIO_DATA, gpiostate); } -static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, - unsigned int event) -{ - if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) - snd_hda_codec_write(codec, nid, 0, - AC_VERB_SET_UNSOLICITED_ENABLE, - (AC_USRSP_EN | event)); -} - static int stac92xx_init(struct hda_codec *codec) { struct sigmatel_spec *spec = codec->spec; @@ -1429,10 +1084,9 @@ static int stac92xx_init(struct hda_codec *codec) /* set up pins */ if (spec->hp_detect) { /* Enable unsolicited responses on the HP widget */ - for (i = 0; i < cfg->hp_outs; i++) - enable_pin_detect(codec, cfg->hp_pins[i], - STAC_HP_EVENT); - stac92xx_auto_init_hp_out(codec); + snd_hda_codec_write(codec, cfg->hp_pin, 0, + AC_VERB_SET_UNSOLICITED_ENABLE, + STAC_UNSOL_ENABLE); /* fake event to set up pins */ codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); } else { @@ -1477,9 +1131,6 @@ static void stac92xx_free(struct hda_codec *codec) kfree(spec->kctl_alloc); } - if (spec->bios_pin_configs) - kfree(spec->bios_pin_configs); - kfree(spec); } @@ -1488,8 +1139,6 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, { unsigned int pin_ctl = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); - if (flag == AC_PINCTL_OUT_EN && (pin_ctl & AC_PINCTL_IN_EN)) - return; snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_ctl | flag); @@ -1505,57 +1154,33 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, pin_ctl & ~flag); } -static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) -{ - if (!nid) - return 0; - if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00) - & (1 << 31)) - return 1; - return 0; -} - -static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) +static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) { struct sigmatel_spec *spec = codec->spec; struct auto_pin_cfg *cfg = &spec->autocfg; int i, presence; - presence = 0; - for (i = 0; i < cfg->hp_outs; i++) { - presence = get_pin_presence(codec, cfg->hp_pins[i]); - if (presence) - break; - } + if ((res >> 26) != STAC_HP_EVENT) + return; + + presence = snd_hda_codec_read(codec, cfg->hp_pin, 0, + AC_VERB_GET_PIN_SENSE, 0x00) >> 31; if (presence) { /* disable lineouts, enable hp */ for (i = 0; i < cfg->line_outs; i++) stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], AC_PINCTL_OUT_EN); - for (i = 0; i < cfg->speaker_outs; i++) - stac92xx_reset_pinctl(codec, cfg->speaker_pins[i], - AC_PINCTL_OUT_EN); + stac92xx_set_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); } else { /* enable lineouts, disable hp */ for (i = 0; i < cfg->line_outs; i++) stac92xx_set_pinctl(codec, cfg->line_out_pins[i], AC_PINCTL_OUT_EN); - for (i = 0; i < cfg->speaker_outs; i++) - stac92xx_set_pinctl(codec, cfg->speaker_pins[i], - AC_PINCTL_OUT_EN); + stac92xx_reset_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); } } -static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) -{ - switch (res >> 26) { - case STAC_HP_EVENT: - stac92xx_hp_detect(codec, res); - break; - } -} - #ifdef CONFIG_PM static int stac92xx_resume(struct hda_codec *codec) { @@ -1563,7 +1188,6 @@ static int stac92xx_resume(struct hda_codec *codec) int i; stac92xx_init(codec); - stac92xx_set_config_regs(codec); for (i = 0; i < spec->num_mixers; i++) snd_hda_resume_ctls(codec, spec->mixers[i]); if (spec->multiout.dig_out_nid) @@ -1596,18 +1220,12 @@ static int patch_stac9200(struct hda_codec *codec) return -ENOMEM; codec->spec = spec; - spec->num_pins = 8; - spec->pin_nids = stac9200_pin_nids; spec->board_config = snd_hda_check_board_config(codec, stac9200_cfg_tbl); - if (spec->board_config < 0) { - snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); - err = stac92xx_save_bios_config_regs(codec); - if (err < 0) { - stac92xx_free(codec); - return err; - } - spec->pin_configs = spec->bios_pin_configs; - } else { + if (spec->board_config < 0) + snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); + else { + spec->num_pins = 8; + spec->pin_nids = stac9200_pin_nids; spec->pin_configs = stac9200_brd_tbl[spec->board_config]; stac92xx_set_config_regs(codec); } @@ -1643,19 +1261,13 @@ static int patch_stac922x(struct hda_codec *codec) return -ENOMEM; codec->spec = spec; - spec->num_pins = 10; - spec->pin_nids = stac922x_pin_nids; spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl); - if (spec->board_config < 0) { - snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " - "using BIOS defaults\n"); - err = stac92xx_save_bios_config_regs(codec); - if (err < 0) { - stac92xx_free(codec); - return err; - } - spec->pin_configs = spec->bios_pin_configs; - } else if (stac922x_brd_tbl[spec->board_config] != NULL) { + if (spec->board_config < 0) + snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " + "using BIOS defaults\n"); + else if (stac922x_brd_tbl[spec->board_config] != NULL) { + spec->num_pins = 10; + spec->pin_nids = stac922x_pin_nids; spec->pin_configs = stac922x_brd_tbl[spec->board_config]; stac92xx_set_config_regs(codec); } @@ -1669,6 +1281,25 @@ static int patch_stac922x(struct hda_codec *codec) spec->multiout.dac_nids = spec->dac_nids; + switch (spec->board_config) { + case STAC_D965_2112: + spec->adc_nids = stac9227_adc_nids; + spec->mux_nids = stac9227_mux_nids; +#if 0 + spec->multiout.dac_nids = d965_2112_dac_nids; + spec->multiout.num_dacs = ARRAY_SIZE(d965_2112_dac_nids); +#endif + spec->init = d965_2112_core_init; + spec->mixer = stac9227_mixer; + break; + case STAC_D965_284B: + spec->adc_nids = stac9227_adc_nids; + spec->mux_nids = stac9227_mux_nids; + spec->init = stac9227_core_init; + spec->mixer = stac9227_mixer; + break; + } + err = stac92xx_parse_auto_config(codec, 0x08, 0x09); if (err < 0) { stac92xx_free(codec); @@ -1693,94 +1324,26 @@ static int patch_stac927x(struct hda_codec *codec) return -ENOMEM; codec->spec = spec; - spec->num_pins = 14; - spec->pin_nids = stac927x_pin_nids; spec->board_config = snd_hda_check_board_config(codec, stac927x_cfg_tbl); - if (spec->board_config < 0) { + if (spec->board_config < 0) snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n"); - err = stac92xx_save_bios_config_regs(codec); - if (err < 0) { - stac92xx_free(codec); - return err; - } - spec->pin_configs = spec->bios_pin_configs; - } else if (stac927x_brd_tbl[spec->board_config] != NULL) { + else { + spec->num_pins = 14; + spec->pin_nids = stac927x_pin_nids; spec->pin_configs = stac927x_brd_tbl[spec->board_config]; stac92xx_set_config_regs(codec); } - switch (spec->board_config) { - case STAC_D965_3ST: - spec->adc_nids = stac927x_adc_nids; - spec->mux_nids = stac927x_mux_nids; - spec->num_muxes = 3; - spec->init = d965_core_init; - spec->mixer = stac9227_mixer; - break; - case STAC_D965_5ST: - spec->adc_nids = stac927x_adc_nids; - spec->mux_nids = stac927x_mux_nids; - spec->num_muxes = 3; - spec->init = d965_core_init; - spec->mixer = stac9227_mixer; - break; - default: - spec->adc_nids = stac927x_adc_nids; - spec->mux_nids = stac927x_mux_nids; - spec->num_muxes = 3; - spec->init = stac927x_core_init; - spec->mixer = stac927x_mixer; - } - - spec->multiout.dac_nids = spec->dac_nids; - - err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); - if (err < 0) { - stac92xx_free(codec); - return err; - } - - codec->patch_ops = stac92xx_patch_ops; - - return 0; -} - -static int patch_stac9205(struct hda_codec *codec) -{ - struct sigmatel_spec *spec; - int err; - - spec = kzalloc(sizeof(*spec), GFP_KERNEL); - if (spec == NULL) - return -ENOMEM; - - codec->spec = spec; - spec->num_pins = 14; - spec->pin_nids = stac9205_pin_nids; - spec->board_config = snd_hda_check_board_config(codec, stac9205_cfg_tbl); - if (spec->board_config < 0) { - snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); - err = stac92xx_save_bios_config_regs(codec); - if (err < 0) { - stac92xx_free(codec); - return err; - } - spec->pin_configs = spec->bios_pin_configs; - } else { - spec->pin_configs = stac9205_brd_tbl[spec->board_config]; - stac92xx_set_config_regs(codec); - } - - spec->adc_nids = stac9205_adc_nids; - spec->mux_nids = stac9205_mux_nids; + spec->adc_nids = stac927x_adc_nids; + spec->mux_nids = stac927x_mux_nids; spec->num_muxes = 3; - spec->init = stac9205_core_init; - spec->mixer = stac9205_mixer; + spec->init = stac927x_core_init; + spec->mixer = stac927x_mixer; spec->multiout.dac_nids = spec->dac_nids; - err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); + err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); if (err < 0) { stac92xx_free(codec); return err; @@ -1792,10 +1355,10 @@ static int patch_stac9205(struct hda_codec *codec) } /* - * STAC9872 hack + * STAC 7661(?) hack */ -/* static config for Sony VAIO FE550G and Sony VAIO AR */ +/* static config for Sony VAIO FE550G */ static hda_nid_t vaio_dacs[] = { 0x2 }; #define VAIO_HP_DAC 0x5 static hda_nid_t vaio_adcs[] = { 0x8 /*,0x6*/ }; @@ -1826,23 +1389,6 @@ static struct hda_verb vaio_init[] = { {} }; -static struct hda_verb vaio_ar_init[] = { - {0x0a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP <- 0x2 */ - {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Speaker <- 0x5 */ - {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ - {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ -/* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */ - {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ - {0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */ - {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ - {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ -/* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */ - {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ - {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, /* CD-in -> 0x6 */ - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Mic-in -> 0x9 */ - {} -}; - /* bind volumes of both NID 0x02 and 0x05 */ static int vaio_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -1882,38 +1428,6 @@ static int vaio_master_sw_put(struct snd_kcontrol *kcontrol, } static struct snd_kcontrol_new vaio_mixer[] = { - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Volume", - .info = snd_hda_mixer_amp_volume_info, - .get = snd_hda_mixer_amp_volume_get, - .put = vaio_master_vol_put, - .tlv = { .c = snd_hda_mixer_amp_tlv }, - .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), - }, - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Master Playback Switch", - .info = snd_hda_mixer_amp_switch_info, - .get = snd_hda_mixer_amp_switch_get, - .put = vaio_master_sw_put, - .private_value = HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), - }, - /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ - HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Capture Source", - .count = 1, - .info = stac92xx_mux_enum_info, - .get = stac92xx_mux_enum_get, - .put = stac92xx_mux_enum_put, - }, - {} -}; - -static struct snd_kcontrol_new vaio_ar_mixer[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Master Playback Volume", @@ -1933,8 +1447,6 @@ static struct snd_kcontrol_new vaio_ar_mixer[] = { /* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */ HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT), HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT), - /*HDA_CODEC_MUTE("Optical Out Switch", 0x10, 0, HDA_OUTPUT), - HDA_CODEC_VOLUME("Optical Out Volume", 0x10, 0, HDA_OUTPUT),*/ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", @@ -1946,7 +1458,7 @@ static struct snd_kcontrol_new vaio_ar_mixer[] = { {} }; -static struct hda_codec_ops stac9872_patch_ops = { +static struct hda_codec_ops stac7661_patch_ops = { .build_controls = stac92xx_build_controls, .build_pcms = stac92xx_build_pcms, .init = stac92xx_init, @@ -1956,34 +1468,23 @@ static struct hda_codec_ops stac9872_patch_ops = { #endif }; -enum { /* FE and SZ series. id=0x83847661 and subsys=0x104D0700 or 104D1000. */ - CXD9872RD_VAIO, - /* Unknown. id=0x83847662 and subsys=0x104D1200 or 104D1000. */ - STAC9872AK_VAIO, - /* Unknown. id=0x83847661 and subsys=0x104D1200. */ - STAC9872K_VAIO, - /* AR Series. id=0x83847664 and subsys=104D1300 */ - CXD9872AKD_VAIO - }; - -static struct hda_board_config stac9872_cfg_tbl[] = { - { .modelname = "vaio", .config = CXD9872RD_VAIO }, - { .modelname = "vaio-ar", .config = CXD9872AKD_VAIO }, +enum { STAC7661_VAIO }; + +static struct hda_board_config stac7661_cfg_tbl[] = { + { .modelname = "vaio", .config = STAC7661_VAIO }, { .pci_subvendor = 0x104d, .pci_subdevice = 0x81e6, - .config = CXD9872RD_VAIO }, + .config = STAC7661_VAIO }, { .pci_subvendor = 0x104d, .pci_subdevice = 0x81ef, - .config = CXD9872RD_VAIO }, - { .pci_subvendor = 0x104d, .pci_subdevice = 0x81fd, - .config = CXD9872AKD_VAIO }, + .config = STAC7661_VAIO }, {} }; -static int patch_stac9872(struct hda_codec *codec) +static int patch_stac7661(struct hda_codec *codec) { struct sigmatel_spec *spec; int board_config; - board_config = snd_hda_check_board_config(codec, stac9872_cfg_tbl); + board_config = snd_hda_check_board_config(codec, stac7661_cfg_tbl); if (board_config < 0) /* unknown config, let generic-parser do its job... */ return snd_hda_parse_generic_codec(codec); @@ -1994,9 +1495,7 @@ static int patch_stac9872(struct hda_codec *codec) codec->spec = spec; switch (board_config) { - case CXD9872RD_VAIO: - case STAC9872AK_VAIO: - case STAC9872K_VAIO: + case STAC7661_VAIO: spec->mixer = vaio_mixer; spec->init = vaio_init; spec->multiout.max_channels = 2; @@ -2008,22 +1507,9 @@ static int patch_stac9872(struct hda_codec *codec) spec->input_mux = &vaio_mux; spec->mux_nids = vaio_mux_nids; break; - - case CXD9872AKD_VAIO: - spec->mixer = vaio_ar_mixer; - spec->init = vaio_ar_init; - spec->multiout.max_channels = 2; - spec->multiout.num_dacs = ARRAY_SIZE(vaio_dacs); - spec->multiout.dac_nids = vaio_dacs; - spec->multiout.hp_nid = VAIO_HP_DAC; - spec->num_adcs = ARRAY_SIZE(vaio_adcs); - spec->adc_nids = vaio_adcs; - spec->input_mux = &vaio_mux; - spec->mux_nids = vaio_mux_nids; - break; } - codec->patch_ops = stac9872_patch_ops; + codec->patch_ops = stac7661_patch_ops; return 0; } @@ -2039,12 +1525,12 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x }, { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x }, { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x }, - { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac927x }, - { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac927x }, - { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac927x }, - { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac927x }, - { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac927x }, - { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac927x }, + { .id = 0x83847618, .name = "STAC9227", .patch = patch_stac922x }, + { .id = 0x83847619, .name = "STAC9227", .patch = patch_stac922x }, + { .id = 0x83847616, .name = "STAC9228", .patch = patch_stac922x }, + { .id = 0x83847617, .name = "STAC9228", .patch = patch_stac922x }, + { .id = 0x83847614, .name = "STAC9229", .patch = patch_stac922x }, + { .id = 0x83847615, .name = "STAC9229", .patch = patch_stac922x }, { .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x }, { .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x }, { .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x }, @@ -2055,20 +1541,6 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = { { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, - /* The following does not take into account .id=0x83847661 when subsys = - * 104D0C00 which is STAC9225s. Because of this, some SZ Notebooks are - * currently not fully supported. - */ - { .id = 0x83847661, .name = "CXD9872RD/K", .patch = patch_stac9872 }, - { .id = 0x83847662, .name = "STAC9872AK", .patch = patch_stac9872 }, - { .id = 0x83847664, .name = "CXD9872AKD", .patch = patch_stac9872 }, - { .id = 0x838476a0, .name = "STAC9205", .patch = patch_stac9205 }, - { .id = 0x838476a1, .name = "STAC9205D", .patch = patch_stac9205 }, - { .id = 0x838476a2, .name = "STAC9204", .patch = patch_stac9205 }, - { .id = 0x838476a3, .name = "STAC9204D", .patch = patch_stac9205 }, - { .id = 0x838476a4, .name = "STAC9255", .patch = patch_stac9205 }, - { .id = 0x838476a5, .name = "STAC9255D", .patch = patch_stac9205 }, - { .id = 0x838476a6, .name = "STAC9254", .patch = patch_stac9205 }, - { .id = 0x838476a7, .name = "STAC9254D", .patch = patch_stac9205 }, + { .id = 0x83847661, .name = "STAC7661", .patch = patch_stac7661 }, {} /* terminator */ }; diff --git a/trunk/sound/pci/ice1712/aureon.c b/trunk/sound/pci/ice1712/aureon.c index 9e76cebd2d22..9492f3d2455b 100644 --- a/trunk/sound/pci/ice1712/aureon.c +++ b/trunk/sound/pci/ice1712/aureon.c @@ -60,7 +60,6 @@ #include "ice1712.h" #include "envy24ht.h" #include "aureon.h" -#include /* WM8770 registers */ #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ @@ -661,12 +660,6 @@ static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e return change; } -static DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); -static DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1); -static DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0); -static DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0); -static DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0); - /* * Logarithmic volume values for WM8770 * Computed as 20 * Log10(255 / x) @@ -1416,13 +1409,10 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Master Playback Volume", .info = wm_master_vol_info, .get = wm_master_vol_get, - .put = wm_master_vol_put, - .tlv = { .p = db_scale_wm_dac } + .put = wm_master_vol_put }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1434,14 +1424,11 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Front Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (2 << 8) | 0, - .tlv = { .p = db_scale_wm_dac } + .private_value = (2 << 8) | 0 }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1453,14 +1440,11 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Rear Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (2 << 8) | 2, - .tlv = { .p = db_scale_wm_dac } + .private_value = (2 << 8) | 2 }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1472,14 +1456,11 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Center Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (1 << 8) | 4, - .tlv = { .p = db_scale_wm_dac } + .private_value = (1 << 8) | 4 }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1491,14 +1472,11 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "LFE Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (1 << 8) | 5, - .tlv = { .p = db_scale_wm_dac } + .private_value = (1 << 8) | 5 }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1510,14 +1488,11 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Side Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (2 << 8) | 6, - .tlv = { .p = db_scale_wm_dac } + .private_value = (2 << 8) | 6 } }; @@ -1531,13 +1506,10 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "PCM Playback Volume", .info = wm_pcm_vol_info, .get = wm_pcm_vol_get, - .put = wm_pcm_vol_put, - .tlv = { .p = db_scale_wm_pcm } + .put = wm_pcm_vol_put }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1548,13 +1520,10 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Capture Volume", .info = wm_adc_vol_info, .get = wm_adc_vol_get, - .put = wm_adc_vol_put, - .tlv = { .p = db_scale_wm_adc } + .put = wm_adc_vol_put }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1598,14 +1567,11 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "AC97 Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_MASTER|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_master } + .private_value = AC97_MASTER|AUREON_AC97_STEREO }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1617,14 +1583,11 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "CD Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_CD|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } + .private_value = AC97_CD|AUREON_AC97_STEREO }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1636,14 +1599,11 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Aux Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_AUX|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } + .private_value = AC97_AUX|AUREON_AC97_STEREO }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1655,14 +1615,11 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Line Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_LINE|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } + .private_value = AC97_LINE|AUREON_AC97_STEREO }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1674,14 +1631,11 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Mic Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_MIC, - .tlv = { .p = db_scale_ac97_gain } + .private_value = AC97_MIC }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1703,14 +1657,11 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "AC97 Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_MASTER|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_master } + .private_value = AC97_MASTER|AUREON_AC97_STEREO }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1722,14 +1673,11 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "CD Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_AUX|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } + .private_value = AC97_AUX|AUREON_AC97_STEREO }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1737,18 +1685,15 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { .info = aureon_ac97_mute_info, .get = aureon_ac97_mute_get, .put = aureon_ac97_mute_put, - .private_value = AC97_CD + .private_value = AC97_CD, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Phono Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_CD|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } + .private_value = AC97_CD|AUREON_AC97_STEREO }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1760,14 +1705,11 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Line Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_LINE|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } + .private_value = AC97_LINE|AUREON_AC97_STEREO }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1779,14 +1721,11 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Mic Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_MIC, - .tlv = { .p = db_scale_ac97_gain } + .private_value = AC97_MIC }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -1805,14 +1744,11 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Aux Playback Volume", .info = aureon_ac97_vol_info, .get = aureon_ac97_vol_get, .put = aureon_ac97_vol_put, - .private_value = AC97_VIDEO|AUREON_AC97_STEREO, - .tlv = { .p = db_scale_ac97_gain } + .private_value = AC97_VIDEO|AUREON_AC97_STEREO }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, diff --git a/trunk/sound/pci/ice1712/ice1712.c b/trunk/sound/pci/ice1712/ice1712.c index dc69392eafa3..bf20858d9f19 100644 --- a/trunk/sound/pci/ice1712/ice1712.c +++ b/trunk/sound/pci/ice1712/ice1712.c @@ -62,7 +62,6 @@ #include #include #include -#include #include @@ -1378,7 +1377,6 @@ static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struc return change; } -static DECLARE_TLV_DB_SCALE(db_scale_playback, -14400, 150, 0); static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = { { @@ -1392,15 +1390,12 @@ static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Multi Playback Volume", .info = snd_ice1712_pro_mixer_volume_info, .get = snd_ice1712_pro_mixer_volume_get, .put = snd_ice1712_pro_mixer_volume_put, .private_value = 0, .count = 10, - .tlv = { .p = db_scale_playback } }, }; @@ -1425,14 +1420,11 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitd static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "H/W Multi Capture Volume", .info = snd_ice1712_pro_mixer_volume_info, .get = snd_ice1712_pro_mixer_volume_get, .put = snd_ice1712_pro_mixer_volume_put, .private_value = 10, - .tlv = { .p = db_scale_playback } }; static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = { @@ -1865,7 +1857,7 @@ static int snd_ice1712_pro_internal_clock_put(struct snd_kcontrol *kcontrol, { struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); static unsigned int xrate[13] = { - 8000, 9600, 11025, 12000, 16000, 22050, 24000, + 8000, 9600, 11025, 12000, 1600, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000 }; unsigned char oval; @@ -1932,7 +1924,7 @@ static int snd_ice1712_pro_internal_clock_default_get(struct snd_kcontrol *kcont { int val; static unsigned int xrate[13] = { - 8000, 9600, 11025, 12000, 16000, 22050, 24000, + 8000, 9600, 11025, 12000, 1600, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000 }; @@ -1949,7 +1941,7 @@ static int snd_ice1712_pro_internal_clock_default_put(struct snd_kcontrol *kcont struct snd_ctl_elem_value *ucontrol) { static unsigned int xrate[13] = { - 8000, 9600, 11025, 12000, 16000, 22050, 24000, + 8000, 9600, 11025, 12000, 1600, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000 }; unsigned char oval; diff --git a/trunk/sound/pci/ice1712/phase.c b/trunk/sound/pci/ice1712/phase.c index e08d73f4ff85..502da1c8b5f7 100644 --- a/trunk/sound/pci/ice1712/phase.c +++ b/trunk/sound/pci/ice1712/phase.c @@ -46,7 +46,6 @@ #include "ice1712.h" #include "envy24ht.h" #include "phase.h" -#include /* WM8770 registers */ #define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */ @@ -697,9 +696,6 @@ static int phase28_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ct return 0; } -static DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); -static DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1); - static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -710,13 +706,10 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Master Playback Volume", .info = wm_master_vol_info, .get = wm_master_vol_get, - .put = wm_master_vol_put, - .tlv = { .p = db_scale_wm_dac } + .put = wm_master_vol_put }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -728,14 +721,11 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Front Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (2 << 8) | 0, - .tlv = { .p = db_scale_wm_dac } + .private_value = (2 << 8) | 0 }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -747,14 +737,11 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Rear Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (2 << 8) | 2, - .tlv = { .p = db_scale_wm_dac } + .private_value = (2 << 8) | 2 }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -766,14 +753,11 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Center Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (1 << 8) | 4, - .tlv = { .p = db_scale_wm_dac } + .private_value = (1 << 8) | 4 }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -785,14 +769,11 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "LFE Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (1 << 8) | 5, - .tlv = { .p = db_scale_wm_dac } + .private_value = (1 << 8) | 5 }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -804,14 +785,11 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Side Playback Volume", .info = wm_vol_info, .get = wm_vol_get, .put = wm_vol_put, - .private_value = (2 << 8) | 6, - .tlv = { .p = db_scale_wm_dac } + .private_value = (2 << 8) | 6 } }; @@ -825,13 +803,10 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "PCM Playback Volume", .info = wm_pcm_vol_info, .get = wm_pcm_vol_get, - .put = wm_pcm_vol_put, - .tlv = { .p = db_scale_wm_pcm } + .put = wm_pcm_vol_put }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, diff --git a/trunk/sound/pci/ice1712/pontis.c b/trunk/sound/pci/ice1712/pontis.c index 6c74c2d2e7f3..0efcad9260a5 100644 --- a/trunk/sound/pci/ice1712/pontis.c +++ b/trunk/sound/pci/ice1712/pontis.c @@ -31,7 +31,6 @@ #include #include -#include #include "ice1712.h" #include "envy24ht.h" @@ -565,8 +564,6 @@ static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el return changed; } -static DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1); - /* * mixers */ @@ -574,23 +571,17 @@ static DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1); static struct snd_kcontrol_new pontis_controls[] __devinitdata = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "PCM Playback Volume", .info = wm_dac_vol_info, .get = wm_dac_vol_get, .put = wm_dac_vol_put, - .tlv = { .p = db_scale_volume }, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Capture Volume", .info = wm_adc_vol_info, .get = wm_adc_vol_get, .put = wm_adc_vol_put, - .tlv = { .p = db_scale_volume }, }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, diff --git a/trunk/sound/pci/ice1712/prodigy192.c b/trunk/sound/pci/ice1712/prodigy192.c index 41b2605daa3a..fdb5cb8fac97 100644 --- a/trunk/sound/pci/ice1712/prodigy192.c +++ b/trunk/sound/pci/ice1712/prodigy192.c @@ -35,7 +35,6 @@ #include "envy24ht.h" #include "prodigy192.h" #include "stac946x.h" -#include static inline void stac9460_put(struct snd_ice1712 *ice, int reg, unsigned char val) { @@ -357,9 +356,6 @@ static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl } #endif -static DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0); -static DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0); - /* * mixers */ @@ -372,18 +368,14 @@ static struct snd_kcontrol_new stac_controls[] __devinitdata = { .get = stac9460_dac_mute_get, .put = stac9460_dac_mute_put, .private_value = 1, - .tlv = { .p = db_scale_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Master Playback Volume", .info = stac9460_dac_vol_info, .get = stac9460_dac_vol_get, .put = stac9460_dac_vol_put, .private_value = 1, - .tlv = { .p = db_scale_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -395,14 +387,11 @@ static struct snd_kcontrol_new stac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "DAC Volume", .count = 6, .info = stac9460_dac_vol_info, .get = stac9460_dac_vol_get, .put = stac9460_dac_vol_put, - .tlv = { .p = db_scale_dac } }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -415,14 +404,11 @@ static struct snd_kcontrol_new stac_controls[] __devinitdata = { }, { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "ADC Volume", .count = 1, .info = stac9460_adc_vol_info, .get = stac9460_adc_vol_get, .put = stac9460_adc_vol_put, - .tlv = { .p = db_scale_adc } }, #if 0 { diff --git a/trunk/sound/pci/ice1712/revo.c b/trunk/sound/pci/ice1712/revo.c index bf98ea34feb0..fec9440cb310 100644 --- a/trunk/sound/pci/ice1712/revo.c +++ b/trunk/sound/pci/ice1712/revo.c @@ -87,33 +87,16 @@ static void revo_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) * initialize the chips on M-Audio Revolution cards */ -#define AK_DAC(xname,xch) { .name = xname, .num_channels = xch } +static unsigned int revo71_num_stereo_front[] = {2}; +static char *revo71_channel_names_front[] = {"PCM Playback Volume"}; -static struct snd_akm4xxx_dac_channel revo71_front[] = { - AK_DAC("PCM Playback Volume", 2) -}; - -static struct snd_akm4xxx_dac_channel revo71_surround[] = { - AK_DAC("PCM Center Playback Volume", 1), - AK_DAC("PCM LFE Playback Volume", 1), - AK_DAC("PCM Side Playback Volume", 2), - AK_DAC("PCM Rear Playback Volume", 2), -}; +static unsigned int revo71_num_stereo_surround[] = {1, 1, 2, 2}; +static char *revo71_channel_names_surround[] = {"PCM Center Playback Volume", "PCM LFE Playback Volume", + "PCM Side Playback Volume", "PCM Rear Playback Volume"}; -static struct snd_akm4xxx_dac_channel revo51_dac[] = { - AK_DAC("PCM Playback Volume", 2), - AK_DAC("PCM Center Playback Volume", 1), - AK_DAC("PCM LFE Playback Volume", 1), - AK_DAC("PCM Rear Playback Volume", 2), -}; - -static struct snd_akm4xxx_adc_channel revo51_adc[] = { - { - .name = "PCM Capture Volume", - .switch_name = "PCM Capture Switch", - .num_channels = 2 - }, -}; +static unsigned int revo51_num_stereo[] = {2, 1, 1, 2}; +static char *revo51_channel_names[] = {"PCM Playback Volume", "PCM Center Playback Volume", + "PCM LFE Playback Volume", "PCM Rear Playback Volume"}; static struct snd_akm4xxx akm_revo_front __devinitdata = { .type = SND_AK4381, @@ -121,7 +104,8 @@ static struct snd_akm4xxx akm_revo_front __devinitdata = { .ops = { .set_rate_val = revo_set_rate_val }, - .dac_info = revo71_front, + .num_stereo = revo71_num_stereo_front, + .channel_names = revo71_channel_names_front }; static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = { @@ -143,7 +127,8 @@ static struct snd_akm4xxx akm_revo_surround __devinitdata = { .ops = { .set_rate_val = revo_set_rate_val }, - .dac_info = revo71_surround, + .num_stereo = revo71_num_stereo_surround, + .channel_names = revo71_channel_names_surround }; static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { @@ -164,7 +149,8 @@ static struct snd_akm4xxx akm_revo51 __devinitdata = { .ops = { .set_rate_val = revo_set_rate_val }, - .dac_info = revo51_dac, + .num_stereo = revo51_num_stereo, + .channel_names = revo51_channel_names }; static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { @@ -173,25 +159,7 @@ static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { .data_mask = VT1724_REVO_CDOUT, .clk_mask = VT1724_REVO_CCLK, .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, - .cs_addr = VT1724_REVO_CS1 | VT1724_REVO_CS2, - .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, - .add_flags = VT1724_REVO_CCLK, /* high at init */ - .mask_flags = 0, -}; - -static struct snd_akm4xxx akm_revo51_adc __devinitdata = { - .type = SND_AK5365, - .num_adcs = 2, - .adc_info = revo51_adc, -}; - -static struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = { - .caddr = 2, - .cif = 0, - .data_mask = VT1724_REVO_CDOUT, - .clk_mask = VT1724_REVO_CCLK, - .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, - .cs_addr = VT1724_REVO_CS0 | VT1724_REVO_CS2, + .cs_addr = 0, .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, .add_flags = VT1724_REVO_CCLK, /* high at init */ .mask_flags = 0, @@ -234,13 +202,9 @@ static int __devinit revo_init(struct snd_ice1712 *ice) snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE); break; case VT1724_SUBDEVICE_REVOLUTION51: - ice->akm_codecs = 2; + ice->akm_codecs = 1; if ((err = snd_ice1712_akm4xxx_init(ak, &akm_revo51, &akm_revo51_priv, ice)) < 0) return err; - err = snd_ice1712_akm4xxx_init(ak + 1, &akm_revo51_adc, - &akm_revo51_adc_priv, ice); - if (err < 0) - return err; /* unmute all codecs - needed! */ snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE); break; diff --git a/trunk/sound/pci/ice1712/revo.h b/trunk/sound/pci/ice1712/revo.h index efbb86ec3289..dea52ea219df 100644 --- a/trunk/sound/pci/ice1712/revo.h +++ b/trunk/sound/pci/ice1712/revo.h @@ -42,7 +42,7 @@ extern struct snd_ice1712_card_info snd_vt1724_revo_cards[]; #define VT1724_REVO_CCLK 0x02 #define VT1724_REVO_CDIN 0x04 /* not used */ #define VT1724_REVO_CDOUT 0x08 -#define VT1724_REVO_CS0 0x10 /* AK5365 chipselect for Rev. 5.1 */ +#define VT1724_REVO_CS0 0x10 /* not used */ #define VT1724_REVO_CS1 0x20 /* front AKM4381 chipselect */ #define VT1724_REVO_CS2 0x40 /* surround AKM4355 chipselect */ #define VT1724_REVO_MUTE (1<<22) /* 0 = all mute, 1 = normal operation */ diff --git a/trunk/sound/pci/intel8x0.c b/trunk/sound/pci/intel8x0.c index 72dbaedcbdf5..6874263f1681 100644 --- a/trunk/sound/pci/intel8x0.c +++ b/trunk/sound/pci/intel8x0.c @@ -2251,16 +2251,6 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) /* ACLink on, 2 channels */ cnt = igetdword(chip, ICHREG(GLOB_CNT)); cnt &= ~(ICH_ACLINK | ICH_PCM_246_MASK); -#ifdef CONFIG_SND_AC97_POWER_SAVE - /* do cold reset - the full ac97 powerdown may leave the controller - * in a warm state but actually it cannot communicate with the codec. - */ - iputdword(chip, ICHREG(GLOB_CNT), cnt & ~ICH_AC97COLD); - cnt = igetdword(chip, ICHREG(GLOB_CNT)); - udelay(10); - iputdword(chip, ICHREG(GLOB_CNT), cnt | ICH_AC97COLD); - msleep(1); -#else /* finish cold or do warm reset */ cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM; iputdword(chip, ICHREG(GLOB_CNT), cnt); @@ -2275,7 +2265,6 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing) return -EIO; __ok: -#endif if (probing) { /* wait for any codec ready status. * Once it becomes ready it should remain ready @@ -2496,7 +2485,7 @@ static int intel8x0_resume(struct pci_dev *pci) card->shortname, chip); chip->irq = pci->irq; synchronize_irq(chip->irq); - snd_intel8x0_chip_init(chip, 0); + snd_intel8x0_chip_init(chip, 1); /* re-initialize mixer stuff */ if (chip->device_type == DEVICE_INTEL_ICH4) { @@ -2626,7 +2615,6 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip) /* not 48000Hz, tuning the clock.. */ chip->ac97_bus->clock = (chip->ac97_bus->clock * 48000) / pos; printk(KERN_INFO "intel8x0: clocking to %d\n", chip->ac97_bus->clock); - snd_ac97_update_power(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 0); } #ifdef CONFIG_PROC_FS diff --git a/trunk/sound/pci/intel8x0m.c b/trunk/sound/pci/intel8x0m.c index 268e2f7241ea..91850281f89b 100644 --- a/trunk/sound/pci/intel8x0m.c +++ b/trunk/sound/pci/intel8x0m.c @@ -1045,8 +1045,6 @@ static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state) for (i = 0; i < chip->pcm_devs; i++) snd_pcm_suspend_all(chip->pcm[i]); snd_ac97_suspend(chip->ac97); - if (chip->irq >= 0) - free_irq(chip->irq, chip); pci_disable_device(pci); pci_save_state(pci); return 0; @@ -1060,9 +1058,6 @@ static int intel8x0m_resume(struct pci_dev *pci) pci_restore_state(pci); pci_enable_device(pci); pci_set_master(pci); - request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_DISABLED|IRQF_SHARED, - card->shortname, chip); - chip->irq = pci->irq; snd_intel8x0_chip_init(chip, 0); snd_ac97_resume(chip->ac97); diff --git a/trunk/sound/pci/mixart/mixart.c b/trunk/sound/pci/mixart/mixart.c index 216aee5f93e7..cc43ecd67906 100644 --- a/trunk/sound/pci/mixart/mixart.c +++ b/trunk/sound/pci/mixart/mixart.c @@ -1109,13 +1109,13 @@ static long long snd_mixart_BA0_llseek(struct snd_info_entry *entry, offset = offset & ~3; /* 4 bytes aligned */ switch(orig) { - case SEEK_SET: + case 0: /* SEEK_SET */ file->f_pos = offset; break; - case SEEK_CUR: + case 1: /* SEEK_CUR */ file->f_pos += offset; break; - case SEEK_END: /* offset is negative */ + case 2: /* SEEK_END, offset is negative */ file->f_pos = MIXART_BA0_SIZE + offset; break; default: @@ -1135,13 +1135,13 @@ static long long snd_mixart_BA1_llseek(struct snd_info_entry *entry, offset = offset & ~3; /* 4 bytes aligned */ switch(orig) { - case SEEK_SET: + case 0: /* SEEK_SET */ file->f_pos = offset; break; - case SEEK_CUR: + case 1: /* SEEK_CUR */ file->f_pos += offset; break; - case SEEK_END: /* offset is negative */ + case 2: /* SEEK_END, offset is negative */ file->f_pos = MIXART_BA1_SIZE + offset; break; default: diff --git a/trunk/sound/pci/mixart/mixart_mixer.c b/trunk/sound/pci/mixart/mixart_mixer.c index 13de0f71d4b7..ed47b732c103 100644 --- a/trunk/sound/pci/mixart/mixart_mixer.c +++ b/trunk/sound/pci/mixart/mixart_mixer.c @@ -31,7 +31,6 @@ #include "mixart_core.h" #include "mixart_hwdep.h" #include -#include #include "mixart_mixer.h" static u32 mixart_analog_level[256] = { @@ -389,17 +388,12 @@ static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e return changed; } -static DECLARE_TLV_DB_SCALE(db_scale_analog, -9600, 50, 0); - static struct snd_kcontrol_new mixart_control_analog_level = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), /* name will be filled later */ .info = mixart_analog_vol_info, .get = mixart_analog_vol_get, .put = mixart_analog_vol_put, - .tlv = { .p = db_scale_analog }, }; /* shared */ @@ -872,19 +866,14 @@ static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem return changed; } -static DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0); - static struct snd_kcontrol_new snd_mixart_pcm_vol = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), /* name will be filled later */ /* count will be filled later */ .info = mixart_digital_vol_info, /* shared */ .get = mixart_pcm_vol_get, .put = mixart_pcm_vol_put, - .tlv = { .p = db_scale_digital }, }; @@ -995,13 +984,10 @@ static int mixart_monitor_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ static struct snd_kcontrol_new mixart_control_monitor_vol = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Monitoring Volume", .info = mixart_digital_vol_info, /* shared */ .get = mixart_monitor_vol_get, .put = mixart_monitor_vol_put, - .tlv = { .p = db_scale_digital }, }; /* diff --git a/trunk/sound/pci/pcxhr/pcxhr_mixer.c b/trunk/sound/pci/pcxhr/pcxhr_mixer.c index b133ad9e095e..94e63a1e90d9 100644 --- a/trunk/sound/pci/pcxhr/pcxhr_mixer.c +++ b/trunk/sound/pci/pcxhr/pcxhr_mixer.c @@ -31,7 +31,6 @@ #include "pcxhr_hwdep.h" #include "pcxhr_core.h" #include -#include #include #include "pcxhr_mixer.h" @@ -44,9 +43,6 @@ #define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */ #define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */ -static DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 0); -static DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -12800, 100, 0); - static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel) { int err, vol; @@ -134,13 +130,10 @@ static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol, static struct snd_kcontrol_new pcxhr_control_analog_level = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), /* name will be filled later */ .info = pcxhr_analog_vol_info, .get = pcxhr_analog_vol_get, .put = pcxhr_analog_vol_put, - /* tlv will be filled later */ }; /* shared */ @@ -195,7 +188,6 @@ static struct snd_kcontrol_new pcxhr_control_output_switch = { #define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */ #define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */ -static DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0); #define MORE_THAN_ONE_STREAM_LEVEL 0x000001 #define VALID_STREAM_PAN_LEVEL_MASK 0x800000 @@ -351,14 +343,11 @@ static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol, static struct snd_kcontrol_new snd_pcxhr_pcm_vol = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), /* name will be filled later */ /* count will be filled later */ .info = pcxhr_digital_vol_info, /* shared */ .get = pcxhr_pcm_vol_get, .put = pcxhr_pcm_vol_put, - .tlv = { .p = db_scale_digital }, }; @@ -444,13 +433,10 @@ static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol, static struct snd_kcontrol_new pcxhr_control_monitor_vol = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Monitoring Volume", .info = pcxhr_digital_vol_info, /* shared */ .get = pcxhr_monitor_vol_get, .put = pcxhr_monitor_vol_put, - .tlv = { .p = db_scale_digital }, }; /* @@ -942,7 +928,6 @@ int pcxhr_create_mixer(struct pcxhr_mgr *mgr) temp = pcxhr_control_analog_level; temp.name = "Master Playback Volume"; temp.private_value = 0; /* playback */ - temp.tlv.p = db_scale_analog_playback; if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) return err; /* output mute controls */ @@ -978,7 +963,6 @@ int pcxhr_create_mixer(struct pcxhr_mgr *mgr) temp = pcxhr_control_analog_level; temp.name = "Master Capture Volume"; temp.private_value = 1; /* capture */ - temp.tlv.p = db_scale_analog_capture; if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0) return err; diff --git a/trunk/sound/pci/riptide/riptide.c b/trunk/sound/pci/riptide/riptide.c index fe210c853442..f435fcd6dca9 100644 --- a/trunk/sound/pci/riptide/riptide.c +++ b/trunk/sound/pci/riptide/riptide.c @@ -673,13 +673,9 @@ static struct lbuspath lbus_rec_path = { #define FIRMWARE_VERSIONS 1 static union firmware_version firmware_versions[] = { { - .firmware = { - .ASIC = 3, - .CODEC = 2, - .AUXDSP = 3, - .PROG = 773, - }, - }, + .firmware.ASIC = 3,.firmware.CODEC = 2, + .firmware.AUXDSP = 3,.firmware.PROG = 773, + }, }; static u32 atoh(unsigned char *in, unsigned int len) diff --git a/trunk/sound/pci/rme9652/hdsp.c b/trunk/sound/pci/rme9652/hdsp.c index d3e07de433b0..e5a52da77b85 100644 --- a/trunk/sound/pci/rme9652/hdsp.c +++ b/trunk/sound/pci/rme9652/hdsp.c @@ -726,36 +726,22 @@ static int hdsp_get_iobox_version (struct hdsp *hdsp) } -#ifdef HDSP_FW_LOADER -static int __devinit hdsp_request_fw_loader(struct hdsp *hdsp); -#endif - -static int hdsp_check_for_firmware (struct hdsp *hdsp, int load_on_demand) +static int hdsp_check_for_firmware (struct hdsp *hdsp, int show_err) { - if (hdsp->io_type == H9652 || hdsp->io_type == H9632) - return 0; + if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0; if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) { + snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n"); hdsp->state &= ~HDSP_FirmwareLoaded; - if (! load_on_demand) + if (! show_err) return -EIO; - snd_printk(KERN_ERR "Hammerfall-DSP: firmware not present.\n"); /* try to load firmware */ - if (! (hdsp->state & HDSP_FirmwareCached)) { -#ifdef HDSP_FW_LOADER - if (! hdsp_request_fw_loader(hdsp)) - return 0; -#endif - snd_printk(KERN_ERR - "Hammerfall-DSP: No firmware loaded nor " - "cached, please upload firmware.\n"); - return -EIO; - } - if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) { - snd_printk(KERN_ERR - "Hammerfall-DSP: Firmware loading from " - "cache failed, please upload manually.\n"); - return -EIO; + if (hdsp->state & HDSP_FirmwareCached) { + if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) + snd_printk(KERN_ERR "Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n"); + } else { + snd_printk(KERN_ERR "Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n"); } + return -EIO; } return 0; } @@ -3195,16 +3181,8 @@ snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) return; } } else { - int err = -EINVAL; -#ifdef HDSP_FW_LOADER - err = hdsp_request_fw_loader(hdsp); -#endif - if (err < 0) { - snd_iprintf(buffer, - "No firmware loaded nor cached, " - "please upload firmware.\n"); - return; - } + snd_iprintf(buffer, "No firmware loaded nor cached, please upload firmware.\n"); + return; } } @@ -3873,7 +3851,7 @@ static int snd_hdsp_trigger(struct snd_pcm_substream *substream, int cmd) if (hdsp_check_for_iobox (hdsp)) return -EIO; - if (hdsp_check_for_firmware(hdsp, 0)) /* no auto-loading in trigger */ + if (hdsp_check_for_firmware(hdsp, 1)) return -EIO; spin_lock(&hdsp->lock); diff --git a/trunk/sound/pci/trident/trident_main.c b/trunk/sound/pci/trident/trident_main.c index ebbe12d78d8c..4930cc6b054d 100644 --- a/trunk/sound/pci/trident/trident_main.c +++ b/trunk/sound/pci/trident/trident_main.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include @@ -2628,8 +2627,6 @@ static int snd_trident_vol_control_get(struct snd_kcontrol *kcontrol, return 0; } -static DECLARE_TLV_DB_SCALE(db_scale_gvol, -6375, 25, 0); - static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -2656,7 +2653,6 @@ static struct snd_kcontrol_new snd_trident_vol_music_control __devinitdata = .get = snd_trident_vol_control_get, .put = snd_trident_vol_control_put, .private_value = 16, - .tlv = { .p = db_scale_gvol }, }; static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata = @@ -2667,7 +2663,6 @@ static struct snd_kcontrol_new snd_trident_vol_wave_control __devinitdata = .get = snd_trident_vol_control_get, .put = snd_trident_vol_control_put, .private_value = 0, - .tlv = { .p = db_scale_gvol }, }; /*--------------------------------------------------------------------------- @@ -2735,7 +2730,6 @@ static struct snd_kcontrol_new snd_trident_pcm_vol_control __devinitdata = .info = snd_trident_pcm_vol_control_info, .get = snd_trident_pcm_vol_control_get, .put = snd_trident_pcm_vol_control_put, - /* FIXME: no tlv yet */ }; /*--------------------------------------------------------------------------- @@ -2845,8 +2839,6 @@ static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol *kcontrol, return change; } -static DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1); - static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, @@ -2856,7 +2848,6 @@ static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata = .info = snd_trident_pcm_rvol_control_info, .get = snd_trident_pcm_rvol_control_get, .put = snd_trident_pcm_rvol_control_put, - .tlv = { .p = db_scale_crvol }, }; /*--------------------------------------------------------------------------- @@ -2912,7 +2903,6 @@ static struct snd_kcontrol_new snd_trident_pcm_cvol_control __devinitdata = .info = snd_trident_pcm_cvol_control_info, .get = snd_trident_pcm_cvol_control_get, .put = snd_trident_pcm_cvol_control_put, - .tlv = { .p = db_scale_crvol }, }; static void snd_trident_notify_pcm_change1(struct snd_card *card, diff --git a/trunk/sound/pci/via82xx.c b/trunk/sound/pci/via82xx.c index 6db3d4cc4d8d..08da9234efb3 100644 --- a/trunk/sound/pci/via82xx.c +++ b/trunk/sound/pci/via82xx.c @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include @@ -1278,18 +1277,7 @@ static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream) if (! ratep->used) ratep->rate = 0; spin_unlock_irq(&ratep->lock); - if (! ratep->rate) { - if (! viadev->direction) { - snd_ac97_update_power(chip->ac97, - AC97_PCM_FRONT_DAC_RATE, 0); - snd_ac97_update_power(chip->ac97, - AC97_PCM_SURR_DAC_RATE, 0); - snd_ac97_update_power(chip->ac97, - AC97_PCM_LFE_DAC_RATE, 0); - } else - snd_ac97_update_power(chip->ac97, - AC97_PCM_LR_ADC_RATE, 0); - } + viadev->substream = NULL; return 0; } @@ -1699,29 +1687,21 @@ static int snd_via8233_pcmdxs_volume_put(struct snd_kcontrol *kcontrol, return change; } -static DECLARE_TLV_DB_SCALE(db_scale_dxs, -9450, 150, 1); - static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = { .name = "PCM Playback Volume", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .info = snd_via8233_dxs_volume_info, .get = snd_via8233_pcmdxs_volume_get, .put = snd_via8233_pcmdxs_volume_put, - .tlv = { .p = db_scale_dxs } }; static struct snd_kcontrol_new snd_via8233_dxs_volume_control __devinitdata = { .name = "VIA DXS Playback Volume", .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .count = 4, .info = snd_via8233_dxs_volume_info, .get = snd_via8233_dxs_volume_get, .put = snd_via8233_dxs_volume_put, - .tlv = { .p = db_scale_dxs } }; /* @@ -2413,7 +2393,6 @@ static int __devinit check_dxs_list(struct pci_dev *pci, int revision) { .subvendor = 0x16f3, .subdevice = 0x6405, .action = VIA_DXS_SRC }, /* Jetway K8M8MS */ { .subvendor = 0x1734, .subdevice = 0x1078, .action = VIA_DXS_SRC }, /* FSC Amilo L7300 */ { .subvendor = 0x1734, .subdevice = 0x1093, .action = VIA_DXS_SRC }, /* FSC */ - { .subvendor = 0x1734, .subdevice = 0x10ab, .action = VIA_DXS_SRC }, /* FSC */ { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */ { .subvendor = 0x1849, .subdevice = 0x9739, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */ { .subvendor = 0x1849, .subdevice = 0x9761, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */ diff --git a/trunk/sound/pci/vx222/vx222.c b/trunk/sound/pci/vx222/vx222.c index e7cd8acab59a..9c03c6b4e490 100644 --- a/trunk/sound/pci/vx222/vx222.c +++ b/trunk/sound/pci/vx222/vx222.c @@ -26,7 +26,6 @@ #include #include #include -#include #include "vx222.h" #define CARD_NAME "VX222" @@ -73,9 +72,6 @@ MODULE_DEVICE_TABLE(pci, snd_vx222_ids); /* */ -static DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0); -static DECLARE_TLV_DB_SCALE(db_scale_akm, -7350, 50, 0); - static struct snd_vx_hardware vx222_old_hw = { .name = "VX222/Old", @@ -85,7 +81,6 @@ static struct snd_vx_hardware vx222_old_hw = { .num_ins = 1, .num_outs = 1, .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, - .output_level_db_scale = db_scale_old_vol, }; static struct snd_vx_hardware vx222_v2_hw = { @@ -97,7 +92,6 @@ static struct snd_vx_hardware vx222_v2_hw = { .num_ins = 1, .num_outs = 1, .output_level_max = VX2_AKM_LEVEL_MAX, - .output_level_db_scale = db_scale_akm, }; static struct snd_vx_hardware vx222_mic_hw = { @@ -109,7 +103,6 @@ static struct snd_vx_hardware vx222_mic_hw = { .num_ins = 1, .num_outs = 1, .output_level_max = VX2_AKM_LEVEL_MAX, - .output_level_db_scale = db_scale_akm, }; diff --git a/trunk/sound/pci/vx222/vx222_ops.c b/trunk/sound/pci/vx222/vx222_ops.c index 5e51950e05f9..9b6d345b83a6 100644 --- a/trunk/sound/pci/vx222/vx222_ops.c +++ b/trunk/sound/pci/vx222/vx222_ops.c @@ -28,7 +28,6 @@ #include #include -#include #include #include "vx222.h" @@ -846,8 +845,6 @@ static void vx2_set_input_level(struct snd_vx222 *chip) #define MIC_LEVEL_MAX 0xff -static DECLARE_TLV_DB_SCALE(db_scale_mic, -6450, 50, 0); - /* * controls API for input levels */ @@ -925,24 +922,18 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v static struct snd_kcontrol_new vx_control_input_level = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Capture Volume", .info = vx_input_level_info, .get = vx_input_level_get, .put = vx_input_level_put, - .tlv = { .p = db_scale_mic }, }; static struct snd_kcontrol_new vx_control_mic_level = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Mic Capture Volume", .info = vx_mic_level_info, .get = vx_mic_level_get, .put = vx_mic_level_put, - .tlv = { .p = db_scale_mic }, }; /* diff --git a/trunk/sound/pci/ymfpci/ymfpci_main.c b/trunk/sound/pci/ymfpci/ymfpci_main.c index 24f6fc52f898..a55b5fd7da64 100644 --- a/trunk/sound/pci/ymfpci/ymfpci_main.c +++ b/trunk/sound/pci/ymfpci/ymfpci_main.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -1478,15 +1477,11 @@ static int snd_ymfpci_put_single(struct snd_kcontrol *kcontrol, return change; } -static DECLARE_TLV_DB_LINEAR(db_scale_native, TLV_DB_GAIN_MUTE, 0); - #define YMFPCI_DOUBLE(xname, xindex, reg) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ .info = snd_ymfpci_info_double, \ .get = snd_ymfpci_get_double, .put = snd_ymfpci_put_double, \ - .private_value = reg, \ - .tlv = { .p = db_scale_native } } + .private_value = reg } static int snd_ymfpci_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { diff --git a/trunk/sound/pcmcia/pdaudiocf/pdaudiocf.c b/trunk/sound/pcmcia/pdaudiocf/pdaudiocf.c index fd3590fcaedb..1c09e5f49da8 100644 --- a/trunk/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/trunk/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -206,7 +206,7 @@ static void snd_pdacf_detach(struct pcmcia_device *link) snd_pdacf_powerdown(chip); chip->chip_status |= PDAUDIOCF_STAT_IS_STALE; /* to be sure */ snd_card_disconnect(chip->card); - snd_card_free_when_closed(chip->card); + snd_card_free_in_thread(chip->card); } /* diff --git a/trunk/sound/pcmcia/vx/vxp_mixer.c b/trunk/sound/pcmcia/vx/vxp_mixer.c index bced7b623b12..e237f6c2018f 100644 --- a/trunk/sound/pcmcia/vx/vxp_mixer.c +++ b/trunk/sound/pcmcia/vx/vxp_mixer.c @@ -23,7 +23,6 @@ #include #include #include -#include #include "vxpocket.h" #define MIC_LEVEL_MIN 0 @@ -64,17 +63,12 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v return 0; } -static DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0); - static struct snd_kcontrol_new vx_control_mic_level = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | - SNDRV_CTL_ELEM_ACCESS_TLV_READ), .name = "Mic Capture Volume", .info = vx_mic_level_info, .get = vx_mic_level_get, .put = vx_mic_level_put, - .tlv = { .p = db_scale_mic }, }; /* diff --git a/trunk/sound/pcmcia/vx/vxpocket.c b/trunk/sound/pcmcia/vx/vxpocket.c index 3089fcca800e..cafe6640cc1a 100644 --- a/trunk/sound/pcmcia/vx/vxpocket.c +++ b/trunk/sound/pcmcia/vx/vxpocket.c @@ -27,7 +27,6 @@ #include #include #include -#include /* */ @@ -66,7 +65,7 @@ static void vxpocket_release(struct pcmcia_device *link) } /* - * destructor, called from snd_card_free_when_closed() + * destructor, called from snd_card_free_in_thread() */ static int snd_vxpocket_dev_free(struct snd_device *device) { @@ -91,8 +90,6 @@ static int snd_vxpocket_dev_free(struct snd_device *device) * Only output levels can be modified */ -static DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0); - static struct snd_vx_hardware vxpocket_hw = { .name = "VXPocket", .type = VX_TYPE_VXPOCKET, @@ -102,7 +99,6 @@ static struct snd_vx_hardware vxpocket_hw = { .num_ins = 1, .num_outs = 1, .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, - .output_level_db_scale = db_scale_old_vol, }; /* VX-pocket 440 @@ -124,7 +120,6 @@ static struct snd_vx_hardware vxp440_hw = { .num_ins = 2, .num_outs = 2, .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, - .output_level_db_scale = db_scale_old_vol, }; @@ -368,7 +363,7 @@ static void vxpocket_detach(struct pcmcia_device *link) chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */ snd_card_disconnect(chip->card); vxpocket_release(link); - snd_card_free_when_closed(chip->card); + snd_card_free_in_thread(chip->card); } /* diff --git a/trunk/sound/ppc/awacs.c b/trunk/sound/ppc/awacs.c index 05dabe454658..82d791be7499 100644 --- a/trunk/sound/ppc/awacs.c +++ b/trunk/sound/ppc/awacs.c @@ -801,10 +801,11 @@ snd_pmac_awacs_init(struct snd_pmac *chip) chip->revision = (in_le32(&chip->awacs->codec_stat) >> 12) & 0xf; #ifdef PMAC_AMP_AVAIL if (chip->revision == 3 && chip->has_iic && CHECK_CUDA_AMP()) { - struct awacs_amp *amp = kzalloc(sizeof(*amp), GFP_KERNEL); + struct awacs_amp *amp = kmalloc(sizeof(*amp), GFP_KERNEL); if (! amp) return -ENOMEM; chip->mixer_data = amp; + memset(amp, 0, sizeof(*amp)); chip->mixer_free = awacs_amp_free; awacs_amp_set_vol(amp, 0, 63, 63, 0); /* mute and zero vol */ awacs_amp_set_vol(amp, 1, 63, 63, 0); diff --git a/trunk/sound/ppc/beep.c b/trunk/sound/ppc/beep.c index 5f38f670102c..5fec1e58f310 100644 --- a/trunk/sound/ppc/beep.c +++ b/trunk/sound/ppc/beep.c @@ -215,18 +215,15 @@ int __init snd_pmac_attach_beep(struct snd_pmac *chip) { struct pmac_beep *beep; struct input_dev *input_dev; - struct snd_kcontrol *beep_ctl; void *dmabuf; int err = -ENOMEM; beep = kzalloc(sizeof(*beep), GFP_KERNEL); - if (! beep) - return -ENOMEM; dmabuf = dma_alloc_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4, &beep->addr, GFP_KERNEL); input_dev = input_allocate_device(); - if (! dmabuf || ! input_dev) - goto fail1; + if (!beep || !dmabuf || !input_dev) + goto fail; /* FIXME: set more better values */ input_dev->name = "PowerMac Beep"; @@ -247,24 +244,17 @@ int __init snd_pmac_attach_beep(struct snd_pmac *chip) beep->volume = BEEP_VOLUME; beep->running = 0; - beep_ctl = snd_ctl_new1(&snd_pmac_beep_mixer, chip); - err = snd_ctl_add(chip->card, beep_ctl); + err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_beep_mixer, chip)); if (err < 0) - goto fail1; - - chip->beep = beep; + goto fail; - err = input_register_device(beep->dev); - if (err) - goto fail2; - - return 0; - - fail2: snd_ctl_remove(chip->card, beep_ctl); - fail1: input_free_device(input_dev); - if (dmabuf) - dma_free_coherent(&chip->pdev->dev, BEEP_BUFLEN * 4, - dmabuf, beep->addr); + chip->beep = beep; + input_register_device(beep->dev); + + return 0; + + fail: input_free_device(input_dev); + kfree(dmabuf); kfree(beep); return err; } diff --git a/trunk/sound/ppc/daca.c b/trunk/sound/ppc/daca.c index 57202b0f033e..46eebf5610e3 100644 --- a/trunk/sound/ppc/daca.c +++ b/trunk/sound/ppc/daca.c @@ -258,9 +258,10 @@ int __init snd_pmac_daca_init(struct snd_pmac *chip) request_module("i2c-powermac"); #endif /* CONFIG_KMOD */ - mix = kzalloc(sizeof(*mix), GFP_KERNEL); + mix = kmalloc(sizeof(*mix), GFP_KERNEL); if (! mix) return -ENOMEM; + memset(mix, 0, sizeof(*mix)); chip->mixer_data = mix; chip->mixer_free = daca_cleanup; mix->amp_on = 1; /* default on */ diff --git a/trunk/sound/ppc/keywest.c b/trunk/sound/ppc/keywest.c index 272ae38e9b18..fb05938dcbd9 100644 --- a/trunk/sound/ppc/keywest.c +++ b/trunk/sound/ppc/keywest.c @@ -64,10 +64,11 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter) if (strncmp(i2c_device_name(adapter), "mac-io", 6)) return 0; /* ignored */ - new_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); if (! new_client) return -ENOMEM; + memset(new_client, 0, sizeof(*new_client)); new_client->addr = keywest_ctx->addr; i2c_set_clientdata(new_client, keywest_ctx); new_client->adapter = adapter; @@ -117,9 +118,6 @@ int __init snd_pmac_tumbler_post_init(void) { int err; - if (!keywest_ctx || !keywest_ctx->client) - return -ENXIO; - if ((err = keywest_ctx->init_client(keywest_ctx)) < 0) { snd_printk(KERN_ERR "tumbler: %i :cannot initialize the MCS\n", err); return err; diff --git a/trunk/sound/ppc/powermac.c b/trunk/sound/ppc/powermac.c index 2264574fa06b..fa9a44ab487e 100644 --- a/trunk/sound/ppc/powermac.c +++ b/trunk/sound/ppc/powermac.c @@ -181,14 +181,21 @@ static int __init alsa_card_pmac_init(void) if ((err = platform_driver_register(&snd_pmac_driver)) < 0) return err; device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0); - return 0; + if (!IS_ERR(device)) { + if (platform_get_drvdata(device)) + return 0; + platform_device_unregister(device); + err = -ENODEV; + } else + err = PTR_ERR(device); + platform_driver_unregister(&snd_pmac_driver); + return err; } static void __exit alsa_card_pmac_exit(void) { - if (!IS_ERR(device)) - platform_device_unregister(device); + platform_device_unregister(device); platform_driver_unregister(&snd_pmac_driver); } diff --git a/trunk/sound/ppc/tumbler.c b/trunk/sound/ppc/tumbler.c index cdff53e4a17e..692c61177678 100644 --- a/trunk/sound/ppc/tumbler.c +++ b/trunk/sound/ppc/tumbler.c @@ -190,7 +190,7 @@ static int check_audio_gpio(struct pmac_gpio *gp) ret = do_gpio_read(gp); - return (ret & 0x1) == (gp->active_val & 0x1); + return (ret & 0xd) == (gp->active_val & 0xd); } static int read_audio_gpio(struct pmac_gpio *gp) @@ -198,8 +198,7 @@ static int read_audio_gpio(struct pmac_gpio *gp) int ret; if (! gp->addr) return 0; - ret = do_gpio_read(gp); - ret = (ret & 0x02) !=0; + ret = ((do_gpio_read(gp) & 0x02) !=0); return ret == gp->active_state; } @@ -1036,7 +1035,7 @@ static struct device_node *find_audio_device(const char *name) return NULL; for (np = np->child; np; np = np->sibling) { - const char *property = get_property(np, "audio-gpio", NULL); + char *property = get_property(np, "audio-gpio", NULL); if (property && strcmp(property, name) == 0) return np; } @@ -1063,8 +1062,7 @@ static long tumbler_find_device(const char *device, const char *platform, struct pmac_gpio *gp, int is_compatible) { struct device_node *node; - const u32 *base; - u32 addr; + u32 *base, addr; if (is_compatible) node = find_compatible_audio_device(device); @@ -1076,9 +1074,9 @@ static long tumbler_find_device(const char *device, const char *platform, return -ENODEV; } - base = get_property(node, "AAPL,address", NULL); + base = (u32 *)get_property(node, "AAPL,address", NULL); if (! base) { - base = get_property(node, "reg", NULL); + base = (u32 *)get_property(node, "reg", NULL); if (!base) { DBG("(E) cannot find address for device %s !\n", device); snd_printd("cannot find address for device %s\n", device); @@ -1092,13 +1090,13 @@ static long tumbler_find_device(const char *device, const char *platform, gp->addr = addr & 0x0000ffff; /* Try to find the active state, default to 0 ! */ - base = get_property(node, "audio-gpio-active-state", NULL); + base = (u32 *)get_property(node, "audio-gpio-active-state", NULL); if (base) { gp->active_state = *base; gp->active_val = (*base) ? 0x5 : 0x4; gp->inactive_val = (*base) ? 0x4 : 0x5; } else { - const u32 *prop = NULL; + u32 *prop = NULL; gp->active_state = 0; gp->active_val = 0x4; gp->inactive_val = 0x5; @@ -1107,7 +1105,7 @@ static long tumbler_find_device(const char *device, const char *platform, * as we don't yet have an interpreter for these things */ if (platform) - prop = get_property(node, platform, NULL); + prop = (u32 *)get_property(node, platform, NULL); if (prop) { if (prop[3] == 0x9 && prop[4] == 0x9) { gp->active_val = 0xd; @@ -1318,9 +1316,10 @@ int __init snd_pmac_tumbler_init(struct snd_pmac *chip) request_module("i2c-powermac"); #endif /* CONFIG_KMOD */ - mix = kzalloc(sizeof(*mix), GFP_KERNEL); + mix = kmalloc(sizeof(*mix), GFP_KERNEL); if (! mix) return -ENOMEM; + memset(mix, 0, sizeof(*mix)); mix->headphone_irq = -1; chip->mixer_data = mix; diff --git a/trunk/sound/sparc/dbri.c b/trunk/sound/sparc/dbri.c index e4935fca12df..f3ae6e23610e 100644 --- a/trunk/sound/sparc/dbri.c +++ b/trunk/sound/sparc/dbri.c @@ -2,8 +2,6 @@ * Driver for DBRI sound chip found on Sparcs. * Copyright (C) 2004, 2005 Martin Habets (mhabets@users.sourceforge.net) * - * Converted to ring buffered version by Krzysztof Helt (krzysztof.h1@wp.pl) - * * Based entirely upon drivers/sbus/audio/dbri.c which is: * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) * Copyright (C) 1998, 1999 Brent Baccala (baccala@freesoft.org) @@ -36,7 +34,7 @@ * (the second one is a monitor/tee pipe, valid only for serial input). * * The mmcodec is connected via the CHI bus and needs the data & some - * parameters (volume, output selection) timemultiplexed in 8 byte + * parameters (volume, balance, output selection) timemultiplexed in 8 byte * chunks. It also has a control mode, which serves for audio format setting. * * Looking at the CS4215 data sheet it is easy to set up 2 or 4 codecs on @@ -85,7 +83,7 @@ MODULE_PARM_DESC(id, "ID string for Sun DBRI soundcard."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable Sun DBRI soundcard."); -#undef DBRI_DEBUG +#define DBRI_DEBUG #define D_INT (1<<0) #define D_GEN (1<<1) @@ -106,14 +104,16 @@ static char *cmds[] = { #define dprintk(a, x...) if(dbri_debug & a) printk(KERN_DEBUG x) +#define DBRI_CMD(cmd, intr, value) ((cmd << 28) | \ + (1 << 27) | \ + value) #else -#define dprintk(a, x...) do { } while (0) - -#endif /* DBRI_DEBUG */ +#define dprintk(a, x...) -#define DBRI_CMD(cmd, intr, value) ((cmd << 28) | \ - (intr << 27) | \ +#define DBRI_CMD(cmd, intr, value) ((cmd << 28) | \ + (intr << 27) | \ value) +#endif /* DBRI_DEBUG */ /*************************************************************************** CS4215 specific definitions and structures @@ -160,7 +160,7 @@ static struct { /* { NA, (1 << 4), (5 << 3) }, */ { 48000, (1 << 4), (6 << 3) }, { 9600, (1 << 4), (7 << 3) }, - { 5512, (2 << 4), (0 << 3) }, /* Actually 5512.5 */ + { 5513, (2 << 4), (0 << 3) }, /* Actually 5512.5 */ { 11025, (2 << 4), (1 << 3) }, { 18900, (2 << 4), (2 << 3) }, { 22050, (2 << 4), (3 << 3) }, @@ -240,21 +240,28 @@ static struct { #define REG9 0x24UL /* Interrupt Queue Pointer */ #define DBRI_NO_CMDS 64 +#define DBRI_NO_INTS 1 /* Note: the value of this define was + * originally 2. The ringbuffer to store + * interrupts in dma is currently broken. + * This is a temporary fix until the ringbuffer + * is fixed. + */ #define DBRI_INT_BLK 64 #define DBRI_NO_DESCS 64 #define DBRI_NO_PIPES 32 -#define DBRI_MAX_PIPE (DBRI_NO_PIPES - 1) + +#define DBRI_MM_ONB 1 +#define DBRI_MM_SB 2 #define DBRI_REC 0 #define DBRI_PLAY 1 #define DBRI_NO_STREAMS 2 /* One transmit/receive descriptor */ -/* When ba != 0 descriptor is used */ struct dbri_mem { volatile __u32 word1; - __u32 ba; /* Transmit/Receive Buffer Address */ - __u32 nda; /* Next Descriptor Address */ + volatile __u32 ba; /* Transmit/Receive Buffer Address */ + volatile __u32 nda; /* Next Descriptor Address */ volatile __u32 word4; }; @@ -262,8 +269,8 @@ struct dbri_mem { * the CPU and the DBRI */ struct dbri_dma { - s32 cmd[DBRI_NO_CMDS]; /* Place for commands */ - volatile s32 intr[DBRI_INT_BLK]; /* Interrupt field */ + volatile s32 cmd[DBRI_NO_CMDS]; /* Place for commands */ + volatile s32 intr[DBRI_NO_INTS * DBRI_INT_BLK]; /* Interrupt field */ struct dbri_mem desc[DBRI_NO_DESCS]; /* Xmit/receive descriptors */ }; @@ -275,43 +282,58 @@ enum in_or_out { PIPEinput, PIPEoutput }; struct dbri_pipe { u32 sdp; /* SDP command word */ + enum in_or_out direction; int nextpipe; /* Next pipe in linked list */ + int prevpipe; + int cycle; /* Offset of timeslot (bits) */ int length; /* Length of timeslot (bits) */ int first_desc; /* Index of first descriptor */ int desc; /* Index of active descriptor */ volatile __u32 *recv_fixed_ptr; /* Ptr to receive fixed data */ }; +struct dbri_desc { + int inuse; /* Boolean flag */ + int next; /* Index of next desc, or -1 */ + unsigned int len; +}; + /* Per stream (playback or record) information */ struct dbri_streaminfo { struct snd_pcm_substream *substream; u32 dvma_buffer; /* Device view of Alsa DMA buffer */ + int left; /* # of bytes left in DMA buffer */ int size; /* Size of DMA buffer */ size_t offset; /* offset in user buffer */ int pipe; /* Data pipe used */ int left_gain; /* mixer elements */ int right_gain; + int balance; }; /* This structure holds the information for both chips (DBRI & CS4215) */ struct snd_dbri { struct snd_card *card; /* ALSA card */ + struct snd_pcm *pcm; int regs_size, irq; /* Needed for unload */ struct sbus_dev *sdev; /* SBUS device info */ spinlock_t lock; - struct dbri_dma *dma; /* Pointer to our DMA block */ + volatile struct dbri_dma *dma; /* Pointer to our DMA block */ u32 dma_dvma; /* DBRI visible DMA address */ void __iomem *regs; /* dbri HW regs */ + int dbri_version; /* 'e' and up is OK */ int dbri_irqp; /* intr queue pointer */ + int wait_send; /* sequence of command buffers send */ + int wait_ackd; /* sequence of command buffers acknowledged */ struct dbri_pipe pipes[DBRI_NO_PIPES]; /* DBRI's 32 data pipes */ - int next_desc[DBRI_NO_DESCS]; /* Index of next desc, or -1 */ - spinlock_t cmdlock; /* Protects cmd queue accesses */ - s32 *cmdptr; /* Pointer to the last queued cmd */ + struct dbri_desc descs[DBRI_NO_DESCS]; + int chi_in_pipe; + int chi_out_pipe; int chi_bpf; struct cs4215 mm; /* mmcodec special info */ @@ -323,6 +345,8 @@ struct snd_dbri { #define DBRI_MAX_VOLUME 63 /* Output volume */ #define DBRI_MAX_GAIN 15 /* Input gain */ +#define DBRI_RIGHT_BALANCE 255 +#define DBRI_MID_BALANCE (DBRI_RIGHT_BALANCE >> 1) /* DBRI Reg0 - Status Control Register - defines. (Page 17) */ #define D_P (1<<15) /* Program command & queue pointer valid */ @@ -545,7 +569,7 @@ struct snd_dbri { #define DBRI_TD_TBC (1<<0) /* Transmit buffer Complete */ #define DBRI_TD_STATUS(v) ((v)&0xff) /* Transmit status */ /* Maximum buffer size per TD: almost 8Kb */ -#define DBRI_TD_MAXCNT ((1 << 13) - 4) +#define DBRI_TD_MAXCNT ((1 << 13) - 1) /* Receive descriptor defines */ #define DBRI_RD_F (1<<31) /* End of Frame */ @@ -609,124 +633,93 @@ The list is terminated with a WAIT command, which generates a CPU interrupt to signal completion. Since the DBRI can run in parallel with the CPU, several means of -synchronization present themselves. The method implemented here is only -use of the dbri_cmdwait() to wait for execution of batch of sent commands. +synchronization present themselves. The method implemented here is close +to the original scheme (Rudolf's), and uses 2 counters (wait_send and +wait_ackd) to synchronize the command buffer between the CPU and the DBRI. -A circular command buffer is used here. A new command is being added -while another can be executed. The scheme works by adding two WAIT commands -after each sent batch of commands. When the next batch is prepared it is -added after the WAIT commands then the WAITs are replaced with single JUMP -command to the new batch. The the DBRI is forced to reread the last WAIT -command (replaced by the JUMP by then). If the DBRI is still executing -previous commands the request to reread the WAIT command is ignored. +A more sophisticated scheme might involve a circular command buffer +or an array of command buffers. A routine could fill one with +commands and link it onto a list. When a interrupt signaled +completion of the current command buffer, look on the list for +the next one. Every time a routine wants to write commands to the DBRI, it must -first call dbri_cmdlock() and get pointer to a free space in -dbri->dma->cmd buffer. After this, the commands can be written to -the buffer, and dbri_cmdsend() is called with the final pointer value -to send them to the DBRI. +first call dbri_cmdlock() and get an initial pointer into dbri->dma->cmd +in return. dbri_cmdlock() will block if the previous commands have not +been completed yet. After this the commands can be written to the buffer, +and dbri_cmdsend() is called with the final pointer value to send them +to the DBRI. */ -#define MAXLOOPS 20 -/* - * Wait for the current command string to execute - */ -static void dbri_cmdwait(struct snd_dbri *dbri) +static void dbri_process_interrupt_buffer(struct snd_dbri * dbri); + +enum dbri_lock { NoGetLock, GetLock }; +#define MAXLOOPS 10 + +static volatile s32 *dbri_cmdlock(struct snd_dbri * dbri, enum dbri_lock get) { int maxloops = MAXLOOPS; - unsigned long flags; + +#ifndef SMP + if ((get == GetLock) && spin_is_locked(&dbri->lock)) { + printk(KERN_ERR "DBRI: cmdlock called while in spinlock."); + } +#endif /* Delay if previous commands are still being processed */ - spin_lock_irqsave(&dbri->lock, flags); - while ((--maxloops) > 0 && (sbus_readl(dbri->regs + REG0) & D_P)) { - spin_unlock_irqrestore(&dbri->lock, flags); + while ((--maxloops) > 0 && (dbri->wait_send != dbri->wait_ackd)) { msleep_interruptible(1); - spin_lock_irqsave(&dbri->lock, flags); + /* If dbri_cmdlock() got called from inside the + * interrupt handler, this will do the processing. + */ + dbri_process_interrupt_buffer(dbri); } - spin_unlock_irqrestore(&dbri->lock, flags); - if (maxloops == 0) { - printk(KERN_ERR "DBRI: Chip never completed command buffer\n"); + printk(KERN_ERR "DBRI: Chip never completed command buffer %d\n", + dbri->wait_send); } else { dprintk(D_CMD, "Chip completed command buffer (%d)\n", MAXLOOPS - maxloops - 1); } -} -/* - * Lock the command queue and returns pointer to a space for len cmd words - * It locks the cmdlock spinlock. - */ -static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len) -{ - /* Space for 2 WAIT cmds (replaced later by 1 JUMP cmd) */ - len += 2; - spin_lock(&dbri->cmdlock); - if (dbri->cmdptr - dbri->dma->cmd + len < DBRI_NO_CMDS - 2) - return dbri->cmdptr + 2; - else if (len < sbus_readl(dbri->regs + REG8) - dbri->dma_dvma) - return dbri->dma->cmd; - else - printk(KERN_ERR "DBRI: no space for commands."); - return 0; + /*if (get == GetLock) spin_lock(&dbri->lock); */ + return &dbri->dma->cmd[0]; } -/* - * Send prepared cmd string. It works by writting a JUMP cmd into - * the last WAIT cmd and force DBRI to reread the cmd. - * The JUMP cmd points to the new cmd string. - * It also releases the cmdlock spinlock. - * - * Lock must not be held before calling this. - */ -static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) +static void dbri_cmdsend(struct snd_dbri * dbri, volatile s32 * cmd) { - s32 tmp, addr; - static int wait_id = 0; - - wait_id++; - wait_id &= 0xffff; /* restrict it to a 16 bit counter. */ - *(cmd) = DBRI_CMD(D_WAIT, 1, wait_id); - *(cmd+1) = DBRI_CMD(D_WAIT, 1, wait_id); - - /* Replace the last command with JUMP */ - addr = dbri->dma_dvma + (cmd - len - dbri->dma->cmd) * sizeof(s32); - *(dbri->cmdptr+1) = addr; - *(dbri->cmdptr) = DBRI_CMD(D_JUMP, 0, 0); - -#ifdef DBRI_DEBUG - if (cmd > dbri->cmdptr) { - s32 *ptr; - - for (ptr = dbri->cmdptr; ptr < cmd+2; ptr++) - dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); - } else { - s32 *ptr = dbri->cmdptr; + volatile s32 *ptr; + u32 reg; + for (ptr = &dbri->dma->cmd[0]; ptr < cmd; ptr++) { dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); - ptr++; - dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); - for (ptr = dbri->dma->cmd; ptr < cmd+2; ptr++) { - dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); - } } -#endif - /* Reread the last command */ - tmp = sbus_readl(dbri->regs + REG0); - tmp |= D_P; - sbus_writel(tmp, dbri->regs + REG0); + if ((cmd - &dbri->dma->cmd[0]) >= DBRI_NO_CMDS - 1) { + printk(KERN_ERR "DBRI: Command buffer overflow! (bug in driver)\n"); + /* Ignore the last part. */ + cmd = &dbri->dma->cmd[DBRI_NO_CMDS - 3]; + } + + dbri->wait_send++; + dbri->wait_send &= 0xffff; /* restrict it to a 16 bit counter. */ + *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); + *(cmd++) = DBRI_CMD(D_WAIT, 1, dbri->wait_send); + + /* Set command pointer and signal it is valid. */ + sbus_writel(dbri->dma_dvma, dbri->regs + REG8); + reg = sbus_readl(dbri->regs + REG0); + reg |= D_P; + sbus_writel(reg, dbri->regs + REG0); - dbri->cmdptr = cmd; - spin_unlock(&dbri->cmdlock); + /*spin_unlock(&dbri->lock); */ } /* Lock must be held when calling this */ static void dbri_reset(struct snd_dbri * dbri) { int i; - u32 tmp; dprintk(D_GEN, "reset 0:%x 2:%x 8:%x 9:%x\n", sbus_readl(dbri->regs + REG0), @@ -736,20 +729,13 @@ static void dbri_reset(struct snd_dbri * dbri) sbus_writel(D_R, dbri->regs + REG0); /* Soft Reset */ for (i = 0; (sbus_readl(dbri->regs + REG0) & D_R) && i < 64; i++) udelay(10); - - /* A brute approach - DBRI falls back to working burst size by itself - * On SS20 D_S does not work, so do not try so high. */ - tmp = sbus_readl(dbri->regs + REG0); - tmp |= D_G | D_E; - tmp &= ~D_S; - sbus_writel(tmp, dbri->regs + REG0); } /* Lock must not be held before calling this */ static void dbri_initialize(struct snd_dbri * dbri) { - s32 *cmd; - u32 dma_addr; + volatile s32 *cmd; + u32 dma_addr, tmp; unsigned long flags; int n; @@ -757,34 +743,42 @@ static void dbri_initialize(struct snd_dbri * dbri) dbri_reset(dbri); - /* Initialize pipes */ - for (n = 0; n < DBRI_NO_PIPES; n++) - dbri->pipes[n].desc = dbri->pipes[n].first_desc = -1; + cmd = dbri_cmdlock(dbri, NoGetLock); + dprintk(D_GEN, "init: cmd: %p, int: %p\n", + &dbri->dma->cmd[0], &dbri->dma->intr[0]); - spin_lock_init(&dbri->cmdlock); /* * Initialize the interrupt ringbuffer. */ + for (n = 0; n < DBRI_NO_INTS - 1; n++) { + dma_addr = dbri->dma_dvma; + dma_addr += dbri_dma_off(intr, ((n + 1) & DBRI_INT_BLK)); + dbri->dma->intr[n * DBRI_INT_BLK] = dma_addr; + } dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0); - dbri->dma->intr[0] = dma_addr; + dbri->dma->intr[n * DBRI_INT_BLK] = dma_addr; dbri->dbri_irqp = 1; + + /* Initialize pipes */ + for (n = 0; n < DBRI_NO_PIPES; n++) + dbri->pipes[n].desc = dbri->pipes[n].first_desc = -1; + + /* A brute approach - DBRI falls back to working burst size by itself + * On SS20 D_S does not work, so do not try so high. */ + tmp = sbus_readl(dbri->regs + REG0); + tmp |= D_G | D_E; + tmp &= ~D_S; + sbus_writel(tmp, dbri->regs + REG0); + /* * Set up the interrupt queue */ - spin_lock(&dbri->cmdlock); - cmd = dbri->cmdptr = dbri->dma->cmd; + dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0); *(cmd++) = DBRI_CMD(D_IIQ, 0, 0); *(cmd++) = dma_addr; - *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); - dbri->cmdptr = cmd; - *(cmd++) = DBRI_CMD(D_WAIT, 1, 0); - *(cmd++) = DBRI_CMD(D_WAIT, 1, 0); - dma_addr = dbri->dma_dvma + dbri_dma_off(cmd, 0); - sbus_writel(dma_addr, dbri->regs + REG8); - spin_unlock(&dbri->cmdlock); + dbri_cmdsend(dbri, cmd); spin_unlock_irqrestore(&dbri->lock, flags); - dbri_cmdwait(dbri); } /* @@ -815,9 +809,9 @@ static void reset_pipe(struct snd_dbri * dbri, int pipe) { int sdp; int desc; - s32 *cmd; + volatile int *cmd; - if (pipe < 0 || pipe > DBRI_MAX_PIPE) { + if (pipe < 0 || pipe > 31) { printk(KERN_ERR "DBRI: reset_pipe called with illegal pipe number\n"); return; } @@ -828,29 +822,25 @@ static void reset_pipe(struct snd_dbri * dbri, int pipe) return; } - cmd = dbri_cmdlock(dbri, 3); + cmd = dbri_cmdlock(dbri, NoGetLock); *(cmd++) = DBRI_CMD(D_SDP, 0, sdp | D_SDP_C | D_SDP_P); *(cmd++) = 0; - *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); - dbri_cmdsend(dbri, cmd, 3); + dbri_cmdsend(dbri, cmd); desc = dbri->pipes[pipe].first_desc; - if ( desc >= 0) - do { - dbri->dma->desc[desc].nda = dbri->dma->desc[desc].ba = 0; - desc = dbri->next_desc[desc]; - } while (desc != -1 && desc != dbri->pipes[pipe].first_desc); + while (desc != -1) { + dbri->descs[desc].inuse = 0; + desc = dbri->descs[desc].next; + } dbri->pipes[pipe].desc = -1; dbri->pipes[pipe].first_desc = -1; } -/* - * Lock must be held before calling this. - */ +/* FIXME: direction as an argument? */ static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp) { - if (pipe < 0 || pipe > DBRI_MAX_PIPE) { + if (pipe < 0 || pipe > 31) { printk(KERN_ERR "DBRI: setup_pipe called with illegal pipe number\n"); return; } @@ -870,87 +860,119 @@ static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp) dbri->pipes[pipe].sdp = sdp; dbri->pipes[pipe].desc = -1; dbri->pipes[pipe].first_desc = -1; + if (sdp & D_SDP_TO_SER) + dbri->pipes[pipe].direction = PIPEoutput; + else + dbri->pipes[pipe].direction = PIPEinput; reset_pipe(dbri, pipe); } -/* - * Lock must be held before calling this. - */ +/* FIXME: direction not needed */ static void link_time_slot(struct snd_dbri * dbri, int pipe, - int prevpipe, int nextpipe, + enum in_or_out direction, int basepipe, int length, int cycle) { - s32 *cmd; + volatile s32 *cmd; int val; + int prevpipe; + int nextpipe; - if (pipe < 0 || pipe > DBRI_MAX_PIPE - || prevpipe < 0 || prevpipe > DBRI_MAX_PIPE - || nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) { + if (pipe < 0 || pipe > 31 || basepipe < 0 || basepipe > 31) { printk(KERN_ERR "DBRI: link_time_slot called with illegal pipe number\n"); return; } - if (dbri->pipes[pipe].sdp == 0 - || dbri->pipes[prevpipe].sdp == 0 - || dbri->pipes[nextpipe].sdp == 0) { + if (dbri->pipes[pipe].sdp == 0 || dbri->pipes[basepipe].sdp == 0) { printk(KERN_ERR "DBRI: link_time_slot called on uninitialized pipe\n"); return; } - dbri->pipes[prevpipe].nextpipe = pipe; + /* Deal with CHI special case: + * "If transmission on edges 0 or 1 is desired, then cycle n + * (where n = # of bit times per frame...) must be used." + * - DBRI data sheet, page 11 + */ + if (basepipe == 16 && direction == PIPEoutput && cycle == 0) + cycle = dbri->chi_bpf; + + if (basepipe == pipe) { + prevpipe = pipe; + nextpipe = pipe; + } else { + /* We're not initializing a new linked list (basepipe != pipe), + * so run through the linked list and find where this pipe + * should be sloted in, based on its cycle. CHI confuses + * things a bit, since it has a single anchor for both its + * transmit and receive lists. + */ + if (basepipe == 16) { + if (direction == PIPEinput) { + prevpipe = dbri->chi_in_pipe; + } else { + prevpipe = dbri->chi_out_pipe; + } + } else { + prevpipe = basepipe; + } + + nextpipe = dbri->pipes[prevpipe].nextpipe; + + while (dbri->pipes[nextpipe].cycle < cycle + && dbri->pipes[nextpipe].nextpipe != basepipe) { + prevpipe = nextpipe; + nextpipe = dbri->pipes[nextpipe].nextpipe; + } + } + + if (prevpipe == 16) { + if (direction == PIPEinput) { + dbri->chi_in_pipe = pipe; + } else { + dbri->chi_out_pipe = pipe; + } + } else { + dbri->pipes[prevpipe].nextpipe = pipe; + } + dbri->pipes[pipe].nextpipe = nextpipe; + dbri->pipes[pipe].cycle = cycle; dbri->pipes[pipe].length = length; - cmd = dbri_cmdlock(dbri, 4); + cmd = dbri_cmdlock(dbri, NoGetLock); - if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) { - /* Deal with CHI special case: - * "If transmission on edges 0 or 1 is desired, then cycle n - * (where n = # of bit times per frame...) must be used." - * - DBRI data sheet, page 11 - */ - if (prevpipe == 16 && cycle == 0) - cycle = dbri->chi_bpf; - - val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(prevpipe) | pipe; + if (direction == PIPEinput) { + val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(prevpipe) | pipe; *(cmd++) = DBRI_CMD(D_DTS, 0, val); - *(cmd++) = 0; *(cmd++) = D_TS_LEN(length) | D_TS_CYCLE(cycle) | D_TS_NEXT(nextpipe); + *(cmd++) = 0; } else { - val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(prevpipe) | pipe; + val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(prevpipe) | pipe; *(cmd++) = DBRI_CMD(D_DTS, 0, val); + *(cmd++) = 0; *(cmd++) = D_TS_LEN(length) | D_TS_CYCLE(cycle) | D_TS_NEXT(nextpipe); - *(cmd++) = 0; } - *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); - dbri_cmdsend(dbri, cmd, 4); + dbri_cmdsend(dbri, cmd); } -#if 0 -/* - * Lock must be held before calling this. - */ static void unlink_time_slot(struct snd_dbri * dbri, int pipe, enum in_or_out direction, int prevpipe, int nextpipe) { - s32 *cmd; + volatile s32 *cmd; int val; - if (pipe < 0 || pipe > DBRI_MAX_PIPE - || prevpipe < 0 || prevpipe > DBRI_MAX_PIPE - || nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) { + if (pipe < 0 || pipe > 31 || prevpipe < 0 || prevpipe > 31) { printk(KERN_ERR "DBRI: unlink_time_slot called with illegal pipe number\n"); return; } - cmd = dbri_cmdlock(dbri, 4); + cmd = dbri_cmdlock(dbri, NoGetLock); if (direction == PIPEinput) { val = D_DTS_VI | D_DTS_DEL | D_DTS_PRVIN(prevpipe) | pipe; @@ -963,11 +985,9 @@ static void unlink_time_slot(struct snd_dbri * dbri, int pipe, *(cmd++) = 0; *(cmd++) = D_TS_NEXT(nextpipe); } - *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); - dbri_cmdsend(dbri, cmd, 4); + dbri_cmdsend(dbri, cmd); } -#endif /* xmit_fixed() / recv_fixed() * @@ -981,16 +1001,13 @@ static void unlink_time_slot(struct snd_dbri * dbri, int pipe, * the actual time slot is. The interrupt handler takes care of bit * ordering and alignment. An 8-bit time slot will always end up * in the low-order 8 bits, filled either MSB-first or LSB-first, - * depending on the settings passed to setup_pipe(). - * - * Lock must not be held before calling it. + * depending on the settings passed to setup_pipe() */ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) { - s32 *cmd; - unsigned long flags; + volatile s32 *cmd; - if (pipe < 16 || pipe > DBRI_MAX_PIPE) { + if (pipe < 16 || pipe > 31) { printk(KERN_ERR "DBRI: xmit_fixed: Illegal pipe number\n"); return; } @@ -1015,22 +1032,17 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) if (dbri->pipes[pipe].sdp & D_SDP_MSB) data = reverse_bytes(data, dbri->pipes[pipe].length); - cmd = dbri_cmdlock(dbri, 3); + cmd = dbri_cmdlock(dbri, GetLock); *(cmd++) = DBRI_CMD(D_SSP, 0, pipe); *(cmd++) = data; - *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); - - spin_lock_irqsave(&dbri->lock, flags); - dbri_cmdsend(dbri, cmd, 3); - spin_unlock_irqrestore(&dbri->lock, flags); - dbri_cmdwait(dbri); + dbri_cmdsend(dbri, cmd); } static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr) { - if (pipe < 16 || pipe > DBRI_MAX_PIPE) { + if (pipe < 16 || pipe > 31) { printk(KERN_ERR "DBRI: recv_fixed called with illegal pipe number\n"); return; } @@ -1059,16 +1071,12 @@ static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr) * and work by building chains of descriptors which identify the * data buffers. Buffers too large for a single descriptor will * be spread across multiple descriptors. - * - * All descriptors create a ring buffer. - * - * Lock must be held before calling this. */ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period) { struct dbri_streaminfo *info = &dbri->stream_info[streamno]; __u32 dvma_buffer; - int desc; + int desc = 0; int len; int first_desc = -1; int last_desc = -1; @@ -1111,23 +1119,11 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period len &= ~3; } - /* Free descriptors if pipe has any */ - desc = dbri->pipes[info->pipe].first_desc; - if ( desc >= 0) - do { - dbri->dma->desc[desc].nda = dbri->dma->desc[desc].ba = 0; - desc = dbri->next_desc[desc]; - } while (desc != -1 && desc != dbri->pipes[info->pipe].first_desc); - - dbri->pipes[info->pipe].desc = -1; - dbri->pipes[info->pipe].first_desc = -1; - - desc = 0; while (len > 0) { int mylen; for (; desc < DBRI_NO_DESCS; desc++) { - if (!dbri->dma->desc[desc].ba) + if (!dbri->descs[desc].inuse) break; } if (desc == DBRI_NO_DESCS) { @@ -1135,33 +1131,37 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period return -1; } - if (len > DBRI_TD_MAXCNT) - mylen = DBRI_TD_MAXCNT; /* 8KB - 4 */ - else + if (len > DBRI_TD_MAXCNT) { + mylen = DBRI_TD_MAXCNT; /* 8KB - 1 */ + } else { mylen = len; - - if (mylen > period) + } + if (mylen > period) { mylen = period; + } - dbri->next_desc[desc] = -1; + dbri->descs[desc].inuse = 1; + dbri->descs[desc].next = -1; dbri->dma->desc[desc].ba = dvma_buffer; dbri->dma->desc[desc].nda = 0; if (streamno == DBRI_PLAY) { + dbri->descs[desc].len = mylen; dbri->dma->desc[desc].word1 = DBRI_TD_CNT(mylen); dbri->dma->desc[desc].word4 = 0; - dbri->dma->desc[desc].word1 |= - DBRI_TD_F | DBRI_TD_B; + if (first_desc != -1) + dbri->dma->desc[desc].word1 |= DBRI_TD_M; } else { + dbri->descs[desc].len = 0; dbri->dma->desc[desc].word1 = 0; dbri->dma->desc[desc].word4 = DBRI_RD_B | DBRI_RD_BCNT(mylen); } - if (first_desc == -1) + if (first_desc == -1) { first_desc = desc; - else { - dbri->next_desc[last_desc] = desc; + } else { + dbri->descs[last_desc].next = desc; dbri->dma->desc[last_desc].nda = dbri->dma_dvma + dbri_dma_off(desc, desc); } @@ -1176,24 +1176,21 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period return -1; } - dbri->dma->desc[last_desc].nda = - dbri->dma_dvma + dbri_dma_off(desc, first_desc); - dbri->next_desc[last_desc] = first_desc; + dbri->dma->desc[last_desc].word1 &= ~DBRI_TD_M; + if (streamno == DBRI_PLAY) { + dbri->dma->desc[last_desc].word1 |= + DBRI_TD_I | DBRI_TD_F | DBRI_TD_B; + } dbri->pipes[info->pipe].first_desc = first_desc; dbri->pipes[info->pipe].desc = first_desc; -#ifdef DBRI_DEBUG - for (desc = first_desc; desc != -1; ) { + for (desc = first_desc; desc != -1; desc = dbri->descs[desc].next) { dprintk(D_DESC, "DESC %d: %08x %08x %08x %08x\n", desc, dbri->dma->desc[desc].word1, dbri->dma->desc[desc].ba, dbri->dma->desc[desc].nda, dbri->dma->desc[desc].word4); - desc = dbri->next_desc[desc]; - if ( desc == first_desc ) - break; } -#endif return 0; } @@ -1210,30 +1207,56 @@ multiplexed serial interface which the DBRI can operate in either master enum master_or_slave { CHImaster, CHIslave }; -/* - * Lock must not be held before calling it. - */ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_slave, int bits_per_frame) { - s32 *cmd; + volatile s32 *cmd; int val; + static int chi_initialized = 0; /* FIXME: mutex? */ - /* Set CHI Anchor: Pipe 16 */ + if (!chi_initialized) { - cmd = dbri_cmdlock(dbri, 4); - val = D_DTS_VO | D_DTS_VI | D_DTS_INS - | D_DTS_PRVIN(16) | D_PIPE(16) | D_DTS_PRVOUT(16); - *(cmd++) = DBRI_CMD(D_DTS, 0, val); - *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16); - *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16); - *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); - dbri_cmdsend(dbri, cmd, 4); + cmd = dbri_cmdlock(dbri, GetLock); + + /* Set CHI Anchor: Pipe 16 */ + + val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(16) | D_PIPE(16); + *(cmd++) = DBRI_CMD(D_DTS, 0, val); + *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16); + *(cmd++) = 0; + + val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(16) | D_PIPE(16); + *(cmd++) = DBRI_CMD(D_DTS, 0, val); + *(cmd++) = 0; + *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16); + + dbri->pipes[16].sdp = 1; + dbri->pipes[16].nextpipe = 16; + dbri->chi_in_pipe = 16; + dbri->chi_out_pipe = 16; + +#if 0 + chi_initialized++; +#endif + } else { + int pipe; - dbri->pipes[16].sdp = 1; - dbri->pipes[16].nextpipe = 16; + for (pipe = dbri->chi_in_pipe; + pipe != 16; pipe = dbri->pipes[pipe].nextpipe) { + unlink_time_slot(dbri, pipe, PIPEinput, + 16, dbri->pipes[pipe].nextpipe); + } + for (pipe = dbri->chi_out_pipe; + pipe != 16; pipe = dbri->pipes[pipe].nextpipe) { + unlink_time_slot(dbri, pipe, PIPEoutput, + 16, dbri->pipes[pipe].nextpipe); + } - cmd = dbri_cmdlock(dbri, 4); + dbri->chi_in_pipe = 16; + dbri->chi_out_pipe = 16; + + cmd = dbri_cmdlock(dbri, GetLock); + } if (master_or_slave == CHIslave) { /* Setup DBRI for CHI Slave - receive clock, frame sync (FS) @@ -1272,9 +1295,8 @@ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_sla *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); *(cmd++) = DBRI_CMD(D_CDM, 0, D_CDM_XCE | D_CDM_XEN | D_CDM_REN); - *(cmd++) = DBRI_CMD(D_PAUSE, 0, 0); - dbri_cmdsend(dbri, cmd, 4); + dbri_cmdsend(dbri, cmd); } /* @@ -1285,14 +1307,9 @@ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_sla In the standard SPARC audio configuration, the CS4215 codec is attached to the DBRI via the CHI interface and few of the DBRI's PIO pins. - * Lock must not be held before calling it. - */ static void cs4215_setup_pipes(struct snd_dbri * dbri) { - unsigned long flags; - - spin_lock_irqsave(&dbri->lock, flags); /* * Data mode: * Pipe 4: Send timeslots 1-4 (audio data) @@ -1316,9 +1333,6 @@ static void cs4215_setup_pipes(struct snd_dbri * dbri) setup_pipe(dbri, 17, D_SDP_FIXED | D_SDP_TO_SER | D_SDP_MSB); setup_pipe(dbri, 18, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); setup_pipe(dbri, 19, D_SDP_FIXED | D_SDP_FROM_SER | D_SDP_MSB); - spin_unlock_irqrestore(&dbri->lock, flags); - - dbri_cmdwait(dbri); } static int cs4215_init_data(struct cs4215 *mm) @@ -1350,7 +1364,7 @@ static int cs4215_init_data(struct cs4215 *mm) mm->status = 0; mm->version = 0xff; mm->precision = 8; /* For ULAW */ - mm->channels = 1; + mm->channels = 2; return 0; } @@ -1365,8 +1379,16 @@ static void cs4215_setdata(struct snd_dbri * dbri, int muted) } else { /* Start by setting the playback attenuation. */ struct dbri_streaminfo *info = &dbri->stream_info[DBRI_PLAY]; - int left_gain = info->left_gain & 0x3f; - int right_gain = info->right_gain & 0x3f; + int left_gain = info->left_gain % 64; + int right_gain = info->right_gain % 64; + + if (info->balance < DBRI_MID_BALANCE) { + right_gain *= info->balance; + right_gain /= DBRI_MID_BALANCE; + } else { + left_gain *= DBRI_RIGHT_BALANCE - info->balance; + left_gain /= DBRI_MID_BALANCE; + } dbri->mm.data[0] &= ~0x3f; /* Reset the volume bits */ dbri->mm.data[1] &= ~0x3f; @@ -1375,8 +1397,8 @@ static void cs4215_setdata(struct snd_dbri * dbri, int muted) /* Now set the recording gain. */ info = &dbri->stream_info[DBRI_REC]; - left_gain = info->left_gain & 0xf; - right_gain = info->right_gain & 0xf; + left_gain = info->left_gain % 16; + right_gain = info->right_gain % 16; dbri->mm.data[2] |= CS4215_LG(left_gain); dbri->mm.data[3] |= CS4215_RG(right_gain); } @@ -1391,7 +1413,6 @@ static void cs4215_open(struct snd_dbri * dbri) { int data_width; u32 tmp; - unsigned long flags; dprintk(D_MM, "cs4215_open: %d channels, %d bits\n", dbri->mm.channels, dbri->mm.precision); @@ -1416,7 +1437,6 @@ static void cs4215_open(struct snd_dbri * dbri) * bits. The CS4215, it seems, observes TSIN (the delayed signal) * even if it's the CHI master. Don't ask me... */ - spin_lock_irqsave(&dbri->lock, flags); tmp = sbus_readl(dbri->regs + REG0); tmp &= ~(D_C); /* Disable CHI */ sbus_writel(tmp, dbri->regs + REG0); @@ -1435,16 +1455,15 @@ static void cs4215_open(struct snd_dbri * dbri) */ data_width = dbri->mm.channels * dbri->mm.precision; - link_time_slot(dbri, 4, 16, 16, data_width, dbri->mm.offset); - link_time_slot(dbri, 20, 4, 16, 32, dbri->mm.offset + 32); - link_time_slot(dbri, 6, 16, 16, data_width, dbri->mm.offset); - link_time_slot(dbri, 21, 6, 16, 16, dbri->mm.offset + 40); + link_time_slot(dbri, 20, PIPEoutput, 16, 32, dbri->mm.offset + 32); + link_time_slot(dbri, 4, PIPEoutput, 16, data_width, dbri->mm.offset); + link_time_slot(dbri, 6, PIPEinput, 16, data_width, dbri->mm.offset); + link_time_slot(dbri, 21, PIPEinput, 16, 16, dbri->mm.offset + 40); /* FIXME: enable CHI after _setdata? */ tmp = sbus_readl(dbri->regs + REG0); tmp |= D_C; /* Enable CHI */ sbus_writel(tmp, dbri->regs + REG0); - spin_unlock_irqrestore(&dbri->lock, flags); cs4215_setdata(dbri, 0); } @@ -1456,7 +1475,6 @@ static int cs4215_setctrl(struct snd_dbri * dbri) { int i, val; u32 tmp; - unsigned long flags; /* FIXME - let the CPU do something useful during these delays */ @@ -1493,7 +1511,6 @@ static int cs4215_setctrl(struct snd_dbri * dbri) * done in hardware by a TI 248 that delays the DBRI->4215 * frame sync signal by eight clock cycles. Anybody know why? */ - spin_lock_irqsave(&dbri->lock, flags); tmp = sbus_readl(dbri->regs + REG0); tmp &= ~D_C; /* Disable CHI */ sbus_writel(tmp, dbri->regs + REG0); @@ -1507,20 +1524,17 @@ static int cs4215_setctrl(struct snd_dbri * dbri) * Pipe 19: Receive timeslot 7 (version). */ - link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset); - link_time_slot(dbri, 18, 16, 16, 8, dbri->mm.offset); - link_time_slot(dbri, 19, 18, 16, 8, dbri->mm.offset + 48); - spin_unlock_irqrestore(&dbri->lock, flags); + link_time_slot(dbri, 17, PIPEoutput, 16, 32, dbri->mm.offset); + link_time_slot(dbri, 18, PIPEinput, 16, 8, dbri->mm.offset); + link_time_slot(dbri, 19, PIPEinput, 16, 8, dbri->mm.offset + 48); /* Wait for the chip to echo back CLB (Control Latch Bit) as zero */ dbri->mm.ctrl[0] &= ~CS4215_CLB; xmit_fixed(dbri, 17, *(int *)dbri->mm.ctrl); - spin_lock_irqsave(&dbri->lock, flags); tmp = sbus_readl(dbri->regs + REG0); tmp |= D_C; /* Enable CHI */ sbus_writel(tmp, dbri->regs + REG0); - spin_unlock_irqrestore(&dbri->lock, flags); for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) { msleep_interruptible(1); @@ -1600,7 +1614,8 @@ static int cs4215_prepare(struct snd_dbri * dbri, unsigned int rate, CS4215_BSEL_128 | CS4215_FREQ[freq_idx].xtal; dbri->mm.channels = channels; - if (channels == 2) + /* Stereo bit: 8 bit stereo not working yet. */ + if ((channels > 1) && (dbri->mm.precision == 16)) dbri->mm.ctrl[1] |= CS4215_DFR_STEREO; ret = cs4215_setctrl(dbri); @@ -1640,6 +1655,7 @@ static int cs4215_init(struct snd_dbri * dbri) } cs4215_setup_pipes(dbri); + cs4215_init_data(&dbri->mm); /* Enable capture of the status & version timeslots. */ @@ -1668,71 +1684,88 @@ buffer and calls dbri_process_one_interrupt() for each interrupt word. Complicated interrupts are handled by dedicated functions (which appear first in this file). Any pending interrupts can be serviced by calling dbri_process_interrupt_buffer(), which works even if the CPU's -interrupts are disabled. +interrupts are disabled. This function is used by dbri_cmdlock() +to make sure we're synced up with the chip before each command sequence, +even if we're running cli'ed. */ /* xmit_descs() * - * Starts transmiting the current TD's for recording/playing. + * Transmit the current TD's for recording/playing, if needed. * For playback, ALSA has filled the DMA memory with new data (we hope). */ -static void xmit_descs(struct snd_dbri *dbri) +static void xmit_descs(unsigned long data) { + struct snd_dbri *dbri = (struct snd_dbri *) data; struct dbri_streaminfo *info; - s32 *cmd; + volatile s32 *cmd; unsigned long flags; int first_td; if (dbri == NULL) return; /* Disabled */ + /* First check the recording stream for buffer overflow */ info = &dbri->stream_info[DBRI_REC]; spin_lock_irqsave(&dbri->lock, flags); - if (info->pipe >= 0) { + if ((info->left >= info->size) && (info->pipe >= 0)) { first_td = dbri->pipes[info->pipe].first_desc; dprintk(D_DESC, "xmit_descs rec @ TD %d\n", first_td); /* Stream could be closed by the time we run. */ - if (first_td >= 0) { - cmd = dbri_cmdlock(dbri, 2); - *(cmd++) = DBRI_CMD(D_SDP, 0, - dbri->pipes[info->pipe].sdp - | D_SDP_P | D_SDP_EVERY | D_SDP_C); - *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); - dbri_cmdsend(dbri, cmd, 2); - - /* Reset our admin of the pipe. */ - dbri->pipes[info->pipe].desc = first_td; + if (first_td < 0) { + goto play; } + + cmd = dbri_cmdlock(dbri, NoGetLock); + *(cmd++) = DBRI_CMD(D_SDP, 0, + dbri->pipes[info->pipe].sdp + | D_SDP_P | D_SDP_EVERY | D_SDP_C); + *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); + dbri_cmdsend(dbri, cmd); + + /* Reset our admin of the pipe & bytes read. */ + dbri->pipes[info->pipe].desc = first_td; + info->left = 0; } +play: + spin_unlock_irqrestore(&dbri->lock, flags); + + /* Now check the playback stream for buffer underflow */ info = &dbri->stream_info[DBRI_PLAY]; + spin_lock_irqsave(&dbri->lock, flags); - if (info->pipe >= 0) { + if ((info->left <= 0) && (info->pipe >= 0)) { first_td = dbri->pipes[info->pipe].first_desc; dprintk(D_DESC, "xmit_descs play @ TD %d\n", first_td); /* Stream could be closed by the time we run. */ - if (first_td >= 0) { - cmd = dbri_cmdlock(dbri, 2); - *(cmd++) = DBRI_CMD(D_SDP, 0, - dbri->pipes[info->pipe].sdp - | D_SDP_P | D_SDP_EVERY | D_SDP_C); - *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); - dbri_cmdsend(dbri, cmd, 2); - - /* Reset our admin of the pipe. */ - dbri->pipes[info->pipe].desc = first_td; + if (first_td < 0) { + spin_unlock_irqrestore(&dbri->lock, flags); + return; } - } + cmd = dbri_cmdlock(dbri, NoGetLock); + *(cmd++) = DBRI_CMD(D_SDP, 0, + dbri->pipes[info->pipe].sdp + | D_SDP_P | D_SDP_EVERY | D_SDP_C); + *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); + dbri_cmdsend(dbri, cmd); + + /* Reset our admin of the pipe & bytes written. */ + dbri->pipes[info->pipe].desc = first_td; + info->left = info->size; + } spin_unlock_irqrestore(&dbri->lock, flags); } +static DECLARE_TASKLET(xmit_descs_task, xmit_descs, 0); + /* transmission_complete_intr() * * Called by main interrupt handler when DBRI signals transmission complete @@ -1742,9 +1775,9 @@ static void xmit_descs(struct snd_dbri *dbri) * them as available. Stops when the first descriptor is found without * TBC (Transmit Buffer Complete) set, or we've run through them all. * - * The DMA buffers are not released. They form a ring buffer and - * they are filled by ALSA while others are transmitted by DMA. - * + * The DMA buffers are not released, but re-used. Since the transmit buffer + * descriptors are not clobbered, they can be re-submitted as is. This is + * done by the xmit_descs() tasklet above since that could take longer. */ static void transmission_complete_intr(struct snd_dbri * dbri, int pipe) @@ -1770,9 +1803,21 @@ static void transmission_complete_intr(struct snd_dbri * dbri, int pipe) dprintk(D_INT, "TD %d, status 0x%02x\n", td, status); dbri->dma->desc[td].word4 = 0; /* Reset it for next time. */ - info->offset += DBRI_RD_CNT(dbri->dma->desc[td].word1); + info->offset += dbri->descs[td].len; + info->left -= dbri->descs[td].len; + + /* On the last TD, transmit them all again. */ + if (dbri->descs[td].next == -1) { + if (info->left > 0) { + printk(KERN_WARNING + "%d bytes left after last transfer.\n", + info->left); + info->left = 0; + } + tasklet_schedule(&xmit_descs_task); + } - td = dbri->next_desc[td]; + td = dbri->descs[td].next; dbri->pipes[pipe].desc = td; } @@ -1796,18 +1841,30 @@ static void reception_complete_intr(struct snd_dbri * dbri, int pipe) return; } - dbri->pipes[pipe].desc = dbri->next_desc[rd]; + dbri->descs[rd].inuse = 0; + dbri->pipes[pipe].desc = dbri->descs[rd].next; status = dbri->dma->desc[rd].word1; dbri->dma->desc[rd].word1 = 0; /* Reset it for next time. */ info = &dbri->stream_info[DBRI_REC]; info->offset += DBRI_RD_CNT(status); + info->left += DBRI_RD_CNT(status); /* FIXME: Check status */ dprintk(D_INT, "Recv RD %d, status 0x%02x, len %d\n", rd, DBRI_RD_STATUS(status), DBRI_RD_CNT(status)); + /* On the last TD, transmit them all again. */ + if (dbri->descs[rd].next == -1) { + if (info->left > info->size) { + printk(KERN_WARNING + "%d bytes recorded in %d size buffer.\n", + info->left, info->size); + } + tasklet_schedule(&xmit_descs_task); + } + /* Notify ALSA */ if (spin_is_locked(&dbri->lock)) { spin_unlock(&dbri->lock); @@ -1835,11 +1892,16 @@ static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x) channel, code, rval); } + if (channel == D_INTR_CMD && command == D_WAIT) { + dbri->wait_ackd = val; + if (dbri->wait_send != val) { + printk(KERN_ERR "Processing wait command %d when %d was send.\n", + val, dbri->wait_send); + } + return; + } + switch (code) { - case D_INTR_CMDI: - if (command != D_WAIT) - printk(KERN_ERR "DBRI: Command read interrupt\n"); - break; case D_INTR_BRDY: reception_complete_intr(dbri, channel); break; @@ -1852,10 +1914,8 @@ static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x) * resend SDP command with clear pipe bit (C) set */ { - /* FIXME: do something useful in case of underrun */ - printk(KERN_ERR "DBRI: Underrun error\n"); -#if 0 - s32 *cmd; + volatile s32 *cmd; + int pipe = channel; int td = dbri->pipes[pipe].desc; @@ -1866,7 +1926,6 @@ static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x) | D_SDP_P | D_SDP_C | D_SDP_2SAME); *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, td); dbri_cmdsend(dbri, cmd); -#endif } break; case D_INTR_FXDT: @@ -1887,7 +1946,9 @@ static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x) /* dbri_process_interrupt_buffer advances through the DBRI's interrupt * buffer until it finds a zero word (indicating nothing more to do * right now). Non-zero words require processing and are handed off - * to dbri_process_one_interrupt AFTER advancing the pointer. + * to dbri_process_one_interrupt AFTER advancing the pointer. This + * order is important since we might recurse back into this function + * and need to make sure the pointer has been advanced first. */ static void dbri_process_interrupt_buffer(struct snd_dbri * dbri) { @@ -1896,8 +1957,10 @@ static void dbri_process_interrupt_buffer(struct snd_dbri * dbri) while ((x = dbri->dma->intr[dbri->dbri_irqp]) != 0) { dbri->dma->intr[dbri->dbri_irqp] = 0; dbri->dbri_irqp++; - if (dbri->dbri_irqp == DBRI_INT_BLK) + if (dbri->dbri_irqp == (DBRI_NO_INTS * DBRI_INT_BLK)) dbri->dbri_irqp = 1; + else if ((dbri->dbri_irqp & (DBRI_INT_BLK - 1)) == 0) + dbri->dbri_irqp++; dbri_process_one_interrupt(dbri, x); } @@ -1957,6 +2020,8 @@ static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id, dbri_process_interrupt_buffer(dbri); + /* FIXME: Write 0 into regs to ACK interrupt */ + spin_unlock(&dbri->lock); return IRQ_HANDLED; @@ -1974,8 +2039,8 @@ static struct snd_pcm_hardware snd_dbri_pcm_hw = { SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_BE, - .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_5512, - .rate_min = 5512, + .rates = SNDRV_PCM_RATE_8000_48000, + .rate_min = 8000, .rate_max = 48000, .channels_min = 1, .channels_max = 2, @@ -1986,39 +2051,6 @@ static struct snd_pcm_hardware snd_dbri_pcm_hw = { .periods_max = 1024, }; -static int snd_hw_rule_format(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *c = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_mask fmt; - - snd_mask_any(&fmt); - if (c->min > 1) { - fmt.bits[0] &= SNDRV_PCM_FMTBIT_S16_BE; - return snd_mask_refine(f, &fmt); - } - return 0; -} - -static int snd_hw_rule_channels(struct snd_pcm_hw_params *params, - struct snd_pcm_hw_rule *rule) -{ - struct snd_interval *c = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_interval ch; - - snd_interval_any(&ch); - if (!(f->bits[0] & SNDRV_PCM_FMTBIT_S16_BE)) { - ch.min = ch.max = 1; - ch.integer = 1; - return snd_interval_refine(c, &ch); - } - return 0; -} - static int snd_dbri_open(struct snd_pcm_substream *substream) { struct snd_dbri *dbri = snd_pcm_substream_chip(substream); @@ -2031,19 +2063,12 @@ static int snd_dbri_open(struct snd_pcm_substream *substream) spin_lock_irqsave(&dbri->lock, flags); info->substream = substream; + info->left = 0; info->offset = 0; info->dvma_buffer = 0; info->pipe = -1; spin_unlock_irqrestore(&dbri->lock, flags); - snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_CHANNELS, - snd_hw_rule_format, 0, SNDRV_PCM_HW_PARAM_FORMAT, - -1); - snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_FORMAT, - snd_hw_rule_channels, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - -1); - cs4215_open(dbri); return 0; @@ -2056,6 +2081,7 @@ static int snd_dbri_close(struct snd_pcm_substream *substream) dprintk(D_USR, "close audio output.\n"); info->substream = NULL; + info->left = 0; info->offset = 0; return 0; @@ -2108,7 +2134,6 @@ static int snd_dbri_hw_free(struct snd_pcm_substream *substream) struct snd_dbri *dbri = snd_pcm_substream_chip(substream); struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream); int direction; - dprintk(D_USR, "hw_free.\n"); /* hw_free can get called multiple times. Only unmap the DMA once. @@ -2123,10 +2148,7 @@ static int snd_dbri_hw_free(struct snd_pcm_substream *substream) substream->runtime->buffer_size, direction); info->dvma_buffer = 0; } - if (info->pipe != -1) { - reset_pipe(dbri, info->pipe); - info->pipe = -1; - } + info->pipe = -1; return snd_pcm_lib_free_pages(substream); } @@ -2135,16 +2157,18 @@ static int snd_dbri_prepare(struct snd_pcm_substream *substream) { struct snd_dbri *dbri = snd_pcm_substream_chip(substream); struct dbri_streaminfo *info = DBRI_STREAM(dbri, substream); + struct snd_pcm_runtime *runtime = substream->runtime; int ret; info->size = snd_pcm_lib_buffer_bytes(substream); if (DBRI_STREAMNO(substream) == DBRI_PLAY) info->pipe = 4; /* Send pipe */ - else + else { info->pipe = 6; /* Receive pipe */ + info->left = info->size; /* To trigger submittal */ + } spin_lock_irq(&dbri->lock); - info->offset = 0; /* Setup the all the transmit/receive desciptors to cover the * whole DMA buffer. @@ -2152,6 +2176,8 @@ static int snd_dbri_prepare(struct snd_pcm_substream *substream) ret = setup_descs(dbri, DBRI_STREAMNO(substream), snd_pcm_lib_period_bytes(substream)); + runtime->stop_threshold = DBRI_TD_MAXCNT / runtime->channels; + spin_unlock_irq(&dbri->lock); dprintk(D_USR, "prepare audio output. %d bytes\n", info->size); @@ -2168,11 +2194,14 @@ static int snd_dbri_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_START: dprintk(D_USR, "start audio, period is %d bytes\n", (int)snd_pcm_lib_period_bytes(substream)); - /* Re-submit the TDs. */ - xmit_descs(dbri); + /* Enable & schedule the tasklet that re-submits the TDs. */ + xmit_descs_task.data = (unsigned long)dbri; + tasklet_schedule(&xmit_descs_task); break; case SNDRV_PCM_TRIGGER_STOP: dprintk(D_USR, "stop audio.\n"); + /* Make the tasklet bail out immediately. */ + xmit_descs_task.data = 0; reset_pipe(dbri, info->pipe); break; default: @@ -2190,8 +2219,8 @@ static snd_pcm_uframes_t snd_dbri_pointer(struct snd_pcm_substream *substream) ret = bytes_to_frames(substream->runtime, info->offset) % substream->runtime->buffer_size; - dprintk(D_USR, "I/O pointer: %ld frames of %ld.\n", - ret, substream->runtime->buffer_size); + dprintk(D_USR, "I/O pointer: %ld frames, %d bytes left.\n", + ret, info->left); return ret; } @@ -2225,6 +2254,7 @@ static int __devinit snd_dbri_pcm(struct snd_dbri * dbri) pcm->private_data = dbri; pcm->info_flags = 0; strcpy(pcm->name, dbri->card->shortname); + dbri->pcm = pcm; if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, @@ -2273,6 +2303,7 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol, { struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); struct dbri_streaminfo *info = &dbri->stream_info[kcontrol->private_value]; + unsigned long flags; int changed = 0; if (info->left_gain != ucontrol->value.integer.value[0]) { @@ -2287,9 +2318,13 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol, /* First mute outputs, and wait 1/8000 sec (125 us) * to make sure this takes. This avoids clicking noises. */ + spin_lock_irqsave(&dbri->lock, flags); + cs4215_setdata(dbri, 1); udelay(125); cs4215_setdata(dbri, 0); + + spin_unlock_irqrestore(&dbri->lock, flags); } return changed; } @@ -2336,6 +2371,7 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); + unsigned long flags; int elem = kcontrol->private_value & 0xff; int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; @@ -2368,9 +2404,13 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol, /* First mute outputs, and wait 1/8000 sec (125 us) * to make sure this takes. This avoids clicking noises. */ + spin_lock_irqsave(&dbri->lock, flags); + cs4215_setdata(dbri, 1); udelay(125); cs4215_setdata(dbri, 0); + + spin_unlock_irqrestore(&dbri->lock, flags); } return changed; } @@ -2433,6 +2473,7 @@ static int __init snd_dbri_mixer(struct snd_dbri * dbri) for (idx = DBRI_REC; idx < DBRI_NO_STREAMS; idx++) { dbri->stream_info[idx].left_gain = 0; dbri->stream_info[idx].right_gain = 0; + dbri->stream_info[idx].balance = DBRI_MID_BALANCE; } return 0; @@ -2464,11 +2505,12 @@ static void dbri_debug_read(struct snd_info_entry * entry, struct dbri_pipe *pptr = &dbri->pipes[pipe]; snd_iprintf(buffer, "Pipe %d: %s SDP=0x%x desc=%d, " - "len=%d next %d\n", + "len=%d @ %d prev: %d next %d\n", pipe, - ((pptr->sdp & D_SDP_TO_SER) ? "output" : "input"), - pptr->sdp, pptr->desc, - pptr->length, pptr->nextpipe); + (pptr->direction == + PIPEinput ? "input" : "output"), pptr->sdp, + pptr->desc, pptr->length, pptr->cycle, + pptr->prevpipe, pptr->nextpipe); } } } @@ -2507,6 +2549,7 @@ static int __init snd_dbri_create(struct snd_card *card, dbri->card = card; dbri->sdev = sdev; dbri->irq = irq->pri; + dbri->dbri_version = sdev->prom_name[9]; dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma), &dbri->dma_dvma); @@ -2626,7 +2669,7 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n", dev, dbri->regs, - dbri->irq, sdev->prom_name[9], dbri->mm.version); + dbri->irq, dbri->dbri_version, dbri->mm.version); dev++; return 0; diff --git a/trunk/sound/synth/emux/emux_proc.c b/trunk/sound/synth/emux/emux_proc.c index 59144ec026e4..58b9601f3ad0 100644 --- a/trunk/sound/synth/emux/emux_proc.c +++ b/trunk/sound/synth/emux/emux_proc.c @@ -128,8 +128,10 @@ void snd_emux_proc_init(struct snd_emux *emu, struct snd_card *card, int device) void snd_emux_proc_free(struct snd_emux *emu) { - snd_info_free_entry(emu->proc); - emu->proc = NULL; + if (emu->proc) { + snd_info_unregister(emu->proc); + emu->proc = NULL; + } } #endif /* CONFIG_PROC_FS */ diff --git a/trunk/sound/usb/usbaudio.c b/trunk/sound/usb/usbaudio.c index 49248fa7aef4..d32d83d970cc 100644 --- a/trunk/sound/usb/usbaudio.c +++ b/trunk/sound/usb/usbaudio.c @@ -68,7 +68,7 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Vendor ID for this card */ static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 }; /* Product ID for this card */ -static int nrpacks = 8; /* max. number of packets per urb */ +static int nrpacks = 4; /* max. number of packets per urb */ static int async_unlink = 1; static int device_setup[SNDRV_CARDS]; /* device parameter for this card*/ @@ -100,7 +100,7 @@ MODULE_PARM_DESC(device_setup, "Specific device setup (if needed)."); * */ -#define MAX_PACKS 20 +#define MAX_PACKS 10 #define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */ #define MAX_URBS 8 #define SYNC_URBS 4 /* always four urbs for sync */ @@ -123,7 +123,6 @@ struct audioformat { unsigned int rate_min, rate_max; /* min/max rates */ unsigned int nr_rates; /* number of rate table entries */ unsigned int *rate_table; /* rate table */ - unsigned int needs_knot; /* any unusual rates? */ }; struct snd_usb_substream; @@ -1760,9 +1759,6 @@ static int check_hw_params_convention(struct snd_usb_substream *subs) } channels[f->format] |= (1 << f->channels); rates[f->format] |= f->rates; - /* needs knot? */ - if (f->needs_knot) - goto __out; } /* check whether channels and rates match for all formats */ cmaster = rmaster = 0; @@ -1803,38 +1799,6 @@ static int check_hw_params_convention(struct snd_usb_substream *subs) return err; } -/* - * If the device supports unusual bit rates, does the request meet these? - */ -static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, - struct snd_usb_substream *subs) -{ - struct list_head *p; - struct snd_pcm_hw_constraint_list constraints_rates; - int err; - - list_for_each(p, &subs->fmt_list) { - struct audioformat *fp; - fp = list_entry(p, struct audioformat, list); - - if (!fp->needs_knot) - continue; - - constraints_rates.count = fp->nr_rates; - constraints_rates.list = fp->rate_table; - constraints_rates.mask = 0; - - err = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_rates); - - if (err < 0) - return err; - } - - return 0; -} - /* * set up the runtime hardware information. @@ -1897,8 +1861,6 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) return err; - if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0) - return err; } return 0; } @@ -2087,7 +2049,7 @@ static struct usb_driver usb_audio_driver = { }; -#if defined(CONFIG_PROC_FS) && defined(CONFIG_SND_VERBOSE_PROCFS) +#if defined(CONFIG_PROCFS) && defined(CONFIG_SND_VERBOSE_PROCFS) /* * proc interface for list the supported pcm formats @@ -2298,9 +2260,10 @@ static int add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct aud } /* create a new pcm */ - as = kzalloc(sizeof(*as), GFP_KERNEL); + as = kmalloc(sizeof(*as), GFP_KERNEL); if (! as) return -ENOMEM; + memset(as, 0, sizeof(*as)); as->pcm_index = chip->pcm_devs; as->chip = chip; as->fmt_type = fp->fmt_type; @@ -2444,7 +2407,6 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform unsigned char *fmt, int offset) { int nr_rates = fmt[offset]; - int found; if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) { snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n", chip->dev->devnum, fp->iface, fp->altsetting); @@ -2467,7 +2429,6 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform return -1; } - fp->needs_knot = 0; fp->nr_rates = nr_rates; fp->rate_min = fp->rate_max = combine_triple(&fmt[8]); for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) { @@ -2476,19 +2437,13 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform fp->rate_min = rate; else if (rate > fp->rate_max) fp->rate_max = rate; - found = 0; for (c = 0; c < (int)ARRAY_SIZE(conv_rates); c++) { if (rate == conv_rates[c]) { - found = 1; fp->rates |= (1 << c); break; } } - if (!found) - fp->needs_knot = 1; } - if (fp->needs_knot) - fp->rates |= SNDRV_PCM_RATE_KNOT; } else { /* continuous rates */ fp->rates = SNDRV_PCM_RATE_CONTINUOUS; @@ -2678,12 +2633,13 @@ static int parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no) csep = NULL; } - fp = kzalloc(sizeof(*fp), GFP_KERNEL); + fp = kmalloc(sizeof(*fp), GFP_KERNEL); if (! fp) { snd_printk(KERN_ERR "cannot malloc\n"); return -ENOMEM; } + memset(fp, 0, sizeof(*fp)); fp->iface = iface_no; fp->altsetting = altno; fp->altset_idx = i; @@ -3545,7 +3501,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) } usb_chip[chip->index] = NULL; mutex_unlock(®ister_mutex); - snd_card_free_when_closed(card); + snd_card_free(card); } else { mutex_unlock(®ister_mutex); } diff --git a/trunk/sound/usb/usbmixer.c b/trunk/sound/usb/usbmixer.c index e516d6adbb22..491e975a0c87 100644 --- a/trunk/sound/usb/usbmixer.c +++ b/trunk/sound/usb/usbmixer.c @@ -37,7 +37,6 @@ #include #include #include -#include #include "usbaudio.h" @@ -417,26 +416,6 @@ static inline int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channe return set_ctl_value(cval, SET_CUR, (cval->control << 8) | channel, value); } -/* - * TLV callback for mixer volume controls - */ -static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *_tlv) -{ - struct usb_mixer_elem_info *cval = kcontrol->private_data; - DECLARE_TLV_DB_SCALE(scale, 0, 0, 0); - - if (size < sizeof(scale)) - return -ENOMEM; - /* USB descriptions contain the dB scale in 1/256 dB unit - * while ALSA TLV contains in 1/100 dB unit - */ - scale[2] = (convert_signed_value(cval, cval->min) * 100) / 256; - scale[3] = (convert_signed_value(cval, cval->res) * 100) / 256; - if (copy_to_user(_tlv, scale, sizeof(scale))) - return -EFAULT; - return 0; -} /* * parser routines begin here... @@ -954,12 +933,6 @@ static void build_feature_ctl(struct mixer_build *state, unsigned char *desc, } strlcat(kctl->id.name + len, control == USB_FEATURE_MUTE ? " Switch" : " Volume", sizeof(kctl->id.name)); - if (control == USB_FEATURE_VOLUME) { - kctl->tlv.c = mixer_vol_tlv; - kctl->vd[0].access |= - SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; - } break; default: diff --git a/trunk/sound/usb/usbmixer_maps.c b/trunk/sound/usb/usbmixer_maps.c index 7c4dcb3f436a..37accb68652d 100644 --- a/trunk/sound/usb/usbmixer_maps.c +++ b/trunk/sound/usb/usbmixer_maps.c @@ -234,26 +234,6 @@ static struct usbmix_name_map justlink_map[] = { { 0 } /* terminator */ }; -/* TerraTec Aureon 5.1 MkII USB */ -static struct usbmix_name_map aureon_51_2_map[] = { - /* 1: IT USB */ - /* 2: IT Mic */ - /* 3: IT Line */ - /* 4: IT SPDIF */ - /* 5: OT SPDIF */ - /* 6: OT Speaker */ - /* 7: OT USB */ - { 8, "Capture Source" }, /* SU */ - { 9, "Master Playback" }, /* FU */ - { 10, "Mic Capture" }, /* FU */ - { 11, "Line Capture" }, /* FU */ - { 12, "IEC958 In Capture" }, /* FU */ - { 13, "Mic Playback" }, /* FU */ - { 14, "Line Playback" }, /* FU */ - /* 15: MU */ - {} /* terminator */ -}; - /* * Control map entries */ @@ -296,10 +276,6 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = { .id = USB_ID(0x0c45, 0x1158), .map = justlink_map, }, - { - .id = USB_ID(0x0ccd, 0x0028), - .map = aureon_51_2_map, - }, { 0 } /* terminator */ }; diff --git a/trunk/sound/usb/usbquirks.h b/trunk/sound/usb/usbquirks.h index a7e9563a01df..9351846d7a9d 100644 --- a/trunk/sound/usb/usbquirks.h +++ b/trunk/sound/usb/usbquirks.h @@ -123,10 +123,6 @@ YAMAHA_DEVICE(0x103e, NULL), YAMAHA_DEVICE(0x103f, NULL), YAMAHA_DEVICE(0x1040, NULL), YAMAHA_DEVICE(0x1041, NULL), -YAMAHA_DEVICE(0x1042, NULL), -YAMAHA_DEVICE(0x1043, NULL), -YAMAHA_DEVICE(0x1044, NULL), -YAMAHA_DEVICE(0x1045, NULL), YAMAHA_DEVICE(0x2000, "DGP-7"), YAMAHA_DEVICE(0x2001, "DGP-5"), YAMAHA_DEVICE(0x2002, NULL), @@ -145,7 +141,6 @@ YAMAHA_DEVICE(0x500b, "DME64N"), YAMAHA_DEVICE(0x500c, "DME24N"), YAMAHA_DEVICE(0x500d, NULL), YAMAHA_DEVICE(0x500e, NULL), -YAMAHA_DEVICE(0x500f, NULL), YAMAHA_DEVICE(0x7000, "DTX"), YAMAHA_DEVICE(0x7010, "UB99"), #undef YAMAHA_DEVICE diff --git a/trunk/usr/Makefile b/trunk/usr/Makefile index 5b31c0b61c76..e93824269da2 100644 --- a/trunk/usr/Makefile +++ b/trunk/usr/Makefile @@ -35,9 +35,6 @@ quiet_cmd_initfs = GEN $@ cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input) targets := initramfs_data.cpio.gz -# do not try to update files included in initramfs -$(deps_initramfs): ; - $(deps_initramfs): klibcdirs # We rebuild initramfs_data.cpio.gz if: # 1) Any included file is newer then initramfs_data.cpio.gz